关于 openai-assistants
openai-assistants 是面向开发者的技能,用于维护基于 OpenAI Assistants API v2 的应用或迁移至 Responses API。内容涵盖 Assistant、持久化线程、运行任务、流式处理和内置工具;该 API 计划于 2026 年上半年停止服务。
主要功能
- 01Assistant 和线程生命周期管理
- 02异步运行任务与流式处理
- 03Code Interpreter、File Search 和函数
- 04向量存储与文件上传
- 05迁移至 Responses API 的指南
适用场景
- 01维护现有 Assistants API 应用
- 02实现持久化的助手对话
- 03流式获取运行进度和响应
- 04规划从 Assistants 迁移至 Responses API
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ jackspace/ claudeskillz --skill openai-assistants安装后在 Claude Code 中输入/openai-assistants确认已加载。
附带文件README.mdSKILL.json
详细介绍
OpenAI Assistants API v2
状态:已可用于生产环境(计划于 2026 年上半年弃用) 软件包:[email protected] 最后更新:2025-10-25 v1 弃用时间:2024 年 12 月 18 日 v2 计划结束时间:2026 年上半年(迁移至 Responses API)
⚠️ 重要:弃用通知
OpenAI 宣布,Assistants API 将弃用,并由 Responses API 取代。
时间表:
- ✅ 2024 年 12 月 18 日:Assistants API v1 弃用
- ⏳ 2026 年上半年:计划停止支持 Assistants API v2
- ✅ 现在:Responses API 已推出(新项目推荐使用)
你仍应使用此技能吗?
- ✅ 是,如果:你已有 Assistants API 代码(有 12–18 个月的迁移窗口)
- ✅ 是,如果:你需要维护旧版应用
- ✅ 是,如果:你正计划从 Assistants 迁移至 Responses
- ❌ 否,如果:你正开始一个新项目(请改用 openai-responses 技能)
迁移路径:
完整迁移指南请参阅 references/migration-to-responses.md。
目录
- 快速开始
- 核心概念
- Assistants
- Threads
- Messages
- Runs
- 流式 Runs
- 工具
- 向量存储
- 文件上传
- Thread 生命周期管理
- 错误处理
- 生产环境最佳实践
- 与其他技能的关系
快速开始
安装
npm install [email protected]
环境设置
export OPENAI_API_KEY="sk-..."
基础 Assistant(Node.js SDK)
import OpenAI from 'openai';
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
});
// 1. Create an assistant
const assistant = await openai.beta.assistants.create({
name: "Math Tutor",
instructions: "You are a personal math tutor. Write and run code to answer math questions.",
tools: [{ type: "code_interpreter" }],
model: "gpt-4o",
});
// 2. Create a thread
const thread = await openai.beta.threads.create();
// 3. Add a message to the thread
await openai.beta.threads.messages.create(thread.id, {
role: "user",
content: "I need to solve the equation `3x + 11 = 14`. Can you help me?",
});
// 4. Create a run
const run = await openai.beta.threads.runs.create(thread.id, {
assistant_id: assistant.id,
});
// 5. Poll for completion
let runStatus = await openai.beta.threads.runs.retrieve(thread.id, run.id);
while (runStatus.status !== 'completed') {
await new Promise(resolve => setTimeout(resolve, 1000));
runStatus = await openai.beta.threads.runs.retrieve(thread.id, run.id);
}
// 6. Retrieve messages
const messages = await openai.beta.threads.messages.list(thread.id);
console.log(messages.data[0].content[0].text.value);
基础 Assistant(Fetch - Cloudflare Workers)
// 1. Create assistant
const assistant = await fetch('https://api.openai.com/v1/assistants', {
method: 'POST',
headers: {
'Authorization': `Bearer ${env.OPENAI_API_KEY}`,
'Content-Type': 'application/json',
'OpenAI-Beta': 'assistants=v2',
},
body: JSON.stringify({
name: "Math Tutor",
instructions: "You are a helpful math tutor.",
model: "gpt-4o",
}),
});
const assistantData = await assistant.json();
// 2. Create thread
const thread = await fetch('https://api.openai.com/v1/threads', {
method: 'POST',
headers: {
'Authorization': `Bearer ${env.OPENAI_API_KEY}`,
'Content-Type': 'application/json',
'OpenAI-Beta': 'assistants=v2',
},
});
const threadData = await thread.json();
// 3. Add message and create run
const run = await fetch(`https://api.openai.com/v1/threads/${threadData.id}/runs`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${env.OPENAI_API_KEY}`,
'Content-Type': 'application/json',
'OpenAI-Beta': 'assistants=v2',
},
body: JSON.stringify({
assistant_id: assistantData.id,
additional_messages: [{
role: "user",
content: "What is 3x + 11 = 14?",
}],
}),
});
// Poll for completion...
核心概念
Assistants API 使用四种主要对象:
1. Assistants
经过配置的 AI 实体,包含:
- 指令(系统提示词,最多 256k 个字符)
- 模型(gpt-4o、gpt-5 等)
- 工具(Code Interpreter、File Search、Functions)
- 文件附件
- 元数据
2. Threads
对话容器,具有以下特点:
- 存储消息历史
- 在多次运行之间持久保存
- 可包含元数据
- 最多支持 100,000 条消息
3. Messages
Thread 中的单条消息:
- 用户消息(输入)
- Assistant 消息(输出)
- 可包含文件附件
- 支持文本和图像内容
4. Runs
在 Thread 上执行 Assistant:
- 异步处理
- 有多种状态(queued、in_progress、completed、failed 等)
- 可流式传输结果
- 自动处理工具调用
Assistants
创建 Assistant
const assistant = await openai.beta.assistants.create({
name: "Data Analyst",
instructions: "You are a data analyst. Use code interpreter to analyze data and create visualizations.",
model: "gpt-4o",
tools: [
{ type: "code_interpreter" },
{ type: "file_search" },
],
tool_resources: {
file_search: {
vector_store_ids: ["vs_abc123"],
},
},
metadata: {
department: "analytics",
version: "1.0",
},
});
参数:
model(必填):模型 ID(gpt-4o、gpt-5、gpt-4-turbo)instructions:系统提示词(v2 中最多 256k 个字符;v1 中为 32k)name:Assistant 名称(最多 256 个字符)description:描述(最多 512 个字符)tools:工具数组(最多 128 个工具)tool_resources:工具所需资源(向量存储、文件)temperature:0–2(默认值为 1)top_p:0–1(默认值为 1)response_format:"auto"、"json_object" 或 JSON Schemametadata:键值对(最多 16 对)
获取 Assistant
const assistant = await openai.beta.assistants.retrieve("asst_abc123");
更新 Assistant
const updatedAssistant = await openai.beta.assistants.update("asst_abc123", {
instructions: "Updated instructions",
tools: [{ type: "code_interpreter" }, { type: "file_search" }],
});
删除 Assistant
await openai.beta.assistants.del("asst_abc123");
列出 Assistants
const assistants = await openai.beta.assistants.list({
limit: 20,
order: "desc",
});
Threads
Threads 用于存储对话历史,并在多次运行之间持久保存。
创建 Thread
// Empty thread
const thread = await openai.beta.threads.create();
// Thread with initial messages
const thread = await openai.beta.threads.create({
messages: [
{
role: "user",
content: "Hello! I need help with Python.",
metadata: { source: "web" },
},
],
metadata: {
user_id: "user_123",
session_id: "session_456",
},
});
获取 Thread
const thread = await openai.beta.threads.retrieve("thread_abc123");
更新 Thread 元数据
const thread = await openai.beta.threads.update("thread_abc123", {
metadata: {
user_id: "user_123",
last_active: new Date().toISOString(),
},
});
删除 Thread
await openai.beta.threads.del("thread_abc123");
⚠️ 警告:删除 Thread 也会删除其中的所有消息和 Runs。此操作无法撤销。
Messages
向 Thread 添加消息
const message = await openai.beta.threads.messages.create("thread_abc123", {
role: "user",
content: "Can you analyze this data?",
attachments: [
{
file_id: "file_abc123",
tools: [{ type: "code_interpreter" }],
},
],
metadata: {
timestamp: new Date().toISOString(),
},
});
参数:
role:仅限 "user"(Assistant 消息由 Runs 创建)content:文本或内容块数组attachments:包含关联工具的文件metadata:键值对
获取 Message
const message = await openai.beta.threads.messages.retrieve(
"thread_abc123",
"msg_abc123"
);
列出 Messages
const messages = await openai.beta.threads.messages.list("thread_abc123", {
limit: 20,
order: "desc", // "asc" or "desc"
});
// Iterate through messages
for (const message of messages.data) {
console.log(`${message.role}: ${message.content[0].text.value}`);
}
更新消息元数据
const message = await openai.beta.threads.messages.update(
"thread_abc123",
"msg_abc123",
{
metadata: {
edited: "true",
edit_timestamp: new Date().toISOString(),
},
}
);
删除消息
await openai.beta.threads.messages.del("thread_abc123", "msg_abc123");
运行
运行会在一个线程上执行助手。
创建运行
const run = await openai.beta.threads.runs.create("thread_abc123", {
assistant_id: "asst_abc123",
instructions: "Please address the user as Jane Doe.",
additional_messages: [
{
role: "user",
content: "Can you help me with this?",
},
],
});
参数:
assistant_id(必填):要使用的助手instructions:覆盖助手指令additional_messages:在运行前添加消息tools:覆盖助手工具metadata:键值对temperature:覆盖 temperaturetop_p:覆盖 top_pmax_prompt_tokens:限制输入 token 数量max_completion_tokens:限制输出 token 数量
获取运行
const run = await openai.beta.threads.runs.retrieve(
"thread_abc123",
"run_abc123"
);
console.log(run.status); // queued, in_progress, requires_action, completed, failed, etc.
运行状态
| 状态 | 描述 |
|---|---|
queued | 运行正在等待启动 |
in_progress | 运行正在执行 |
requires_action | 函数调用需要你的输入 |
cancelling | 正在取消 |
cancelled | 运行已取消 |
failed | 运行失败(检查 last_error) |
completed | 运行已成功完成 |
expired | 运行已过期(最长 10 分钟) |
轮询模式
async function pollRunCompletion(threadId: string, runId: string) {
let run = await openai.beta.threads.runs.retrieve(threadId, runId);
while (['queued', 'in_progress', 'cancelling'].includes(run.status)) {
await new Promise(resolve => setTimeout(resolve, 1000)); // Wait 1 second
run = await openai.beta.threads.runs.retrieve(threadId, runId);
}
if (run.status === 'failed') {
throw new Error(`Run failed: ${run.last_error?.message}`);
}
if (run.status === 'requires_action') {
// Handle function calling (see Function Calling section)
return run;
}
return run; // completed
}
const run = await openai.beta.threads.runs.create(threadId, { assistant_id: assistantId });
const completedRun = await pollRunCompletion(threadId, run.id);
取消运行
const run = await openai.beta.threads.runs.cancel("thread_abc123", "run_abc123");
⚠️ 重要:取消操作是异步的。请检查 status 是否变为 cancelled。
列出运行
const runs = await openai.beta.threads.runs.list("thread_abc123", {
limit: 10,
order: "desc",
});
流式运行
使用服务器发送事件(SSE)实时传输运行事件。
基本流式传输
const stream = await openai.beta.threads.runs.stream("thread_abc123", {
assistant_id: "asst_abc123",
});
for await (const event of stream) {
if (event.event === 'thread.message.delta') {
const delta = event.data.delta.content?.[0]?.text?.value;
if (delta) {
process.stdout.write(delta);
}
}
}
流式事件类型
| 事件 | 描述 |
|---|---|
thread.run.created | 运行已创建 |
thread.run.in_progress | 运行已开始 |
thread.run.step.created | 步骤已创建(工具调用、消息创建) |
thread.run.step.delta | 步骤进度更新 |
thread.message.created | 消息已创建 |
thread.message.delta | 消息内容正在流式传输 |
thread.message.completed | 消息已完成 |
thread.run.completed | 运行已完成 |
thread.run.failed | 运行失败 |
thread.run.requires_action | 需要进行函数调用 |
完整流式传输示例
async function streamAssistantResponse(threadId: string, assistantId: string) {
const stream = await openai.beta.threads.runs.stream(threadId, {
assistant_id: assistantId,
});
for await (const event of stream) {
switch (event.event) {
case 'thread.run.created':
console.log('\\nRun started...');
break;
case 'thread.message.delta':
const delta = event.data.delta.content?.[0];
if (delta?.type === 'text' && delta.text?.value) {
process.stdout.write(delta.text.value);
}
break;
case 'thread.run.step.delta':
const toolCall = event.data.delta.step_details;
if (toolCall?.type === 'tool_calls') {
const codeInterpreter = toolCall.tool_calls?.[0]?.code_interpreter;
if (codeInterpreter?.input) {
console.log('\\nExecuting code:', codeInterpreter.input);
}
}
break;
case 'thread.run.completed':
console.log('\\n\\nRun completed!');
break;
case 'thread.run.failed':
console.error('\\nRun failed:', event.data.last_error);
break;
case 'thread.run.requires_action':
// Handle function calling
console.log('\\nFunction calling required');
break;
}
}
}
工具
Assistants API 支持三种类型的工具:
代码解释器
在沙盒环境中执行 Python 代码。
功能:
- 运行 Python 代码
- 生成图表
- 处理文件(CSV、JSON、文本、图像等)
- 返回文件输出(图像、数据文件)
- 安装软件包(可用软件包有限)
示例:
const assistant = await openai.beta.assistants.create({
name: "Data Analyst",
instructions: "You are a data analyst. Use Python to analyze data and create visualizations.",
model: "gpt-4o",
tools: [{ type: "code_interpreter" }],
});
// Upload a file
const file = await openai.files.create({
file: fs.createReadStream("sales_data.csv"),
purpose: "assistants",
});
// Create thread with file
const thread = await openai.beta.threads.create({
messages: [{
role: "user",
content: "Analyze this sales data and create a visualization.",
attachments: [{
file_id: file.id,
tools: [{ type: "code_interpreter" }],
}],
}],
});
// Run
const run = await openai.beta.threads.runs.create(thread.id, {
assistant_id: assistant.id,
});
// Poll for completion and retrieve outputs
输出文件:
代码解释器可以生成文件(图像、CSV 等)。通过以下方式访问:
const messages = await openai.beta.threads.messages.list(thread.id);
const message = messages.data[0];
for (const content of message.content) {
if (content.type === 'image_file') {
const fileId = content.image_file.file_id;
const fileContent = await openai.files.content(fileId);
// Save or process file
}
}
文件搜索
使用向量存储对已上传的文档进行语义搜索。
主要功能:
- 每个助手最多支持 10,000 个文件(是 v1 的 500 倍)
- 自动分块和嵌入
- 向量 + 关键词搜索
- 支持多线程并行查询
- 高级重排序
定价:
- 向量存储费用为 $0.10/GB/天
- 前 1GB 免费
示例:
// 1. Create vector store
const vectorStore = await openai.beta.vectorStores.create({
name: "Product Documentation",
metadata: { category: "docs" },
});
// 2. Upload files to vector store
const file = await openai.files.create({
file: fs.createReadStream("product_guide.pdf"),
purpose: "assistants",
});
await openai.beta.vectorStores.files.create(vectorStore.id, {
file_id: file.id,
});
// 3. Create assistant with file search
const assistant = await openai.beta.assistants.create({
name: "Product Support",
instructions: "Use file search to answer questions about our products.",
model: "gpt-4o",
tools: [{ type: "file_search" }],
tool_resources: {
file_search: {
vector_store_ids: [vectorStore.id],
},
},
});
// 4. Create thread and run
const thread = await openai.beta.threads.create({
messages: [{
role: "user",
content: "How do I install the product?",
}],
});
const run = await openai.beta.threads.runs.create(thread.id, {
assistant_id: assistant.id,
});
最佳实践:
- 使用前等待向量存储状态变为
completed - 使用元数据进行筛选(即将推出)
- 适当拆分较大的文档
- 监控存储费用
函数调用
定义供助手调用的自定义函数。
示例:
const assistant = await openai.beta.assistants.create({
name: "Weather Assistant",
instructions: "You help users get weather information.",
model: "gpt-4o",
tools: [{
type: "function",
function: {
name: "get_weather",
description: "Get the current weather for a location",
parameters: {
type: "object",
properties: {
location: {
type: "string",
description: "City name, e.g., 'San Francisco'",
},
unit: {
type: "string",
enum: ["celsius", "fahrenheit"],
description: "Temperature unit",
},
},
required: ["location"],
},
},
}],
});
// Create thread and run
const thread = await openai.beta.threads.create({
messages: [{
role: "user",
content: "What's the weather in San Francisco?",
}],
});
let run = await openai.beta.threads.runs.create(thread.id, {
assistant_id: assistant.id,
});
// Poll until requires_action
while (run.status === 'in_progress' || run.status === 'queued') {
await new Promise(resolve => setTimeout(resolve, 1000));
run = await openai.beta.threads.runs.retrieve(thread.id, run.id);
}
if (run.status === 'requires_action') {
const toolCalls = run.required_action.submit_tool_outputs.tool_calls;
const toolOutputs = [];
for (const toolCall of toolCalls) {
if (toolCall.function.name === 'get_weather') {
const args = JSON.parse(toolCall.function.arguments);
// Call your actual weather API
const weather = await getWeatherAPI(args.location, args.unit);
toolOutputs.push({
tool_call_id: toolCall.id,
output: JSON.stringify(weather),
});
}
}
// Submit tool outputs
run = await openai.beta.threads.runs.submitToolOutputs(thread.id, run.id, {
tool_outputs: toolOutputs,
});
// Continue polling...
}
向量存储
向量存储可对大量文档集合进行高效的语义搜索。
创建向量存储
const vectorStore = await openai.beta.vectorStores.create({
name: "Legal Documents",
metadata: {
department: "legal",
category: "contracts",
},
expires_after: {
anchor: "last_active_at",
days: 7, // Auto-delete 7 days after last use
},
});
向向量存储添加文件
单个文件:
const file = await openai.files.create({
file: fs.createReadStream("contract.pdf"),
purpose: "assistants",
});
await openai.beta.vectorStores.files.create(vectorStore.id, {
file_id: file.id,
});
批量上传:
const fileBatch = await openai.beta.vectorStores.fileBatches.create(vectorStore.id, {
file_ids: ["file_abc123", "file_def456", "file_ghi789"],
});
// Poll for batch completion
let batch = await openai.beta.vectorStores.fileBatches.retrieve(vectorStore.id, fileBatch.id);
while (batch.status === 'in_progress') {
await new Promise(resolve => setTimeout(resolve, 1000));
batch = await openai.beta.vectorStores.fileBatches.retrieve(vectorStore.id, fileBatch.id);
}
检查向量存储状态
const vectorStore = await openai.beta.vectorStores.retrieve("vs_abc123");
console.log(vectorStore.status); // "in_progress", "completed", "failed"
console.log(vectorStore.file_counts); // { in_progress: 0, completed: 50, failed: 0 }
⚠️ 重要:与文件搜索搭配使用前,请等待 status: "completed"。
列出向量存储
const stores = await openai.beta.vectorStores.list({
limit: 20,
order: "desc",
});
更新向量存储
const vectorStore = await openai.beta.vectorStores.update("vs_abc123", {
name: "Updated Name",
metadata: { updated: "true" },
});
删除向量存储
await openai.beta.vectorStores.del("vs_abc123");
文件上传
上传文件以供代码解释器或文件搜索使用。
上传文件
import fs from 'fs';
const file = await openai.files.create({
file: fs.createReadStream("document.pdf"),
purpose: "assistants",
});
console.log(file.id); // file_abc123
支持的格式:
- Code Interpreter:.c、.cpp、.csv、.docx、.html、.java、.json、.md、.pdf、.php、.pptx、.py、.rb、.tex、.txt、.css、.jpeg、.jpg、.js、.gif、.png、.tar、.ts、.xlsx、.xml、.zip
- File Search:.c、.cpp、.docx、.html、.java、.json、.md、.pdf、.php、.pptx、.py、.rb、.tex、.txt、.css、.js、.ts、.go
大小限制:
- Code Interpreter:每个文件最大 512 MB
- File Search:每个文件最大 512 MB
- Vector Store:最多 10,000 个文件
获取文件信息
const file = await openai.files.retrieve("file_abc123");
下载文件内容
const content = await openai.files.content("file_abc123");
// Returns binary content
删除文件
await openai.files.del("file_abc123");
列出文件
const files = await openai.files.list({
purpose: "assistants",
});
线程生命周期管理
妥善管理线程生命周期可避免常见错误。
模式 1:每个用户使用一个线程
async function getOrCreateUserThread(userId: string): Promise<string> {
// Check if thread exists in your database
let threadId = await db.getThreadIdForUser(userId);
if (!threadId) {
// Create new thread
const thread = await openai.beta.threads.create({
metadata: { user_id: userId },
});
threadId = thread.id;
await db.saveThreadIdForUser(userId, threadId);
}
return threadId;
}
模式 2:检查活跃运行
async function ensureNoActiveRun(threadId: string) {
const runs = await openai.beta.threads.runs.list(threadId, {
limit: 1,
order: "desc",
});
const latestRun = runs.data[0];
if (latestRun && ['queued', 'in_progress', 'cancelling'].includes(latestRun.status)) {
throw new Error('Thread already has an active run. Wait or cancel first.');
}
}
// Before creating new run
await ensureNoActiveRun(threadId);
const run = await openai.beta.threads.runs.create(threadId, { assistant_id });
模式 3:清理线程
async function cleanupOldThreads(maxAgeHours = 24) {
const threads = await openai.beta.threads.list({ limit: 100 });
for (const thread of threads.data) {
const createdAt = new Date(thread.created_at * 1000);
const ageHours = (Date.now() - createdAt.getTime()) / (1000 * 60 * 60);
if (ageHours > maxAgeHours) {
await openai.beta.threads.del(thread.id);
}
}
}
错误处理
常见错误与解决方案
1. 线程已有活跃运行
Error: 400 Can't add messages to thread_xxx while a run run_xxx is active.
解决方案:
// Wait for run to complete or cancel it
const run = await openai.beta.threads.runs.retrieve(threadId, runId);
if (['queued', 'in_progress'].includes(run.status)) {
await openai.beta.threads.runs.cancel(threadId, runId);
// Wait for cancellation
while (run.status !== 'cancelled') {
await new Promise(resolve => setTimeout(resolve, 500));
run = await openai.beta.threads.runs.retrieve(threadId, runId);
}
}
2. 运行轮询超时
长时间运行的任务可能会超过合理的轮询时限。
解决方案:
async function pollWithTimeout(threadId: string, runId: string, maxSeconds = 300) {
const startTime = Date.now();
while (true) {
const run = await openai.beta.threads.runs.retrieve(threadId, runId);
if (!['queued', 'in_progress'].includes(run.status)) {
return run;
}
const elapsed = (Date.now() - startTime) / 1000;
if (elapsed > maxSeconds) {
await openai.beta.threads.runs.cancel(threadId, runId);
throw new Error('Run exceeded timeout');
}
await new Promise(resolve => setTimeout(resolve, 1000));
}
}
3. Vector Store 尚未就绪
在索引完成前使用 Vector Store。
解决方案:
async function waitForVectorStore(vectorStoreId: string) {
let store = await openai.beta.vectorStores.retrieve(vectorStoreId);
while (store.status === 'in_progress') {
await new Promise(resolve => setTimeout(resolve, 2000));
store = await openai.beta.vectorStores.retrieve(vectorStoreId);
}
if (store.status === 'failed') {
throw new Error('Vector store indexing failed');
}
return store;
}
4. 文件上传格式问题
不支持的文件格式会导致错误。
解决方案:
const SUPPORTED_FORMATS = {
code_interpreter: ['.csv', '.json', '.pdf', '.txt', '.py', '.js', '.xlsx'],
file_search: ['.pdf', '.docx', '.txt', '.md', '.html'],
};
function validateFile(filename: string, tool: string) {
const ext = filename.substring(filename.lastIndexOf('.')).toLowerCase();
if (!SUPPORTED_FORMATS[tool].includes(ext)) {
throw new Error(`Unsupported file format for ${tool}: ${ext}`);
}
}
完整的错误目录请参阅 references/top-errors.md。
生产环境最佳实践
1. 使用 Assistant ID(不要重新创建)
❌ 不好:
// Creates new assistant on every request!
const assistant = await openai.beta.assistants.create({ ... });
✅ 好:
// Create once, store ID, reuse
const ASSISTANT_ID = process.env.ASSISTANT_ID || await createAssistant();
async function createAssistant() {
const assistant = await openai.beta.assistants.create({ ... });
console.log('Save this ID:', assistant.id);
return assistant.id;
}
2. 实施完善的错误处理
async function createRunWithRetry(threadId: string, assistantId: string, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await openai.beta.threads.runs.create(threadId, {
assistant_id: assistantId,
});
} catch (error) {
if (error.status === 429) {
// Rate limit - wait and retry
await new Promise(resolve => setTimeout(resolve, 2000 * (i + 1)));
continue;
}
if (error.message?.includes('active run')) {
// Wait for active run to complete
await new Promise(resolve => setTimeout(resolve, 5000));
continue;
}
throw error; // Other errors
}
}
throw new Error('Max retries exceeded');
}
3. 监控成本
// Track usage
const run = await openai.beta.threads.runs.retrieve(threadId, runId);
console.log('Tokens used:', run.usage);
// { prompt_tokens: 150, completion_tokens: 200, total_tokens: 350 }
// Set limits
const run = await openai.beta.threads.runs.create(threadId, {
assistant_id: assistantId,
max_prompt_tokens: 1000,
max_completion_tokens: 500,
});
4. 清理资源
// Delete old threads
async function cleanupUserThread(userId: string) {
const threadId = await db.getThreadIdForUser(userId);
if (threadId) {
await openai.beta.threads.del(threadId);
await db.deleteThreadIdForUser(userId);
}
}
// Delete unused vector stores
async function cleanupVectorStores(keepDays = 30) {
const stores = await openai.beta.vectorStores.list({ limit: 100 });
for (const store of stores.data) {
const ageSeconds = Date.now() / 1000 - store.created_at;
const ageDays = ageSeconds / (60 * 60 * 24);
if (ageDays > keepDays) {
await openai.beta.vectorStores.del(store.id);
}
}
}
5. 使用流式传输提升用户体验
// Show progress in real-time
async function streamToUser(threadId: string, assistantId: string) {
const stream = await openai.beta.threads.runs.stream(threadId, {
assistant_id: assistantId,
});
for await (const event of stream) {
if (event.event === 'thread.message.delta') {
const delta = event.data.delta.content?.[0]?.text?.value;
if (delta) {
// Send to user immediately
sendToClient(delta);
}
}
}
}
与其他技能的关系
与 openai-api 技能的比较
openai-api(Chat Completions):
- 无状态请求
- 手动管理历史记录
- 直接返回响应
- 适用于:简单文本生成、函数调用
openai-assistants:
- 有状态对话(线程)
- 自动管理历史记录
- 内置工具(Code Interpreter、File Search)
- 适用于:聊天机器人、数据分析、RAG
与 openai-responses 技能的比较
openai-responses(Responses API):
- ✅ 新项目推荐使用
- 更好地保留推理过程
- 现代 MCP 集成
- 积极开发中
openai-assistants:
- ⚠️ 将于 2026 年上半年弃用
- 适用于旧版应用
- 提供迁移路径
**迁移:**请参阅 references/migration-to-responses.md
从 v1 迁移到 v2
v1 已弃用:2024 年 12 月 18 日
主要变更:
- Retrieval → File Search:
retrieval工具已替换为file_search - Vector Stores:文件现在按 Vector Store 组织(上限为 10,000 个文件)
- Instructions 限制:从 32k 增至 256k 个字符
- 文件附件:现在属于消息级,而非助手级
完整指南请参阅 references/migration-from-v1.md。
后续步骤
模板:
templates/basic-assistant.ts- 简易数学辅导templates/code-interpreter-assistant.ts- 数据分析templates/file-search-assistant.ts- 使用 Vector Store 的 RAGtemplates/function-calling-assistant.ts- 自定义工具templates/streaming-assistant.ts- 实时流式传输
参考资料:
references/top-errors.md- 12 个常见错误及解决方案references/thread-lifecycle.md- 线程管理模式references/vector-stores.md- Vector Store 深入介绍
相关技能:
openai-responses- 现代替代方案(推荐)openai-api- Chat Completions(无状态)
最后更新:2025-10-25 软件包版本:[email protected] 状态:可用于生产环境(将于 2026 年上半年弃用)