函数调用:让大模型从「会聊」变成「会干」
大模型天生只会「说话」,不会「做事」。Function Calling(函数调用 / 工具使用)就是把一句自然语言,翻译成一次真正的动作——查天气、读数据库、发邮件、跑代码。本文用时间线、对比图和一段真实故事,把它的来龙去脉讲清楚。
01开场:从「陪聊」到「办事」
想象你雇了一个记忆力超群、读过万卷书的助手。你问他「明天北京会下雨吗」,他微笑着说:「根据我训练时看到的规律,北京在夏秋交界时常有阵雨。」——听起来有道理,但他根本没看明天的天气预报。
问题不在他聪不聪明,而在于他被关在一个只有文字的房间里:能说,不能查;能猜,不能算;能编,不能做。Function Calling 就是给这间屋子开了一扇门——门外是真实世界,是工具,是能真正改变状态的操作。
02背景:LLM 的三个天生短板
为什么非得有 Function Calling?因为它补的是大模型出厂自带的硬伤。下面这段对话很典型:
⏱知识会过期
训练数据有截止日期,之后的事(实时股价、今天天气、刚上的新闻)一概不知,只能「编造一个像样的」。
🧮算不准
语言模型本质是「预测下一个词」,不是计算器。大数乘除、精确统计、复杂推理容易出错,还特别自信。
🔒碰不到现实
不能读数据库、不能调 API、不能发消息、不能下单。它的世界只有输入过的那几段文本。
这三道墙,靠「把模型训得更大」也跨不过去——因为有些信息根本不在训练数据里,有些动作根本不该由模型自己完成。唯一的办法是:让模型学会「我不知道 / 我算不了 / 我办不到时,去叫工具」。
03历史:Function Calling 是怎么来的
它不是某天突然冒出来的,而是「想让 AI 用工具」这件事,从土办法一步步走到原生能力的进化史。
关键转折:从「约定」到「原生」
早期(2020–2022)大家靠 prompt 工程:在提示里写「请只返回 JSON {"tool":"...","args":{...}}」,再用代码去解析。这能跑,但模型经常不守规矩——多了个逗号、加了句解释、漏了字段,解析就崩。本质是把「结构化输出」这种硬工程问题,甩给了本来就爱自由的生成模型。
2023 年 6 月,OpenAI 在 API 里加入 tools / functions 参数:模型被专门训练去识别「什么时候该调用、调哪个、参数怎么填」,并且输出被约束成机器可校验的 JSON。从「求模型配合」变成「模型天生就会」。之后 Claude、Gemini 等纷纷推出等价的 tool use / function declarations,能力成为行业标配。
04它解决了什么:把「语言」变成「动作」
用一张图看 Function Calling 前后,同一个问题发生了什么变化。
🔌打通真实世界
模型能查询实时数据、调用业务系统,回答不再是「训练记忆里的回声」,而是「此刻的事实」。
⚙️把计算外包
精确运算、检索、统计交给专门的程序,模型只负责「决策用哪个工具」,准确率与可靠性大幅提升。
🤝从「答」到「办」
能发邮件、下单、写库——AI 第一次具备「改变外部状态」的能力,从参谋变成执行者。
🧠承认「不知道」
模型学会在不确定时求助工具,反而更可信;幻觉被「查证回路」天然抑制。
05原理:一次调用长什么样
核心就三步:你告诉模型有哪些工具 → 模型决定调哪个、填什么参数 → 你执行并把结果还回去。工具用 JSON Schema 描述,模型生成的就是一份合规的「调用申请」。
① 描述工具(Tool Schema)
{
"name": "get_weather",
"description": "查询指定城市、指定日期的天气",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string", "description": "城市名,如 北京"},
"date": {"type": "string", "description": "日期,如 明天 / 2026-09-08"}
},
"required": ["city"]
}
}
注意 description 极重要:模型靠它判断「该不该调、怎么填」。写得含糊,模型就乱调。
② 模型决策 → 执行 → 回填(循环)
06怎么用:一个最小实战架子
下面是一段「伪代码」,展示最常见的 ReAct 循环(思考—行动—观察)。真实 SDK(OpenAI / Anthropic / 通义等)接口细节不同,但骨架一致。
messages = [用户问题]
tools = [get_weather, search_web, calc] # 你的工具 schema 列表
while True:
resp = llm.chat(messages, tools=tools) # 把工具清单交给模型
if not resp.tool_calls: # 模型说「不用工具了」
print(resp.text) # → 这就是最终回答
break
for call in resp.tool_calls: # 可能一次多个(并行)
args = json.loads(call.arguments) # 模型填的参数
result = run_tool(call.name, args) # 你来执行(校验后再跑!)
messages.append({ # 把结果回填进上下文
"role": "tool",
"tool_call_id": call.id,
"content": result
})
并行调用
当多个工具互不依赖(同时查天气和汇率),模型一次返回多个 tool_call,你并发执行,省掉往返延迟。这是 2024 年后主流模型都支持的能力。
07应用场景:AI 的工具箱
凡是「模型干不好、但程序很擅长」的事,都适合交给 Function Calling。下面是几类高频场景:
🌐实时信息
天气、股价、汇率、航班、新闻——补足知识截止的短板。
📚检索与知识
查数据库、搜内部文档、RAG 召回——让回答有依据。
🧮精确计算
计算器、日历排期、单位换算——把算不准的活外包。
💻代码执行
跑 Python 分析数据、画图表——让模型「动手算」而非「嘴上算」。
✉️执行动作
发邮件、建工单、下单、写库——AI 第一次能改变现实状态。
🔗外部 API
调支付、地图、CRM——把 SaaS 世界连进对话。
08一个完整故事:订机票 + 查天气
把前面所有概念串起来。用户只说了一句话,背后却跑了好几轮 Function Calling:
search_flights(from="上海",to="北京",date="这周五")。get_weather(city="北京",date="这周五")。回填:多云、22℃。book_flight(flight_id="...")。写操作触发确认环节,你弹窗让用户二次确认。整个过程里,模型始终是指挥官,工具是手脚,而「确认订票」这种危险动作由你的代码把关。这就是 Function Calling 最动人的样子:自然语言进,真实结果出。
09发展:并行、结构化、MCP、Agent
⚡并行调用
一次返回多个独立调用,并发执行,大幅降低多工具任务的延迟。
📐结构化输出
从「调工具」延伸到「按 schema 出 JSON」,用于抽取、分类、表单填充。
🔌MCP 协议
2024 年提出的工具「标准化接入协议」:工具如何被发现、调用、返回有了统一规范,模型与工具解耦,即插即用。
🤖Agent 编排
把「调用工具」放进自主循环,加规划、记忆、反思,FC 成为 Agent 的能力底座。
10常见坑
参数非法
模型可能生成 schema 外的字段/类型,必须服务端校验再执行,别直接 eval。
幻觉调用
编造不存在的工具或参数,需约束可调用集合、校验 name 是否真的是你注册的工具。
副作用失控
写操作要权限、确认或沙箱;警惕工具返回内容里的「提示注入」。
流式解析
流式输出下要能增量拼出完整 JSON 再执行,解析失败要有重试与兜底。
陷入死循环
模型反复调用却不给终态,要设最大轮数(max_turns)强制收口。
成本与延迟
每轮都把工具结果塞回上下文,长链路会撑爆 token、拖慢响应,注意裁剪。
11一图总结
Function Calling 不是某个花哨功能,而是大模型「落地成人手」的那块基石:它把会聊的天,变成了会干的活。理解了它,也就理解了今天所有 AI Agent、AI 搜索、AI 办公产品的共同起点。