文章

OpenAI Assistants API 介绍 [译]

概览

Assistants API 允许您在自己的应用程序中构建 AI Assistant。一个 Assistant 有自己的指令 (instructions) ,并且可以利用模型 (models)、工具 (tools) 和 知识库 (knowledge) 来回应用户查询。目前,Assistants API 支持三种类型的工具:Code Interpreter(代码解释器)、Retrieval(检索)和 Function calling(函数调用)。未来,我们计划发布更多由 OpenAI 构建的工具,并允许您在我们的平台上提供自己的工具。

您可以通过 Assistants playground 来探索 Assistants API 的功能,或遵循本指南中详细描述的步骤来实施集成。从宏观角度看,Assistants API 的典型集成流程包括以下几个步骤:

  1. 在 API 中创建一个 Assistant,为其设定特定的指令并选定一个模型。如有必要,可以启用诸如代码解释器、检索和函数调用等工具。
  2. 当用户开始对话时,创建一个 Thread。
  3. 用户提问时,向 Thread 添加消息 (Messages)。
  4. 在 Thread 上运行 Assistant,以产生响应。这一过程会自动调用相关的工具。

Assistants API 目前处于 beta 阶段,我们正在积极地增加更多功能。欢迎在我们的开发者论坛中分享您的反馈!

调用 Assistants API 时,您需要传递一个 beta HTTP 头。如果您使用的是 OpenAI 的官方 Python 或 Node.js SDK,这将自动处理。

1
OpenAI-Beta: assistants=v1

这里有份入门指南,可以引导您了解创建并运行一个集成了 Code Interpreter 的 Assistant 的关键步骤。

Assistants playground

除了 Assistants API,我们还提供了一个需要登录才能使用的 Assistants playground。这个 playground 是探索 Assistants API 功能和学习如何在不编写任何代码的情况下构建您自己的 Assistant 的绝佳方式。

步骤 1:创建一个 Assistant

Assistant 代表一个可以配置的实体,它使用多个参数来响应用户的消息,如:

  • 指令 instructions:指导 Assistant 和模型的行为或响应方式。
  • 模型 model:您可以指定任何 GPT-3.5 或 GPT-4 模型,包括精调模型。注意:检索工具需要 gpt-3.5-turbo-1106 和 gpt-4-1106-preview 模型。
  • 工具 tools:API 支持由 OpenAI 构建和托管的 Code Interpreter 和检索工具。
  • 功能 functions:API 允许您定义自定义函数签名,其行为类似于我们的函数调用功能。

在这个示例中,我们正在创建一个 Assistant,它是一个启用了 Code Interpreter 工具的个人数学导师。

1
2
3
4
5
6
7
8
9
10
curl "https://api.openai.com/v1/assistants" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -H "OpenAI-Beta: assistants=v1" \
  -d '{
    "instructions": "You are a personal math tutor. Write and run code to answer math questions.",
    "name": "Math Tutor",
    "tools": [{"type": "code_interpreter"}],
    "model": "gpt-4"
  }'

步骤 2:创建一个 Thread

Thread 代表一个对话。我们建议在用户开始对话时为每个用户创建一个 Thread。通过创建消息(Messages),在这个 Thread 中传递任何特定于用户的上下文和文件。

1
2
3
4
5
curl https://api.openai.com/v1/threads \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -H "OpenAI-Beta: assistants=v1" \
  -d ''

Thread 没有大小限制。您可以向 Thread 添加任意数量的消息。Assistant 将确保发送给模型的请求符合最大上下文窗口,使用我们已经在 ChatGPT 上广泛测试的相关优化技术,如截断。当您使用 Assistants API 时,您将控制权委托给了模型,以决定在任何给定运行中传递多少输入令牌,这意味着在某些情况下您对运行 Assistant 的成本的控制力会减少,但您不必自己处理管理上下文窗口的复杂性。

步骤 3:向 Thread 添加一个消息

