OpenAI API 中的函数调用:它究竟做什么以及如何正确使用

CometAPI
Zoom JohnApr 20, 2026
OpenAI API 中的函数调用:它究竟做什么以及如何正确使用

你把用户消息传给 GPT API,模型并没有返回自然语言答案,而是给出一个结构化的 JSON 对象,明确告诉你要调用哪个函数,以及使用哪些参数。这就是“函数调用”——它正在改变你能用 LLM 构建的应用形态。

函数调用

大多数开发者听到“函数调用”,就以为模型会替他们执行代码。并不会。

使用函数调用时,LLM 本身不会执行函数。相反,它会识别合适的函数、收集所需的参数,并以结构化的 JSON 格式提供这些信息。

你的应用仍然负责运行实际逻辑。模型只是告诉你该运行什么以及输入是什么。

这个区别比听起来更重要,它影响从集成架构到安全思考的方方面面。

函数调用到底是什么——以及大家常见的误解

函数调用(也称工具调用)为 OpenAI 模型与外部系统交互、访问训练数据之外的数据提供了强大而灵活的方式。

命名本身就是第一处混淆。人们以为模型在执行某些东西。其实不是。

关于函数调用有很多名字与解释,但归根结底就是一句话:“函数调用是大型语言模型的一种结构化输出能力。” LLM 自己不会调用任何函数;它会在你提供的预定义函数中建议应该调用哪一个。

第二个误解在于旧的 API 接口。

随着 2023-12-01-preview 版本 API 的发布,functionsfunction_call 参数已被弃用。functions 的替代者是 tools 参数。

如果你在跟随一个仍使用旧 functions 参数的教程,你已经在使用弃用语法了。请改用 toolstool_choice

函数是工具的一种特定类型,由 JSON 模式定义。函数定义允许模型将数据传递到你的应用,使你的代码能够访问数据或执行模型建议的动作。

正是这种模式让函数调用相比纯提示在可靠性上更具优势——你不再指望模型正确格式化输出,而是在 API 层面强制结构。

函数调用在 OpenAI API 中如何工作——逐步说明

工具调用是你的应用与模型通过 OpenAI API 进行的多步对话。工具调用流程有五个高层步骤:向模型发起请求并提供可调用的工具……

以下是每一步在实践中的表现。

Step 1: Define your function schemas. 你在 tools 参数中将每个可用函数描述为一个 JSON 对象。该模式包含函数名、模型用于决定何时调用它的自然语言描述,以及遵循 JSON Schema 约定的 parameters 块。

你的 description 越具体——在何种情境下可以且应该调用该函数——效果越好。不过要注意,函数描述属于提示的一部分,同样会消耗 tokens。

Step 2: Send the request. 使用用户消息和你的 tools 列表调用 Chat Completions API。模型会同时看到两者。

Step 3: The model decides whether to call a function.

当模型审视提示后判断为完成指令需要调用某个可用工具时,它会返回一种特殊响应形式,即工具调用。如果模型收到提示“what is the weather in Paris?”,它可能会返回对 get_weather 工具的调用,并使用 Paris 作为 location 参数。

Step 4: Your code executes the function. 你解析模型的响应,提取函数名与参数,并在你的运行时中执行实际代码。API 返回的是结构化 JSON——由你决定如何处理它。

Step 5: Send the result back.

然后你将所有工具定义、原始提示、模型的工具调用以及该工具调用的输出一起发回模型,最终收到一条文本回复

—— 比如:“The weather in Paris today is 25°C.”

函数调用流程图

大多数教程忽略的一个细节:

当你在函数定义中设置 strict: true 时,Structured Outputs 可以保证模型为函数调用生成的参数严格匹配你提供的 JSON Schema。

strict 设置为 true 能确保函数调用可靠地遵循函数模式,而非仅尽力而为。OpenAI 建议始终启用严格模式。

永远如此。没有不启用的理由。

你还需要了解并行函数调用。

根据用户查询,若使用的是 2023 年 11 月 6 日或之后发布的最新模型,模型会触发并行函数调用。

这意味着像“what's the weather in London and Tokyo?” 这样的单次请求可以触发两个并行的工具调用,而不是顺序地串行调用。

