Skip to content

3.5 实战:实现自定义 LangChain Tool

引言

小白理解 - 什么是 LangChain Tool?

Tool = AI 能调用的"技能"

类比:AI 就像一个实习生

  • 实习生很聪明,但不会所有事
  • 你给他一个工具箱(Tools)
  • 工具箱里有:搜索工具、计算器、天气查询...
  • 实习生根据任务,选择合适的工具使用
用户:"北京今天天气怎么样?"

AI 思考:"这需要查天气,我有 WeatherTool!"

AI 调用:WeatherTool.run(location="北京")

AI 回答:"北京今天晴天 25°C"

为什么要自定义 Tool?

LangChain 内置了一些 Tool,但你的业务可能需要:

  • 查询公司内部数据库
  • 调用自己的 API
  • 执行特定计算

所以你需要学会自己写 Tool!

完整的 Tool 类实现

小白理解 - 代码结构

BaseTool(抽象基类)

 │ 定义"Tool必须有什么":
 │ - name:工具名字
 │ - description:工具描述(告诉AI这工具干啥)
 │ - _run():实际执行的逻辑
 │ - run():公开接口(自动计数等)

 └── WeatherTool(你的自定义工具)
      │ 实现:
      │ - name = "weather"
      │ - description = "获取城市天气"
      │ - _run() = 查天气的代码
python
from abc import ABC, abstractmethod
from typing import Optional
from pydantic import BaseModel, Field

class ToolInput(BaseModel):
    """Tool 输入基类"""
    pass

class BaseTool(ABC):
    """Tool 抽象基类"""

    def __init__(self):
        self.call_count = 0

    @property
    @abstractmethod
    def name(self) -> str:
        pass

    @property
    @abstractmethod
    def description(self) -> str:
        pass

    @abstractmethod
    def _run(self, **kwargs) -> str:
        pass

    def run(self, **kwargs) -> str:
        """公共运行接口"""
        self.call_count += 1
        return self._run(**kwargs)

class WeatherInput(ToolInput):
    location: str = Field(description="城市名称")

class WeatherTool(BaseTool):
    """天气查询工具"""

    @property
    def name(self) -> str:
        return "weather"

    @property
    def description(self) -> str:
        return "获取城市天气信息"

    def _run(self, location: str) -> str:
        return f"{location} 的天气:晴天 25°C"

# 使用
tool = WeatherTool()
print(tool.run(location="北京"))
print(f"调用次数: {tool.call_count}")

关键代码解读

代码作用为什么需要
@abstractmethod子类必须实现确保每个 Tool 都有名字和描述
@property属性化访问tool.name 而不是 tool.name()
_run()实际逻辑你只需要实现这个
run()公开接口自动计数、日志、错误处理
BaseModelPydantic 验证自动验证输入参数

更多 Tool 示例

计算器 Tool

python
class CalculatorTool(BaseTool):
    """计算器工具"""

    @property
    def name(self) -> str:
        return "calculator"

    @property
    def description(self) -> str:
        return "执行数学计算"

    def _run(self, expression: str) -> str:
        try:
            result = eval(expression)  # 注意:生产环境要安全处理
            return str(result)
        except Exception as e:
            return f"计算错误: {e}"

# 使用
calc = CalculatorTool()
print(calc.run(expression="2 + 3 * 4"))  # 14

搜索 Tool

python
class SearchTool(BaseTool):
    """搜索工具"""

    @property
    def name(self) -> str:
        return "search"

    @property
    def description(self) -> str:
        return "搜索互联网获取信息"

    def _run(self, query: str) -> str:
        # 实际应用中这里会调用搜索 API
        return f"搜索 '{query}' 的结果:..."

# 使用
search = SearchTool()
print(search.run(query="Python 教程"))

本节小结

概念一句话解释
ToolAI 能调用的技能
BaseTool所有 Tool 的父类模板
nameTool 的名字(AI 用来识别)
descriptionTool 的描述(AI 用来理解何时使用)
_run()你需要实现的核心逻辑
run()公开接口,带自动计数

创建自己的 Tool 只需 4 步

  1. 继承 BaseTool
  2. 实现 name 属性
  3. 实现 description 属性
  4. 实现 _run() 方法

下一节:3.6 小结和复习

基于 MIT 许可证发布。内容版权归作者所有。