Function Calling —— AI 怎么学会"调工具"的
来源:2023 年 6 月 OpenAI 发布 Function Calling,随后成为所有主流模型的标配
一句话:Function Calling = 你先把"有哪些工具"告诉模型,模型不自己执行,只回复一张"点菜单"(函数名 + 参数),由你的代码去执行,再把结果喂回给它。
1. 它解决什么问题
第 1 篇末尾说过,LLM 的三大残疾之一:只会说话,不会动手。你问它"北京现在多少度",它只能瞎编——因为它根本没联网。
Function Calling 的思路非常聪明:模型不需要真的联网,它只需要"会说要什么"。
2. 工作原理(一次完整往返)
你的程序 模型
│ ① "这是工具清单+用户问题" ──→ │
│ │ 模型思考:要答这题得先查天气
│ ② ←── "请调用 get_weather(城市=北京)"(结构化 JSON)
│
│ ③ 你的代码真的去调天气 API,拿到 28℃
│
│ ④ "工具返回:28℃" ──→ │
│ │ 模型组织语言
│ ⑤ ←── "北京现在 28℃,晴" ✅
核心认知:模型自始至终没执行任何东西。 它只是输出了一段结构化的"我要调 XX 函数、参数是 YY",真正动手的是你的代码。这就是"点菜"和"做菜"的分工。
3. 代码示例(OpenAI 兼容协议)
tools = [{
"type": "function",
"function": {
"name": "get_weather",
"description": "查询指定城市当前天气",
"parameters": {
"type": "object",
"properties": {"city": {"type": "string", "description": "城市名"}},
"required": ["city"]
}
}
}]
# 第 1 步:带上工具清单发起对话
resp = client.chat.completions.create(
model="deepseek-chat",
messages=[{"role": "user", "content": "北京现在多少度?"}],
tools=tools
)
# 第 2 步:模型如果决定调工具,会返回 tool_calls
call = resp.choices[0].message.tool_calls[0]
# call.function.name == "get_weather"
# call.function.arguments == '{"city": "北京"}'
# 第 3 步:你的代码执行真正的查询(这里假装调了天气 API)
result = query_weather_api(city="北京") # → "28℃,晴"
# 第 4 步:把结果喂回模型,让它组织最终回答
resp2 = client.chat.completions.create(
model="deepseek-chat",
messages=[
{"role": "user", "content": "北京现在多少度?"},
{"role": "assistant", "tool_calls": [call]},
{"role": "tool", "content": result}
],
tools=tools
)
print(resp2.choices[0].message.content) # "北京现在 28℃,晴。"
4. 和其他概念的区别
| 概念 | 模型扮演的角色 | 典型场景 |
|---|---|---|
| Function Calling | 点菜(说清要调什么) | 查天气、查订单、发邮件——单次工具调用 |
| MCP(第 5 篇) | 点菜 + 统一菜单标准 | 让模型用上"全城餐厅共享菜单",不用每家重新写 |
| Agent(第 5 篇) | 自己点菜、吃、再点、循环到饱 | 多步骤任务:查→算→再查→汇总 |
MCP 出现之前:你有 M 个应用想接 N 个工具,要写 M×N 份适配代码。MCP 之后:工具写一次 MCP Server,所有支持 MCP 的模型/应用都能用——这就是它被称为"AI 的 USB-C"的原因。
5. 能用来干什么
- 查实时数据:天气、股价、物流、汇率
- 操作业务系统:查数据库、写工单、控制智能家居
- 内容处理:调 OCR、翻译、TTS 服务
- 你博客的例子:「AI 专栏文章被搜索」→ 模型调你后端的
search_posts函数返回结果
下一篇:模型还是不认识你的私有文档——RAG 知识库,让 AI"开卷考试"。