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 的典型集成流程包括以下几个步骤:
- 在 API 中创建一个 Assistant,为其设定特定的指令并选定一个模型。如有必要,可以启用诸如代码解释器、检索和函数调用等工具。
- 当用户开始对话时,创建一个 Thread。
- 用户提问时,向 Thread 添加消息 (Messages)。
- 在 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 目前处于测试阶段,我们正积极地增加更多功能。欢迎在我们的开发者论坛分享您的反馈!
- Assistants 可以调用 OpenAI 的模型并附上特定指令,以调整它们的个性和能力。
- Assistants 可以同时访问多个工具。这些工具既可以是 OpenAI 托管的工具 —— 如代码解释器和知识检索 —— 也可以是您构建/托管的工具(通过函数调用)。
- Assistants 可以访问持久性 Threads,这些 Threads 通过存储消息历史并在对话过长时进行截断,从而简化了 AI 应用的开发。您只需创建一次 Thread,随后随着用户回应,就可以向其追加消息。
- 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 的行为:
- 使用 instructions 参数来引导 Assistant 的个性并定义其目标。这些指令与 Chat Completions API 中的系统消息类似。
- 使用 tools 参数允许 Assistant 最多访问 128 个工具。您可以让其访问 OpenAI 托管的工具,如 code_interpreter 和 retrieval,或通过函数调用来访问第三方工具。
- 使用 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 生命周期
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 字段中。步骤细节可以分为两种类型:
- message_creation:当 Assistant 在 Thread 上创建消息时,会生成这个 Run Step。
- 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