跳到主要内容

工具定义与使用

工具是 Agent 与外部世界交互的桥梁。工具的 namedescriptionargs_schema 决定了模型是否及如何选择调用工具。


多工具组合

多个工具可以一起使用:

from langchain.agents import create_agent
from langchain_core.tools import tool

@tool
def get_weather(city: str) -> str:
"""获取指定城市的天气信息"""
data = {"北京": "晴,25°C", "上海": "多云,28°C"}
return f"{city}{data.get(city, '未知')}"

@tool
def calculate(expression: str) -> str:
"""计算数学表达式"""
try:
return str(eval(expression))
except:
return "计算出错"

# 传入工具列表
agent = create_agent(
model=model,
tools=[get_weather, calculate],
system_prompt="你是多功能助手"
)

工具定义方式

@tool 装饰器

适合快速原型开发和简单工具实现。

技术特点

  • 自动参数推断
  • 代码简洁,一行装饰器完成
  • 无需复杂配置
from langchain_core.tools import tool

@tool
def multiply(a: int, b: int) -> int:
"""Multiplies a and b."""
return a * b

StructuredTool.from_function

适合需要参数校验的生产环境。

技术特点

  • 强类型校验:Pydantic 模型进行参数验证
  • 异步支持coroutine 参数支持异步
  • 完整元数据:name、description、return_direct 等配置
  • 生产就绪:内置错误处理和参数校验
from pydantic import BaseModel, Field
from langchain_core.tools import StructuredTool

# 定义参数校验模型
class DivideInput(BaseModel):
dividend: float = Field(description="被除数")
divisor: float = Field(description="除数,不能为零")

def divide(dividend: float, divisor: float) -> float:
if divisor == 0:
raise ValueError("除数不能为零")
return dividend / divisor

# 创建工具
division_tool = StructuredTool.from_function(
func=divide,
name="DivisionTool",
description="安全执行除法运算,自动处理除零错误",
args_schema=DivideInput,
return_direct=False,
)

继承 StructuredTool

适合复杂业务逻辑和状态管理。

技术特点

  • 完全自定义工具行为
  • 支持工具内部状态维护
  • 适合复杂业务逻辑封装
from langchain_core.tools import StructuredTool
from pydantic import BaseModel, Field
from typing import Type

class OrderQueryInput(BaseModel):
order_id: str = Field(description="订单编号")
include_details: bool = Field(default=False, description="是否包含商品明细")

class OrderQueryTool(StructuredTool):
name: str = "query_order"
description: str = "查询电商平台订单状态"
args_schema: Type[BaseModel] = OrderQueryInput
return_direct: bool = False

def _run(self, order_id: str, include_details: bool = False) -> dict:
order_db = {"ORD-2024-1234": {"status": "已发货", "express": "顺丰"}}
if order_id not in order_db:
return {"error": f"订单 {order_id} 不存在"}
result = order_db[order_id]
if include_details:
result["items"] = ["商品A × 2"]
return result

# 使用
agent = create_agent(model=model, tools=[OrderQueryTool()])

三种方式对比

特性@toolfrom_function继承
代码简洁度⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
参数控制自动推断args_schema 强校验完全自定义
异步支持
适用场景快速原型生产环境复杂业务

通过强制化 Schema 和规范化提示词,建立统一的工具使用规范。

规范要求:

  • 工具名称必须动词开头
  • 每个工具使用标准化 schema
  • 工具描述必须包含三件事:能干什么、不能干什么、典型输入示例

工具描述

描述规范

# ❌ 描述不清晰
@tool
def query(sql):
"""查询数据库"""

# ✅ 描述清晰
@tool
def query_database(sql: str) -> str:
"""
执行 SQL 查询,仅限内部业务数据库。
参数:sql SQL语句
示例:select * from users limit 5
"""

好的描述应包含:

  1. 工具能干什么
  2. 工具不能干什么
  3. 典型输入示例

return_direct

  • return_direct=True:工具结果直接返回(不经过 LLM 处理)
  • return_direct=False(默认):工具结果经过 LLM 处理后返回

内置工具

LangChain 提供了丰富的内置工具,无需自己定义:

工具作用
python_replPythonREPLTool执行 Python 代码
shellShellTool执行命令行
humanHumanTool人工输入
requests_getRequestsGetToolGET 请求
requests_postRequestsPostToolPOST 请求
tavily_searchTavilySearchResults搜索
web_loaderWebBaseLoader网页加载
read_fileReadFileTool读取文件
write_fileWriteFileTool写入文件
sql_db_queryQuerySQLDatabaseToolSQL 查询
retrieverVectorStoreToolRAG 检索

更多内置工具:LangChain 官方文档


工具调用优化

当工具较多时,Agent 可能选错工具。

Tool Router

使用意图分类器精确匹配工具。

INTENT_PROMPT = """
你是意图分类器,只返回:search | pdf | database | math
"""

def classify_intent(query):
return llm.invoke([("system", INTENT_PROMPT), ("user", query)]).content

动态加载工具

按需加载工具,避免上下文过长。

TOOL_GROUPS = {
"search": [search_web],
"pdf": [extract_pdf_text],
"database": [query_database],
}

def create_agent_for_intent(user_query: str):
intent = classify_intent(user_query)
return create_agent(model, TOOL_GROUPS.get(intent, []))

层次化架构

Router Agent(意图识别)

Search Agent | PDF Agent | Math Agent

统一工具规范

  • 工具名称必须动词开头
  • 描述必须包含:功能、限制、示例