从零理解 LangChain + LangGraph 的工具调用机制
🧠 从零理解 LangChain + LangGraph 的工具调用机制
目标:掌握如何使用 LangChain 定义函数工具(tool),并通过 LangGraph 构建一个能自动调用工具的智能体(Agent-like)流程。
一、代码整体结构概览
这段代码实现了以下功能:
- 安全设置环境变量(
OPENAI_API_KEY和OPENAI_BASE_URL) - 初始化一个支持工具调用的大语言模型(LLM)
- 定义一个 Python 函数作为“工具”(
multiply) - 将工具绑定到 LLM 上,使其能“理解并调用”该函数
- 使用 LangGraph 构建一个状态图(StateGraph),实现单节点推理流程
- 测试两种输入:普通问候 vs 工具调用请求
最终,当用户说 “Multiply 2 and 3” 时,模型应返回一个包含 tool_calls 的 AIMessage,指明要调用 multiply(a=2, b=3)。
二、关键组件详解
1. 环境变量安全设置
1 | def _set_env(var: str): |
- 使用
getpass.getpass()避免 API Key 明文显示在终端。 - 设置
OPENAI_API_KEY是必须的;OPENAI_BASE_URL则用于代理(如你提供的https://api.apiyi.com/v1)。
✅ 最佳实践:永远不要把密钥写死在代码中!
2. 初始化支持工具调用的 LLM
1 | from langchain_openai import ChatOpenAI |
ChatOpenAI是 LangChain 对 OpenAI 兼容 API 的封装。bind_tools([multiply])告诉模型:“你可以调用这些函数”,并自动生成 OpenAI 格式的 function calling schema。- 注意:
deepseek-chat必须支持工具调用(即 function/tool calling 能力),否则会失败。
🔍 深度提示:
bind_tools会自动从函数的 docstring 和类型注解中提取参数信息,生成 JSON Schema。
例如,multiply 会被转换为:
1 | { |
3. 定义工具函数
1 | def multiply(a: int, b: int) -> int: |
- 函数必须有 类型注解 和 docstring,LangChain 才能正确解析。
- 返回值类型不影响工具调用(调用发生在模型输出阶段,不执行函数本身)。
⚠️ 注意:当前代码 只让模型“提议”调用工具,但 并未实际执行
multiply。若要执行,需额外添加工具调用节点(见后文扩展)。
4. 使用 LangGraph 构建状态图
1 | from langgraph.graph import MessagesState, StateGraph, START, END |
MessagesState是 LangGraph 内置的状态类,只包含messages: list[BaseMessage]。tool_calling_llm节点:接收消息历史,调用 LLM(带工具),返回新消息。- 整个图是 单节点线性流程:输入 → LLM → 输出。
📌 这是一个“非完整 Agent”——它能生成工具调用,但不会自动执行或响应结果。
5. 测试与输出
1 | # 测试 1:普通对话 |
- 第一次:模型返回普通
AIMessage。 - 第二次:模型应返回
AIMessage,其中tool_calls字段非空,包含:1
2
3
4{
"name": "multiply",
"args": {"a": 2, "b": 3}
}
通过 m.pretty_print() 可直观看到消息结构。
三、为什么这很重要?——工具调用的意义
大模型本身不能直接计算 2*3,但通过 工具调用机制,它可以:
- 识别用户意图(“需要计算乘法”)
- 结构化表达需求(生成标准 tool call)
- 交由外部系统执行(你的 Python 函数、数据库、API 等)
这是构建 智能体(Agent) 的核心基础。
四、执行流程可视化
流程图

五、下一步:如何真正“执行”工具?
当前代码只到“提议调用”。要完成闭环,需:
- 添加一个 工具执行节点
- 在图中判断是否有
tool_calls - 若有,则调用对应函数,并将结果以
ToolMessage形式回传
示例扩展逻辑:
1 | from langchain_core.messages import ToolMessage |
然后构建更复杂的图(如:LLM → 工具调用?→ 是 → 执行 → 返回 → LLM 继续回答)。
六、总结:关键知识点记忆卡
| 概念 | 说明 |
|---|---|
bind_tools |
将 Python 函数注册为 LLM 可调用的工具 |
MessagesState |
LangGraph 中管理对话历史的标准状态 |
tool_calls |
AIMessage 中的字段,表示模型希望调用的工具 |
StateGraph |
用于构建多步骤、条件分支的智能体流程 |
| 工具调用 ≠ 工具执行 | 模型只“提议”,需开发者实现“执行+反馈” |
七、延伸思考
- 如果模型同时调用多个工具怎么办?
- 如何防止模型滥用工具(如无限循环)?
- 能否结合 ReAct 或 Plan-and-Execute 框架?
这些问题正是 LangGraph 设计要解决的——用图结构编排复杂智能体行为。
希望这篇文章帮你不仅“看懂代码”,更能建立系统性认知。动手尝试添加真正的工具执行逻辑,你会对 LangChain + LangGraph 的能力有更深体会!🚀
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 Nosaw博客!
评论









