← 全部文章

Assistants 关停之后:OpenAI Responses API 迁移模式与架构指南

Assistants API 在 8 月 26 日关停。这篇指南面向已经完成迁移的团队,讲清楚 Responses API 的对话状态管理、工具编排、流式传输,以及通过 OpenAI 兼容网关实现跨服务商路由的实际做法。

· TheRouter

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 CompletionsDashScope 使用 OpenAI 兼容的 Chat Completions,不原生支持 Responses API 格式,但 Qwen 模型可以通过 Chat Completions 路由访问。

路由架构

通过 TheRouter 这样的网关路由 Responses API 流量时,有几点需要注意。

  1. **无状态请求路由没有障碍。**如果使用手动状态回放(上面的方案三),同一个请求可以发到任何支持 Responses API input 格式的服务商。
  2. 有状态参数是服务商专有的。previous_response_id、store: true 和 Conversations API 只在请求到达 OpenAI 时有效。路由器无法为其他服务商合成服务端状态。
  3. **工具可用性因服务商而异。**带 web_search 或 function 工具的请求可以路由到支持它们的服务商。带 file_search 或 code_interpreter 的请求必须到 OpenAI。
  4. **降级需要谨慎处理。**如果 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,是两个独立的端点,对象结构不同。

延伸阅读

本文涉及的模型

帮助与联系