📞 Function Calling:模型「说」,代码「做」
两轮对话 + 中间执行,模型只出 JSON 意图。顺便讲清 Function Calling 和 Tool Calling 到底啥关系。
📚 本文目录
Function Calling 在解决什么问题
🗣️ 没有它之前:靠猜
想让模型调工具,只能解析自然语言:模型说「我需要查一下北京的天气」,开发者写 if/else 判断它「说」的是要查天气,再手动调 API。
这做法极其脆弱——模型换个说法,if/else 就失配了,无法标准化。
🎯 有了它之后:出 JSON
Function Calling 把这件事固定下来:模型不「说」要调工具,而是直接输出一段结构化的 JSON,开发者按格式解析就行。
准确率大幅提升,也有统一标准对接。
OpenAI 2023 年推出,Claude/Gemini/Qwen 都支持
三个角色:一场任务委托
👔 开发者 = HR
给每个工具写「职位说明书」(JSON schema),告诉模型:我们有哪些工具、每个能做什么、需要哪些参数。
🧠 模型 = 经理
读完说明书,决定「这个任务需要调哪个工具、参数填什么」,然后把指令下达出来。
它全程只是「下指令」,不亲自执行任何代码。
🧑💻 你的代码 = 员工
真正去跑函数、访问网络、查数据库,把结果汇报回来。
关键:模型没有执行权限,也没有直接访问网络的权限。
一句话焊死:模型只负责决策(选什么工具、填什么参数),执行由宿主代码完成。这是整个机制的核心设计,也是面试最容易踩的误区。
工具定义:JSON schema
📋 schema = 工具说明书
一份结构化 JSON,告诉模型工具叫什么、能做什么、需要哪些参数。
核心字段:name(名字)、description(描述)、parameters(参数类型/必填/enum/说明)。
🎯 命门:description
模型判断要不要调、参数怎么填的唯一依据就是 description。
❌ 写「获取天气」→ 模型瞎猜
✅ 写「查询指定城市的实时天气,含气温、天气状况、风向风速,仅支持中国大陆城市」→ 选得准
参数 description 同理:格式要求、示例值、限制条件都要写进去。写得越清晰,模型的选择越准确。
例如 city 参数要写「城市名称,如北京/上海,不要带省份前缀」;unit 用 enum: ["celsius", "fahrenheit"] 限定取值。
运行时:两轮对话 + 中间执行
并行工具调用
⚡ 一次出多个 tool_calls
tool_calls 是个列表。问「北京和上海的天气」,模型一次返回两个调用请求,代码可同时执行(asyncio.gather / 线程),拿齐结果一次性塞回。
避免串行跑两轮的延迟。
🔗 前提:无依赖
并行调用要求几个工具之间没有依赖关系。
✅ 查北京天气 + 查上海天气 → 可并行
❌ 先查订单号、再查物流 → 第二个依赖第一个,只能串行
那 Function Calling 和 Tool Calling 呢?
官方口径:OpenAI 文档第一句就写 Function calling, also known as tool calling——在模型侧两者是同一个东西,模型都只「说想法」。
差异在概念范围,不在执行能力:
| 🧠 Function Calling | 🛠️ Tool Calling | |
|---|---|---|
| 定位 | 早期/狭义:模型输出「调哪个函数+JSON参数」 | 现代/广义:在工具箱选工具 + Agent 循环 |
| 范围 | 函数是工具的一种 | 函数、搜索、代码执行、MCP 都是工具 |
| 执行 | 模型侧不执行 | 模型侧也不执行,是应用/框架/平台跑 |
| 演进 | functions/function_call(老 API) | tools/tool_calls(新 API,支持并行+多类型) |
准确版本
两者在模型侧都不执行代码。执行代码的是你的应用、框架或服务商 server tool。
别被框架骗到
LangChain 的 @tool 装饰器把 schema、parser、executor 全包了,看似「模型会执行」,其实是框架帮你写了 if tool_calls 的循环。
server tool 是特例
Anthropic 的 web_search/code_execution 是服务端执行,但那是官方白名单能力,不是 Claude 本体跑你业务代码。
Function Calling 是让模型「说」结构化 JSON 意图(调哪个函数、参数是啥)、由宿主代码「做」的机制,运行时是两轮对话 + 中间执行。它和 Tool Calling 在模型侧是同一件事,差异只在概念范围——FC 是早期狭义说法(函数),Tool Calling 是现代广义说法(工具+Agent 循环),两者模型侧都不执行代码。
我用一句话概括:模型不输出自然语言,而是输出结构化的 JSON 告诉我们它要调哪个函数、参数是什么,我们拿到 JSON 去真正执行,再把结果塞回对话,模型基于结果生成最终答案。运行时是两轮对话加中间执行:第一轮把工具列表和问题一起给模型,模型判断需要调工具就输出 tool_calls;我们执行;第二轮把 tool 结果挂回对话再问一次模型,它才给最终答案。
用 JSON schema 定义,包含 name、description、parameters。其中 description 最重要,因为模型判断要不要调这个工具、参数怎么填,唯一依赖的就是这段描述。如果只写「获取天气」,模型就会瞎猜;要写清楚使用场景、限制条件,比如「查询指定城市的实时天气,仅支持中国大陆城市」。参数的 description 也一样,格式要求、示例值、枚举都要写进去。
在模型侧它俩其实是同一个东西,OpenAI 文档直接写 Function calling also known as tool calling,模型都只输出意图不执行。区别在概念范围:Function Calling 是早期狭义的说法,指模型输出调哪个函数加 JSON 参数;Tool Calling 是现代广义的说法,指模型在工具箱里选工具再加 Agent 循环。函数是工具的一种,工具还可以是搜索、代码执行、MCP。两者模型侧都不执行代码,真正执行的是我们的应用或框架。