消息(Message)包含文本,以及您允许用户上传的任何文件。消息需要添加到特定的 Thread 中。目前不支持像在 GPT-4 Vision 的 Chat Completions 中那样通过消息对象添加图像,但我们计划在未来几个月内增加对它们的支持。您仍然可以上传图像,通过检索的方式进行处理。

1
2
3
4
5
6
7
8
curl https://api.openai.com/v1/threads/thread_abc123/messages \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -H "OpenAI-Beta: assistants=v1" \
  -d '{
      "role": "user",
      "content": "I need to solve the equation `3x + 11 = 14`. Can you help me?"
    }'

现在,如果您列出一个 Thread 中的消息,您将看到这条消息已被追加。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
  "object": "list",
  "data": [
    {
      "created_at": 1696995451,
      "id": "msg_abc123",
      "object": "thread.message",
      "thread_id": "thread_abc123",
      "role": "user",
      "content": [{
        "type": "text",
        "text": {
          "value": "I need to solve the equation `3x + 11 = 14`. Can you help me?",
          "annotations": []
        }
      }],
      ...
}

步骤 4:启动 Assistant

为了使 Assistant 对用户的消息做出响应,您需要创建一个 Run。这个操作会让 Assistant 分析 Thread 的内容,并根据情况决定是否调用工具(如果启用了的话)或者直接使用模型来以最佳方式回答问题。在 Run 进行的过程中,Assistant 会以 “assistant” 的角色将消息添加到 Thread 中。Assistant 还会自动选择哪些之前的消息应包含在模型的上下文窗口内。这不仅会影响定价,还会影响模型的表现。目前的做法是基于我们在构建 ChatGPT 时的学习经验而优化的,并且可能会随时间而发展。

在创建 Run 时,您可以选择性地向 Assistant 提供额外的指示,但请注意,这些指示会覆盖 Assistant 的默认指示。

1
2
3
4
5
6
7
8
curl https://api.openai.com/v1/threads/thread_abc123/runs \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -H "Content-Type: application/json" \
  -H "OpenAI-Beta: assistants=v1" \
  -d '{
    "assistant_id": "asst_abc123",
    "instructions": "请称呼用户为 Jane Doe。用户拥有高级账户。"
  }'

步骤 5:检查 Run 状态

默认情况下,Run 会进入排队状态。您可以定期检索 Run 以查看其状态是否已更改为已完成。

1
2
3
curl https://api.openai.com/v1/threads/thread_abc123/runs/run_abc123 \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -H "OpenAI-Beta: assistants=v1"

步骤 6:显示 Assistant 的响应

一旦 Run 完成,您就可以列出 Assistant 向 Thread 添加的消息。

1
2
3
4
curl https://api.openai.com/v1/threads/thread_abc123/messages \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -H "OpenAI-Beta: assistants=v1"

最后一步,向用户展示这些消息!在这次 Run 期间,Assistant 向 Thread 中添加了两条新的消息。以下是这些消息可能的展示样例:

ROLE CONTENT
user 我需要解这个方程:3x + 11 = 14。你能帮我吗?
assistant 当然可以,Jane Doe。要解方程 (3x + 11 = 14) 中的 (x),你需要将 (x) 单独放在方程的一边。这是操作步骤:
从方程的两边各减去 11,得到 (3x = 3)。
然后,两边各除以 3 来解出 (x)。
让我来为你计算 (x) 的值。
assistant 方程 (3x + 11 = 14) 的解是 (x = 1)。

如果您想探索或展示助手及其工具的内部工作原理,您还可以检索此次 Run 的 Run Steps

Assistants 工作原理(Beta)

Assistants API 旨在帮助开发者打造能执行多种任务的强大 AI 助手。