函数调用的真实世界用例

天气示例之所以流行,是因为它简洁。但真实的生产用例更杂乱,也更有趣。

Customer support pipelines with live data

函数调用在大量用例中都很有用——例如,当用户询问“what are my recent orders?”时,AI 助手需要从内部系统抓取最新客户数据,然后再生成回复。

模型识别意图、从上下文中抽取客户 ID,并调用你的 CRM 内部 API。无需脆弱的正则,也不需要对逗号缺失就会崩的提示模板。

Structured data extraction at scale

另一个强力用例是数据抽取流水线:抓取原始文本,将其转换为结构化数据,并保存到数据库。无需为每种文档类型手工微调解析逻辑,就能在数千份文档中获得一致的模式。

Natural language to API translation

由 LLM 驱动的数据抽取与标注方案、将自然语言转换为 API 调用或有效数据库查询的应用、与知识库交互的对话式知识检索引擎——这些都受益于函数调用对输出格式的保障。当你需要用输出驱动下游系统时,就无法容忍可变性。

Agentic workflows with multiple tools

对开发者而言,函数调用让实时数据访问成为可能,可以通过抓取最新股价、天气或近期数据库条目来弥补训练截止的不足。它也支持动作执行——将 LLM 从被动观察者转变为会改变状态的主动参与者,比如发送邮件、更新 CRM 或部署代码。

与普通聊天机器人的关键区别:模型不仅在生成文本,还在编排跨系统的实际操作。

函数调用的最佳实践——开发者常犯的错

这是大多数教程完全跳过的一节,这也是团队最终在凌晨两点调试诡异生产故障的原因。

写得过于模糊的描述。 模型依赖你的函数描述来决定何时调用它。如果描述很泛,比如“处理用户请求”,模型就没有可靠信号来决定何时触发。请具体说明触发条件与期望的输入结构。把描述当作契约,而非标签。

一次暴露过多函数

函数描述会在输入提示中消耗相当数量的 tokens。

在系统提示中加载 50+ 个工具定义会产生两个问题:成本与时延,因为工具定义会占用输入 tokens;以及准确率下降,因为工具选项越多,模型选择正确工具的能力越差。

从用例真正需要的最小函数集开始。

假设模型不会幻觉出参数。 它会的。

模型可能会幻觉出参数——尤其是在可选字段没有用 enum 清晰界定时。这正是 strict: true 重要的原因:它消除了模型在你的模式之外“发明”字段的可能。

没有处理多轮循环。 开发者常常只构建“幸福路径”——用户发问,模型调用函数,结束。

模型可能会生成与你定义的模式不匹配的函数调用,或尝试调用你未提供的函数。如果模型在生成意外的函数调用,试着在 system message 中加入一句话:“Only use the functions you have been provided with.”

为边界情况做好准备。

在写入操作前跳过确认步骤。

要清楚那些你计划执行的函数调用在现实世界中的影响,尤其是会触发执行代码、更新数据库、发送通知等动作的函数。对会执行动作的函数,强烈建议实现用户在执行前确认的步骤。

如果一个函数调用可能删除数据、汇款或修改外部状态,应先由人批准。

安全性与可靠性考量

函数调用扩展了 LLM 的能力,也扩展了攻击者能让它做的事情。

这里的主要威胁是提示注入(prompt injection)。

提示注入的最终目标各不相同,但可能包括通过下游工具调用外流私密数据、执行不对齐的动作或以其他方式以非预期方式改变模型行为。

当你的函数调用可以发送邮件、查询数据库或触发 webhooks 时,一次注入攻击不仅仅是聊天机器人跑题——它可能是一次安全事件。

随着 AI 系统走出聊天、开始调用工具并采取行动,提示注入变得更加严重。隐藏在网页、文档或外部工具中的恶意指令,可能试图覆盖系统行为、暴露敏感信息或触发不该发生的动作。

缓解策略有几个具体层面。

设计工作流,确保不受信任的数据永远不会直接驱动代理行为。从外部输入中只提取特定的结构化字段——例如枚举或已验证的 JSON——以限制注入风险在节点之间传播。

