助手函数调用
试用版

与 Chat Completions API 类似,Assistants API 支持函数调用。函数调用允许您向 Assistants API 描述函数,并让它智能地返回需要调用的函数及其参数。

快速入门

在此示例中,我们将创建一个天气助手,并定义两个函数 和 ,作为助手可以调用的工具。 根据用户查询,如果使用我们的 2023 年 11 月 6 日或之后发布的最新型号。 在我们使用并行函数调用的示例中,我们将询问 Assistant 的天气情况 旧金山就像今天一样,有可能下雨。我们还展示了如何通过 streaming 输出 Assistant 的响应。get_current_temperatureget_rain_probability

随着结构化输出的推出,您现在可以在通过 Assistants API 进行函数调用时使用该参数。 有关更多信息,请参阅函数调用指南。 请注意,使用视觉时,Assistants API 不支持结构化输出。strict: true

步骤 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 查询导致并行函数调用。pendingrequires_actionstatustool_calls

请注意,A 运行在创建后 10 分钟过期。请务必在 10 分钟之前提交您的工具输出。

您将在 中看到 两个,这表示用户查询触发了并行函数调用。tool_callsrequired_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 object truncated here (在此处截断对象,以提高可读性)

您发起 Run 和提交的方式会有所不同,具体取决于您是否使用流式处理。 尽管在这两种情况下都需要同时提交。 然后,您可以通过提交您调用的函数的工具输出来完成 Run。 传递对象中引用的每个 Headers 以将输出与每个函数调用匹配。tool_callstool_callstool_call_idrequired_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
      }
    }
  ]
)