端午节前OpenAI发布了o3/o4-mini模型的Function Calling指南,这份指南可以说是目前网上最硬核权威的大模型函数调用实战手册,没有之一。
如果您有Agent,又刚好接的是OpenAI接口的大模型,那这篇文章对您来说绝对值得好好研究一下。即便不是,其中的核心思路和最佳实践对其他支持Function Calling的推理模型(如DeepSeek R1)同样适用。
在o系列模型中,OpenAI引入了"开发者消息"这个概念,用来明确告诉推理模型指令来自开发者。实际上,你提供的任何系统消息都会在内部自动转换为开发者消息,所以在实际使用中可以把开发者提示当作传统的系统提示来理解。这个看似微小的变化实际上为模型提供了更清晰的指令层次结构,让AI能够更好地区分不同来源的信息。
其他模型的对应关系: 需要注意的是,并非所有模型都有"开发者消息"概念。比如DeepSeek R1等模型仍然使用传统的system message来承担相同功能。如果你用的是其他模型,只需要将本文提到的"开发者提示"内容放在system message中即可,效果是一样的。
角色提示在Function Calling中变得更加重要,因为它不仅定义了AI的行为基调,还明确了可执行的操作范围。OpenAI在指南中提供了一个标准的角色设定示例,这个示例值得每个开发者学习和借鉴。一个好的角色设定就像给AI戴上了专业的"工作帽",让它在特定领域内发挥最大效能。
官方角色设定示例:
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虽然很聪明,但在工具调用顺序上仍可能犯错,就像一个新手程序员可能在目录不存在时就尝试创建文件。OpenAI提供了从简单到复杂的两种解决方案,让开发者可以根据实际需求选择合适的指导方式。
简单场景的顺序指导:
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`
这种详细的步骤序列特别适合复杂的业务流程,每一步都明确指定了要使用的工具,让AI像有经验的员工一样严格按流程办事。
明确定义何时使用工具和何时不使用工具,这是避免AI"过度热情"或"消极怠工"的关键。OpenAI提供了一个完整的边界设定示例,这个示例展示了如何全面地定义工具使用规则。
完整的工具使用边界示例:
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.
这个示例的价值在于它不仅定义了使用和不使用工具的具体场景,还强调了主动性和持续性——要求AI在遇到失败时不要放弃,而是尝试替代方案,这种"不达目的不罢休"的设定让AI更像一个负责任的助手。
o3/o4-mini作为推理模型,内部已经具备了完整的思维链能力,不需要开发者额外诱导推理过程。实际上,要求推理模型进行额外的计划和推理可能会适得其反,就像让一个已经很会思考的人再去学习"如何思考"一样多余。模型会在调用工具前自动输出推理令牌,这个过程是自然发生的,不需要人为干预。
适用于其他推理模型: 这个原则同样适用于其他推理模型,比如DeepSeek R1会自动输出reasoning_content(思维链内容),Claude的思维模式等。所有这些推理模型都不需要你在提示中额外添加"请仔细思考"、"一步步分析"这类CoT提示。
需要注意的是,模型的推理过程不一定总是伴随推理摘要,因为推理摘要需要达到一定数量的实质性推理令牌才会生成。这意味着对于简单的工具调用,你可能看不到详细的推理过程,但这并不表示模型没有思考。理解这一点有助于开发者正确解读模型的输出,不要因为没有看到推理摘要就认为模型没有进行充分的思考。
函数描述承担着双重使命:告诉模型何时调用这个函数,以及如何构造调用参数。OpenAI在指南中提供了一个标准的函数定义示例,展示了函数描述的基本结构和要素。一个好的函数描述应该像一份精确的合同,明确规定了推理模型和工具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
}]
这个示例展示了函数定义的标准格式,其中description字段"Get current temperature for provided coordinates in celsius."就是我们要重点关注的函数描述部分。
在函数描述中嵌入使用标准是一个高级技巧,OpenAI提供了一个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.
这个示例的精妙之处在于它不仅说明了函数的基本功能,还详细规定了使用条件、限制和替代方案,就像给每个工具配备了一个小助手来判断使用时机。
虽然推理模型对少样本提示的依赖不如传统模型那么强,但在函数参数构造方面,例子仍然很有价值。OpenAI提供了一个正则表达式工具的完整示例,展示了如何通过对照表来指导参数构造。
正则表达式工具的少样本提示示例:
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
这种直观的对照表让模型一眼就能理解参数转换规则,避免了反复试错的过程,特别适合处理复杂的格式转换需求。
OpenAI特别强调了关键规则前置的重要性,并提供了一个反面教材来说明问题。在函数描述中,最重要的规则应该放在最前面,让模型第一时间看到关键信息。
错误的描述方式(冗长且关键信息后置):
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.
OpenAI的测试显示,将关键规则前置的提示比这种冗长描述的准确率高出6%,这个数字在生产环境中意味着显著的性能差异。
o3模型在某些情况下可能出现函数调用幻觉,比如承诺在后台调用工具但实际没有执行,或者承诺在未来的对话轮次中调用某个工具。这就像一个员工说"我会处理这件事"但实际上什么都没做,或者说"我稍后会联系客户"但从来没有行动。这种幻觉虽然看起来无害,但会严重影响用户体验和系统可靠性。
解决幻觉问题的第一个方法是在提示中明确禁止这种行为,OpenAI提供了具体的指令模板。这种直白的指令就像给AI立下了"说到做到"的规矩,让它明白承诺和执行必须同步进行。
防范幻觉的明确指令:
Do NOT promise to call a function later. If a function call is required, emit it now; otherwise respond normally.
参数验证指令:
Validate arguments against the format before sending the call; if you are unsure, ask for clarification instead of guessing.
这些指令简洁明了,直接告诉AI什么不能做,什么应该做,避免了模糊的表述可能带来的误解。
将函数定义中的strict参数设置为true是防范幻觉的技术手段,这确保函数调用严格遵循定义的模式。对于有复杂格式要求的参数(如有效的Python代码),OpenAI建议添加额外的验证指令。这种双重保险机制让AI在调用函数前必须通过格式检查,就像代码审查一样确保质量。
Responses API的核心优势在于能够在单次对话的多个工具调用之间保持推理项目(reasoning items)的持续性。这就像让AI在处理复杂任务时能够"记住"之前的思考过程,而不是每次都从零开始。o3/o4-mini模型正是基于这种持续性推理进行训练的,所以在推理过程中保持这些推理项目能够显著提升模型在工具调用决策方面的智能水平和性能表现。
如果你不希望OpenAI处理状态管理,可以使用encrypted_content参数来自行管理推理状态。这种方式让你在享受推理持续性好处的同时,保持对数据的完全控制。实现方法很简单:在API调用中包含include=["reasoning.encrypted_content"],然后将返回的加密推理内容添加到下一次请求的上下文中,这样就能在不泄露推理细节的情况下保持推理的连续性。
OpenAI提供了一个完整的代码示例,展示了如何使用Responses API来保持推理状态的连续性。这个示例包含了从工具定义到状态管理的完整流程,是实际开发中的重要参考。
完整的Responses API使用示例:
from openai import OpenAI
import requests
import json
client = OpenAI()
defget_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.
这个示例展示了推理状态的完整传递过程,让模型能够基于之前的思考过程做出更智能的决策,最终实现更准确和连贯的工具调用体验。
当你同时使用托管工具和自定义工具时,明确定义每个工具的使用边界变得至关重要。OpenAI提供了一个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模型通常能够独立解决任务,但工具往往能提供更可靠的答案。OpenAI提供了一个code_interpreter优先使用的示例,展示了如何引导模型优先使用工具而不是依赖内部知识。
优先使用工具的指导示例:
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.
这种指导让AI明白什么时候应该"借助外力"而不是"单打独斗",确保结果的准确性和可靠性。
对于可能重叠的工具功能,OpenAI提供了一个详细的决策边界和回退机制示例,展示了如何处理工具功能重叠的情况。
决策边界和回退机制示例:
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(Model Context Protocol)时,利用allowed_tools参数过滤工具是一个重要的优化策略。OpenAI提供了一个Git MCP服务器的配置示例,展示了如何只选择必要的工具。
MCP工具过滤配置示例:
"tools": [
{
"type": "mcp",
"server_label": "gitmcp",
"server_url": "https://gitmcp.io/openai/tiktoken",
"allowed_tools": ["search_tiktoken_documentation", "fetch_tiktoken_documentation"],
"require_approval": "never"
}
]
这个示例展示了如何从Git MCP服务器中只选择"search_tiktoken_documentation"和"fetch_tiktoken_documentation"这两个工具,而忽略其他不相关的功能,既节省了上下文又提高了效率。
为了减少延迟,确保传递mcp_list_tools或包含previous_response_id,这样API就不需要重复导入工具列表。这种缓存机制特别适合高频使用的场景,能够显著提升响应速度。同时,建议将推理模型保留给高复杂度任务,对于简单的工具调用可以考虑使用更轻量级的解决方案,这样既保证了性能又控制了成本。
虽然o3和o4-mini模型没有硬性的工具数量上限,但实际指导建议是:少于100个工具且每个工具少于20个参数的配置被认为是在训练分布范围内,应该能够在预期的可靠性范围内表现。即使在技术上符合训练分布,更多的工具也可能引入歧义或混淆,特别是当多个工具有重叠用途或模糊描述时,模型可能会调用错误的工具或犹豫不决。
关于参数结构是否应该深度嵌套还是扁平化,OpenAI建议在有疑问时倾向于扁平化设计。扁平结构通常更容易让模型推理:在扁平模式中,参数字段是顶级的且立即可见,这减少了内部解析和结构化的需要,有助于防止部分填充嵌套对象或无效字段组合等问题。对于自然涉及结构化输入的领域(如配置负载、丰富搜索过滤器或表单提交),嵌套有助于组织相关参数,但必须使用清晰的字段描述、anyOf逻辑或严格模式来防范无效参数组合。
这份指南的建议假设你使用标准的tools模型参数来传递函数模式,正如OpenAI函数调用通用指南中所示。如果你通过自然语言在开发者编写的提示中提供自定义工具定义(比如在开发者消息或用户消息中内联定义工具),这份指南可能不完全适用。在这种情况下,模型不依赖其内部工具模式先验知识,你可能需要更明确的少样本示例、输出格式和工具选择标准,参数构造可靠性也可能在没有模式级锚定的情况下降低。
这些最佳实践并不局限于OpenAI的模型。无论你使用的是DeepSeek R1、qwen3、Claude,还是其他支持Function Calling的推理模型,这里面的核心思路——如何设计清晰的函数描述、如何设定合理的工具边界、如何防范调用幻觉等——都是相通的。毕竟,好的设计理念和工程实践是跨平台的。
Reference:https://cookbook.openai.com/examples/o-series/o3o4-mini_prompting_guide
文章来自于“AI修猫Prompt”,作者“AI修猫Prompt”。
【开源免费】AutoGPT是一个允许用户创建和运行智能体的(AI Agents)项目。用户创建的智能体能够自动执行各种任务,从而让AI有步骤的去解决实际问题。
项目地址:https://github.com/Significant-Gravitas/AutoGPT
【开源免费】MetaGPT是一个“软件开发公司”的智能体项目,只需要输入一句话的老板需求,MetaGPT即可输出用户故事 / 竞品分析 / 需求 / 数据结构 / APIs / 文件等软件开发的相关内容。MetaGPT内置了各种AI角色,包括产品经理 / 架构师 / 项目经理 / 工程师,MetaGPT提供了一个精心调配的软件公司研发全过程的SOP。
项目地址:https://github.com/geekan/MetaGPT/blob/main/docs/README_CN.md
【开源免费】LangGPT 是一个通过结构化和模板化的方法,编写高质量的AI提示词的开源项目。它可以让任何非专业的用户轻松创建高水平的提示词,进而高质量的帮助用户通过AI解决问题。
项目地址:https://github.com/langgptai/LangGPT/blob/main/README_zh.md
在线使用:https://kimi.moonshot.cn/kimiplus/conpg00t7lagbbsfqkq0