助手函数调用试用版
与 Chat Completions API 类似,Assistants API 支持函数调用。函数调用允许您向 Assistants API 描述函数,并让它智能地返回需要调用的函数及其参数。
快速入门
在此示例中,我们将创建一个天气助手,并定义两个函数 和 ,作为助手可以调用的工具。
根据用户查询,如果使用我们的
2023 年 11 月 6 日或之后发布的最新型号。
在我们使用并行函数调用的示例中,我们将询问 Assistant 的天气情况
旧金山就像今天一样,有可能下雨。我们还展示了如何通过 streaming 输出 Assistant 的响应。get_current_temperature
get_rain_probability
步骤 1:定义函数
在创建助手时,您将首先定义助手参数下的函数。tools
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
from openai import OpenAI
client = OpenAI()
assistant = client.beta.assistants.create(
instructions="You are a weather bot. Use the provided functions to answer questions.",
model="gpt-4o",
tools=[
{
"type": "function",
"function": {
"name": "get_current_temperature",
"description": "Get the current temperature for a specific location",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city and state, e.g., San Francisco, CA"
},
"unit": {
"type": "string",
"enum": ["Celsius", "Fahrenheit"],
"description": "The temperature unit to use. Infer this from the user's location."
}
},
"required": ["location", "unit"]
}
}
},
{
"type": "function",
"function": {
"name": "get_rain_probability",
"description": "Get the probability of rain for a specific location",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city and state, e.g., San Francisco, CA"
}
},
"required": ["location"]
}
}
}
]
)
第 2 步:创建话题并添加消息
在用户开始对话时创建一个话题,并在用户提问时将消息添加到话题中。
1
2
3
4
5
6
thread = client.beta.threads.create()
message = client.beta.threads.messages.create(
thread_id=thread.id,
role="user",
content="What's the weather in San Francisco today and the likelihood it'll rain?",
)
第 3 步:启动运行
当您启动包含触发一个或多个函数的用户 Message 的 Run on Thread 时,
Run 将进入一个状态。处理完后,运行将进入一种状态,您可以
通过检查 Run 的 .这表示您需要运行工具并将其输出提交到
Assistant 继续 Run 执行。在我们的例子中,我们将看到两个 ,这表明
user 查询导致并行函数调用。pending
requires_action
status
tool_calls
您将在 中看到 两个,这表示用户查询触发了并行函数调用。tool_calls
required_action
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
{
"id": "run_qJL1kI9xxWlfE0z1yfL0fGg9",
...
"status": "requires_action",
"required_action": {
"submit_tool_outputs": {
"tool_calls": [
{
"id": "call_FthC9qRpsL5kBpwwyw6c7j4k",
"function": {
"arguments": "{"location": "San Francisco, CA"}",
"name": "get_rain_probability"
},
"type": "function"
},
{
"id": "call_RpEDoB8O0FTL9JoKTuCVFOyR",
"function": {
"arguments": "{"location": "San Francisco, CA", "unit": "Fahrenheit"}",
"name": "get_current_temperature"
},
"type": "function"
}
]
},
...
"type": "submit_tool_outputs"
}
}
您发起 Run 和提交的方式会有所不同,具体取决于您是否使用流式处理。
尽管在这两种情况下都需要同时提交。
然后,您可以通过提交您调用的函数的工具输出来完成 Run。
传递对象中引用的每个 Headers 以将输出与每个函数调用匹配。tool_calls
tool_calls
tool_call_id
required_action
对于流式处理情况,我们创建了一个 EventHandler 类来处理响应流中的事件,并使用 Python 和 Node SDK 中的“submit tool outputs stream”帮助程序一次提交所有工具输出。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
from typing_extensions import override
from openai import AssistantEventHandler
class EventHandler(AssistantEventHandler):
@override
def on_event(self, event):
# Retrieve events that are denoted with 'requires_action'
# since these will have our tool_calls
if event.event == 'thread.run.requires_action':
run_id = event.data.id # Retrieve the run ID from the event data
self.handle_requires_action(event.data, run_id)
def handle_requires_action(self, data, run_id):
tool_outputs = []
for tool in data.required_action.submit_tool_outputs.tool_calls:
if tool.function.name == "get_current_temperature":
tool_outputs.append({"tool_call_id": tool.id, "output": "57"})
elif tool.function.name == "get_rain_probability":
tool_outputs.append({"tool_call_id": tool.id, "output": "0.06"})
# Submit all tool_outputs at the same time
self.submit_tool_outputs(tool_outputs, run_id)
def submit_tool_outputs(self, tool_outputs, run_id):
# Use the submit_tool_outputs_stream helper
with client.beta.threads.runs.submit_tool_outputs_stream(
thread_id=self.current_run.thread_id,
run_id=self.current_run.id,
tool_outputs=tool_outputs,
event_handler=EventHandler(),
) as stream:
for text in stream.text_deltas:
print(text, end="", flush=True)
print()
with client.beta.threads.runs.stream(
thread_id=thread.id,
assistant_id=assistant.id,
event_handler=EventHandler()
) as stream:
stream.until_done()
使用结构化输出
当您通过提供 来启用结构化输出时,OpenAI API 将在您的第一个请求中预处理您提供的架构,然后使用此构件将模型约束到您的架构。strict: true
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
from openai import OpenAI
client = OpenAI()
assistant = client.beta.assistants.create(
instructions="You are a weather bot. Use the provided functions to answer questions.",
model="gpt-4o-2024-08-06",
tools=[
{
"type": "function",
"function": {
"name": "get_current_temperature",
"description": "Get the current temperature for a specific location",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city and state, e.g., San Francisco, CA"
},
"unit": {
"type": "string",
"enum": ["Celsius", "Fahrenheit"],
"description": "The temperature unit to use. Infer this from the user's location."
}
},
"required": ["location", "unit"],
"additionalProperties": False
},
"strict": True
}
},
{
"type": "function",
"function": {
"name": "get_rain_probability",
"description": "Get the probability of rain for a specific location",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city and state, e.g., San Francisco, CA"
}
},
"required": ["location"],
"additionalProperties": False
},
"strict": True
}
}
]
)