Assistants API 目前处于测试阶段,我们正积极地增加更多功能。欢迎在我们的开发者论坛分享您的反馈!

  1. Assistants 可以调用 OpenAI 的模型并附上特定指令,以调整它们的个性和能力。
  2. Assistants 可以同时访问多个工具。这些工具既可以是 OpenAI 托管的工具 —— 如代码解释器和知识检索 —— 也可以是您构建/托管的工具(通过函数调用)。
  3. Assistants 可以访问持久性 Threads,这些 Threads 通过存储消息历史并在对话过长时进行截断,从而简化了 AI 应用的开发。您只需创建一次 Thread,随后随着用户回应,就可以向其追加消息。
  4. Assistants 还可以访问多种格式的文件 — 无论是作为其创建过程的一部分,还是作为 Assistants 与用户之间的 Threads 中的一部分。在使用工具时,Assistants 还可以创建文件(例如图像、电子表格等),并在其创建的消息中引用这些文件。

Objects(对象)

对象 它代表的内容
Assistant 使用 OpenAI 的模型并调用工具的定制 AI
Thread Assistant 和用户之间的对话会话。Thread 存储消息并自动处理截断,以便内容适应模型的上下文。
Message 由 Assistant 或用户创建的消息。消息可以包括文本、图像和其他文件。消息以列表形式存储在 Thread 上。
Run 在 Thread 上调用 Assistant 的操作。Assistant 使用其配置和 Thread 的消息执行任务,通过调用模型和工具。在 Run 过程中,Assistant 会向 Thread 追加消息。
Run Step Assistant 在 Run 过程中采取的详细步骤列表。Assistant 可以在其运行期间调用工具或创建消息。检查 Run Steps 可以让您深入了解 Assistant 如何得出最终结果。

创建 Assistants

为了获得最佳效果和最大兼容性,我们推荐在 Assistants API 中使用 OpenAI 的最新模型。

要开始创建一个 Assistant,您只需指定要使用的模型。但您还可以通过以下方式进一步自定义 Assistant 的行为:

  1. 使用 instructions 参数来引导 Assistant 的个性并定义其目标。这些指令与 Chat Completions API 中的系统消息类似。
  2. 使用 tools 参数允许 Assistant 最多访问 128 个工具。您可以让其访问 OpenAI 托管的工具,如 code_interpreter 和 retrieval,或通过函数调用来访问第三方工具。
  3. 使用 file_ids 参数来为工具(如 code_interpreter 和 retrieval)提供对文件的访问权限。这些文件通过文件上传端点上传,并且必须设置为 assistants 用途,才能与此 API 一起使用。

例如,要创建一个能够基于 .csv 文件生成数据可视化的 Assistant,请先上传一个文件:

1
2
3
4
curl https://api.openai.com/v1/files \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -F purpose="assistants" \
  -F file="@mydata.csv"

然后,使用上传的文件创建 Assistant:

1
2
3
4
5
6
7
8
9
10
11
curl https://api.openai.com/v1/assistants \
  -H 'Authorization: Bearer $OPENAI_API_KEY' \
  -H 'Content-Type: application/json' \
  -H 'OpenAI-Beta: assistants=v1' \
  -d '{
    "name": "Data visualizer",
    "description": "You are great at creating beautiful data visualizations. You analyze data present in .csv files, understand trends, and come up with data visualizations relevant to those trends. You also share a brief text summary of the trends observed.",
    "model": "gpt-4-1106-preview",
    "tools": [{"type": "code_interpreter"}],
    "file_ids": ["file-BK7bzQj3FfZFXr7DbL6xJwfo"]
  }'

每个 Assistant 最多可附加 20 个文件,每个文件最大为 512 MB。此外,您的组织上传的所有文件总大小不应超过 100GB。您可以通过我们的帮助中心请求增加此存储限制。

您还可以使用 AssistantFile 对象来创建、删除或查看 Assistant 与 File 对象之间的关联。请注意,删除 AssistantFile 只会解除该文件与 Assistant 之间的关系,并不会删除原始的 File 对象。若要删除文件,请使用文件删除端点。

管理 Threads 和 Messages

Threads 和 Messages 构成了 Assistant 与用户之间的对话会话。您可以在 Thread 中存储无限量的 Messages。当 Messages 的总大小超出模型的上下文窗口时,Thread 将尝试包含尽可能多的适应上下文窗口的消息,并且淘汰最旧的消息。请注意,这种截断策略可能会随着时间的推移而调整。

