Function Calling(函数调用)详解
更新: 10/14/2026字数: 0 字 时长: 0 分钟

一、核心概念:大模型是如何"理解并调用"函数的?
很多人第一次听见Function Calling,以为是大模型真的去服务器里"运行"了一段代码。其实不是的。
大模型本质上是一个概率生成器(它只擅长根据上下文接龙文字)。它做不到在沙箱里跑 Python 或调系统的 API。Function Calling 的真相是:大模型只负责"做决策"和"翻译参数"。
- 大模型不执行函数:它只是在读了用户的话和你的函数定义后,觉得"此时应该调用函数 A,参数是 X 和 Y"。
- 大模型输出结构化文本:它把这个决定伪装成一段特定的 JSON 格式文本吐给你的程序。
- 真正的执行者是你的后端代码:你的程序拦截到这段 JSON,在本地服务器运行真正的函数,再把运行结果喂回给大模型。
二、标准的代码交互流程(以 OpenAI / 兼容 API 为例)
一个完整的 Function Calling 交互,通常需要前后 3 轮对话:
第 1 轮:开发者声明工具,用户提出需求
你向大模型发送请求时,除了常规的 messages(对话历史),还要加上一个 tools(或 functions)字段,告诉大模型:"我这里有这几个工具你可以用。"
// 发送给大模型的请求载荷 (Payload)
{
"model": "gpt-4o",
"messages": [
{"role": "user", "content": "北京明天穿什么衣服合适?"}
],
"tools": [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "获取指定城市和日期的天气信息",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "城市名称,例如:北京"
},
"date": {
"type": "string",
"description": "日期,格式为 YYYY-MM-DD"
}
},
"required": ["location"]
}
}
}
]
}第 2 轮:大模型识别意图,返回"工具调用指令"
大模型分析后,发现用户的需求和 get_weather 完美匹配。它不会直接回答"北京明天多云",而是返回一个带有 tool_calls 的响应:
{
"role": "assistant",
"content": null,
"tool_calls": [
{
"id": "call_abc123xyz",
"type": "function",
"function": {
"name": "get_weather",
"arguments": "{\"location\": \"北京\", \"date\": \"2026-10-14\"}"
}
}
]
}第 3 轮:你的后端执行代码,将结果传回,大模型生成最终回复
- 你的代码截获到
tool_calls,解析出location="北京"和date="2026-10-14"。 - 你的程序去调真实的天气 API,得到结果:
{"temperature": "22°C", "condition": "晴"}。 - 你把这个结果包装成
tool类型的角色,再次发给大模型:
[
{"role": "user", "content": "北京明天穿什么衣服合适?"},
{"role": "assistant", "tool_calls": [...]}, // 上一步模型吐的指令
{
"role": "tool",
"tool_call_id": "call_abc123xyz",
"content": "{\"temperature\": \"22°C\", \"condition\": \"晴\"}"
}
]- 大模型看到结果后,组织最终的自然语言答复给用户:"北京明天是晴天,气温约 22°C,建议穿轻薄的外套或长袖衬衫。"
三、三大核心技术细节
要用好 Function Calling,有几个底层设计非常关键:
1. JSON Schema 的重要性
在定义工具的 parameters 时,大模型强制要求使用 JSON Schema 规范。它相当于 JSON 数据的"合同",规定了对象里有哪些字段、每个字段是什么类型、哪些必填,甚至对取值做严格限制。
以下就是一个标准的 JSON Schema(天气工具的参数定义):
{
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "城市名称,例如:北京"
},
"date": {
"type": "string",
"description": "日期,格式为 YYYY-MM-DD"
},
"temperature_unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"description": "温度单位:摄氏度或华氏度"
}
},
"required": ["location"]
}几个核心关键字:
type:字段的数据类型。常见的有string(字符串)、number/integer(数字)、boolean(布尔)、array(数组,用items定义元素类型)、object(嵌套对象)。properties:定义对象里可以包含哪些字段。enum:枚举,限定字段只能从给定值里选一个(如上例的temperature_unit只能传celsius或fahrenheit)。required:必填项。缺少必填参数时,模型会向用户追问而不是瞎编。
description 比类型更重要:大模型靠自然语言理解参数。只写 {"type": "string", "name": "q"},它根本不知道 q 是啥;补上 description(如"用户的全局搜索关键词,支持模糊搜索,严禁包含特殊符号"),它就能精准提取用户话里的核心词填进去。给每个字段写清晰、带示例的 description,是保证工具调用成功率的核心秘诀。
2. Tool Choice(工具选择策略)
你可以通过参数控制大模型对待工具的态度:
auto(默认):模型自己决定是直接和用户聊天,还是去调用工具。none:强制模型不使用任何工具,只进行普通对话。- 强制指定:你可以硬性规定模型这一轮必须调用某个特定的工具(常用于多步骤复杂 Agent 的强控制流)。
3. 并行函数调用(Parallel Function Calling)
现代先进的大模型支持在同一轮对话中返回多个工具调用。
- 例如用户说:"帮我查一下北京和上海明天的天气。"
- 模型可以一次性吐出两个
tool_calls分别查北京和上海,后端并发去请求,然后再把两个结果一起喂给模型。这大大减少了多轮对话的延迟。
四、开发中的常见痛点与"坑"
- 大模型"幻觉参数":有时候用户没说全信息,大模型可能会自己"瞎编"一个合理的参数传给函数。因此,在后端代码接收到大模型传来的参数时,必须进行二次校验与防呆处理。
- 长提示词与 Token 消耗:如果你给大模型注册了几十个甚至上百个工具,每次请求光是
tools里面的 JSON Schema 描述就会吃掉大量的 Prompt Token。因此,复杂的生产系统通常会做工具检索(Tool Retrieval)——根据用户当前的意图,先用向量检索或简单分类,动态挑选最相关的 3~5 个工具塞给模型,而不是一次性全量加载。 - 错误处理机制:如果你的 API 挂了,或者返回了
404 Not Found,不要直接报错中断。你需要把这个错误信息(作为tool结果)传回给大模型,大模型具备一定的容错和解释能力,它会温柔地告诉用户:"不好意思,天气服务暂时开小差了,请稍后再试。"
Function Calling 从根本上打通了"自然语言"与"结构化世界"的壁垒,把大模型从一个"只会夸夸其谈的聊天机器"变成了"能够驱动软件系统的数字员工"。
五、Function Calling 和 MCP 区别
两者常被一起讨论,但解决的是不同层级的问题:Function Calling 是"能力",MCP 是"协议"。
1. 核心定位对比
Function Calling(能力层):大模型的一项原生底层能力,解决了"无法产生结构化数据"的问题——能把自然语言精准提取为
{"name": "func_name", "args": {...}}这样的 JSON。- 局限:只定义了格式、没定义连接方式。工具定义要硬编码进请求,新增工具要改所有代码,且各家接口规范不统一、难以复用。
MCP(协议层):一套开放的客户端-服务器通信协议(类似 HTTP/REST),解决工具生态的"碎片化"与"重复造轮子"。
- 优势:工具只写一次、部署为 MCP Server,任何支持 MCP 的客户端(Cursor、Claude Desktop 等)都能动态连接、即插即用,无需硬编码实现。
2. 工作架构对比
纯 Function Calling:逻辑全侵入在应用代码里。
用户输入 → 应用代码(硬编码工具定义) → 大模型(返回 JSON 指令) → 应用代码手动调 API → 结果喂回大模型 → 生成回答结合 MCP:工具解耦为独立服务。
用户输入 → MCP 客户端
1. 向 MCP Server 动态获取工具列表
2. 把工具定义塞给大模型
3. 大模型用 Function Calling 吐出 JSON 调用
4. 客户端按 MCP 协议转发给 Server 执行并返回3. 维度对比表
| 维度 | Function Calling | MCP 协议 |
|---|---|---|
| 所属层级 | 算法/模型层(参数提取与意图判断) | 系统/网络层(通信规范) |
| 扮演角色 | 决策者与翻译官 | 基础设施与管道 |
| 代码耦合度 | 高耦合,与应用代码绑定 | 低耦合,工具独立运行 |
| 工具发现方式 | 静态,调用前写死在代码里 | 动态,连接后自动扫描 |
| 跨模型/应用复用 | 差,换框架需适配 | 极佳,一套规范多方复用 |
4. 总结
MCP 不是 Function Calling 的替代品,而是它的"升级载体"。 MCP 负责管理连接"军火库"(工具与数据源),大模型则用 Function Calling 作为"瞄准镜和触发器",决定何时调用哪件武器。