GPTMap

ChatGPT Memory 架构解析:长上下文、向量检索与跨会话持久化

从架构师视角拆 ChatGPT Memory 的三层:1.05M token 长上下文 + 向量检索(RAG)+ 跨会话持久化层。覆盖 vector store 选型、memory 写入策略、上下文压缩、token 成本控制。

TL;DR
从架构师视角拆 ChatGPT Memory:三层组成——(1) 1.05M token 长上下文(直接放 prompt);(2) 向量检索层(按需召回 memory 项);(3) 跨会话持久化(每次对话结束后摘要 + 存入 vector store)。本文覆盖五个落地决策:(1) vector store 选型(pgvector / Pinecone / Weaviate);(2) memory 写入时机(每 turn 写 vs 摘要后写);(3) 上下文压缩策略(sliding window / hierarchical summary);(4) token 成本控制(cache 复用 + 分层 memory);(5) 跨会话一致性保证。
ChatGPT Memory 是 ChatGPT 在多次会话间保留用户偏好 / 事实 / 历史对话的能力,由『长上下文(1.05M token)+ 向量检索 + 跨会话持久化』三层组成。架构师关心的是:怎么在自家产品里搭一套等价方案,包括 vector store 选型、memory 写入策略、上下文压缩、token 成本控制。

ChatGPT Memory 不是『神奇的记忆』——它是三层架构组合:1.05M token 长上下文 + 向量检索(RAG)+ 跨会话持久化。本文从架构师视角拆这三层、给自家产品搭 Memory 的选型建议、写入策略、压缩算法、token 成本控制。

Memory 三层架构

┌─────────────────────────────────────────────┐
│  Layer 1: 长上下文(1.05M token)             │
│  - 最近 N 轮对话原文                          │
│  - 当前会话摘要                               │
│  - 用户偏好缓存                               │
└─────────────────────────────────────────────┘
              ↑ 召回 / 写入
┌─────────────────────────────────────────────┐
│  Layer 2: 向量检索层                          │
│  - 语义匹配(用户 query → 候选 memory 项)      │
│  - top-K 召回 + 重排序                        │
│  - 返回 (memory_id, text, score, timestamp)   │
└─────────────────────────────────────────────┘
              ↑ 持久化
┌─────────────────────────────────────────────┐
│  Layer 3: 持久化存储                          │
│  - Vector store(pgvector / Pinecone)        │
│  - KV store(偏好 / 设置)                    │
│  - 完整对话存档(用于重训练 / 审计)           │
└─────────────────────────────────────────────┘

每层承担不同职责

  • Layer 1(长上下文):给模型『回忆』窗口。1.05M token 看似大,但每次调用都塞满 cost 极高,所以只放『最近 N 轮 + 当前摘要』。
  • Layer 2(向量检索):按需召回历史 memory。Layer 1 放不下时,从 vector store 找 top-K 相关项塞 prompt。
  • Layer 3(持久化):memory 数据落盘。新对话进来 → 摘要 → 写入;用户删除 → 删除;跨设备同步。

核心设计原则——memory 不是用来替代 prompt 的,是用来减少重复输入保留跨会话上下文的。

Vector store 选型

生产环境选型取决于规模:

规模推荐理由
< 100K 向量pgvector跟 Postgres 共用一个 DB,零额外组件,足够好用
100K - 10MPinecone全托管,性能好,开发简单
> 10MWeaviate / Milvus自托管,性能强,但要运维团队

pgvector 实操

-- 启用 pgvector
CREATE EXTENSION IF NOT EXISTS vector;

-- memory 表
CREATE TABLE memories (
  id BIGSERIAL PRIMARY KEY,
  user_id TEXT NOT NULL,
  conversation_id TEXT,
  memory_text TEXT NOT NULL,
  embedding vector(3072),  -- text-embedding-3-large 维度
  memory_type TEXT,        -- 'preference' / 'fact' / 'summary'
  confidence FLOAT,
  created_at TIMESTAMPTZ DEFAULT now(),
  version INTEGER DEFAULT 1
);

