函数调用为 OpenAI 模型提供了一种强大而灵活的方式与您的代码或外部服务进行交互。本指南将解释如何将模型连接到您自己的自定义代码以获取数据或采取行动。
获取天气发送邮件搜索知识库
使用 get_weather 函数的函数调用示例
Python
code-sample-pre
<span style="color:var(--text-default)"><code class="language-python"><code><span style="color:var(--text-disabled)">1
</span><span style="color:var(--text-disabled)">2
</span><span style="color:var(--text-disabled)">3
</span><span style="color:var(--text-disabled)">4
</span><span style="color:var(--text-disabled)">5
</span><span style="color:var(--text-disabled)">6
</span><span style="color:var(--text-disabled)">7
</span><span style="color:var(--text-disabled)">8
</span><span style="color:var(--text-disabled)">9
</span><span style="color:var(--text-disabled)">10
</span><span style="color:var(--text-disabled)">11
</span><span style="color:var(--text-disabled)">12
</span><span style="color:var(--text-disabled)">13
</span><span style="color:var(--text-disabled)">14
</span><span style="color:var(--text-disabled)">15
</span><span style="color:var(--text-disabled)">16
</span><span style="color:var(--text-disabled)">17
</span><span style="color:var(--text-disabled)">18
</span><span style="color:var(--text-disabled)">19
</span><span style="color:var(--text-disabled)">20
</span><span style="color:var(--text-disabled)">21
</span><span style="color:var(--text-disabled)">22
</span><span style="color:var(--text-disabled)">23
</span><span style="color:var(--text-disabled)">24
</span><span style="color:var(--text-disabled)">25
</span><span style="color:var(--text-disabled)">26
</span><span style="color:var(--text-disabled)">27
</span><span style="color:var(--text-disabled)">28
</span><span style="color:var(--text-disabled)">29
</span><span style="color:var(--text-disabled)">30
</span></code><span style="color:var(--syntax2)">from</span> openai <span style="color:var(--syntax2)">import</span> OpenAI
client = OpenAI()
tools = [{
<span style="color:var(--syntax3)">"type"</span>: <span style="color:var(--syntax3)">"function"</span>,
<span style="color:var(--syntax3)">"name"</span>: <span style="color:var(--syntax3)">"get_weather"</span>,
<span style="color:var(--syntax3)">"description"</span>: <span style="color:var(--syntax3)">"Get current temperature for a given location."</span>,
<span style="color:var(--syntax3)">"parameters"</span>: {
<span style="color:var(--syntax3)">"type"</span>: <span style="color:var(--syntax3)">"object"</span>,
<span style="color:var(--syntax3)">"properties"</span>: {
<span style="color:var(--syntax3)">"location"</span>: {
<span style="color:var(--syntax3)">"type"</span>: <span style="color:var(--syntax3)">"string"</span>,
<span style="color:var(--syntax3)">"description"</span>: <span style="color:var(--syntax3)">"City and country e.g. Bogotá, Colombia"</span>
}
},
<span style="color:var(--syntax3)">"required"</span>: [
<span style="color:var(--syntax3)">"location"</span>
],
<span style="color:var(--syntax3)">"additionalProperties"</span>: <span style="color:var(--syntax2)">False</span>
}
}]
response = client.responses.create(
model=<span style="color:var(--syntax3)">"gpt-4o"</span>,
<span style="color:var(--syntax1)">input</span>=[{<span style="color:var(--syntax3)">"role"</span>: <span style="color:var(--syntax3)">"user"</span>, <span style="color:var(--syntax3)">"content"</span>: <span style="color:var(--syntax3)">"What is the weather like in Paris today?"</span>}],
tools=tools
)
<span style="color:var(--syntax1)">print</span>(response.output)</code></span>
输出
code-sample-pre
<span style="color:var(--text-default)"><code class="language-json"><code><span style="color:var(--text-disabled)">1
</span><span style="color:var(--text-disabled)">2
</span><span style="color:var(--text-disabled)">3
</span><span style="color:var(--text-disabled)">4
</span><span style="color:var(--text-disabled)">5
</span><span style="color:var(--text-disabled)">6
</span><span style="color:var(--text-disabled)">7
</span></code>[{
<span style="color:var(--syntax4)">"type"</span>: <span style="color:var(--syntax3)">"function_call"</span>,
<span style="color:var(--syntax4)">"id"</span>: <span style="color:var(--syntax3)">"fc_12345xyz"</span>,
<span style="color:var(--syntax4)">"call_id"</span>: <span style="color:var(--syntax3)">"call_12345xyz"</span>,
<span style="color:var(--syntax4)">"name"</span>: <span style="color:var(--syntax3)">"get_weather"</span>,
<span style="color:var(--syntax4)">"arguments"</span>: <span style="color:var(--syntax3)">"{\"location\":\"Paris, France\"}"</span>
}]</code></span>
在Playground中试验函数调用并生成函数模式!
概述
您可以通过函数调用 让模型访问您自己的自定义代码。根据系统提示和消息,模型可能会决定调用这些函数 ---而不是(或除了)生成文本或音频。
然后,您将执行函数代码,发回结果,模型会将它们合并到最终响应中。

