Assistants 关停之后:OpenAI Responses API 迁移模式与架构指南
Assistants API 在 8 月 26 日关停。这篇指南面向已经完成迁移的团队,讲清楚 Responses API 的对话状态管理、工具编排、流式传输,以及通过 OpenAI 兼容网关实现跨服务商路由的实际做法。
Assistants API 在 2026 年 8 月 26 日正式关停。如果你正在读这篇文章,截止日期要么就在明天,要么已经过去了。迁移清单和事后复盘分析在本博客的其他文章里都能找到。这篇文章假设你已经完成了 Assistants 的迁出,现在需要在 Responses API 上把东西建好。
下面是一份实用的架构指南,涵盖没有了服务端 Thread 之后对话状态怎么管、工具编排如何替代 Run 对象、流式传输有什么不同,以及 OpenAI 兼容网关在跨服务商路由中扮演什么角色。
Responses API 相比 Assistants 带来了什么
Assistants API 帮你管状态,Thread 存消息,Run 轮询完成状态,服务器编排工具调用。方便归方便,代价是锁定。Thread 和 Run 对象只存在于 OpenAI 的服务器上,没有办法在另一个服务商那里回放,也不能缓存到本地或在自己的基础设施里检视完整的编排状态。
Responses API 把这个服务端托管的生命周期换成了无状态(或可选有状态)的请求模型。每次调用 POST /v1/responses 都接收一个 input 数组,返回一个 output 数组。模型可以在一次请求中调用多个工具。状态在你手里。
影响架构决策的几个关键变化如下。
- **没有服务端线程了。**对话状态通过
previous_response_id传递,或者用 Conversations API 管理,再不然就手动把input回放出来。 - **内置 agentic loop。**模型可以在一次请求中串联 web search、file search、code interpreter、函数调用和 MCP 工具调用,不需要轮询。
- 类型化的输出项。
choices[0].message没了,换成一个output数组,里面有独立的reasoning、message、function_call、web_search_call项。 - **缓存利用率更好。**OpenAI 表示,相同工作量下 Responses API 比 Chat Completions 的缓存命中率高 40-80%。
没有服务端 Thread 之后的对话状态管理
Assistants 把对话历史存在 Thread 对象里。Responses API 提供三种状态管理方式,可移植性和复杂度各有取舍。
方案一:previous_response_id(最简单,仅限 OpenAI)
把上一个响应的 id 传进去就能串联多轮对话。
first = client.responses.create(
model="gpt-5.6",
input="解释一下 CAP 定理。",
)
second = client.responses.create(
model="gpt-5.6",
input="再给我一个具体的例子。",
previous_response_id=first.id,
)
这是最接近 Assistants Thread 的方案。OpenAI 在服务端存储上下文并自动回放。不过 previous_response_id 是 OpenAI 专有参数。DeepSeek 的 Responses API 不支持它(DeepSeek 的实现是无状态的)。需要跨服务商可移植性的话,选方案二或方案三。
方案二:Conversations API(新接口,仅限 OpenAI)
Conversations API 提供持久化、可命名的对话。在多个会话需要引用同一段对话历史时比较有用。和 previous_response_id 一样,这也是 OpenAI 专有的。
方案三:手动状态回放(可移植)
把每个响应的完整 output 数组追加到下一个请求的 input 数组里。
history = [{"role": "user", "content": "解释一下 CAP 定理。"}]
response = client.responses.create(
model="gpt-5.6",
input=history,
store=False,
)
# 回放所有 output 项,包括加密的 reasoning 项
history += response.output
history.append({"role": "user", "content": "给我一个例子。"})
next_response = client.responses.create(
model="gpt-5.6",
input=history,
store=False,
)
任何支持 Responses API input 格式的服务商都能用这种方式。DeepSeek 接受相同的 input 项结构(message、function_call、function_call_output、reasoning、web_search_call 项)。代价是你自己管存储和回放,长对话的每次请求 token 消耗会增加。
**怎么选?**如果要跨服务商路由或想完全掌控状态,用手动回放。如果确定只用 OpenAI、想少写代码,用 previous_response_id。同一个对话里不要混用两种方式。
工具编排:从 Run 轮询到 agentic loop
Assistants API 需要轮询 Run 对象来检查模型是否要调用工具,然后提交工具输出再轮询一次。一个多工具对话可能要来回四五趟。
Responses API 把这个流程取消了。配置了 tools 的请求里,模型可以在一次 API 调用中调用多个工具并整合它们的输出(对内置工具如 web search、file search、code interpreter 来说)。自定义函数调用仍然需要手动提交输出,但请求/响应周期更简洁。
import json
response = client.responses.create(
model="gpt-5.6",
input="东京和纽约现在天气怎么样?",
tools=[{
"type": "function",
"name": "get_weather",
"description": "获取一个城市的当前天气",
"parameters": {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"],
"additionalProperties": False,
},
"strict": True,
}],
)
# 模型可能在 output 中返回多个 function_call 项
tool_outputs = []
for item in response.output:
if item.type == "function_call":
result = get_weather(json.loads(item.arguments)["city"])
tool_outputs.append({
"type": "function_call_output",
"call_id": item.call_id,
"output": json.dumps(result),
})
# 在后续请求中提交工具输出
final = client.responses.create(
model="gpt-5.6",
input=[
*response.output,
*tool_outputs,
],
tools=[{...}],
previous_response_id=response.id,
)
内置工具对 Assistants 功能的替代关系
| Assistants 功能 | Responses API 替代方案 | 说明 |
|---|---|---|
| Code Interpreter | {"type": "code_interpreter"} | 在沙箱里跑 Python,返回文本/图片 |
| File Search (Retrieval) | {"type": "file_search", "vector_store_ids": [...]} | 使用同一套向量存储基础设施 |
| Function calling | {"type": "function", ...} | 请求格式和 Chat Completions 不同 |
| Web browsing (beta) | {"type": "web_search"} | 服务端执行,输出中附带引用 |
跨服务商的工具支持情况
DeepSeek 的 Responses API 支持 function 和 web_search 工具类型。其他内置工具(file_search、code_interpreter、computer_use、mcp)会被静默忽略。多服务商路由的 agentic 工作负载必须按服务商逐一确认工具可用性。
OpenAI 兼容指供应商提供一个 chat-completions 接口,其请求与响应结构与 OpenAI API 契约足够接近——只需替换三个值(API key、base URL、模型名),原来的 OpenAI SDK 调用即可直接工作。最小实践面是POST /v1/chat/completions 带 messages、model, 并返回 OpenAI 形式的流式响应。
流式传输:从 delta 块到语义事件
Chat Completions 的流式传输发送 delta 对象,包含增量内容。Responses API 使用语义化的服务端推送事件(SSE)。每个事件都有一个 type 字段,告诉你正在发生什么。
| 事件类型 | 含义 |
|---|---|
response.created | 请求已接受,响应生成开始 |
response.output_text.delta | 增量文本内容(对应 Chat Completions 的 delta) |
response.function_call_arguments.delta | 增量函数调用参数 JSON |
response.reasoning_text.delta | 思维链文本(启用 reasoning 时) |
response.output_item.added / .done | 一个输出项(message、function_call 等)开始/完成 |
response.completed | 最终事件,携带完整响应对象和 usage |
response.failed | 生成过程出错 |
stream = client.responses.create(
model="gpt-5.6",
input="总结一下最新的 AI 研究趋势。",
stream=True,
)
for event in stream:
if event.type == "response.output_text.delta":
print(event.delta, end="")
elif event.type == "response.completed":
print(f"\n\nTokens: {event.response.usage.total_tokens}")
没有 data: [DONE] 消息。流以 response.completed、response.incomplete 或 response.failed 事件结束。
DeepSeek 的 Responses API 支持相同的 SSE 事件结构,通过兼容网关在 OpenAI 和 DeepSeek 之间路由时,流式行为是一致的。
跨服务商路由的注意事项
Responses API 的 input/output 格式正在成为跨服务商标准,但支持程度参差不齐。
| 服务商 | Responses API 支持情况 | 主要限制 |
|---|---|---|
| OpenAI | 完整支持 | 参考实现 |
| DeepSeek | 部分支持 | 不支持 previous_response_id、store、background、Conversations API。工具仅限 function 和 web_search。不支持的参数会被静默忽略。 |
| DashScope (Qwen) | 通过 Chat Completions | DashScope 使用 OpenAI 兼容的 Chat Completions,不原生支持 Responses API 格式,但 Qwen 模型可以通过 Chat Completions 路由访问。 |
路由架构
通过 TheRouter 这样的网关路由 Responses API 流量时,有几点需要注意。
- **无状态请求路由没有障碍。**如果使用手动状态回放(上面的方案三),同一个请求可以发到任何支持 Responses API input 格式的服务商。
- 有状态参数是服务商专有的。
previous_response_id、store: true和 Conversations API 只在请求到达 OpenAI 时有效。路由器无法为其他服务商合成服务端状态。 - **工具可用性因服务商而异。**带
web_search或function工具的请求可以路由到支持它们的服务商。带file_search或code_interpreter的请求必须到 OpenAI。 - **降级需要谨慎处理。**如果 OpenAI 不可用、降级到 DeepSeek,应用必须处理 DeepSeek 不支持的内置工具缺失的情况。
TheRouter 通过配置的服务商路由 OpenAI 兼容请求。对 Responses API 流量来说,使用手动状态回放加 function 类工具的请求可以顺畅地路由到任何兼容端点。依赖 OpenAI 专有功能(previous_response_id、function 和 web_search 之外的内置工具)的请求应当固定路由到 OpenAI。
上线前的检查清单
把 Responses API 集成推到生产环境之前,逐项确认以下内容。
错误处理
- 在流式模式下处理
response.failed事件,在同步模式下检查status字段 - 为 429(限速)和 500+(服务端错误)响应实现重试逻辑
- 设置
max_output_tokens防止生成成本失控
Token 统计
- 从响应对象中读取
usage.input_tokens和usage.output_tokens - 对推理模型,
output_tokens_details.reasoning_tokens显示思维链的 token 消耗 - 缓存命中的 token 出现在
input_tokens_details.cached_tokens
状态管理
- 如果使用手动回放,把
output数组可靠地持久化(数据库,不要只放内存里) - 推理模型的加密 reasoning 项必须原样回放,才能维持上下文
- 不希望 OpenAI 保留响应时,设置
store: false
降级行为
- 用你实际的工具配置分别测试每个服务商,确认哪些工具被支持
- 当降级服务商静默忽略不支持的工具时,记录日志并告警
- 考虑为 agentic(工具密集型)请求和简单生成请求使用不同的路由规则
迁移验证
- 确认响应解析同时处理
output_text项和function_call项 - 确认结构化输出使用
text.format而非response_format - 针对 OpenAI 和至少一个替代服务商运行集成测试
常见问题
Responses API 比 Chat Completions 贵吗?
不带内置工具的等价文本生成场景下,每 token 价格相同。OpenAI 表示 Responses 的缓存利用率更好,实际花费可能更低。web search 这类内置工具有独立的按次计费。
推理模型能用 Responses API 吗?
可以。从 GPT-5.4 开始,推理模型在 Responses API 中的工具使用体验有改善。Chat Completions 对 GPT-5.4 及以后的模型不支持 reasoning_effort 设为 none 以外的值进行工具调用。
现有的 Chat Completions 集成会受影响吗?
Chat Completions 仍然受支持,没有公布弃用计划。但新功能(内置工具、Conversations API、background 模式)只在 Responses 上提供。
DeepSeek 的 Responses API 和 OpenAI 的完全一样吗?
不一样。DeepSeek 支持核心的请求/响应格式、函数调用和 web search,但不支持有状态功能(previous_response_id、store、Conversations API)和 file_search、code_interpreter 等内置工具。不支持的参数会被静默忽略。
同一个应用里能同时用 Chat Completions 和 Responses API 吗?
可以,但不要在它们之间共享状态。Chat Completions 用 messages/choices,Responses 用 input/output,是两个独立的端点,对象结构不同。
延伸阅读
- OpenAI 官方 Responses API 迁移指南,附代码示例
- DeepSeek Responses API 兼容性说明,DeepSeek 的细节和限制
- OpenAI 对话状态管理文档,三种方式的详细说明
- Assistants to Responses API 迁移路由指南,分步迁移清单
- Assistants API 关停事后复盘,弃用事件的架构教训
- Assistants API 最终迁移清单,最后时刻的迁移步骤
- Assistants API 替代方案对比,Responses vs. Chat Completions vs. 第三方方案