LangChain 工具绑定:`bind_tools` vs `create_agent` 的区别

在 LangChain/LangGraph 中给模型添加工具有两种方式,它们的层级和用途完全不同。


一句话总结

  • model.bind_tools()只告诉模型有哪些工具可用,不负责执行
  • create_agent(tools=...)自动处理整个工具调用循环,开箱即用

model.bind_tools() — 底层接口

代码

from langchain_core.tools import tool
from langchain_openai import ChatOpenAI

@tool
def get_weather(city: str) -> str:
    """查询城市天气。"""
    return f"{city}: 晴天 25°C"

model = ChatOpenAI(model="gpt-4o-mini")
llm_with_tools = model.bind_tools([get_weather], tool_choice="any")

它做了什么?

  1. 把工具的 JSON Schema(名字、参数、描述)附加到模型请求中
  2. 模型知道可以返回 tool_calls
  3. 仅此而已不会自动执行工具

代码

from langchain.messages import HumanMessage, ToolMessage

# 1. 调用模型
response = llm_with_tools.invoke([HumanMessage(content="北京天气?")])

# 2. 手动执行工具
if response.tool_calls:
    tool_call = response.tool_calls[0]
    result = get_weather.invoke(tool_call["args"])

    # 3. 手动把结果传回模型
    tool_msg = ToolMessage(content=result, tool_call_id=tool_call["id"])
    final = llm_with_tools.invoke([
        HumanMessage(content="北京天气?"),
        response,
        tool_msg
    ])
    print(final.content)

tool_choice 参数

含义
"auto" 模型自己决定是否调工具(默认)
"any" 强制模型必须调用至少一个工具
"none" 禁止调用工具
{"type": "function", "function": {"name": "get_weather"}} 强制调用指定工具

create_agent(tools=...) — 高层封装

代码

from langchain.agents import create_agent
from langchain.messages import HumanMessage

agent = create_agent(
    model=model,
    tools=[get_weather],
    system_prompt="你是一个天气助手。"
)

# 一行搞定,不用管中间过程
result = agent.invoke({
    "messages": [HumanMessage(content="北京天气?")]
})
print(result["messages"][-1].content)

它做了什么?

内部自动完成了:

  1. model.bind_tools(tools) — 绑定工具
  2. 构建 StateGraph(推理节点 + 工具节点 + 条件边)
  3. 自动循环:模型决策 → 执行工具 → 结果传回 → 直到完成

你不需要写任何循环逻辑。


对比总结

model.bind_tools() create_agent(tools=...)
层级 底层(模型级别) 高层(Agent 级别)
自动执行工具 ❌ 需手动 ✅ 自动
自动循环 ❌ 需手动 ✅ 自动
可定制性 低(固定 ReAct 模式)
代码量 多(需要写循环) 少(约 10 行)
适用场景 自定义 StateGraph 快速原型

什么时候用哪个?

bind_tools 的场景

  • 你在自己搭建 StateGraph,需要完全控制节点和边
  • 需要在工具调用前后加自定义逻辑(如审批、日志)
  • 多 Agent 协作,每个 Agent 有不同的工具集
  • 需要 tool_choice="any" 等精细控制
# 典型用法:自定义图中的推理节点
def reasoning_node(state):
    prompt = build_prompt(state)
    result = llm_with_tools.invoke(prompt)  # 用 bind_tools 后的模型
    return {"messages": [result]}

create_agent 的场景

  • 快速验证想法
  • 标准的 ReAct 问答 Agent
  • 不需要复杂的控制流
# 典型用法:10 行代码搞定
agent = create_agent(model=model, tools=[...], system_prompt="...")
result = agent.invoke({"messages": [...]})

它们的关系

graph TD A["create_agent(tools=[...])"] --> B["内部调用 model.bind_tools(tools)"] B --> C["构建 StateGraph"] C --> D["添加推理节点 + 工具节点"] D --> E["添加条件边(should_continue)"] E --> F["编译输出可运行的 Agent"]

create_agentbind_tools + StateGraph 的语法糖。当语法糖不够用时(需要自定义流程),你就退回到 bind_tools + 手动搭图。


实际项目中的选择

项目阶段 推荐方式
概念验证 / Demo create_agent
生产级 Agent(需要审批、分类、多步骤) bind_tools + 自定义 StateGraph
多 Agent 系统 每个子 Agent 用 bind_tools,Supervisor 协调
posted @ 2026-05-20 10:54  江鸟Dev  阅读(52)  评论(0)    收藏  举报