函数调用(Function Calling)是大模型调用外部能力最常用的机制:开发者先用 JSON Schema 描述好"有哪些函数、参数长什么样",模型需要查数据或做操作时,便输出一段结构化的调用请求,程序执行函数后把结果回填。关键只有一句话:模型只负责"决定调什么、参数填什么",真正执行代码的永远是你的程序。
它到底在解决什么问题
模型原生只会输出文本,"动手"的事(如查天气、读库、下单)做不了。函数调用在中间搭了一座桥:模型用自然语言理解需求、用结构化格式表达"我要调哪个函数、参数是什么",执行交给程序。这正是工具调用的地基。
一次完整的函数调用长什么样
- 定义:请求带上 tools 数组,写清函数名、描述和参数结构(JSON Schema)。
- 决策:模型需要外部能力时不直接回答,而是返回 tool_calls:函数名加参数 JSON。
- 执行:你的程序解析 tool_calls,调用真正的函数(查 API、读库、跑脚本都行)。
- 回填:把结果作为 tool 消息塞回对话,模型据此组织最终回答。
几个关键组成
- tools 定义:"函数说明书"。描述越清楚填参越准,description 写给模型看。
- tool_choice:控制模型对某函数"必须调 / 可调 / 不调",常用 auto、none 或指定函数名。
- 并行调用:一次返回多个 tool_calls,适合同一轮办多件互不依赖的事。
- 结构化约束:参数必须是合法 JSON,类型错了程序侧直接报错,Schema 约束是刚性的。
它和工具调用、MCP、插件调用到底差在哪
| 维度 | 函数调用 | 工具调用 | MCP | 插件调用 |
|---|---|---|---|---|
| 本质 | 一种调用机制 | 总称 | 连接协议 | 能力分发形态 |
| 谁定义工具 | 开发者定义 | 不一定 | MCP server 暴露 | 平台方封装 |
| 解决的问题 | 模型如何发起调用 | 模型如何用外部能力 | 工具如何被发现和统一接入 | 能力如何分发给用户 |
函数调用由 OpenAI 在 2023 年推开,主流模型多已兼容;工具调用是更大的筐,函数调用、代码执行、MCP 工具都装在里面。记住:MCP 和插件调用:MCP 管"怎么接",插件管"怎么分发",函数调用管"怎么发起"——三者是上下游,不是替代关系。
边界与限制
- 参数幻觉:模型可能编造参数名或填错类型,程序侧必须校验。
- Token 与延迟:多走一轮对话,tools 定义也占上下文,工具一多就贵、就慢。
- 安全红线:别让模型直调删库、转账、群发邮件这类不可逆操作,敏感动作加人工确认。
- 能力差异:各模型支持成熟度不一,小模型常"只说不调"或格式写错。
常见误解
- "模型真的在执行代码"——没有。它只输出调用请求,执行在你的程序里。
- "函数调用就是 MCP"——不是。MCP 是协议层;它暴露的工具,照样可以经由函数调用被模型使用。
- "有了函数调用就不需要插件"——插件面向用户分发能力,函数调用面向开发者,不在同一层面。
- "定义了函数模型就一定会调"——默认 auto,模型觉得不需要就不会调;想强制就显式指定函数名。
FAQ
Q:函数调用和各家 API 的工具参数是一回事吗?
A:同源,都是"模型输出结构化调用、程序执行",差别在字段名和封装,迁移主要改定义格式。
Q:已经在用 MCP,还需要关心函数调用吗?
A:需要。MCP 解决工具怎么接进来,函数调用解决模型怎么发起调用,是上下游,不是二选一。
Q:函数调用能调本地脚本吗?
A:能。函数只是程序入口,背后做什么模型不关心,它只说"调哪个、参数是什么"。