您可以通过以下方式创建一个包含初始消息列表的 Thread:

1
2
3
4
5
6
7
8
9
10
11
12
13
curl https://api.openai.com/v1/threads \
  -H 'Authorization: Bearer $OPENAI_API_KEY' \
  -H 'Content-Type: application/json' \
  -H 'OpenAI-Beta: assistants=v1' \
  -d '{
    "messages": [
      {
          "role": "user",
          "content": "Create 3 data visualizations based on the trends in this file.",
          "file_ids": ["file-wB6RM6wHdA49HfS2DJ9fEyrH"]
      }
    ]
  }'

消息可以包括文本、图像或文件。目前,用户创建的消息暂不支持包含图像文件,但我们计划未来加入此功能。

消息注释

Assistant 创建的消息中,可能会在对象的 content 数组内包含 annotations。这些注释提供了关于如何对消息中的文本进行标注的信息。

注释分为两种类型:

  • file_citation:由检索工具创建的文件引用,用于指向特定文件中的特定引文。这些文件是之前上传的,并被 Assistant 在生成回应时使用。
  • file_path:由代码解释器工具创建的文件路径注释,包含对该工具生成的文件的引用。

当消息对象包含注释时,您会在文本中发现由模型生成的一些模糊的子字符串。这些子字符串应当被注释中的信息所替代。这类字符串可能的形式包括“【13†source】”或“sandbox:/mnt/data/file.csv”等。下面是一个 Python 代码示例,展示了如何使用注释中的信息来替换这些特殊的字符串:

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
# 检索消息对象
message = client.beta.threads.messages.retrieve(
  thread_id="...",
  message_id="..."
)

# 提取消息内容
message_content = message.content[0].text
annotations = message_content.annotations
citations = []

# 遍历注释并添加脚注
for index, annotation in enumerate(annotations):
    # 用脚注替换文本
    message_content.value = message_content.value.replace(annotation.text, f' [{index}]')

    # 根据注释属性收集引用
    if (file_citation := getattr(annotation, 'file_citation', None)):
        cited_file = client.files.retrieve(file_citation.file_id)
        citations.append(f'[{index}] {file_citation.quote} 来自 {cited_file.filename}')
    elif (file_path := getattr(annotation, 'file_path', None)):
        cited_file = client.files.retrieve(file_path.file_id)
        citations.append(f'[{index}] 点击 <这里> 下载 {cited_file.filename}')
        # 注意:上述代码未实现文件下载功能,为了简洁而省略

# 在显示给用户之前,在消息末尾添加脚注
message_content.value += '\n' + '\n'.join(citations)

请注意,上述代码片段出于简洁考虑并未实现文件下载功能。

Runs 和 Run Steps

当您从用户那里在 Thread 中获取了所有需要的上下文后,您可以使用您选择的 Assistant 来运行 Thread。

1
2
3
4
5
6
7
curl https://api.openai.com/v1/threads/THREAD_ID/runs \
  -H 'Authorization: Bearer $OPENAI_API_KEY' \
  -H 'Content-Type: application/json' \
  -H 'OpenAI-Beta: assistants=v1' \
  -d '{
    "assistant_id": "asst_ToSF7Gb04YMj8AMMm50ZLLtY"
  }'

默认情况下,Run 将使用在 Assistant 对象中指定的模型和工具配置,但您在创建 Run 时可以覆盖这些配置,以获得更大的灵活性:

1
2
3
4
5
6
7
8
9
10
curl https://api.openai.com/v1/threads/THREAD_ID/runs \
  -H 'Authorization: Bearer $OPENAI_API_KEY' \
  -H 'Content-Type: application/json' \
  -H 'OpenAI-Beta: assistants=v1' \
  -d '{
    "assistant_id": "ASSISTANT_ID",
    "model": "gpt-4-1106-preview",
    "instructions": "additional instructions",
    "tools": [{"type": "code_interpreter"}, {"type": "retrieval"}]
  }'