此外,

始终验证模型生成的函数调用。包括检查参数、被调用的函数,并确保该调用与预期动作一致。

一个不太好受的事实:

“提示注入,就像网络上的诈骗与社会工程一样,几乎不可能被完全‘解决’。”

这是 OpenAI 自己的评估。现实含义是:你在设计基于代理的函数调用系统时,不应假设模型总会按预期行为。需要纵深防御——验证、范围受限的权限、对破坏性操作引入人的参与——这才是理性的姿态。

函数调用 vs. 提示工程——何时该用哪一个

这个比较经常出现。简短答案:它们解决的是不同问题。把两者混为一谈会导致在该用函数调用时过度工程化提示,或在该用提示时却构建脆弱的函数模式。

函数调用 vs 提示工程

提示工程涉及编写文本输入来引导 LLM 的内部推理——比如让它“step-by-step 思考”。

它塑造模型如何推理。而函数调用则塑造模型产出的形式,并将产出直接路由到你的系统中。

工具调用是让 LLM 与外部系统交互的能力。你可以用提示工程帮助模型决定使用哪个工具,而工具调用是实际执行动作的机制。两者通常都需要,但作用不同。

函数调用相较基于提示的结构化输出的关键技术优势在于:

工具调用是内建在模型中的概念。无需浪费 tokens 和精力去解释“要以某种特定格式返回”。

当你在提示里写“请以包含字段 X、Y、Z 的 JSON 返回答案”时,你在为模型可能不一致地遵循指令付出 tokens。函数调用则在 API 层进行模式强制。

函数调用 API 现已被许多 LLM 平台原生支持,它提供了一个由模式驱动的正式接口,能够实现严格数据校验并与程序化工作流集成。

这就是在需要将数据流入下游系统时选择它而非提示工程的现实理由:一旦进入生产,可靠性不是可选项。

DimensionPrompt EngineeringFunction Calling
Primary purpose塑造模型的推理与语气产出用于系统集成的结构化输出
Output format自由文本(或文本伪装的 JSON)强制的 JSON 模式
Schema reliability尽力而为;易漂移通过 strict: true 得到保证
Token cost简单输出成本更低更高(函数定义会增加 tokens)
When to use推理任务、文本生成、风格控制结构化数据抽取、API 编排、代理式操作
Prompt injection exposure更低(不执行外部工具)更高(函数调用可能触发现实世界操作)

实用准则:如果输出要驱动下游系统——数据库写入、API 调用、代码中的决策分支——用函数调用;如果输出是给人读的,通常用提示工程就足够且更省钱。

关键要点

TopicWhat to Remember
What it is模型输出结构化 JSON,描述要调用哪个函数——它不会执行该函数
Current API surface使用 tools 和 tool_choice;旧的 functions 与 function_call 参数已弃用
Strict mode在函数定义中始终启用 strict: true,以强制遵循模式
Parallel calling在 2023 年 11 月之后发布的模型上受支持;一次请求可触发多个工具调用
Token cost函数模式会占用输入 tokens;尽量减少暴露函数的数量
Security验证所有函数调用输出;切勿允许不受信任的外部内容直接驱动工具调用
vs. Prompt Engineering函数调用在 API 层面强制输出结构;提示工程塑造内部推理
Confirmation steps任何具有现实世界副作用(写入、发送、删除)的函数在执行前都应要求用户确认

如果你想在不同模型上尝试函数调用——GPT-5.4claude opus 4.7gemini 3.1 pro——且不想为每个模型维护单独的 API 凭据,CometAPI 通过一个端点与密钥就能访问所有模型,大幅降低跨模型测试的摩擦。

CometAPI 解决的是基础设施开销:

统一的函数调用语法,覆盖 15+ 模型

单一 API Key —— 无需为 OpenAI/Anthropic/Google 分别开账号

自动模式转换 —— 一次编写,到处测试

内置成本跟踪 —— 实时比较各模型的 token 用量

使用免费额度开始测试获取访问权限

准备好将AI开发成本降低20%了吗?

几分钟内免费开始。包含免费试用额度。无需信用卡。

阅读更多