← 返回 AI大模型从0到1——理论与实操
C3-05 Function Call工具调用
🎯 本章目标:理解 Function Calling(函数调用)机制的原理,学会用原生 API 构建生产级工具调用 Agent。对比手撕 ReAct,理解标准化的力量。
从手撕到 Function Calling
手撕 ReAct 让我们理解了 Agent 的原理,但 Prompt + 正则解析的方式有两个根本问题:
- 不稳定:LLM 输出的 Action 格式不可控,常常格式错误
- 不可移植:不同模型需要重新设计 Prompt 和解析逻辑
2023 年 6 月,OpenAI 推出 Function Calling 能力,让 LLM 原生支持结构化的工具调用:
sequenceDiagram
participant U as 用户
participant A as Agent代码
participant L as LLM
participant T as 工具函数
U->>A: "北京今天天气怎么样?"
A->>L: messages + tools(Schema)
L->>A: tool_calls=[{name:get_weather, args:{city:北京}}]
A->>T: get_weather(city="北京")
T->>A: {"temp": "28°C", "condition": "晴"}
A->>L: messages(含tool结果)
L->>A: "北京今天晴,28°C,适合出行"
A->>U: 最终回答
三大优势:
| 对比项 | 手撕 ReAct | Function Calling |
|---|---|---|
| 格式稳定性 | ❌ 依赖 Prompt 和正则 | ✅ 原生 JSON Schema |
| 跨模型兼容 | ❌ 每个模型要重写 | ✅ OpenAI 标准 |
| 参数验证 | ❌ 手动校验 | ✅ Schema 自动校验 |
| 并行调用 | ❌ 一次一个 | ✅ 一次可多个 |
JSON Schema 工具定义
Function Calling 用 JSON Schema 描述工具。LLM 看到这个 Schema 后,会自动决定是否调用、调哪个、传什么参数。
Python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | |
💡 类比:JSON Schema 就像工具的"产品说明书"。LLM 看到
description字段来决定何时调用,看到parameters字段来决定传什么参数。 description 写得越清晰,LLM 调用越准确。
完整可运行代码
Plain Text
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 | |
Function Calling 核心机制
flowchart TD
A[调用 LLM
传入 messages + tools] --> B{LLM 决定
是否调用工具}
B -->|不调用| C[返回 content
直接给用户]
B -->|调用| D[LLM 返回 tool_calls
JSON 格式]
D --> E[Agent 解析
函数名 + 参数]
E --> F[执行工具函数]
F --> G[工具结果
role=tool 回填]
G --> A
style A fill:#87CEEB
style D fill:#FFE4B5
style F fill:#90EE90
三个关键 API 字段(模型训练时加入):
| 字段 | 位置 | 作用 |
|---|---|---|
tools |
请求参数 | 告诉 LLM 有哪些工具可用(Schema 列表) |
tool_calls |
LLM 返回 | LLM 决定要调用的工具和参数 |
role: tool |
消息列表 | 把工具执行结果回填给 LLM |
Function Calling vs 手撕 ReAct
| 维度 | 手撕 ReAct | Function Calling | 胜出方 |
|---|---|---|---|
| 稳定性 | 依赖 Prompt | 原生支持 | FC ✅ |
| 参数校验 | 手动 | Schema 自动 | FC ✅ |
| 并行调用 | 不支持 | 支持 | FC ✅ |
| 可读性 | 循环 + 字符串 | messages 列表 | FC ✅ |
| 理解原理 | ✅ 直接 | ❌ 抽象 | ReAct ✅ |
| 学习价值 | 基础 | 生产 | 都要学 |
📝 实战建议:先学手撕 ReAct 理解原理,生产项目用 Function Calling。手撕版是"教学版",FC 是"工业版"。两个都要会,就像学开车先学手动挡再开自动挡。
💡 思考:大家有听过mcp server工具调用的吗?是不是有了mcp server工具就不需要function call了呢?