o3/o4-mini 函数调用指南
简介
o3/o4-mini 模型是我们 o 系列模型中最新的模型,它们经过训练,能够在响应前进行更长时间的思考。它们是我们迄今为止最智能的模型,代表了与 o1/o3-mini 在工具调用能力方面的重要进步。这些模型经过训练,能够在思维链(CoT)中原生使用工具,从而提高了围绕何时以及如何使用工具的推理能力。我们发布了一个关于如何通过响应 API 调用函数的指南,本指南在此基础上进行扩展,并告诉您如何通过这些模型获得最佳的函数调用性能。
更好的函数调用性能的提示指南
为了充分利用 o3/o4-mini 模型背后的函数调用智能,我们建议在开发者提示和函数描述方面都遵循一些最佳实践。
关于开发者提示、系统提示和推理模型函数描述的快速说明
我们引入了开发者消息,以便向推理模型明确指示指令来自开发者。在 o 系列模型中,开发者提供的任何系统消息都会在内部自动转换为开发者消息。出于实际目的,您可以将开发者提示视为与传统系统提示类似,但为了清晰和正确起见,本指南将所有此类指令称为开发者提示/消息。
当我们在本文档中提到函数描述时,我们指的是 API 请求的工具参数中每个函数对象描述字段中的解释性文本。此描述告诉模型何时以及如何使用该函数。以下是我们函数调用文档中的一个示例:
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 之间持久的接口契约。
总的来说,函数描述定义了它的作用以及如何调用它。开发者指令为使用工具的代理提供了指导。因此,如果存在多个可以用于类似目的的工具,开发者可以在指令中区分它们。如果代理工作流要求以特定顺序使用工具,或者频繁或谨慎地使用某些工具,这些也应包含在开发者指令中。
结构良好的描述可以通过早期固定关键标准和参数要求来提高准确性并减少误触发。它还允许开发人员在开发者提示之外,更靠近工具定义本身来编码“主动性”控制启发式方法。
- 使用标准:就像您可以通过开发者提示来优化函数调用主动性一样,您可以在函数描述级别进一步优化函数的调用方式。以下是文件创建函数的示例:
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 偶尔会出现延迟行为,例如声称没有足够的时间来完成任务、承诺单独跟进或在明确要求提供更多详细信息时给出简短的答案。我们发现以下步骤有助于改善这种行为:
a. 为不相关的主题开始新的对话: 在切换到新的或不相关的主题时,请开始一个新的对话线程,而不是在同一上下文中继续。这有助于模型专注于当前主题,并防止其受到先前无关上下文的影响,有时会导致响应不完整或懒惰。例如,如果您之前在讨论代码调试,现在想询问有关文档最佳实践的问题,而这不需要先前的对话上下文,请开始新的对话以确保清晰度和重点。
b. 当列表过长时,丢弃不相关的过去工具调用/输出,并将其作为上下文总结在用户消息中: 如果对话历史包含一长串不再相关的先前工具调用或输出,请将其从上下文中删除。而是将关键信息的简洁摘要作为用户消息的一部分提供。这可以使上下文易于管理,并确保模型仅访问最相关的信息。例如,如果您有一系列冗长的工具输出,您可以总结关键结果,并将该摘要包含在您的下一条消息中。
c. 我们正在不断改进我们的模型,并期望在未来版本中解决此问题。
避免思维链提示
由于这些模型是推理模型并产生内部思维链,因此它们不必被明确提示在工具调用之间进行计划和推理。因此,开发人员不应通过要求模型进行更广泛的计划来尝试在每次函数调用前诱导额外的推理。要求推理模型进行更多推理实际上可能会损害性能。
关于推理摘要的快速说明:模型将在调用工具之前输出推理令牌。但是,这些并不总是伴随摘要,因为我们的推理摘要需要最少数量的实际推理令牌才能生成摘要。
响应 API
更好的性能的推理项
我们发布了一个食谱,其中详细介绍了使用响应 API 的好处。在此指南中重申一些要点也值得的。o3/o4-mini 都在其内部推理的训练中进行了训练,该推理在单个轮次内的工具调用之间进行了持久化。因此,在推理期间在工具调用之间持久化这些推理项将导致更高的智能和性能,从而在何时以及如何调用工具方面做出更好的决策。响应允许您持久化这些推理项(由我们或您自己通过加密内容维护,如果您不希望我们处理状态管理),而聊天补全则不能。切换到响应 API 并允许模型访问推理项以在函数调用之间进行交互是在函数调用中榨取尽可能多性能的最简单方法。以下是食谱中的示例,为方便起见转载,展示了如何使用 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)
The current temperature in Paris is about 18.8 °C.
Agentic Experience with Hosted tools.
响应 API 支持一组托管/内置工具。我们最近还在响应 API 中添加了新工具和功能,这使得构建连接到外部服务的代理应用程序更加容易;借助响应 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 模型经过训练,可以原生理解和使用这些模式来进行工具选择和参数构建。
如果您而是通过开发者编写的提示中的自然语言提供自定义工具定义(例如,在开发者消息或用户消息中内联定义工具),则此指南可能不完全适用。在这些情况下: 模型不依赖于其内部工具模式先验。 您可能需要通过少样本示例、输出格式和工具选择标准来更加明确。 没有模式级别的锚定,参数构建的可靠性可能会下降。
尽可能使用结构化工具参数。如果您必须在自由文本中定义工具,请将其视为自定义协议并进行相应测试。