注意:在创建 Run 时,无法覆盖与 Assistant 相关联的 file_ids。您必须使用修改 Assistant 端点来做到这一点。

Run 生命周期

Run 对象可以有多种状态。

STATUS DEFINITION
queued 当 Run 首次创建或完成所需的操作后,它们会转移到 queued 状态。它们应该几乎立即转移到 in_progress。
in_progress 在 in_progress 状态下,Assistant 使用模型和工具执行步骤。您可以通过检查 Run Steps 来查看 Run 的进展。
completed Run 成功完成!您现在可以查看 Assistant 向 Thread 添加的所有消息,以及 Run 执行的所有步骤。您也可以通过向 Thread 添加更多用户消息并创建另一个 Run 来继续对话。
requires_action 使用函数调用工具时,一旦模型确定了要调用的函数的名称和参数,Run 将转移到 requires_action 状态。然后您必须运行这些函数并提交输出,然后 Run 才会继续。如果在 expires_at 时间戳过去之前(大约创建后 10 分钟)未提供输出,Run 将转移到 expired 状态。
expired 当函数调用的输出在 expires_at 之前未提交时,Run 会过期。此外,如果 Run 的执行时间过长,超出 expires_at 中规定的时间,我们的系统将使 Run 过期。
cancelling 您可以尝试使用 Cancel Run 端点来取消 in_progress 中的 Run。一旦取消尝试成功,Run 的状态将转移到 cancelled。取消是尝试性的,不保证成功。
cancelled Run 已成功取消。
failed 您可以通过查看 Run 中的 last_error 对象来了解失败的原因。失败的时间戳将记录在 failed_at 下。

轮询更新

为了保持您的 Run 状态的及时更新,您需要定期检索 Run 对象。每次检索对象时,您可以检查 Run 的状态,以确定您的应用接下来应该做什么。我们计划在不久的将来增加对流式传输的支持,以简化这一过程。

Thread 锁定

当 Run 处于 in_progress 状态且不在终止状态时,Thread 会被锁定。这意味着:

  • 无法向 Thread 添加新消息。
  • 无法在 Thread 上创建新的 Runs。

Run steps

Run Step 状态的含义与 Run 状态相同。

Run Step 对象中大部分有趣的细节都位于 step_details 字段中。步骤细节可以分为两种类型:

  1. message_creation:当 Assistant 在 Thread 上创建消息时,会生成这个 Run Step。
  2. tool_calls:当 Assistant 调用工具时,会生成这个 Run Step。有关此方面的详细信息,请参阅工具指南的相关部分。

数据访问指南

目前,通过 API 创建的 assistants、threads、messages 和 files 都属于整个组织的范畴。因此,任何拥有该组织 API 密钥访问权限的人都可以读取或写入该组织中的 assistants、threads、messages 和 files。

我们强烈建议实施以下数据访问控制:

  • 实施授权。在对 assistants、threads、messages 和 files 进行读取或写入操作之前,确保终端用户有权这样做。例如,在您的数据库中存储终端用户可以访问的对象 ID,并在使用 API 获取对象 ID 之前进行检查。
  • 限制 API 密钥访问。谨慎考虑组织中谁应该拥有 API 密钥,并定期审核此列表。API 密钥允许执行广泛的操作,包括读取和修改敏感信息,如消息和文件。
  • 创建独立账户。考虑为不同的应用程序创建独立的账户/组织,以隔离多个应用程序之间的数据。

限制

在这个测试阶段,我们已知存在一些限制,我们计划在未来几周和几个月内解决。当我们增加额外功能支持时,我们将在此页面上发布更新日志。

  • 支持流式输出(包括消息和 Run Steps)。
  • 支持通知,无需轮询即可共享对象状态更新。
  • 支持将 DALL·E 作为工具。
  • 支持创建包含图像的用户消息。



原文作者:OpenAI
原文链接:https://platform.openai.com/docs/assistants/overview

本文由作者按照 CC BY 4.0 进行授权