在 LangGraph 中定义“工具”(Tool),本质上是将普通的 Python 函数或外部能力(如API)封装起来,供图中的大模型(LLM)节点调用。

🔧 定义工具的基本方法

完整的工具定义与集成流程可以概括为以下几步,你可以通过这个代码结构图快速了解:

对图中的关键环节进行说明:

1. 创建工具函数
最简单的方法是使用 @tool 装饰器。你需要为函数提供清晰的名称描述,因为LLM主要依赖这些来决定何时以及如何使用它。

from langchain.tools import tool

@tool
def search_web(query: str) -> str:
    """根据用户的问题执行网页搜索。"""
    # 调用搜索引擎API
    return f"关于 '{query}' 的搜索结果..."

也可以使用 args_schema 参数来定义更严谨的输入模型(使用Pydantic),或通过 return_direct=True 让代理在调用此工具后直接结束

2. 将工具绑定到模型
创建工具列表后,需要将它们绑定到LLM,使其知道这些工具的存在和调用方式

tools = [search_web, calculator]
model = ChatOpenAI(model="gpt-4")
model_with_tools = model.bind_tools(tools) # 或使用 bind_functions

3. 在图中集成工具
通常,你会创建一个专门的工具执行节点。LangGraph 提供了预置的 ToolNode 来简化这一步,它支持并行执行、错误处理等。

from langgraph.prebuilt import ToolNode, ToolExecutor
# 使用预置节点
tool_node = ToolNode(tools)
# 或者,自定义一个工具节点
tool_executor = ToolExecutor(tools)
def execute_tools(state):
    # 处理LLM的工具调用请求
    action = state['messages'][-1].tool_calls[0]
    result = tool_executor.invoke(action)
    return {"messages": [ToolMessage(content=result, name=action.tool)]}
  1. 然后将这个节点添加到图中,并通过条件边将其与LLM推理节点连接起来,形成一个“思考-行动”的循环。

⚠️ 核心注意事项与最佳实践

为了让工具在图中稳定可靠地工作,需要注意以下几点:

注意事项 说明与建议
1. 工具描述 清晰、准确的描述至关重要,直接决定LLM能否正确调用它。避免模糊,说明输入格式和用途。
2. 状态读写 工具可以直接读取和更新图的状态。通过 InjectedState 访问,或通过返回值更新状态,这能用于传递中间结果。
3. 错误处理 工具调用可能失败。使用 ToolNode 时,可利用其内置的 handle_tool_errors 参数来捕获异常并返回友好信息给LLM,避免图运行中断。
4. 隐藏参数 如果工具需要API密钥、用户ID等不应由LLM控制的参数,应将其放在图的 config 或 state 中,在工具函数内部读取,而非暴露给模型。
5. 工具数量 工具过多会增加LLM的认知负担和token消耗。可考虑根据任务动态筛选工具(如通过语义检索),而非一次性全部提供。
6. 控制流 必须通过条件边清晰定义何时调用工具、何时结束,否则容易产生无限循环。
7. 长期记忆 若需跨对话保存用户偏好等数据,可以使用LangGraph的长期记忆(存储)功能,工具和节点都能读写。
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