-- HNSW 索引(快速近似最近邻)
CREATE INDEX ON memories USING hnsw (embedding vector_cosine_ops)
  WITH (m = 16, ef_construction = 64);

召回 SQL

-- top-5 召回
SELECT id, memory_text, memory_type,
       1 - (embedding <=> $1) AS similarity
FROM memories
WHERE user_id = $2
  AND version = (SELECT MAX(version) FROM memories WHERE user_id = $2)
ORDER BY embedding <=> $1
LIMIT 5;

性能上 pgvector + HNSW 在 100K 向量下召回 < 10ms,足够生产用。

Memory 写入策略

错误做法:每 turn 都写。1 个对话 50 turn 就写 50 条 memory,存储爆炸、噪声多。

正确做法:对话结束后生成三段式 summary 一次写入。

def summarize_and_store(conversation):
    response = client.responses.create(
        model="gpt-5.6-luna",  # 摘要用最便宜的
        input=[
            {"role": "system", "content": """你是 memory 摘要器。给定一段对话,输出三段:

1. 用户偏好(preferences):用户表达的偏好、习惯、风格要求
2. 关键事实(facts):用户提到的事实性信息(住址 / 工作 / 朋友名字等)
3. 对话摘要(summary):1-3 句话总结这次对话的核心内容

每段用 JSON 数组,每个元素 ≤ 200 字。只保留 confidence 高的,标记低 confidence 的不输出。"""},
            {"role": "user", "content": format_conversation(conversation)},
        ],
    )

    result = parse_summary(response.output_text)

    # 写入 vector store
    for memory in result.preferences + result.facts + [result.summary]:
        if memory.confidence < 0.7:
            continue
        embed = embed(memory.text)
        db.insert_memory(
            user_id=conversation.user_id,
            memory_text=memory.text,
            embedding=embed,
            memory_type=memory.type,
            confidence=memory.confidence,
            conversation_id=conversation.id,
        )

关键设计

  • 用最便宜的模型(gpt-5.6-luna)做摘要,节省成本。
  • confidence 阈值过滤噪声(< 0.7 不写入)。
  • 三段式比单一 summary 更结构化,召回时按 type 过滤更精准。

上下文压缩策略

1.05M token 不能每次都塞满 prompt。三种压缩策略叠加用:

Sliding window(最近 N 轮)

# 最近 20 轮对话原文
recent_turns = conversation.messages[-40:]  # 20 turn = 40 message

固定窗口,简单可靠,适合实时对话。

Hierarchical summary(旧对话压缩)

# 超过 20 轮的部分,用 summary 代替
if len(conversation.messages) > 40:
    older_summary = summarize_older(conversation.messages[:-40])
    prompt_messages = [
        {"role": "system", "content": f"对话历史摘要:{older_summary}"},
        *recent_turns,
    ]

每次对话结束,更新一次 summary。

按需召回(vector store 检索)

# 用户问题进来时,按问题召回相关 memory
relevant_memories = recall_top_k(user_query, user_id, k=5)

prompt_messages = [
    {"role": "system", "content": f"用户历史相关记忆:{format_memories(relevant_memories)}"},
    {"role": "system", "content": f"对话历史摘要:{older_summary}"},
    *recent_turns,
    {"role": "user", "content": user_query},
]

召回的 memory 只塞 top-K,不全塞。

Token 成本控制

Memory 系统的成本由三部分组成:

# 假设:每次调用 prompt ≈ 50K tokens(20 turn + summary + 5 memory)
# GPT-5.6 Terra: $2.50/$15 per MTok
cost_per_call = (50 * 0.001 * 2.5) + (1 * 0.001 * 15)  # ≈ $0.14

# 100 万次调用 / 月 = $140K
monthly_cost = 1_000_000 * 0.14  # $140K

