OpenAI API 接口对接完全教程 / 08 - Assistants API
第 08 章 · Assistants API(助手 API)
Assistants API 提供了一个更高层的抽象,内置了线程管理、文件检索和代码解释器,简化复杂 AI 应用的构建。
8.1 核心概念
对象关系模型
Assistant(助手)
├── 指令 (instructions)
├── 模型 (model)
├── 工具 (tools)
└── 文件 (files)
Thread(线程)
└── Messages(消息)
├── user 消息
└── assistant 消息
Run(运行)
├── 状态机 (queued → in_progress → completed)
├── 工具调用 (function / retrieval / code_interpreter)
└── 步骤 (steps)
内置工具
| 工具 | 名称 | 功能 |
|---|---|---|
| 代码解释器 | code_interpreter | 执行 Python 代码、生成图表 |
| 文件检索 | file_search | 搜索上传的文档 |
| 函数调用 | function | 调用自定义函数 |
8.2 创建助手
from openai import OpenAI
client = OpenAI()
# 创建助手
assistant = client.beta.assistants.create(
name="数据分析助手",
instructions="""你是一个专业的数据分析师。
帮助用户分析数据、生成图表和报告。
使用代码解释器处理数据文件。
输出时使用中文,并提供清晰的分析结论。""",
model="gpt-4o",
tools=[
{"type": "code_interpreter"},
{"type": "file_search"},
],
)
print(f"助手 ID: {assistant.id}")
管理助手
# 列出所有助手
assistants = client.beta.assistants.list(limit=10)
for a in assistants.data:
print(f" {a.id}: {a.name}")
# 更新助手
client.beta.assistants.update(
assistant_id=assistant.id,
instructions="更新后的指令...",
model="gpt-4o",
)
# 删除助手
client.beta.assistants.delete(assistant_id=assistant.id)
8.3 线程与消息
创建线程和发送消息
# 创建线程
thread = client.beta.threads.create()
print(f"线程 ID: {thread.id}")
# 添加消息
message = client.beta.threads.messages.create(
thread_id=thread.id,
role="user",
content="请分析这份销售数据,找出趋势和异常。",
)
添加文件到消息
# 上传文件
file = client.files.create(
file=open("sales_data.csv", "rb"),
purpose="assistants",
)
# 带文件的消息
message = client.beta.threads.messages.create(
thread_id=thread.id,
role="user",
content="分析这份销售数据",
attachments=[{
"file_id": file.id,
"tools": [{"type": "file_search"}, {"type": "code_interpreter"}]
}]
)
8.4 运行助手 (Run)
8.4.1 基础运行
import time
# 创建运行
run = client.beta.threads.runs.create(
thread_id=thread.id,
assistant_id=assistant.id,
)
# 轮询等待完成
while run.status in ["queued", "in_progress", "cancelling"]:
time.sleep(1)
run = client.beta.threads.runs.retrieve(
thread_id=thread.id,
run_id=run.id,
)
print(f"状态: {run.status}")
if run.status == "completed":
# 获取回复
messages = client.beta.threads.messages.list(
thread_id=thread.id,
order="desc",
limit=1,
)
for msg in messages.data:
print(msg.content[0].text.value)
elif run.status == "failed":
print(f"运行失败: {run.last_error}")
8.4.2 使用 create_and_poll(推荐)
# 一步完成:创建运行并等待结果
run = client.beta.threads.runs.create_and_poll(
thread_id=thread.id,
assistant_id=assistant.id,
)
if run.status == "completed":
messages = client.beta.threads.messages.list(thread_id=thread.id)
for msg in messages.data:
if msg.role == "assistant":
print(msg.content[0].text.value)
8.4.3 流式运行
with client.beta.threads.runs.stream(
thread_id=thread.id,
assistant_id=assistant.id,
) as stream:
for event in stream:
if event.event == "thread.message.delta":
delta = event.data.delta
if delta.content:
for block in delta.content:
if hasattr(block, 'text') and block.text:
print(block.text.value, end="", flush=True)
elif event.event == "thread.run.failed":
print(f"\n运行失败: {event.data.last_error}")
print()
8.5 代码解释器 (Code Interpreter)
# 上传文件用于代码解释器
file = client.files.create(
file=open("data.csv", "rb"),
purpose="assistants",
)
# 创建带代码解释器的助手
analyst = client.beta.assistants.create(
name="数据分析专家",
instructions="用 Python 分析数据并生成可视化图表。",
model="gpt-4o",
tools=[{"type": "code_interpreter"}],
tool_resources={
"code_interpreter": {
"file_ids": [file.id]
}
}
)
# 运行分析
thread = client.beta.threads.create()
client.beta.threads.messages.create(
thread_id=thread.id,
role="user",
content="请分析数据中的趋势,生成折线图和柱状图。",
)
run = client.beta.threads.runs.create_and_poll(
thread_id=thread.id,
assistant_id=analyst.id,
)
# 获取生成的文件(图表等)
if run.status == "completed":
messages = client.beta.threads.messages.list(thread_id=thread.id)
for msg in messages.data:
for content in msg.content:
if content.type == "image":
print(f"生成图表: {content.image.file_id}")
elif content.type == "text":
print(content.text.value)
8.6 文件检索 (File Search)
# 创建向量存储
vector_store = client.beta.vector_stores.create(
name="产品文档",
)
# 上传文件到向量存储
files = ["manual.pdf", "faq.txt", "specs.docx"]
file_streams = [open(f, "rb") for f in files]
file_batch = client.beta.vector_stores.file_batches.upload_and_poll(
vector_store_id=vector_store.id,
files=file_streams,
)
print(f"文件状态: {file_batch.status}")
print(f"文件数量: {file_batch.file_counts}")
# 创建带检索功能的助手
doc_assistant = client.beta.assistants.create(
name="文档问答助手",
instructions="基于上传的文档回答用户问题,引用具体来源。",
model="gpt-4o",
tools=[{"type": "file_search"}],
tool_resources={
"file_search": {
"vector_store_ids": [vector_store.id]
}
}
)
检索参数调优
run = client.beta.threads.runs.create(
thread_id=thread.id,
assistant_id=doc_assistant.id,
tool_choice={"type": "file_search"},
)
8.7 Function Calling 集成
import json
# 定义工具
tools = [
{
"type": "function",
"function": {
"name": "get_user_info",
"description": "获取用户信息",
"parameters": {
"type": "object",
"properties": {
"user_id": {"type": "string", "description": "用户ID"}
},
"required": ["user_id"]
}
}
}
]
assistant = client.beta.assistants.create(
name="客服助手",
instructions="帮助用户查询订单和账户信息。",
model="gpt-4o",
tools=tools,
)
# 运行并处理工具调用
def run_with_tools(thread_id, assistant_id):
run = client.beta.threads.runs.create_and_poll(
thread_id=thread_id,
assistant_id=assistant_id,
)
# 处理工具调用
while run.status == "requires_action":
tool_outputs = []
for call in run.required_action.submit_tool_outputs.tool_calls:
if call.function.name == "get_user_info":
args = json.loads(call.function.arguments)
result = json.dumps({"name": "张三", "tier": "VIP"})
tool_outputs.append({
"tool_call_id": call.id,
"output": result,
})
run = client.beta.threads.runs.submit_tool_outputs_and_poll(
thread_id=thread_id,
run_id=run.id,
tool_outputs=tool_outputs,
)
return run
8.8 完整对话应用
class AssistantApp:
"""基于 Assistants API 的对话应用"""
def __init__(self, assistant_id: str):
self.client = OpenAI()
self.assistant_id = assistant_id
self.thread = self.client.beta.threads.create()
def chat(self, user_input: str) -> str:
"""发送消息并获取回复"""
# 添加用户消息
self.client.beta.threads.messages.create(
thread_id=self.thread.id,
role="user",
content=user_input,
)
# 运行
run = self.client.beta.threads.runs.create_and_poll(
thread_id=self.thread.id,
assistant_id=self.assistant_id,
)
if run.status == "completed":
messages = self.client.beta.threads.messages.list(
thread_id=self.thread.id,
order="desc",
limit=1,
)
return messages.data[0].content[0].text.value
else:
return f"运行状态: {run.status}"
def get_history(self) -> list[dict]:
"""获取对话历史"""
messages = self.client.beta.threads.messages.list(
thread_id=self.thread.id,
order="asc",
)
return [
{"role": msg.role, "content": msg.content[0].text.value}
for msg in messages.data
if msg.content[0].type == "text"
]
# 使用
app = AssistantApp(assistant_id="asst_xxx")
print(app.chat("你好,请帮我分析数据"))
print(app.chat("按月份统计趋势"))
8.9 运行状态机
queued → in_progress → completed
→ requires_action → in_progress → completed
→ failed
→ cancelled
→ expired
| 状态 | 含义 | 下一步 |
|---|---|---|
queued | 排队中 | 等待 |
in_progress | 运行中 | 等待 |
completed | 完成 | 读取结果 |
requires_action | 需要工具输出 | 提交工具结果 |
failed | 失败 | 检查错误 |
cancelled | 已取消 | - |
expired | 超时过期 | 重新运行 |
8.10 注意事项
- 线程持久化:线程和消息会持久保存,注意定期清理
- 运行超时:默认 10 分钟超时,可通过
expires_at设置 - 并发限制:同一线程同时只能有一个 Run
- 文件大小:单文件最大 512MB,向量存储最大 10000 文件
- 成本:助手会消耗更多 token(系统指令 + 工具定义 + 上下文)
- 不适合简单场景:简单对话直接用 Chat Completions 更高效
8.11 扩展阅读
下一章:09 - Whisper 语音转文字 — 音频转录、多语言、实时处理。