大模型没有记忆:从 Chat Completions 到 Responses API 看对话连续性

在调用 LLM 构建聊天应用时,模型看似具备连续对话的能力。但在底层协议中,模型本身是完全无状态(Stateless)的。搞清楚“上下文如何传递”,是理解大模型系统架构的关键。

核心差异:状态由谁来管?

OpenAI 的两大主流接口展现了不同的设计思路:

维度 Chat Completions API Responses API
状态维护方 客户端应用层 API 服务端
接续方式 每次完整回传历史 messages 数组 仅需传入上一轮的 previous_response_id
若不传上下文 独立隔离(互为“平行世界”) 独立隔离(互为“平行世界”)
多厂商兼容性 极高(已成为跨模型通用工业事实标准) 偏低(OpenAI 专属生态规范)

两者的实现方式对比

1. Chat Completions API:客户端拼接 如果不把过往的对话重新打包发送,第 2 次请求就是一个全新的平行世界,模型对上一轮一无所知。

# 第 3 轮提问时,应用端必须手动把前两轮完整拼装进去

messages = [

    {"role": "user", "content": "我叫张三,请记住我的名字。"},

    {"role": "assistant", "content": "明白,您叫张三。"},

    {"role": "user", "content": "我叫什么名字?"}

]

response = client.chat.completions.create(model="gpt-4o", messages=messages)

逻辑本质:LLM 没有记住任何事,只是应用层每次都把历史记录当成新的 Prompt 完整投喂了一遍。

2. Responses API:服务端引用 Responses API 引入了链式引用机制,客户端无需组装长数组,只需携带上一次响应的唯一凭证:

# 第 1 轮

resp1 = client.responses.create(model="gpt-4o", input="我叫张三")


# 第 2 轮:直接关联上一轮的 Response ID

resp2 = client.responses.create(

    model="gpt-4o",

    previous_response_id=resp1.id,

    input="我叫什么名字?"

 

)

逻辑本质:状态搬运的工作从客户端转移到了 OpenAI 服务端。在推理前,服务端根据 ID 调出上下文并自动填入 Prompt。

使用 Responses API 的技术约束

  • 指令不会默认继承:首轮设置的 instructions(系统指令)不会随 previous_response_id 自动顺延,后续调用仍需单独管理。
  • 并非持久数据库:服务端缓存的 Response 存在生存周期与数据保留策略限制(如 Zero Data Retention 模式),不可当作长期用户画像库使用。

架构启示:从 Prompt 拼装到企业级状态机

模型从来没有诞生过人类般的持久记忆,所谓的“对话连续性(Conversation Continuity)”,本质始终是“如何将过去的上下文精准输入给当前的推理引擎”。

在真实的生产级架构中,上下文早已超出了“聊天气泡记录”的范畴。一个成熟的 AI 平台(如企业级 Agent 编排框架),需要管理:

  • 当前业务节点的推进状态(Workflow State)
  • 跨会话的持久化用户画像(Long-term Context)
  • 动态外部知识库检索结果(RAG Context)

对话连续性的工程核心,从不是纠结于单次 API 的拼接手法,而是在系统层构建一套能够兼顾跨平台兼容、业务状态持久化与 token 成本控制的会话状态管理架构。