优化:

优化节省实现
Prompt caching 复用 system prompt-50% input cost启用 prompt_cache_key + implicit cache
摘要用 Luna 不用 Terra-60% input costsummary_pipeline 用 gpt-5.6-luna
按需召回而不是全塞-30% input costvector recall 只取 top-K
旧对话压缩率提到 80%-20% input costhierarchical summary + 关键事实抽取

四件套上齐,月成本从 $140K 降到 ~$35K。

跨会话一致性

跨设备 / 跨会话保持 memory 一致的关键是版本化

# 写入时带 version
db.insert_memory(
    user_id=user_id,
    memory_text=memory.text,
    embedding=embed,
    version=current_version + 1,  # 单调递增
    created_at=now(),
)

# 召回时只取最新 version
SELECT ... WHERE user_id = $1
  AND version = (
    SELECT MAX(version) FROM memories WHERE user_id = $1
  )

关键设计

  • 每条 memory 带 (user_id, version, created_at, conversation_id)
  • 召回时只取最新 version,旧 memory 软删除(标记 deleted=true)。
  • 用户可以『回滚』——撤销最近一次 memory 写入。

常见坑

  1. 每 turn 都写:存储爆炸 + 噪声多。改用对话结束一次性摘要。
  2. 不标 confidence:低质量 memory 污染召回。LLM 输出时强制 confidence 评分。
  3. 不压缩直接塞:1.05M 看似大但成本高。用 hierarchical summary + sliding window。
  4. 跨会话版本冲突:用户 A 在手机和电脑同步时 memory 冲突。用 version + timestamp 解决。
  5. GDPR 不支持删除:欧盟用户有权要求删除所有 memory 数据。架构上要支持 user_id 级别的整批删除。
  6. 召回的 memory 当成事实:memory 是用户 / 模型生成的,可能错。让模型在 prompt 里知道 memory 是『用户过去说的话』,不是客观事实。

下一步

关键要点

  • Memory 三层架构:长上下文(直接放 prompt,给模型『回忆』窗口)+ 向量检索(RAG,按需召回)+ 持久化层(vector store / DB 落盘)。三层各有 tradeoff,不可互相替代
  • vector store 选型:pgvector(够用 / Postgres 复用 / 10M 以内向量)、Pinecone(全托管 / 性能好 / 贵)、Weaviate(功能多 / 自托管友好 / 运维复杂)。10M 以内 pgvector 性价比最高
  • Memory 写入不能每 turn 都写——会爆存储且大部分是噪声。正确做法:对话结束后让模型生成『摘要 + 偏好 + 事实』三段式 summary,再写入 vector store
  • 上下文压缩:1.05M token 看似很大,但每次都塞满 prompt 成本极高。用 hierarchical summary(旧对话压缩成 summary,新对话保留原文)+ sliding window(最近 N 轮)+ RAG 召回(按需取历史片段)
  • Memory 跨会话一致性的关键是『版本化』——每次写入打 timestamp + conversation_id,查询时按用户最新 version 召回,避免 memory 被旧对话污染

常见问题

传统 RAG 是『一次性召回』——查询时检索 top-K 文档塞 prompt。Memory 是『持续写入 + 按需召回』——每轮对话都可能新增 memory 项,跨会话累积。三层区别:(1) 传统 RAG 通常不修改长上下文;Memory 用 1.05M 长上下文做『最近 N 轮』;(2) 传统 RAG 召回量固定;Memory 按场景召回(问答时多召、闲聊时少召);(3) 传统 RAG 数据源固定;Memory 数据源会随对话增长。

官方参考

相关文章

订阅 GPTMap Weekly

每周一封邮件,精选 OpenAI 重要更新、深度解读与最佳实践。无广告,可随时退订。

GPTMap Editorial发布于 2026-08-13 9 分钟阅读
测试环境(EEAT)
最后测试时间:2026-08-13
使用模型:gpt-5.6