🎯 课程主题
系统讲解 LangChain 中 Tool 的两种调用方式及完整的工具调用消息流转流程,阐明大模型与智能体的核心区别。
📝 核心知识点
1. 工具(Tool)的概念与定位
- 概念说明:工具是明确定义了输入和输出的可调用函数,又称函数调用(Function Calling)。
- 关键细节:
- 工具是智能体要素中最重要的部分。大模型相当于"大脑",工具相当于"眼睛和四肢"。
- 有了工具,大模型才能从"纸上谈兵"走向与外部世界交互(搜索网页、操作数据库、发送邮件等)。
- 大模型 vs 智能体的核心区别:大模型只能分析出需要调用哪个工具,但不能主动执行;智能体既能分析又能主动执行工具调用。
2. 工具的两种调用方式
方式一:直接调用(直接 invoke)
- 概念说明:直接对工具对象调用
invoke()方法。 - 关键细节:传入字典格式参数,与普通函数调用类似,但工具对象有
invoke接口。
# 定义工具(细节后续讲解)
def get_weather(city: str) -> str:
"""获取城市天气"""
return f"{city}天气晴朗"
# 直接调用工具
result = get_weather.invoke({"city": "北京"})
方式二:基于模型调用(bind_tools + invoke)
- 概念说明:将工具绑定到模型,模型根据用户输入判断是否需要调用工具。
- 关键细节:
- 通过
model.bind_tools([tool_list])将工具绑定到模型。 - 返回的
response.tool_calls列表非空时,表示模型识别出了要调用的工具。 - 模型只负责识别工具,不负责执行。
- 通过
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage
model = ChatOpenAI(model="gpt-4o")
# 定义工具
def get_weather(city: str) -> str:
"""获取指定城市的天气"""
return f"{city}天气晴朗"
# 绑定工具
model_with_tools = model.bind_tools([get_weather])
# 模型分析用户需求
response = model_with_tools.invoke("北京今天天气怎么样?")
# 检查是否需要调用工具
if response.tool_calls:
tool_call = response.tool_calls[0]
print(f"需要调用的工具: {tool_call['name']}")
print(f"参数: {tool_call['args']}")
else:
print(response.content)
3. 工具调用的完整流程
用户问题:"北京今天天气如何?"
│
▼
┌─────────────────────────────────────┐
│ 1. 用户问题封装为 HumanMessage │
│ 加入消息列表 │
└─────────────────────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ 2. 模型分析(已绑定 tools) │
│ 输入:用户问题 + 可用工具列表 │
│ 输出:AIMessage(含 tool_calls) │
└─────────────────────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ 3. 模型返回 tool_calls │
│ 识别出需调用 get_weather 工具 │
│ 参数:{"city": "北京"} │
└─────────────────────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ 4. 手动执行工具调用 │
│ tool.invoke() → ToolMessage │
│ 结果:"北京天气晴朗" │
└─────────────────────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ 5. 将 ToolMessage 回传给模型 │
│ 模型整合信息,返回最终回复 │
│ 输出:"北京今天天气晴朗" │
└─────────────────────────────────────┘
4. 从 Message 流转看工具调用
消息列表在工具调用过程中的演变:
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage, AIMessage, ToolMessage
model = ChatOpenAI(model="gpt-4o")
model_with_tools = model.bind_tools([get_weather])
# 初始化消息列表
messages = [HumanMessage(content="北京今天天气怎么样?")]
# 第一步:模型调用 → 获得 AIMessage
response = model_with_tools.invoke(messages)
messages.append(response) # 此时列表: [HumanMessage, AIMessage]
# 第二步:检查 tool_calls 并手动执行工具
for tool_call in response.tool_calls:
if tool_call["name"] == "get_weather":
tool_result = get_weather.invoke(tool_call["args"])
messages.append(ToolMessage(
content=tool_result,
tool_call_id=tool_call["id"]
))
# 此时列表: [HumanMessage, AIMessage, ToolMessage]
# 第三步:再次调用模型获得最终回复
final_response = model_with_tools.invoke(messages)
# 此时列表: [HumanMessage, AIMessage, ToolMessage, AIMessage]
print(final_response.content) # "北京今天天气晴朗。"
消息流转轨迹:
HumanMessage → AIMessage(含tool_calls) → ToolMessage → AIMessage(最终回复)
(第1条) (第2条) (第3条) (第4条)
🏗️ 架构与工作流
整个工具调用本质上是 Message 的流转:用户消息进入 → 模型分析产生含 tool_calls 的 AI 消息 → 工具执行产出 Tool 消息 → 回传模型获得最终回复。当前阶段需手动执行工具(大模型只能识别、不能执行),后续使用 Agent 时可自动完成整个闭环。
💻 代码实战
见上方各知识点的完整代码示例。
⚠️ 常见问题与避坑指南
- 模型不会自动执行工具:
model.bind_tools()只是让模型知道有哪些工具可用,模型返回tool_calls后需要开发者手动调用tool.invoke()执行。 - ToolMessage 必须带 tool_call_id:将工具执行结果回传模型时,需使用
ToolMessage并设置正确的tool_call_id,否则模型无法关联。 - MCP 与 Function Calling 的关系:MCP 不是替代 Function Calling,而是 Function Calling 的一种新的协议实现方式,属于包含关系。
💡 个人总结与延伸
理解完整的工具调用消息流转是掌握 LangChain Agent 开发的关键前提。当前手动执行工具的流程在后续 Agent 章节中会被自动化替代,但底层消息流转逻辑完全一致。建议画图梳理 HumanMessage → AIMessage → ToolMessage → AIMessage 的四步流转,对理解 Agent 原理至关重要。