函数调用有两个主要用例:
获取数据 | 检索最新信息以纳入模型响应 (RAG)。可用于搜索知识库和从 API 检索特定数据(例如当前天气数据)。 |
采取行动 | 执行诸如提交表单、调用 API、修改应用程序状态(UI/前端或后端)或采取代理工作流操作(如交接对话)等操作。 |
示例函数
让我们看看让模型使用get_weather
下面定义的真实函数的步骤:
在您的代码库中实现的示例 get_weather 函数
Python
code-sample-pre
<span style="color:var(--text-default)"><code class="language-python"><code><span style="color:var(--text-disabled)">1
</span><span style="color:var(--text-disabled)">2
</span><span style="color:var(--text-disabled)">3
</span><span style="color:var(--text-disabled)">4
</span><span style="color:var(--text-disabled)">5
</span><span style="color:var(--text-disabled)">6
</span></code><span style="color:var(--syntax2)">import</span> requests
<span style="color:var(--syntax2)">def</span> <span style="color:var(--syntax5)">get_weather</span>(latitude, longitude):
response = requests.get(<span style="color:var(--syntax3)">f"https://api.open-meteo.com/v1/forecast?latitude=</span><span style="color:var(--syntax3)">{latitude}</span><span style="color:var(--syntax3)">&longitude=</span><span style="color:var(--syntax3)">{longitude}</span><span style="color:var(--syntax3)">¤t=temperature_2m,wind_speed_10m&hourly=temperature_2m,relative_humidity_2m,wind_speed_10m"</span>)
data = response.json()
<span style="color:var(--syntax2)">return</span> data[<span style="color:var(--syntax3)">'current'</span>][<span style="color:var(--syntax3)">'temperature_2m'</span>]</code></span>
与之前的图表不同,此函数需要精确的参数latitude
,而longitude
不是一般的location
参数。(但是,我们的模型可以自动确定许多位置的坐标!)
函数调用步骤
- 具有定义功能的 调用模型-- 以及您的系统和用户消息。
步骤 1:使用定义的 get_weather 工具调用模型
Python
code-sample-pre
<span style="color:var(--text-default)"><code class="language-python"><code><span style="color:var(--text-disabled)">1
</span><span style="color:var(--text-disabled)">2
</span><span style="color:var(--text-disabled)">3
</span><span style="color:var(--text-disabled)">4
</span><span style="color:var(--text-disabled)">5
</span><span style="color:var(--text-disabled)">6
</span><span style="color:var(--text-disabled)">7
</span><span style="color:var(--text-disabled)">8
</span><span style="color:var(--text-disabled)">9
</span><span style="color:var(--text-disabled)">10
</span><span style="color:var(--text-disabled)">11
</span><span style="color:var(--text-disabled)">12
</span><span style="color:var(--text-disabled)">13
</span><span style="color:var(--text-disabled)">14
</span><span style="color:var(--text-disabled)">15
</span><span style="color:var(--text-disabled)">16
</span><span style="color:var(--text-disabled)">17
</span><span style="color:var(--text-disabled)">18
</span><span style="color:var(--text-disabled)">19
</span><span style="color:var(--text-disabled)">20
</span><span style="color:var(--text-disabled)">21
</span><span style="color:var(--text-disabled)">22
</span><span style="color:var(--text-disabled)">23
</span><span style="color:var(--text-disabled)">24
</span><span style="color:var(--text-disabled)">25
</span><span style="color:var(--text-disabled)">26
</span><span style="color:var(--text-disabled)">27
</span><span style="color:var(--text-disabled)">28
</span></code><span style="color:var(--syntax2)">from</span> openai <span style="color:var(--syntax2)">import</span> OpenAI
<span style="color:var(--syntax2)">import</span> json
client = OpenAI()
tools = [{
<span style="color:var(--syntax3)">"type"</span>: <span style="color:var(--syntax3)">"function"</span>,
<span style="color:var(--syntax3)">"name"</span>: <span style="color:var(--syntax3)">"get_weather"</span>,
<span style="color:var(--syntax3)">"description"</span>: <span style="color:var(--syntax3)">"Get current temperature for provided coordinates in celsius."</span>,
<span style="color:var(--syntax3)">"parameters"</span>: {
<span style="color:var(--syntax3)">"type"</span>: <span style="color:var(--syntax3)">"object"</span>,
<span style="color:var(--syntax3)">"properties"</span>: {
<span style="color:var(--syntax3)">"latitude"</span>: {<span style="color:var(--syntax3)">"type"</span>: <span style="color:var(--syntax3)">"number"</span>},
<span style="color:var(--syntax3)">"longitude"</span>: {<span style="color:var(--syntax3)">"type"</span>: <span style="color:var(--syntax3)">"number"</span>}
},
<span style="color:var(--syntax3)">"required"</span>: [<span style="color:var(--syntax3)">"latitude"</span>, <span style="color:var(--syntax3)">"longitude"</span>],
<span style="color:var(--syntax3)">"additionalProperties"</span>: <span style="color:var(--syntax2)">False</span>
},
<span style="color:var(--syntax3)">"strict"</span>: <span style="color:var(--syntax2)">True</span>
}]
input_messages = [{<span style="color:var(--syntax3)">"role"</span>: <span style="color:var(--syntax3)">"user"</span>, <span style="color:var(--syntax3)">"content"</span>: <span style="color:var(--syntax3)">"What's the weather like in Paris today?"</span>}]
response = client.responses.create(
model=<span style="color:var(--syntax3)">"gpt-4o"</span>,
<span style="color:var(--syntax1)">input</span>=input_messages,
tools=tools,
)</code></span>
- 模型决定调用函数 ------模型返回名称 和输入参数。
响应.输出
code-sample-pre
<span style="color:var(--text-default)"><code class="language-json"><code><span style="color:var(--text-disabled)">1
</span><span style="color:var(--text-disabled)">2
</span><span style="color:var(--text-disabled)">3
</span><span style="color:var(--text-disabled)">4
</span><span style="color:var(--text-disabled)">5
</span><span style="color:var(--text-disabled)">6
</span><span style="color:var(--text-disabled)">7
</span></code>[{
<span style="color:var(--syntax4)">"type"</span>: <span style="color:var(--syntax3)">"function_call"</span>,
<span style="color:var(--syntax4)">"id"</span>: <span style="color:var(--syntax3)">"fc_12345xyz"</span>,
<span style="color:var(--syntax4)">"call_id"</span>: <span style="color:var(--syntax3)">"call_12345xyz"</span>,
<span style="color:var(--syntax4)">"name"</span>: <span style="color:var(--syntax3)">"get_weather"</span>,
<span style="color:var(--syntax4)">"arguments"</span>: <span style="color:var(--syntax3)">"{\"latitude\":48.8566,\"longitude\":2.3522}"</span>
}]</code></span>
- 执行函数代码 ------解析模型的响应并处理函数调用。
步骤3:执行get_weather函数
Python
code-sample-pre
<span style="color:var(--text-default)"><code class="language-python"><code><span style="color:var(--text-disabled)">1
</span><span style="color:var(--text-disabled)">2
</span><span style="color:var(--text-disabled)">3
</span><span style="color:var(--text-disabled)">4
</span></code>tool_call = response.output[<span style="color:var(--syntax4)">0</span>]
args = json.loads(tool_call.arguments)
result = get_weather(args[<span style="color:var(--syntax3)">"latitude"</span>], args[<span style="color:var(--syntax3)">"longitude"</span>])</code></span>
- 提供结果模型------以便可以将其纳入最终响应中。
步骤 4:提供结果并再次调用模型
Python
code-sample-pre
<span style="color:var(--text-default)"><code class="language-python"><code><span style="color:var(--text-disabled)">1
</span><span style="color:var(--text-disabled)">2
</span><span style="color:var(--text-disabled)">3
</span><span style="color:var(--text-disabled)">4
</span><span style="color:var(--text-disabled)">5
</span><span style="color:var(--text-disabled)">6
</span><span style="color:var(--text-disabled)">7
</span><span style="color:var(--text-disabled)">8
</span><span style="color:var(--text-disabled)">9
</span><span style="color:var(--text-disabled)">10
</span><span style="color:var(--text-disabled)">11
</span><span style="color:var(--text-disabled)">12
</span><span style="color:var(--text-disabled)">13
</span></code>input_messages.append(tool_call) <span style="color:rgba(var(--sh-fg),.5)"># append model's function call message</span>
input_messages.append({ <span style="color:rgba(var(--sh-fg),.5)"># append result message</span>
<span style="color:var(--syntax3)">"type"</span>: <span style="color:var(--syntax3)">"function_call_output"</span>,
<span style="color:var(--syntax3)">"call_id"</span>: tool_call.call_id,
<span style="color:var(--syntax3)">"output"</span>: <span style="color:var(--syntax1)">str</span>(result)
})
response_2 = client.responses.create(
model=<span style="color:var(--syntax3)">"gpt-4o"</span>,
<span style="color:var(--syntax1)">input</span>=input_messages,
tools=tools,
)
<span style="color:var(--syntax1)">print</span>(response_2.output_text)</code></span>
- 模型响应------将结果纳入其输出中。
响应2.输出文本
code-sample-pre
<span style="color:var(--text-default)"><code class="language-json"><span style="color:var(--syntax3)">"The current temperature in Paris is 14°C (57.2°F)."</span></code></span>
定义函数
tools
可以在每个API请求的参数中设置功能。
函数由其架构定义,架构告知模型其功能以及其所需的输入参数。它包含以下字段:
场地 | 描述 |
---|---|
type |
这应该始终function |
name |
函数的名称(例如get_weather ) |
description |
有关何时以及如何使用该功能的详细信息 |
parameters |
定义函数输入参数的JSON 模式 |
strict |
是否对函数调用强制执行严格模式 |
请查看此示例或在下面(或在我们的游乐场)生成您自己的示例。
产生
示例函数架构
code-sample-pre
<span style="color:var(--text-default)"><code class="language-json"><code><span style="color:var(--text-disabled)">1
</span><span style="color:var(--text-disabled)">2
</span><span style="color:var(--text-disabled)">3
</span><span style="color:var(--text-disabled)">4
</span><span style="color:var(--text-disabled)">5
</span><span style="color:var(--text-disabled)">6
</span><span style="color:var(--text-disabled)">7
</span><span style="color:var(--text-disabled)">8
</span><span style="color:var(--text-disabled)">9
</span><span style="color:var(--text-disabled)">10
</span><span style="color:var(--text-disabled)">11
</span><span style="color:var(--text-disabled)">12
</span><span style="color:var(--text-disabled)">13
</span><span style="color:var(--text-disabled)">14
</span><span style="color:var(--text-disabled)">15
</span><span style="color:var(--text-disabled)">16
</span><span style="color:var(--text-disabled)">17
</span><span style="color:var(--text-disabled)">18
</span><span style="color:var(--text-disabled)">19
</span><span style="color:var(--text-disabled)">20
</span><span style="color:var(--text-disabled)">21
</span><span style="color:var(--text-disabled)">22
</span><span style="color:var(--text-disabled)">23
</span><span style="color:var(--text-disabled)">24
</span><span style="color:var(--text-disabled)">25
</span><span style="color:var(--text-disabled)">26
</span><span style="color:var(--text-disabled)">27
</span><span style="color:var(--text-disabled)">28
</span><span style="color:var(--text-disabled)">29
</span><span style="color:var(--text-disabled)">30
</span></code>{
<span style="color:var(--syntax4)">"type"</span>: <span style="color:var(--syntax3)">"function"</span>,
<span style="color:var(--syntax4)">"function"</span>: {
<span style="color:var(--syntax4)">"name"</span>: <span style="color:var(--syntax3)">"get_weather"</span>,
<span style="color:var(--syntax4)">"description"</span>: <span style="color:var(--syntax3)">"Retrieves current weather for the given location."</span>,
<span style="color:var(--syntax4)">"parameters"</span>: {
<span style="color:var(--syntax4)">"type"</span>: <span style="color:var(--syntax3)">"object"</span>,
<span style="color:var(--syntax4)">"properties"</span>: {
<span style="color:var(--syntax4)">"location"</span>: {
<span style="color:var(--syntax4)">"type"</span>: <span style="color:var(--syntax3)">"string"</span>,
<span style="color:var(--syntax4)">"description"</span>: <span style="color:var(--syntax3)">"City and country e.g. Bogotá, Colombia"</span>
},
<span style="color:var(--syntax4)">"units"</span>: {
<span style="color:var(--syntax4)">"type"</span>: <span style="color:var(--syntax3)">"string"</span>,
<span style="color:var(--syntax4)">"enum"</span>: [
<span style="color:var(--syntax3)">"celsius"</span>,
<span style="color:var(--syntax3)">"fahrenheit"</span>
],
<span style="color:var(--syntax4)">"description"</span>: <span style="color:var(--syntax3)">"Units the temperature will be returned in."</span>
}
},
<span style="color:var(--syntax4)">"required"</span>: [
<span style="color:var(--syntax3)">"location"</span>,
<span style="color:var(--syntax3)">"units"</span>
],
<span style="color:var(--syntax4)">"additionalProperties"</span>: <span style="color:var(--syntax2)">false</span>
},
<span style="color:var(--syntax4)">"strict"</span>: <span style="color:var(--syntax2)">true</span>
}
}</code></span>
因为它们parameters
是由JSON 模式定义的,所以您可以利用它的许多丰富的功能,如属性类型、枚举、描述、嵌套对象和递归对象。
定义函数的最佳实践
-
写出清晰详细的函数名称、参数描述和说明。
- 明确描述函数和每个参数的目的(及其格式)以及输出代表什么。
- 使用系统提示来描述何时(以及何时不使用)使用每个功能。 通常,告诉模型确切要做什么。
- 包括示例和边缘情况 ,特别是为了纠正任何重复出现的故障。(注意: 添加示例可能会损害推理模型的性能。)
-
应用软件工程最佳实践。
- 使功能明显且直观 。(最小惊喜原则)
- 使用枚举 和对象结构使无效状态无法表示。(例如
toggle_light(on: bool, off: bool)
允许无效调用) - **通过实习生测试。**实习生/人类是否可以在只给出你给模型的内容的情况下正确使用该功能?(如果不能,他们会问你什么问题?将答案添加到提示中。)
-
减轻模型的负担并尽可能使用代码。
- 不要让模型填充您已知的参数。 例如,如果您已经有
order_id
基于上一个菜单的模型,则不要使用order_id
参数 - 相反,不要使用参数submit_refund()
并传递order_id
代码。 - 合并始终按顺序调用的函数。 例如,如果您始终
mark_location()
在之后调用query_location()
,则只需将标记逻辑移到查询函数调用中。
- 不要让模型填充您已知的参数。 例如,如果您已经有
-
保持函数数量较少以获得更高的准确性。
- 使用不同数量的函数来评估您的表现。
- 尽管这只是一个软建议,但目标是每次执行少于 20 个函数。
-
利用 OpenAI 资源。
- 在Playground中生成并迭代功能模式。
- 考虑进行微调 以提高大量函数或困难任务的函数调用准确性。( 食谱)
代币使用
在底层,函数以模型训练所用的语法注入到系统消息中。这意味着函数会计入模型的上下文限制,并被视为输入标记。如果您遇到标记限制,我们建议限制函数数量或您为函数参数提供的描述的长度。
如果您的工具规范中定义了许多功能,那么也可以使用微调来减少使用的标记数量。
处理函数调用
当模型调用函数时,您必须执行该函数并返回结果。由于模型响应可能包含零个、一个或多个调用,因此最佳做法是假设存在多个调用。
响应数组包含一个值为 的output
条目。每个条目都有一个(稍后用于提交函数结果)、和 JSON 编码的。type``function_call``call_id``name``arguments
具有多个函数调用的示例响应
code-sample-pre
<span style="color:var(--text-default)"><code class="language-json"><code><span style="color:var(--text-disabled)">1
</span><span style="color:var(--text-disabled)">2
</span><span style="color:var(--text-disabled)">3
</span><span style="color:var(--text-disabled)">4
</span><span style="color:var(--text-disabled)">5
</span><span style="color:var(--text-disabled)">6
</span><span style="color:var(--text-disabled)">7
</span><span style="color:var(--text-disabled)">8
</span><span style="color:var(--text-disabled)">9
</span><span style="color:var(--text-disabled)">10
</span><span style="color:var(--text-disabled)">11
</span><span style="color:var(--text-disabled)">12
</span><span style="color:var(--text-disabled)">13
</span><span style="color:var(--text-disabled)">14
</span><span style="color:var(--text-disabled)">15
</span><span style="color:var(--text-disabled)">16
</span><span style="color:var(--text-disabled)">17
</span><span style="color:var(--text-disabled)">18
</span><span style="color:var(--text-disabled)">19
</span><span style="color:var(--text-disabled)">20
</span><span style="color:var(--text-disabled)">21
</span><span style="color:var(--text-disabled)">22
</span><span style="color:var(--text-disabled)">23
</span></code>[
{
<span style="color:var(--syntax4)">"id"</span>: <span style="color:var(--syntax3)">"fc_12345xyz"</span>,
<span style="color:var(--syntax4)">"call_id"</span>: <span style="color:var(--syntax3)">"call_12345xyz"</span>,
<span style="color:var(--syntax4)">"type"</span>: <span style="color:var(--syntax3)">"function_call"</span>,
<span style="color:var(--syntax4)">"name"</span>: <span style="color:var(--syntax3)">"get_weather"</span>,
<span style="color:var(--syntax4)">"arguments"</span>: <span style="color:var(--syntax3)">"{\"location\":\"Paris, France\"}"</span>
},
{
<span style="color:var(--syntax4)">"id"</span>: <span style="color:var(--syntax3)">"fc_67890abc"</span>,
<span style="color:var(--syntax4)">"call_id"</span>: <span style="color:var(--syntax3)">"call_67890abc"</span>,
<span style="color:var(--syntax4)">"type"</span>: <span style="color:var(--syntax3)">"function_call"</span>,
<span style="color:var(--syntax4)">"name"</span>: <span style="color:var(--syntax3)">"get_weather"</span>,
<span style="color:var(--syntax4)">"arguments"</span>: <span style="color:var(--syntax3)">"{\"location\":\"Bogotá, Colombia\"}"</span>
},
{
<span style="color:var(--syntax4)">"id"</span>: <span style="color:var(--syntax3)">"fc_99999def"</span>,
<span style="color:var(--syntax4)">"call_id"</span>: <span style="color:var(--syntax3)">"call_99999def"</span>,
<span style="color:var(--syntax4)">"type"</span>: <span style="color:var(--syntax3)">"function_call"</span>,
<span style="color:var(--syntax4)">"name"</span>: <span style="color:var(--syntax3)">"send_email"</span>,
<span style="color:var(--syntax4)">"arguments"</span>: <span style="color:var(--syntax3)">"{\"to\":\"[email protected]\",\"body\":\"Hi bob\"}"</span>
}
]</code></span>
执行函数调用并附加结果
Python
code-sample-pre
<span style="color:var(--text-default)"><code class="language-python"><code><span style="color:var(--text-disabled)">1
</span><span style="color:var(--text-disabled)">2
</span><span style="color:var(--text-disabled)">3
</span><span style="color:var(--text-disabled)">4
</span><span style="color:var(--text-disabled)">5
</span><span style="color:var(--text-disabled)">6
</span><span style="color:var(--text-disabled)">7
</span><span style="color:var(--text-disabled)">8
</span><span style="color:var(--text-disabled)">9
</span><span style="color:var(--text-disabled)">10
</span><span style="color:var(--text-disabled)">11
</span><span style="color:var(--text-disabled)">12
</span><span style="color:var(--text-disabled)">13
</span></code><span style="color:var(--syntax2)">for</span> tool_call <span style="color:var(--syntax2)">in</span> response.output:
<span style="color:var(--syntax2)">if</span> tool_call.<span style="color:var(--syntax1)">type</span> != <span style="color:var(--syntax3)">"function_call"</span>:
<span style="color:var(--syntax2)">continue</span>
name = tool_call.name
args = json.loads(tool_call.arguments)
result = call_function(name, args)
input_messages.append({
<span style="color:var(--syntax3)">"type"</span>: <span style="color:var(--syntax3)">"function_call_output"</span>,
<span style="color:var(--syntax3)">"call_id"</span>: tool_call.call_id,
<span style="color:var(--syntax3)">"output"</span>: <span style="color:var(--syntax1)">str</span>(result)
})</code></span>
在上面的例子中,我们假设call_function
要路由每个呼叫。以下是一种可能的实现:
执行函数调用并附加结果
Python
code-sample-pre
<span style="color:var(--text-default)"><code class="language-python"><code><span style="color:var(--text-disabled)">1
</span><span style="color:var(--text-disabled)">2
</span><span style="color:var(--text-disabled)">3
</span><span style="color:var(--text-disabled)">4
</span><span style="color:var(--text-disabled)">5
</span></code><span style="color:var(--syntax2)">def</span> <span style="color:var(--syntax5)">call_function</span>(name, args):
<span style="color:var(--syntax2)">if</span> name == <span style="color:var(--syntax3)">"get_weather"</span>:
<span style="color:var(--syntax2)">return</span> get_weather(**args)
<span style="color:var(--syntax2)">if</span> name == <span style="color:var(--syntax3)">"send_email"</span>:
<span style="color:var(--syntax2)">return</span> send_email(**args)</code></span>
格式化结果
结果必须是字符串,但格式由您决定(JSON、错误代码、纯文本等)。模型将根据需要解释该字符串。
如果您的函数没有返回值(例如send_email
),则只需返回一个字符串来指示成功或失败。(例如"success"
)
将结果纳入响应
将结果附加到您的之后input
,您可以将它们发送回模型以获得最终响应。
将结果发送回模型
Python
code-sample-pre
<span style="color:var(--text-default)"><code class="language-python"><code><span style="color:var(--text-disabled)">1
</span><span style="color:var(--text-disabled)">2
</span><span style="color:var(--text-disabled)">3
</span><span style="color:var(--text-disabled)">4
</span><span style="color:var(--text-disabled)">5
</span></code>response = client.responses.create(
model=<span style="color:var(--syntax3)">"gpt-4o"</span>,
<span style="color:var(--syntax1)">input</span>=input_messages,
tools=tools,
)</code></span>
最终回应
code-sample-pre
<span style="color:var(--text-default)"><code class="language-json"><span style="color:var(--syntax3)">"It's about 15°C in Paris, 18°C in Bogotá, and I've sent that email to Bob."</span></code></span>
其他配置
工具选择
默认情况下,模型将确定何时使用以及使用多少工具。您可以使用tool_choice
参数强制执行特定行为。
- 自动:( 默认*)* 调用零个、一个或多个函数。
tool_choice: "auto"
- 必需: 调用一个或多个函数。
tool_choice: "required"
- 强制函数: 只调用一个特定函数。
tool_choice: {"type": "function", "name": "get_weather"}

