下面给你一个在LangChain 中实现 Skill 的完整示例,并结合你前面的认知,说明:
- 什么是 LangChain 里的 Skill
- Skill 与 Tool 的区别
- 如何用
@tool、自定义Skill类来封装能力
一、LangChain 中的 Skill 概念
在 LangChain 生态中,我们通常把智能体自带、基于模型推理或固定逻辑的可复用能力,抽象成 Skill,而把需要调用外部系统 / 服务的功能封装成 Tool。
在实现上,有两种常见方式:
- 直接用
@tool装饰器封装函数:简单快捷,适合通用技能。 - 继承
BaseTool实现自定义 Skill 类:更灵活,可加权限校验、日志、缓存等。
二、环境准备
bash
运行
pip install langchain langchain-openai python-dotenv.env文件配置 OpenAI Key(或你用的其他模型):
plaintext
OPENAI_API_KEY=sk-xxx三、示例 1:基于@tool的简单 Skill 实现
下面实现两个典型的「模型原生能力类 Skill」:
- 文本润色 Skill
- 代码解释 Skill
python
运行
from langchain.tools import tool from langchain_openai import ChatOpenAI from langchain.agents import AgentExecutor, create_react_agent from langchain_core.prompts import PromptTemplate from dotenv import load_dotenv import os load_dotenv() llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0) # ====================== Skill 1:文本润色 ====================== @tool def text_polish_skill(text: str, style: str = "正式") -> str: """ 【文本润色 Skill】:根据指定风格润色文本 Args: text: 待润色的文本 style: 目标风格,可选:正式/口语/公文/幽默 """ prompt = f""" 请将以下文本润色为【{style}】风格,保持原意不变: 原文:{text} """ return llm.invoke(prompt).content # ====================== Skill 2:代码解释 ====================== @tool def code_explain_skill(code: str, language: str = "Python") -> str: """ 【代码解释 Skill】:解释代码的作用和关键步骤 Args: code: 待解释的代码片段 language: 代码语言,默认 Python """ prompt = f""" 请用通俗易懂的语言,解释以下{language}代码的作用、关键步骤和注意事项: ```{language} {code}""" return llm.invoke(prompt).content
====================== 用 Agent 调用 Skill ======================
tools = [text_polish_skill, code_explain_skill]
prompt = PromptTemplate.from_template (""" 你是一个助手,根据用户问题,选择合适的 Skill 来回答。 用户问题:{input} 可用工具:{tools} 工具名列表:{tool_names} 你必须按照 ReAct 格式思考:
- 分析用户问题
- 决定使用哪个工具
- 调用工具并得到结果
- 整理成最终回答 开始! """)
agent = create_react_agent(llm, tools, prompt) agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
ifname== "main":
测试 1:文本润色
print ("=== 测试文本润色 Skill ===") result1 = agent_executor.invoke ({ "input": "帮我把这句话改成正式风格:我今天好忙,一堆事没做完" }) print (result1 ["output"])
测试 2:代码解释
print ("\n=== 测试代码解释 Skill ===") code_snippet = """ def quick_sort (arr): if len (arr) <= 1: return arr pivot = arr [len (arr) // 2] left = [x for x in arr if x < pivot] middle = [x for x in arr if x == pivot] right = [x for x in arr if x > pivot] return quick_sort (left) + middle + quick_sort (right) """ result2 = agent_executor.invoke ({ "input": f"请解释这段代码的作用:\n {code_snippet}" }) print (result2 ["output"])
plaintext
四、示例 2:自定义Skill类(继承BaseTool)
适合需要加日志、权限、缓存的复杂 Skill:
python
运行
from langchain.tools import BaseTool from pydantic import Field from langchain_openai import ChatOpenAI from langchain.agents import AgentExecutor, create_react_agent from langchain_core.prompts import PromptTemplate from dotenv import load_dotenv import os import logging load_dotenv() llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0) logging.basicConfig(level=logging.INFO) # ====================== 自定义 Skill 类 ====================== class ReportGenerateSkill(BaseTool): name: str = "report_generate_skill" description: str = "根据数据生成结构化报告,输入是数据字典和报告标题" def _run(self, data_str: str, title: str) -> str: """ Args: data_str: JSON格式的业务数据(字符串形式) title: 报告标题 """ logging.info(f"调用 ReportGenerateSkill,标题:{title}") prompt = f""" 请根据以下数据,生成一份结构化的业务报告,标题为【{title}】: 数据:{data_str} 报告结构: 1. 核心数据概览 2. 关键指标分析 3. 结论与建议 """ return llm.invoke(prompt).content async def _arun(self, data_str: str, title: str) -> str: # 异步实现(可选) return self._run(data_str, title) # ====================== 使用自定义 Skill ====================== tools = [ReportGenerateSkill()] prompt = PromptTemplate.from_template(""" 你是一个业务助手,根据用户问题,使用 report_generate_skill 生成报告。 用户问题:{input} 可用工具:{tools} 工具名列表:{tool_names} """) agent = create_react_agent(llm, tools, prompt) agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True) if __name__ == "__main__": business_data = """ { "销售额": 128000, "订单数": 4200, "用户数": 18600, "环比增长": "12%" } """ result = agent_executor.invoke({ "input": f"根据以下数据生成一份月度销售报告:\n{business_data}" }) print(result["output"])五、LangChain 中 Skill vs Tool 的关键区别
表格
| 维度 | Skill(示例中的text_polish_skill) | Tool(典型外部工具) |
|---|---|---|
| 依赖 | 仅依赖模型推理,无外部调用 | 依赖外部 API / 数据库 / 系统 |
| 实现 | 通常用@tool封装模型生成逻辑 | 封装 HTTP / 数据库 / 系统调用 |
| 执行 | 模型在进程内完成,无网络请求 | 需要网络 / IO,依赖外部服务 |
| 风险 | 仅在模型推理空间,无直接操作权限 | 可能读写数据、执行命令,需权限管控 |
| 复用 | 适合文本处理、推理、解释类能力 | 适合数据查询、接口调用、系统操作 |
六、和你前面七层架构的对应
- LangChain Agent→ 七层架构中的「Agent」层
- Skill→ 七层架构中的「Skills」层(模型原生能力)
- Tool→ 通过
MCP接入的外部资源(七层架构中的「MCP」连接的工具) - LangChain 的 Chain / AgentExecutor→ 七层架构中的「Harness」框架,负责编排与运行