大模型记忆
2026-04-09
现有主流方案
1. 全量上下文(Full Context Stuffing)
把所有历史信息直接塞进 context window。
代表项目: Claude Projects — 用户可以上传文档和对话历史,每次对话都带入全量上下文。
优点:
- 实现最简单,无需额外系统
- 模型能看到完整信息,不存在召回遗漏
缺点:
- 成本随上下文长度线性增长
- 注意力机制在超长上下文下会衰减("lost in the middle"问题)
- 有硬性窗口上限,无法无限扩展
2. 摘要压缩(Summarization)
定期用 LLM 对历史对话或文档进行摘要,只保留压缩后的版本。
代表项目: LangChain ConversationSummaryMemory — 超过一定轮次后自动调用 LLM 生成摘要替换原始对话。
优点:
- 大幅压缩存储和上下文占用
- 实现相对简单
缺点:
- 有损压缩,细节不可逆丢失
- 摘要本身可能引入幻觉
- 无法回答需要原始细节的问题
3. 纯向量 RAG(Vector Retrieval)
将知识切片后向量化存储,查询时做语义相似度检索,召回相关片段注入上下文。
代表项目: Mem0 — 专为 AI 助手设计的记忆层,对话内容自动提取后存入向量数据库,查询时语义召回。
优点:
- 存储可无限扩展
- 语义搜索能跨越关键词差异找到相关内容
缺点:
- 搜索空间平铺,语义相似 ≠ 真正相关
- 不理解时间,无法区分"历史上说过"和"现在还成立"
- 召回精度受 chunk 质量和 embedding 模型影响大
4. 知识图谱(Knowledge Graph)
将信息结构化为实体-关系三元组存储,支持图查询和推理。
代表项目: Zep — 为 AI 助手提供长期记忆,使用知识图谱存储实体关系,支持跨对话的事实查询。
优点:
- 实体关系显式存储,可直接查询
- 支持多跳推理(A 认识 B,B 负责 C)
缺点:
- 结构化提取本身有损,自然语言转三元组会丢失语境
- 对非结构化知识(偏好、经验)不友好
- 系统复杂度高,通常依赖 Neo4j 等专用图数据库
5. 外部工具记忆(Tool-based Memory)
让模型通过工具调用主动读写记忆,模型自己决定存什么、查什么。
代表项目: OpenAI Memory — ChatGPT 的记忆功能,模型在对话中自动判断哪些信息值得记住,写入持久化存储。
优点:
- 模型主动管理,存储内容质量高
- 用户可见、可控、可编辑
缺点:
- 依赖模型判断,可能漏存重要信息
- 写入时机不稳定,一致性难保证
- 规模化后查询效率问题同纯向量 RAG
各方案对比
| 方案 | 召回精度 | 时效性 | 存储成本 | 实现复杂度 |
|---|---|---|---|---|
| 全量上下文 | ★★★★★ | ★★★★★ | ★☆☆☆☆ | ★☆☆☆☆ |
| 摘要压缩 | ★★☆☆☆ | ★★★☆☆ | ★★★★★ | ★★☆☆☆ |
| 纯向量 RAG | ★★★☆☆ | ★★☆☆☆ | ★★★★☆ | ★★★☆☆ |
| 知识图谱 | ★★★★☆ | ★★★★☆ | ★★★☆☆ | ★★★★★ |
| 外部工具记忆 | ★★★☆☆ | ★★★☆☆ | ★★★★☆ | ★★★☆☆ |
合理的方案:分层混合记忆系统
单一方案都有明显短板。合理的做法是把不同层的职责分清楚,组合使用。
┌─────────────────────────────────────┐
│ 查询入口 │
└──────────────┬──────────────────────┘
│
┌───────▼────────┐
│ 结构层过滤 │ 先缩小搜索空间
└───────┬────────┘
│
┌───────▼────────┐
│ 向量层召回 │ 语义相似度匹配
└───────┬────────┘
│
┌───────▼────────┐
│ 图谱层验证 │ 时效性 + 关系推理
└───────┬────────┘
│
┌───────▼────────┐
│ 存储层原文 │ 逐字返回,不摘要
└────────────────┘
存储层(Storage Layer)
职责: 保存原始内容,永不摘要。
所有用户内容以逐字形式存储,不经过 LLM 压缩。这是整个系统的信息地基。
为什么不摘要:
- LLM 摘要会引入幻觉,把"用户说的"变成"模型理解的"
- 细节一旦丢失不可恢复
- 存储成本远低于召回错误的代价
存储内容分类:
- 原始对话片段
- 文档、代码、笔记的原文
- 用户的明确表述(偏好、决策、事实)
实现: 通常用对象存储或文档数据库(SQLite、PostgreSQL),按 ID 索引,供上层引用。
结构层(Structure Layer)
职责: 给每条记忆打元数据标签,为检索提供前置过滤器。
这是整个系统中对召回精度影响最大的一层。向量搜索的精度瓶颈不在 embedding 质量,在于搜索空间太大。结构层通过元数据把 10 万条候选缩减到几十条,再做向量匹配。
元数据维度设计:
实体维度(属于谁)
└── 人物、项目、组织
主题维度(关于什么)
└── 认证、部署、计费、架构...
类型维度(是什么类型的知识)
├── facts — 决策和选择
├── events — 发生过的事情
├── preferences — 偏好和习惯
├── discoveries — 新发现和突破
└── advice — 建议和解决方案
时间维度(什么时候的)
└── 创建时间、有效期
检索流程:
- 解析查询意图,识别实体和主题
- 用元数据过滤,缩小候选集
- 在候选集内做向量搜索
关键挑战: 分类质量决定召回上限。入库时的分类错误会导致查询时永远找不到。需要对分类逻辑做持续校验。
向量层(Vector Layer)
职责: 在结构层过滤后的候选集内做语义相似度匹配。
不做全库搜索,只在结构层给出的候选范围内检索。这是向量搜索应该处于的正确位置——作为精排器,而不是粗筛器。
核心组件:
- Embedding 模型:将文本转为向量(text-embedding-3-large、BGE、Nomic 等)
- 向量数据库:存储和检索向量(ChromaDB、Qdrant、Weaviate)
- 相似度算法:余弦相似度或点积
设计要点:
- chunk 粒度要合理,太大语义模糊,太小丢失上下文
- embedding 模型要和使用场景匹配(多语言、代码、长文档各有最优选择)
- 召回 top-k 后可加 reranker 做二次排序
图谱层(Graph Layer)
职责: 解决向量搜索无法处理的两类问题——时效性和关系推理。
问题一:时效性
向量搜索不理解时间。同一个问题在不同时间有不同答案,向量搜索会把所有历史版本都召回,无法判断哪个"现在还成立"。
图谱层用带时间戳的三元组解决这个问题:
(项目A, 使用数据库, PostgreSQL, 2025-01 ~ 2025-06)
(项目A, 使用数据库, MongoDB, 2025-06 ~ 2026-01)
(项目A, 使用数据库, PostgreSQL, 2026-01 ~ now )
查询"现在用什么数据库"时,直接查有效期覆盖当前时间的三元组,精确返回。
问题二:关系推理
向量搜索是 chunk 级别的,无法跨文档聚合实体关系。图谱层把实体关系显式存储,支持多跳查询:
谁负责认证模块?
→ 项目A -[包含]→ 认证模块 -[负责人]→ 张三
实现建议:
- 轻量场景:SQLite 存三元组,够用且零依赖
- 复杂场景:Neo4j 或 Kuzu,支持 Cypher 查询语言
- 三元组提取可用 LLM,但要做置信度过滤,避免幻觉写入
各层协作示例
场景: "这个项目现在的认证方案是什么,为什么这么选?"
1. 结构层
解析出:实体=项目A,主题=认证,类型=facts
过滤后候选集:从 50000 条 → 23 条
2. 向量层
在 23 条里做语义搜索
召回 top-3:
- "决定用 JWT,因为需要无状态横向扩展"(2025-03)
- "考虑过 Session,但放弃了"(2025-02)
- "JWT 密钥轮换方案确定"(2025-08)
3. 图谱层
验证时效性:JWT 方案三元组有效期覆盖当前时间 ✓
补充关系:JWT → 依赖 → auth-service(负责人:李四)
4. 存储层
返回原始逐字内容,不做二次摘要
最终注入上下文的是精准的 3 条原文 + 图谱补充的关系信息,而不是 50000 条里随机召回的噪声。
小结
没有银弹。全量上下文在小规模下仍然是最简单有效的选择。分层混合系统的价值在规模化之后才完全体现——当记忆量超过上下文窗口,且对召回精度有较高要求时,这套架构是目前最合理的工程路径。
核心原则只有两条:
- 永不摘要原始内容 — 信息损失不可逆
- 用结构缩小搜索空间 — 向量搜索是精排器,不是粗筛器