您还可以设置tool_choice
为"none"
模仿不传递任何函数的行为。
并行函数调用
模型可能会选择在一次调用中调用多个函数。您可以通过设置parallel_tool_calls
为 来防止这种情况false
,这可确保恰好调用零个或一个工具。
注意: 目前,如果模型一次调用多个函数,那么这些调用的严格模式将被禁用。
严格模式
设置strict
为true
将确保函数调用可靠地遵循函数架构,而不是尽力而为。我们建议始终启用严格模式。
在底层,严格模式通过利用我们的结构化输出功能来工作,因此引入了几个要求:
additionalProperties``false
必须为 中的每个对象设置为parameters
。- 中的所有字段都
properties
必须标记为required
。
您可以通过添加选项来表示可选字段null
(type
见下面的示例)。
已启用严格模式已禁用严格模式
code-sample-pre
<span style="color:var(--text-default)"><code class="language-json"><code><span style="color:var(--text-disabled)">1
</span><span style="color:var(--text-disabled)">2
</span><span style="color:var(--text-disabled)">3
</span><span style="color:var(--text-disabled)">4
</span><span style="color:var(--text-disabled)">5
</span><span style="color:var(--text-disabled)">6
</span><span style="color:var(--text-disabled)">7
</span><span style="color:var(--text-disabled)">8
</span><span style="color:var(--text-disabled)">9
</span><span style="color:var(--text-disabled)">10
</span><span style="color:var(--text-disabled)">11
</span><span style="color:var(--text-disabled)">12
</span><span style="color:var(--text-disabled)">13
</span><span style="color:var(--text-disabled)">14
</span><span style="color:var(--text-disabled)">15
</span><span style="color:var(--text-disabled)">16
</span><span style="color:var(--text-disabled)">17
</span><span style="color:var(--text-disabled)">18
</span><span style="color:var(--text-disabled)">19
</span><span style="color:var(--text-disabled)">20
</span><span style="color:var(--text-disabled)">21
</span><span style="color:var(--text-disabled)">22
</span></code>{
<span style="color:var(--syntax4)">"type"</span>: <span style="color:var(--syntax3)">"function"</span>,
<span style="color:var(--syntax4)">"name"</span>: <span style="color:var(--syntax3)">"get_weather"</span>,
<span style="color:var(--syntax4)">"description"</span>: <span style="color:var(--syntax3)">"Retrieves current weather for the given location."</span>,
<span style="background-color:var(--pill-success-bg)"> <span style="color:var(--syntax4)">"strict"</span>: <span style="color:var(--syntax2)">true</span>,
</span> <span style="color:var(--syntax4)">"parameters"</span>: {
<span style="color:var(--syntax4)">"type"</span>: <span style="color:var(--syntax3)">"object"</span>,
<span style="color:var(--syntax4)">"properties"</span>: {
<span style="color:var(--syntax4)">"location"</span>: {
<span style="color:var(--syntax4)">"type"</span>: <span style="color:var(--syntax3)">"string"</span>,
<span style="color:var(--syntax4)">"description"</span>: <span style="color:var(--syntax3)">"City and country e.g. Bogotá, Colombia"</span>
},
<span style="color:var(--syntax4)">"units"</span>: {
<span style="background-color:var(--pill-success-bg)"> <span style="color:var(--syntax4)">"type"</span>: [<span style="color:var(--syntax3)">"string"</span>, <span style="color:var(--syntax3)">"null"</span>],
</span> <span style="color:var(--syntax4)">"enum"</span>: [<span style="color:var(--syntax3)">"celsius"</span>, <span style="color:var(--syntax3)">"fahrenheit"</span>],
<span style="color:var(--syntax4)">"description"</span>: <span style="color:var(--syntax3)">"Units the temperature will be returned in."</span>
}
},
<span style="background-color:var(--pill-success-bg)"> <span style="color:var(--syntax4)">"required"</span>: [<span style="color:var(--syntax3)">"location"</span>, <span style="color:var(--syntax3)">"units"</span>],
</span><span style="background-color:var(--pill-success-bg)"> <span style="color:var(--syntax4)">"additionalProperties"</span>: <span style="color:var(--syntax2)">false</span>
</span> }
}</code></span>
操场上生成的所有模式都启用了严格模式。
虽然我们建议您启用严格模式,但它有一些限制:
- JSON 模式的某些功能不受支持。(请参阅支持的模式。)
- 架构在第一次请求时会经过额外处理(然后被缓存)。如果您的架构因请求而异,这可能会导致更高的延迟。
- 为了提高性能,模式会被缓存,并且不符合零数据保留的条件。
流媒体
流式传输可用于显示进度,通过显示在模型填充其参数时调用哪个函数,甚至实时显示参数。
流式函数调用与流式常规响应非常相似:您设置stream
并true
获取不同的event
对象。
流式函数调用
Python
code-sample-pre
<span style="color:var(--text-default)"><code class="language-python"><code><span style="color:var(--text-disabled)">1
</span><span style="color:var(--text-disabled)">2
</span><span style="color:var(--text-disabled)">3
</span><span style="color:var(--text-disabled)">4
</span><span style="color:var(--text-disabled)">5
</span><span style="color:var(--text-disabled)">6
</span><span style="color:var(--text-disabled)">7
</span><span style="color:var(--text-disabled)">8
</span><span style="color:var(--text-disabled)">9
</span><span style="color:var(--text-disabled)">10
</span><span style="color:var(--text-disabled)">11
</span><span style="color:var(--text-disabled)">12
</span><span style="color:var(--text-disabled)">13
</span><span style="color:var(--text-disabled)">14
</span><span style="color:var(--text-disabled)">15
</span><span style="color:var(--text-disabled)">16
</span><span style="color:var(--text-disabled)">17
</span><span style="color:var(--text-disabled)">18
</span><span style="color:var(--text-disabled)">19
</span><span style="color:var(--text-disabled)">20
</span><span style="color:var(--text-disabled)">21
</span><span style="color:var(--text-disabled)">22
</span><span style="color:var(--text-disabled)">23
</span><span style="color:var(--text-disabled)">24
</span><span style="color:var(--text-disabled)">25
</span><span style="color:var(--text-disabled)">26
</span><span style="color:var(--text-disabled)">27
</span><span style="color:var(--text-disabled)">28
</span><span style="color:var(--text-disabled)">29
</span><span style="color:var(--text-disabled)">30
</span><span style="color:var(--text-disabled)">31
</span><span style="color:var(--text-disabled)">32
</span></code><span style="color:var(--syntax2)">from</span> openai <span style="color:var(--syntax2)">import</span> OpenAI
client = OpenAI()
tools = [{
<span style="color:var(--syntax3)">"type"</span>: <span style="color:var(--syntax3)">"function"</span>,
<span style="color:var(--syntax3)">"name"</span>: <span style="color:var(--syntax3)">"get_weather"</span>,
<span style="color:var(--syntax3)">"description"</span>: <span style="color:var(--syntax3)">"Get current temperature for a given location."</span>,
<span style="color:var(--syntax3)">"parameters"</span>: {
<span style="color:var(--syntax3)">"type"</span>: <span style="color:var(--syntax3)">"object"</span>,
<span style="color:var(--syntax3)">"properties"</span>: {
<span style="color:var(--syntax3)">"location"</span>: {
<span style="color:var(--syntax3)">"type"</span>: <span style="color:var(--syntax3)">"string"</span>,
<span style="color:var(--syntax3)">"description"</span>: <span style="color:var(--syntax3)">"City and country e.g. Bogotá, Colombia"</span>
}
},
<span style="color:var(--syntax3)">"required"</span>: [
<span style="color:var(--syntax3)">"location"</span>
],
<span style="color:var(--syntax3)">"additionalProperties"</span>: <span style="color:var(--syntax2)">False</span>
}
}]
stream = client.responses.create(
model=<span style="color:var(--syntax3)">"gpt-4o"</span>,
<span style="color:var(--syntax1)">input</span>=[{<span style="color:var(--syntax3)">"role"</span>: <span style="color:var(--syntax3)">"user"</span>, <span style="color:var(--syntax3)">"content"</span>: <span style="color:var(--syntax3)">"What's the weather like in Paris today?"</span>}],
tools=tools,
stream=<span style="color:var(--syntax2)">True</span>
)
<span style="color:var(--syntax2)">for</span> event <span style="color:var(--syntax2)">in</span> stream:
<span style="color:var(--syntax1)">print</span>(event)</code></span>
输出事件
code-sample-pre
<span style="color:var(--text-default)"><code class="language-json"><code><span style="color:var(--text-disabled)">1
</span><span style="color:var(--text-disabled)">2
</span><span style="color:var(--text-disabled)">3
</span><span style="color:var(--text-disabled)">4
</span><span style="color:var(--text-disabled)">5
</span><span style="color:var(--text-disabled)">6
</span><span style="color:var(--text-disabled)">7
</span><span style="color:var(--text-disabled)">8
</span><span style="color:var(--text-disabled)">9
</span><span style="color:var(--text-disabled)">10
</span></code>{<span style="color:var(--syntax4)">"type"</span>:<span style="color:var(--syntax3)">"response.output_item.added"</span>,<span style="color:var(--syntax4)">"response_id"</span>:<span style="color:var(--syntax3)">"resp_1234xyz"</span>,<span style="color:var(--syntax4)">"output_index"</span>:<span style="color:var(--syntax4)">0</span>,<span style="color:var(--syntax4)">"item"</span>:{<span style="color:var(--syntax4)">"type"</span>:<span style="color:var(--syntax3)">"function_call"</span>,<span style="color:var(--syntax4)">"id"</span>:<span style="color:var(--syntax3)">"fc_1234xyz"</span>,<span style="color:var(--syntax4)">"call_id"</span>:<span style="color:var(--syntax3)">"call_1234xyz"</span>,<span style="color:var(--syntax4)">"name"</span>:<span style="color:var(--syntax3)">"get_weather"</span>,<span style="color:var(--syntax4)">"arguments"</span>:<span style="color:var(--syntax3)">""</span>}}
{<span style="color:var(--syntax4)">"type"</span>:<span style="color:var(--syntax3)">"response.function_call_arguments.delta"</span>,<span style="color:var(--syntax4)">"response_id"</span>:<span style="color:var(--syntax3)">"resp_1234xyz"</span>,<span style="color:var(--syntax4)">"item_id"</span>:<span style="color:var(--syntax3)">"fc_1234xyz"</span>,<span style="color:var(--syntax4)">"output_index"</span>:<span style="color:var(--syntax4)">0</span>,<span style="color:var(--syntax4)">"delta"</span>:<span style="color:var(--syntax3)">"{\""</span>}
{<span style="color:var(--syntax4)">"type"</span>:<span style="color:var(--syntax3)">"response.function_call_arguments.delta"</span>,<span style="color:var(--syntax4)">"response_id"</span>:<span style="color:var(--syntax3)">"resp_1234xyz"</span>,<span style="color:var(--syntax4)">"item_id"</span>:<span style="color:var(--syntax3)">"fc_1234xyz"</span>,<span style="color:var(--syntax4)">"output_index"</span>:<span style="color:var(--syntax4)">0</span>,<span style="color:var(--syntax4)">"delta"</span>:<span style="color:var(--syntax3)">"location"</span>}
{<span style="color:var(--syntax4)">"type"</span>:<span style="color:var(--syntax3)">"response.function_call_arguments.delta"</span>,<span style="color:var(--syntax4)">"response_id"</span>:<span style="color:var(--syntax3)">"resp_1234xyz"</span>,<span style="color:var(--syntax4)">"item_id"</span>:<span style="color:var(--syntax3)">"fc_1234xyz"</span>,<span style="color:var(--syntax4)">"output_index"</span>:<span style="color:var(--syntax4)">0</span>,<span style="color:var(--syntax4)">"delta"</span>:<span style="color:var(--syntax3)">"\":\""</span>}
{<span style="color:var(--syntax4)">"type"</span>:<span style="color:var(--syntax3)">"response.function_call_arguments.delta"</span>,<span style="color:var(--syntax4)">"response_id"</span>:<span style="color:var(--syntax3)">"resp_1234xyz"</span>,<span style="color:var(--syntax4)">"item_id"</span>:<span style="color:var(--syntax3)">"fc_1234xyz"</span>,<span style="color:var(--syntax4)">"output_index"</span>:<span style="color:var(--syntax4)">0</span>,<span style="color:var(--syntax4)">"delta"</span>:<span style="color:var(--syntax3)">"Paris"</span>}
{<span style="color:var(--syntax4)">"type"</span>:<span style="color:var(--syntax3)">"response.function_call_arguments.delta"</span>,<span style="color:var(--syntax4)">"response_id"</span>:<span style="color:var(--syntax3)">"resp_1234xyz"</span>,<span style="color:var(--syntax4)">"item_id"</span>:<span style="color:var(--syntax3)">"fc_1234xyz"</span>,<span style="color:var(--syntax4)">"output_index"</span>:<span style="color:var(--syntax4)">0</span>,<span style="color:var(--syntax4)">"delta"</span>:<span style="color:var(--syntax3)">","</span>}
{<span style="color:var(--syntax4)">"type"</span>:<span style="color:var(--syntax3)">"response.function_call_arguments.delta"</span>,<span style="color:var(--syntax4)">"response_id"</span>:<span style="color:var(--syntax3)">"resp_1234xyz"</span>,<span style="color:var(--syntax4)">"item_id"</span>:<span style="color:var(--syntax3)">"fc_1234xyz"</span>,<span style="color:var(--syntax4)">"output_index"</span>:<span style="color:var(--syntax4)">0</span>,<span style="color:var(--syntax4)">"delta"</span>:<span style="color:var(--syntax3)">" France"</span>}
{<span style="color:var(--syntax4)">"type"</span>:<span style="color:var(--syntax3)">"response.function_call_arguments.delta"</span>,<span style="color:var(--syntax4)">"response_id"</span>:<span style="color:var(--syntax3)">"resp_1234xyz"</span>,<span style="color:var(--syntax4)">"item_id"</span>:<span style="color:var(--syntax3)">"fc_1234xyz"</span>,<span style="color:var(--syntax4)">"output_index"</span>:<span style="color:var(--syntax4)">0</span>,<span style="color:var(--syntax4)">"delta"</span>:<span style="color:var(--syntax3)">"\"}"</span>}
{<span style="color:var(--syntax4)">"type"</span>:<span style="color:var(--syntax3)">"response.function_call_arguments.done"</span>,<span style="color:var(--syntax4)">"response_id"</span>:<span style="color:var(--syntax3)">"resp_1234xyz"</span>,<span style="color:var(--syntax4)">"item_id"</span>:<span style="color:var(--syntax3)">"fc_1234xyz"</span>,<span style="color:var(--syntax4)">"output_index"</span>:<span style="color:var(--syntax4)">0</span>,<span style="color:var(--syntax4)">"arguments"</span>:<span style="color:var(--syntax3)">"{\"location\":\"Paris, France\"}"</span>}
{<span style="color:var(--syntax4)">"type"</span>:<span style="color:var(--syntax3)">"response.output_item.done"</span>,<span style="color:var(--syntax4)">"response_id"</span>:<span style="color:var(--syntax3)">"resp_1234xyz"</span>,<span style="color:var(--syntax4)">"output_index"</span>:<span style="color:var(--syntax4)">0</span>,<span style="color:var(--syntax4)">"item"</span>:{<span style="color:var(--syntax4)">"type"</span>:<span style="color:var(--syntax3)">"function_call"</span>,<span style="color:var(--syntax4)">"id"</span>:<span style="color:var(--syntax3)">"fc_1234xyz"</span>,<span style="color:var(--syntax4)">"call_id"</span>:<span style="color:var(--syntax3)">"call_2345abc"</span>,<span style="color:var(--syntax4)">"name"</span>:<span style="color:var(--syntax3)">"get_weather"</span>,<span style="color:var(--syntax4)">"arguments"</span>:<span style="color:var(--syntax3)">"{\"location\":\"Paris, France\"}"</span>}}</code></span>
content
但是,您不是将各块聚合成单个字符串,而是将各块聚合成编码的arguments
JSON 对象。
当模型调用一个或多个函数时,response.output_item.added
每个函数调用都会发出一个包含以下字段的事件:
场地 | 描述 |
---|---|
response_id |
函数调用所属的响应的 id |
output_index |
响应中输出项的索引。这表示响应中的各个函数调用。 |
item |
正在进行的函数调用项包括name 、arguments 和id 字段 |
之后,您将收到一系列response.function_call_arguments.delta
包含delta
该arguments
字段的类型的事件。这些事件包含以下字段:
场地 | 描述 |
---|---|
response_id |
函数调用所属的响应的 id |
item_id |
delta 所属的函数调用项的 id |
output_index |
响应中输出项的索引。这表示响应中的各个函数调用。 |
delta |
该字段的增量arguments 。 |
下面的代码片段演示了如何将delta
s 聚合成最终tool_call
对象。
累积 tool_call 增量
Python
code-sample-pre
<span style="color:var(--text-default)"><code class="language-python"><code><span style="color:var(--text-disabled)">1
</span><span style="color:var(--text-disabled)">2
</span><span style="color:var(--text-disabled)">3
</span><span style="color:var(--text-disabled)">4
</span><span style="color:var(--text-disabled)">5
</span><span style="color:var(--text-disabled)">6
</span><span style="color:var(--text-disabled)">7
</span><span style="color:var(--text-disabled)">8
</span><span style="color:var(--text-disabled)">9
</span><span style="color:var(--text-disabled)">10
</span></code>final_tool_calls = {}
<span style="color:var(--syntax2)">for</span> event <span style="color:var(--syntax2)">in</span> stream:
<span style="color:var(--syntax2)">if</span> event.<span style="color:var(--syntax1)">type</span> === <span style="color:var(--syntax3)">'response.output_item.added'</span>:
final_tool_calls[event.output_index] = event.item;
<span style="color:var(--syntax2)">elif</span> event.<span style="color:var(--syntax1)">type</span> === <span style="color:var(--syntax3)">'response.function_call_arguments.delta'</span>:
index = event.output_index
<span style="color:var(--syntax2)">if</span> final_tool_calls[index]:
final_tool_calls[index].arguments += event.delta</code></span>
累计 final_tool_calls[0]
code-sample-pre
<span style="color:var(--text-default)"><code class="language-json"><code><span style="color:var(--text-disabled)">1
</span><span style="color:var(--text-disabled)">2
</span><span style="color:var(--text-disabled)">3
</span><span style="color:var(--text-disabled)">4
</span><span style="color:var(--text-disabled)">5
</span><span style="color:var(--text-disabled)">6
</span><span style="color:var(--text-disabled)">7
</span></code>{
<span style="color:var(--syntax4)">"type"</span>: <span style="color:var(--syntax3)">"function_call"</span>,
<span style="color:var(--syntax4)">"id"</span>: <span style="color:var(--syntax3)">"fc_1234xyz"</span>,
<span style="color:var(--syntax4)">"call_id"</span>: <span style="color:var(--syntax3)">"call_2345abc"</span>,
<span style="color:var(--syntax4)">"name"</span>: <span style="color:var(--syntax3)">"get_weather"</span>,
<span style="color:var(--syntax4)">"arguments"</span>: <span style="color:var(--syntax3)">"{\"location\":\"Paris, France\"}"</span>
}</code></span>
当模型完成函数调用时,response.function_call_arguments.done
将发出类型为的事件。此事件包含整个函数调用,包括以下字段:
场地 | 描述 |
---|---|
response_id |
函数调用所属的响应的 id |
output_index |
响应中输出项的索引。这表示响应中的各个函数调用。 |
item |
name 包含、arguments 和字段的函数调用项id 。 |
响应