o3/o4-mini 函数调用指南
技术背景
o3/o4-mini 是 OpenAI 推出的新一代推理模型,在响应前会进行更长时间的思考,具备更强的工具调用能力。与之前的 o1/o3-mini 相比,o3/o4-mini 在思维链中原生使用工具,解锁了更智能的工具选择与调用时机。然而,要充分发挥其潜力,开发者需要理解推理模型与传统模型的差异,并采用针对性的提示词和函数设计策略。本指南旨在填补这一知识空白,帮助开发者避免常见陷阱,实现最佳性能。
核心原理
o3/o4-mini 的核心优势在于其内部思维链(CoT)中能够原生调用工具,这意味着模型在推理过程中会自主决定何时使用工具、使用哪个工具以及如何构造参数。这种能力依赖于模型对函数描述和开发者指令的深度理解。函数描述作为模型与工具之间的接口契约,定义了工具的功能、调用条件和参数格式。开发者指令则提供上下文、调用顺序和边界规则。模型通过解析这些信息,在推理过程中动态规划工具调用序列,从而实现复杂任务的自动化。
架构分析
系统架构涉及三个核心组件:开发者提示词(或系统提示词)、函数描述和工具调用执行流程。开发者提示词设定整体行为、上下文和工具使用边界;函数描述定义每个工具的具体接口;工具调用流程则通过 Responses API 实现,支持推理项的保留和传递。Responses API 允许在工具调用之间保留推理项,从而提升决策质量。此外,托管工具(如代码解释器、MCP)可与自定义函数混合使用,通过明确的决策边界避免歧义。
完整实战教程
简介
o3/o4-mini 模型是我们 o 系列中的最新模型,经过训练,在响应之前会进行更长时间的思考。它们是迄今为止我们发布的最智能的模型,并且在工具调用能力上相比 o1/o3-mini 有了显著进步。这些模型经过训练,可以在其思维链(CoT)中原生使用工具,这解锁了在何时以及如何使用工具方面的改进推理能力。我们已经发布了一份关于如何通过 Responses API 使用这些模型调用函数的指南,本指南在此基础上进一步说明如何通过这些模型获得最佳的函数调用性能。
提升函数调用性能的提示词指南
为了充分利用 o3/o4-mini 模型背后的函数调用智能,我们建议在开发者提示词和函数描述中遵循一些最佳实践。
关于推理模型的开发者提示词、系统提示词和函数描述的简要说明
我们引入了开发者消息,以明确告知推理模型指令来自开发者。在 o 系列模型中,开发者提供的任何系统消息都会在内部自动转换为开发者消息。实际上,你可以将开发者提示词视为与传统系统提示词类似——但为了清晰和正确,本指南将所有此类指令统称为开发者提示词/消息。
当本文档提到函数描述时,我们指的是 API 请求的 tool 参数中每个函数对象 description 字段内的解释性文本。该描述告诉模型何时以及如何使用该函数。以下是我们函数调用文档中的一个示例:
tools = [{
"type": "function",
"name": "get_weather",
"description": "Get current temperature for provided coordinates in celsius.",
"parameters": {
"type": "object",
"properties": {
"latitude": {"type": "number"},
"longitude": {"type": "number"}
},
"required": ["latitude", "longitude"],
"additionalProperties": False
},
"strict": True
}]
在这里,"Get current temperature for provided coordinates in celsius." 作为函数描述。
既然我们已经完成了定义,就可以开始探讨最佳实践了。
通过开发者消息设置上下文
- 通用上下文:遵循通用提示工程最佳实践,角色提示有助于设定基础行为、语气并概述可能执行的操作集。例如:
You are an AI retail agent.
As a retail agent, you can help users cancel or modify pending orders, return or exchange delivered orders, modify their default user address, or provide information about their own profile, orders, and related products.
- 函数调用顺序:o3/o4-mini 经过训练,能够借助工具实现目标。然而,在工具调用的顺序上,它可能会犯错。为防止此类情况,建议明确概述完成特定任务的顺序。例如,为防止编码代理可能在尚不存在的目录中创建文件这一失败情况,添加以下内容通常就足够了:
check to see if directories exist before making files
对于高容量且定义明确的任务,我们可以通过明确列出要调用的函数序列来使其更加健壮,例如:
To Process a refund for a delivered order, follow the following steps:
1. Confirm the order was delivered. Use: `order_status_check`
2. Check the refund eligibility policy. Use: `refund_policy_check`
3. Create the refund request. Use: `refund_create`
4. Notify the user of refund status. Use: `user_notify`
- 定义何时使用工具的边界:明确模型在何时调用或不调用某些工具的边界是有帮助的。这既可以在开发者提示级别完成,也可以在工具描述级别完成。以下是一个开发者提示的示例:
Be proactive in using tools to accomplish the user's goal. If a task cannot be completed with a single step, keep going and use multiple tools as needed until the task is completed. Do not stop at the first failure. Try alternative steps or tool combinations until you succeed.
- Use tools when:
- The user wants to cancel or modify an order.
- The user wants to return or exchange a delivered product.
- The user wants to update their address or contact details.
- The user asks for current or personalized order or profile info.
- Do not use tools when:
- The user asks a general question like “What’s your return policy?”
- The user asks something outside your retail role (e.g., “Write a poem”).
If a task is not possible due to real constraints (For example, trying to cancel an already delivered order), explain why clearly and do not call tools blindly.
函数描述
函数的描述应阐明何时应调用它,以及如何构造其参数。
函数的描述是阐明何时应调用该函数以及如何构造其参数的最佳位置。这构成了推理模型与工具API之间持久的接口契约。
通常,函数描述定义了它的功能以及如何调用它。开发者指令则为使用工具的代理提供指导。因此,如果有多个工具可用于类似目的,开发者可以在指令中区分它们。如果代理工作流要求对工具的使用顺序有偏好,或者某些工具使用频繁而另一些使用较少,这些也应写入开发者指令中。
结构良好的描述可以通过提前锚定关键标准和参数要求来提高准确性并减少误触发。它还允许开发者在开发者提示之外、更接近工具定义本身的位置编码“主动性”控制启发式规则。
- 使用标准:类似于通过开发者提示来细化函数调用的主动性,你可以在函数描述层面进一步细化函数的调用方式。以下是一个
file_create函数的示例:
Creates a new file with the specified name and contents in a target directory. This function should be used when persistent storage is needed and the file does not already exist.
- Only call this function if the target directory exists. Check first using the `directory_check` tool.
- Do not use for temporary or one-off content—prefer direct responses for those cases.
- Do not overwrite existing files. Always ensure the file name is unique.
- Do not overwrite existing files.
If replacement is intended and confirmed, use `file_delete` followed by `file_create`, or use `file_update` instead.
- 少样本提示:虽然推理模型不像非推理模型那样能从少样本提示中获益良多,但我们发现少样本提示可以提升工具调用性能,尤其是在模型难以准确构造函数参数时。例如,下面是一个 grep 工具的工具描述示例,作为工具描述传入:
Use this tool to run fast, exact regex searches over text files using the `ripgrep` engine.
- Always escape special regex characters: ( ) [ ] { } + * ? ^ $ | . \\
- Use `\\` to escape any of these characters when they appear in your search string.
- Do NOT perform fuzzy or semantic matches.
- Return only a valid regex pattern string.
Examples:
Literal -> Regex Pattern
function( -> function\\(
value[index] -> value\\[index\\]
file.txt -> file\\.txt
user|admin -> user\\|admin
path\to\file -> path\\\\to\\\\file
- 提前说明关键规则并尽量减少干扰:请注意,在上面的示例中,关于转义特殊字符的指令是模型最先读取的内容之一。一个更差的替代方案是:
Performs a fast regex-based text search that looks for exact pattern matches within files or entire directories, leveraging the ripgrep tool for high-speed scanning.
Output follows ripgrep formatting and can optionally display line numbers and matched lines.
To manage verbosity, results are limited to a maximum of 50 hits.
You can fine-tune the search by specifying inclusion or exclusion rules based on file types or path patterns.
This method is ideal when searching for literal text snippets or specific regular expressions.
It offers more accuracy than semantic methods when the goal is to locate a known string or structure.
It’s generally recommended over semantic search when you’re looking for a specific identifier—such as a function name, variable, or keyword—within a defined set of directories or file types.
这种做法的效果不佳,因为提示词的大部分内容并非规定性的,而构建论证的最重要规则并未突出显示。与上述提示词相比,前一个提示词在使用此 ripgrep 工具的工具调用准确率评估中得分高出 6%。
防范函数调用幻觉
我们意识到,o3 模型可能比其他模型更容易产生幻觉。这些幻觉可能表现为模型承诺在后台调用工具但实际上并未调用,或承诺在未来的轮次中调用工具等。在这种情况下,明确以下几点有助于减少此类幻觉:
- 明确指令:明确指示模型避免常见的幻觉,例如在不可能的情况下承诺未来的函数调用。
Do NOT promise to call a function later. If a function call is required, emit it now; otherwise respond normally.
- 尽早捕获错误参数:
将 strict 设置为 true 将确保函数调用可靠地遵循函数模式。我们建议尽可能开启此选项。
如果你的参数有额外的复杂格式要求(例如有效的 Python 代码等),添加以下指令可以提醒模型预期的格式。
Validate arguments against the format before sending the call; if you are unsure, ask for clarification instead of guessing.
- 关于懒惰行为的另一则说明:
我们注意到 o3 偶尔会出现懒惰行为,例如声称没有足够时间完成任务、承诺稍后单独跟进,或者即使在明确提示要求提供更多细节时也只给出简短回答。我们发现以下步骤有助于改善这种行为:
- 对于不相关的话题,开启新的对话:
当切换到新的或不相关的话题时,请开启新的对话线程,而不是在相同的上下文中继续。这有助于模型专注于当前主题,并防止其受到先前不相关上下文的影响,这些上下文有时会导致不完整或懒惰的回答。例如,如果您之前讨论的是代码调试,而现在想询问文档编写的最佳实践,这不需要之前的对话上下文,请开启新的对话以确保清晰和专注。
- 当列表过长时,丢弃不相关的过往工具调用/输出,并在用户消息中将其总结为上下文:
如果对话历史包含一长串不再相关的先前工具调用或输出,请将其从上下文中移除。相反,在用户消息中提供重要信息的简洁总结。这可以保持上下文可控,并确保模型只访问最相关的信息。例如,如果您有一长串工具输出,您可以总结关键结果,并在下一条消息中仅包含该总结。
- 我们正在不断改进我们的模型,并期望在未来的版本中解决这个问题。
避免思维链提示
由于这些模型是推理模型,并且会产生内部思维链,因此不需要明确提示它们在工具调用之间进行规划和推理。因此,开发者不应试图通过要求模型进行更广泛的规划来在每个函数调用之前诱导额外的推理。要求推理模型进行更多推理实际上可能会损害性能。
关于推理摘要的快速说明:模型在调用工具之前会输出推理令牌。然而,这些并不总是伴随摘要,因为我们的推理摘要需要最少量的实质性推理令牌才能生成摘要。
Responses API
推理项带来更佳性能
我们发布了一份 cookbook,详细说明了使用 responses API 的好处。本指南中也有必要重申几个要点。o3/o4-mini 在训练时,其内部推理会在单轮内的工具调用之间持续存在。因此,在推理过程中,在工具调用之间保留这些推理项,将带来更高的智能和性能,表现为在何时以及如何调用工具方面做出更好的决策。Responses 允许你保留这些推理项(由我们维护,或者如果你不希望我们处理状态管理,也可以通过加密内容由你自己维护),而 Chat Completion 则不支持。切换到 responses API,并允许模型在函数调用之间访问推理项,是尽可能榨取函数调用性能的最简单方法。以下是 cookbook 中的一个示例,为了方便起见在此复现,展示了如何使用 encrypted_content 传回推理项,从而在我们这边不保留任何状态:
from openai import OpenAI
import requests
import json
client = OpenAI()
def get_weather(latitude, longitude):
response = requests.get(f"https://api.open-meteo.com/v1/forecast?latitude={latitude}&longitude={longitude}¤t=temperature_2m,wind_speed_10m&hourly=temperature_2m,relative_humidity_2m,wind_speed_10m")
data = response.json()
return data['current']['temperature_2m']
tools = [{
"type": "function",
"name": "get_weather",
"description": "Get current temperature for provided coordinates in celsius.",
"parameters": {
"type": "object",
"properties": {
"latitude": {"type": "number"},
"longitude": {"type": "number"}
},
"required": ["latitude", "longitude"],
"additionalProperties": False
},
"strict": True
}]
context = [{"role": "user", "content": "What's the weather like in Paris today?"}]
response = client.responses.create(
model="o3",
input=context,
tools=tools,
store=False,
include=["reasoning.encrypted_content"] # Encrypted chain of thought is passed back in the response
)
context += response.output # Add the response to the context (including the encrypted chain of thought)
tool_call = response.output[1]
args = json.loads(tool_call.arguments)
result = get_weather(args["latitude"], args["longitude"])
context.append({
"type": "function_call_output",
"call_id": tool_call.call_id,
"output": str(result)
})
response_2 = client.responses.create(
model="o3",
input=context,
tools=tools,
store=False,
include=["reasoning.encrypted_content"]
)
print(response_2.output_text)
使用托管工具的智能体体验
Responses API 支持一组托管/内置工具。我们最近还在 Responses API 中增加了新工具和功能,使得构建连接外部服务的智能体应用更加容易;借助 Responses API 中的内置工具,开发者可以通过一次 API 调用创建更强大的智能体。
您可以在同一会话中混合搭配托管工具和自定义工具。这解锁了强大的组合模式,但也使得工具路由的清晰性变得至关重要。以下是一些具体建议:
- 在开发者提示中明确界定工具使用边界:如果多个工具可以执行类似的功能(例如,Python 工具和自定义计算器),请指示模型在何时优先使用哪个工具。这可以减少歧义,提高准确性,并避免工具过度使用或使用不足。
You are a helpful research assistant with access to the following tools:
- python tool: for any computation involving math, statistics, or code execution
- calculator: for basic arithmetic or unit conversions when speed is preferred
Always use the python tool for anything involving logic, scripts, or multistep math. Use the calculator tool only for simple 1-step math problems.
- 明确内部知识不足的情况:尽管 o3/o4-mini 模型通常可以自行解决任务,但工具可能提供更可靠的答案。使用系统提示引导模型在工具更合适时不要“试图自行解决”。
You have access to a `code_interpreter`. Always prefer using `code_interpreter` when a user asks a question involving:
- math problems
- data analysis
- generating or executing code
- formatting or transforming structured text
Avoid doing these directly in your own response. Always use the tool instead.
- 由于开发者提示词充当集中、持久的契约,当我们希望将托管工具与自定义函数混合使用时,请在此处明确工具的决策边界,包括覆盖重叠、置信度预期或回退行为:
Use `python` for general math, data parsing, unit conversion, or logic tasks that can be solved without external lookup—for example, computing the total cost from a list of prices.
Use `calculate_shipping_cost` when the user asks for shipping estimates, as it applies business-specific logic and access to live rate tables. Do not attempt to estimate these using the `python` tool.
When both could be used (e.g., calculating a delivery fee), prefer `calculate_shipping_cost` for accuracy and policy compliance. Fall back to `python` only if the custom tool is unavailable or fails.
- 关于 MCP 的更多内容:我们有一份更详细的指南,介绍使用 MCP 工具的最佳实践,但为了完整起见,我们在此重申一些高层指导原则(这些并非特定于 o3/o4-mini,但仍然适用)。
* 过滤工具以避免负载膨胀:利用 allowed_tools 参数仅使用必要的工具,以节省不必要的上下文:由于你并不总是需要 MCP 服务器返回的所有工具,你可以通过 allowed_tools 字段仅过滤出必要的工具。
"tools": [
{
"type": "mcp",
"server_label": "gitmcp",
"server_url": "https://gitmcp.io/openai/tiktoken",
"allowed_tools": ["search_tiktoken_documentation", "fetch_tiktoken_documentation"],
"require_approval": "never"
}
* 通过缓存降低延迟,并将推理模型保留给高复杂度任务:确保要么传回 mcp_list_tools,要么包含 previous_response_id,以避免 API 不必要地重复导入工具列表。
* 将 MCP 与其他工具结合使用:你可以将 MCP 与其他托管工具及自定义函数混合搭配。如果混合使用工具,建议在整体开发者提示中明确决策边界,并明确说明何时使用某个工具而非另一个。MCP 工具指南中的这个示例很好地展示了这一点。
常见问题解答(FAQ)
问:函数数量多少算太多?
答: 对于 o3 和 o4-mini 模型,函数数量没有硬性上限,但根据训练数据分布和观察到的模型行为,确实存在一些实用指导。截至 2025 年 5 月,任何少于约 100 个工具且每个工具参数少于约 20 个的设置都被视为分布内,性能应在预期可靠性范围内。性能仍然取决于你的提示设计和任务复杂度。
即使你在技术上处于训练分布内,更多的工具也可能引入歧义或混淆。以下是一些关键考虑因素:
* 函数描述的清晰度变得至关重要:如果多个工具具有重叠的用途或模糊的描述,模型可能会调用错误的工具,或犹豫不决而不调用任何工具。
* 工具列表的大小会影响延迟和推理深度:更长的列表意味着模型在推理阶段需要解析更多选项。虽然 o3/o4-mini 可以通过其集成的推理流程处理这一点,但如果模式清晰度或调用条件不够明确,性能可能会下降。
* 工具幻觉可能随复杂度增加:尤其是在 o3 中,有报告称当工具集庞大且定义不充分时,会出现幻觉或推测性的工具调用。明确的指令有助于缓解这一问题(例如,“仅使用工具 X、Y、Z。不要发明工具调用或将它们推迟到后续轮次。”)
最终,性能会因用例而异;因此,投资于你信任的评估以进行迭代非常重要。
问:在工具中使用深层嵌套参数可以吗?还是应该“扁平化”模式?
答: 同样没有硬性指导。然而,即使你的嵌套结构在技术上受支持,深层参数树也可能影响性能或可靠性。如有疑问,我们建议你倾向于使参数扁平化。
扁平结构通常更容易让模型推理:在更扁平的模式中,参数字段是顶层的,立即可见。这减少了内部解析和结构化的需要,有助于防止部分填充的嵌套对象或无效字段组合等问题。对于深层嵌套对象,尤其是具有重复或语义相似字段名的对象,模型更可能省略或误用参数。
嵌套有助于组织复杂逻辑,但需要额外注意:对于自然涉及结构化输入的领域,如配置负载、丰富的搜索过滤器或表单提交,嵌套有助于组织相关参数。但是,你必须使用清晰的字段描述、anyOf 逻辑或严格模式等技术,以防止无效的参数组合并提高模型可靠性。
选择最佳方式是通过你自己的评估进行测试并衡量成功。没有“一刀切”的解决方案,因为调用行为是涌现的且对提示敏感。
问:这些函数调用指导是否适用于自定义工具格式?
答: 不保证。本文档中的指导假设你使用标准的 tools 模型参数来传递函数模式,如我们的函数调用通用指南所示。我们的 o3/o4-mini 模型经过训练,可以原生理解并使用这些模式进行工具选择和参数构建。
如果你是通过开发者编写的提示中的自然语言提供自定义工具定义(例如,在开发者消息或用户消息中内联定义工具),则此指南可能不完全适用。在这些情况下:
- 模型不依赖其内部的工具模式先验知识。
- 你可能需要更明确地提供少样本示例、输出格式和工具选择标准。
- 没有模式级锚定,参数构建的可靠性可能会降低。
尽可能使用结构化的工具参数。如果必须在自由文本中定义工具,请将其视为自定义协议并进行相应测试。
常见问题
常见错误包括:1) 函数描述模糊导致误调用;2) 未明确工具调用顺序导致步骤错误;3) 模型幻觉,承诺调用但未执行;4) 参数格式错误;5) 上下文过长导致性能下降。排查方法:使用 strict 模式确保参数符合模式;在开发者提示中明确禁止幻觉行为;定期清理对话历史,丢弃不相关的工具输出;利用评估集测试不同提示词的效果。
企业应用扩展
生产环境优化建议:1) 使用 Responses API 并保留推理项以提升性能;2) 利用 allowed_tools 过滤 MCP 工具,减少上下文负担;3) 通过缓存降低延迟;4) 对于高复杂度任务,优先使用推理模型,简单任务可回退到非推理模型以节省成本;5) 建立完善的评估体系,持续迭代提示词和函数设计。
总结
本指南面向有编程基础的开发者,深入讲解如何通过 OpenAI o3/o4-mini 推理模型实现高性能函数调用。内容涵盖提示词工程最佳实践、函数描述优化、幻觉防范、Responses API 的推理项利用、托管工具与自定义工具的混合使用,以及常见问题解答。通过具体示例和代码,帮助开发者掌握工具调用的高级技巧,提升智能体应用的准确性和可靠性。
- --
内容来源与验证
- 内容等级:PREMIUM_A
- 质量等级:S_CANDIDATE
- 难度:中级
- 验证等级:V1
- 原文作者:billchen-openai, prashantmital-openai
- 原文日期:2025-05-26
- 来源许可:MIT
- 来源版本:
8728e8d902225666101ce0c44046663212b09857 - 查看原文
站内还有更多完整实战教程
加入会员,解锁全部教程、完整代码与持续更新内容。
加入会员