为什么不用 RAG 做记忆系统 ——压缩上下文与 memory.md 的架构选择

对话记忆 ≠ 知识检索。用向量数据库存对话历史,就像用 Google 搜索来记住你昨天吃了什么。

先摆结论

在做 AI 应用落地时,有些团队把 RAG(检索增强生成)当成万金油------知识库用 RAG,对话历史也用 RAG,用户偏好还是用 RAG。但是实际用下来会发现 AI 总是失忆,用户体验糟糕。

根本原因在于:RAG 是为查找外部知识而设计的,不是为记住对话上下文设计的。

这两件事虽然都需要存储 + 检索,但底层需求完全不同。

RAG 是什么,它本来解决什么问题

RAG(Retrieval-Augmented Generation)的工作流程:

flowchart LR A[文档/FAQ/手册] -->|切片 + 向量化| B[(向量数据库)] C[用户提问] -->|向量化| D{语义相似度搜索} B --> D D -->|召回 top-k 片段| E[拼入 Prompt] C --> E E --> F[模型生成回答]

这个场景是 RAG 的主战场:大规模、相对静态、面向事实查询的知识库

✅ RAG 真正擅长的问题:

  • "我们公司的退款政策是什么?"
  • "合同第 7 条款说了什么?"
  • "Python asyncio 的最佳实践是什么?"

这些都是主动查询外部事实的场景,RAG 完全胜任。

当 RAG 遇到对话记忆

很多团队会把用户的对话历史也存入向量数据库,逻辑看似合理:"我把每次对话都存下来,下次用户问相关问题时,检索出来给 AI 看,AI 就有记忆了。"

实际上呢?

让我们看一个真实的失败场景。

案例:某 AI 私人助手,对话历史存入向量数据库

第一天的对话:

👤 我最近在学 Rust,帮我规划一下学习路径

🤖 好的!建议你从所有权系统开始......(详细规划)

👤 顺便说一下,我的技术背景是 Python,做了 5 年后端

三天后,新的对话:

👤 帮我写一个 Rust 的 HTTP 客户端示例

🤖 ❌ 好的,这是一个基础的 HTTP 客户端示例。首先你需要了解什么是 HTTP 协议......(从零开始解释基础概念)

为什么失败?

用户的查询是写 HTTP 客户端,而历史中我有 5 年 Python 后端经验这句话,和这个查询的语义相似度极低,向量检索根本不会召回它。

flowchart TD Q["用户查询:帮我写 Rust HTTP 客户端"] DB[(向量数据库\n存有对话历史)] Q -->|向量化 + 相似度搜索| DB DB -->|"❌ 未召回:我有5年Python经验\n语义距离太远"| X[关键信息丢失] DB -->|"✅ 召回了:Rust HTTP 相关片段\n但缺少用户背景"| Y[回答缺乏个性化] X --> Z["AI 把用户当初学者,从头解释 HTTP"] Y --> Z

RAG 用于记忆系统的四大结构性缺陷

缺陷 1:相关性 ≠ 重要性

向量检索召回的是语义最相似 的内容,不是最重要的内容。

用户说"我不喜欢废话连篇的回答"------这是极其重要的偏好,但它和绝大多数技术问题的语义距离都很远,几乎永远不会被检索到。

缺陷 2:上下文是整体,不是碎片

对话中"我、我老婆、我们的项目"是一个整体叙事。但是被切片存储后,人称关系断裂,AI 拿到孤立片段,很容易产生理解错误。

比如"她不喜欢这个方案"存入向量库后,下次检索出来,AI 已经不知道"她"是谁了。

缺陷 3:增加了不确定性

RAG 召回的 top-k 策略是概率性的。同一个问题,在不同时机、不同 embedding 模型版本下,可能召回完全不同的历史片段,导致 AI 行为难以预测和调试。

缺陷 4:维护成本高

问题 影响
需要运维向量数据库(Pinecone / Weaviate...) 增加基础设施复杂度
embedding 模型版本更新 历史数据要重新向量化
用户信息发生变化 旧向量还在库里持续干扰

那既然有这么多缺陷,我们实际落地时要怎么办呢?

方案一:压缩上下文(Context Compression)

压缩上下文的核心思路:不要让 AI 去检索记忆,而是直接把精炼过的记忆放进 context 里。

flowchart TD A["对话进行 N 轮\ntoken 快到上限"] --> B["触发压缩\nAI 将 N 轮浓缩为结构化摘要"] B --> C["摘要存入普通 KV 数据库\n无需向量化"] C --> D["丢弃原始对话\n用摘要继续对话"] D --> E["新对话继续积累"] E -->|"再次触发压缩"| B

效果对比

同样的问题,换了方案之后。

注入 system prompt 的摘要:

csharp 复制代码
【用户背景】
- 5 年 Python 后端经验,熟悉 FastAPI 和 async 编程
- 目前正在学习 Rust,已完成所有权章节
- 偏好:代码示例简洁,不需要解释基础概念

【上次对话摘要 (2025-03-18)】
用户询问了 Rust 学习路径,决定下一步学习 async/await。
用户明确表示不喜欢理论解释,更喜欢直接看代码。

对话效果:

👤 帮我写一个 Rust 的 HTTP 客户端示例

🤖 ✅ 直接上代码,用 reqwest 库。考虑到你熟悉 Python async,这里的 .await 语法应该很眼熟:

rust 复制代码
use reqwest;
async fn fetch(url: &str) -> Result<String, reqwest::Error> {
    reqwest::get(url).await?.text().await
}

AI 知道用户是老手,直接给代码;知道用户学过 Python async,做了类比------一切关键上下文都完整保留了。

方案二:memory.md(结构化记忆文件)

压缩上下文解决了会话历史的问题,但还有另一类记忆:关于用户本身的长期事实性记忆。比如职业背景、沟通偏好、正在进行的项目......

这些不应该每次都从对话历史中重新推断,而应该有一个固定的用户档案------这就是 memory.md

示例文件:

markdown 复制代码
## 基本信息
- 职业:后端工程师,5 年经验,主力语言 Python
- 时区:Asia/Shanghai,上班时间 10:00-19:00
- 沟通偏好:简洁直接,代码优先,不需要废话

## 正在进行的项目
- **Rust 学习**:进度到第 8 章(错误处理),目标是重写内部数据管道
- **工作项目**:某 SaaS 产品 API 性能优化,技术栈 FastAPI + PostgreSQL

## 重要偏好
- 不喜欢过度解释显而易见的概念
- 喜欢类比 Python 来理解新语言特性
- 代码示例:真实可运行 > 简化示例

## 最近的关键决策
- 2025-03-15:决定用 tokio 作为 Rust 异步运行时
- 2025-03-10:选择了 reqwest 作为 HTTP 客户端库

## 待跟进
- 等用户确认是否需要帮助设计数据库 schema

memory.md 的关键特性:

特性 说明
人类可读可编辑 用户可直接打开查看、修改,完全透明
确定性读取 全文注入 prompt,不存在召回率问题
轻量易维护 普通文本文件,不依赖任何外部向量服务
信息密度高 1000 token 可覆盖几个月的关键记忆
AI 自动维护 发现新重要信息时,自动更新对应字段

两个方案如何配合

两层架构,解决不同时间尺度的记忆问题:

flowchart TD subgraph 短期["🔵 短期记忆(会话内)"] A1[对话轮次 1] A2[对话轮次 2] A3[对话轮次 N] end subgraph 长期["🟢 长期记忆(跨会话)"] C["memory.md\n用户长期档案"] end A1 & A2 & A3 -->|"触发压缩"| B["压缩摘要\n(当前会话精华)"] B --> SP["System Prompt\n= memory.md + 压缩摘要"] C --> SP SP --> AI[AI 回答] AI -->|"发现新信息时自动更新"| C

关键点:两层记忆都不需要向量检索,都是确定性地注入 system prompt 的。

这避免了所有的召回率问题,让 AI 的行为变得可预测、可调试。

那 RAG 什么时候用?

判断标准只有一个:

这条信息,是用户主动问 出来的(查询外部知识),还是在对话中被动透露的(积累的上下文)?

  • 前者 → 用 RAG
  • 后者 → 用 memory.md + 压缩上下文
场景 推荐方案
用户对话历史 压缩上下文摘要
用户偏好 / 背景 memory.md
公司内部文档 / FAQ RAG(向量检索)
正在进行的任务状态 memory.md 待跟进字段
大规模技术文档语义搜索 RAG(向量检索)

业界是怎么做的

这套思路并不是凭空而来,看几个真实的工业级产品,会发现殊途同归。

OpenAI Codex / Claude Code :这类工具在启动时会扫描项目目录,把 README.md、目录结构、关键配置文件直接读入上下文,同时在对话中自动维护一份"当前任务状态"的结构化摘要。它们几乎不用向量检索来回忆之前的操作------而是靠不断压缩和更新的 working memory 来维持任务连贯性。

OpenClaw / Cursor 等 : Cursor 的 .cursorrules 文件本质上就是 memory.md 的工程化实现------一个由开发者手写(或 AI 辅助维护)的项目级偏好文件,每次对话都全量注入。用户发现告诉 AI 一次就永远记住的最可靠方式,不是让 AI 检索历史对话,而是直接写进这个文件。

Anthropic Claude 和 ChatGPT 的 Memory 功能 :官方记忆功能正是生成结构化的用户档案 Markdown 片段,在每次对话开始时注入 system prompt。

落地时的注意事项

1. 压缩摘要的触发时机

不要等到 context 真的撑满了再压缩,那时候已经来不及了。推荐的策略:

  • 固定轮数触发:每 15-20 轮对话压缩一次,简单可靠
  • token 阈值触发:当 context 用量超过模型上限的 60%-70% 时触发,留出压缩本身需要的空间
  • 话题切换触发:检测到用户开始讨论新话题时,把旧话题先压缩归档

2. 压缩摘要的 Prompt 设计

压缩质量直接决定记忆质量,这步不能偷懒。一个有效的压缩 prompt 应该明确告诉 AI 要保留什么:

markdown 复制代码
请将以下对话压缩为结构化摘要,必须保留:
1. 用户透露的个人背景和偏好
2. 已经做出的决策和选择(不要省略)
3. 未完成的任务和待跟进事项
4. 重要的上下文约束(如技术栈、团队规范)

不需要保留:
- 具体的代码细节(除非是核心架构决策)
- 过程中的错误尝试
- 礼貌性寒暄

输出格式为 Markdown,使用 ## 分节。

3. memory.md 的更新策略

不要让 AI 在每轮对话后都去判断要不要更新 memory.md,这会引入大量无意义的写操作,也会让 AI 分心。更好的做法:

  • 异步更新:在每次对话结束后(用户关闭会话),单独跑一次提炼新信息的任务
  • 增量 diff:让 AI 只输出新增/修改/删除的字段,不要每次重写整个文件
  • 版本控制memory.md 最好用 git 管理,方便回滚和审计

4. memory.md 的大小控制

肯定不是越大越好。

注入 prompt 是有 token 成本的,而且太长的 memory.md 反而会稀释重要信息的权重。

我的粗浅的经验值:500-1500 token 是可靠区间,超过 2000 token 就要考虑归档旧内容了。可以给 memory.md 做个分层:

  • memory.md:当前活跃的核心信息(≤1000 token,每次注入)
  • memory_archive.md:历史归档(不注入,只在用户主动询问时检索)

5. 警惕污染

AI 自动维护 memory.md 时,偶尔会写入错误信息------比如误解了用户的意思,或者把临时性的表述当成了长期偏好。

应对方法:

  • 在 UI 上给用户提供查看或者编辑记忆的入口,让用户能随时纠正
  • memory.md 的写操作做人工确认(至少在产品早期),积累足够样本后再改成全自动

写在最后

我之前一直写 Java 相关的技术文章,框架、性能调优、微服务架构......写了很多年,也算积累了一些东西。

但这一阵开始转向 AI 应用落地,刚开始是有点迷茫的。这个领域变化太快,概念满天飞,每隔几天就有新的模型、新的框架、新的最佳实践冒出来,感觉自己永远在追赶。

于是我就干脆停下来,不追热点了,老老实实地去做项目、踩坑、复盘。这篇文章里关于 RAG 做记忆系统的问题,就是我们团队实际踩过的坑。在我看来,这些东西才是应该认真沉淀和分享的,而且这些经验,只有真正做过落地才知道。

以后我会慢慢把这些心得整理出来分享,关于 AI 应用架构、prompt 工程、agent 设计......都是从实际项目里提炼的精华。

最后,想跟大家说:不要怕被 AI 淘汰。

我在实际做 AI 应用的过程中,越来越清楚地感受到一件事------AI 现在有多强大,就有多需要人来掌舵。 至少目前的阶段仍然如此。

模型不知道你的业务边界在哪里,不知道你的用户真正在意什么,不知道一个决策背后的组织博弈,不知道什么时候该停下来让人工介入。这些判断,现阶段全都需要人来做。

所以现在这个阶段,真正的竞争不是"你 vs AI",而是 "会用 AI 的你 vs 不会用 AI 的你"

掌握足够的 AI 使用和应用技能,不只是不被淘汰,更可能是借着这波浪潮,做出以前根本没条件做的东西。

共勉。

相关推荐
智能工业品检测-奇妙智能2 小时前
国产化系统的性价比对比
人工智能·spring boot·后端·openclaw·奇妙智能
咚咚王者2 小时前
人工智能之语言领域 自然语言处理 第十九章 深度学习框架
人工智能·深度学习·自然语言处理
独隅2 小时前
Python AI 全面使用指南:从数据基石到智能决策
开发语言·人工智能·python
啊巴矲2 小时前
小白从零开始勇闯人工智能:机器学习汇总(复习大纲篇)
人工智能
耶叶2 小时前
如何在AndroidStudio里面接入你的AI助手
人工智能·android-studio
OpenBayes贝式计算2 小时前
教程上新丨基于 GPU 部署 OpenClaw,轻松接入飞书/Discord 等社交软件
人工智能·深度学习·机器学习
编码忘我2 小时前
java强引用、软引用、弱引用、虚引用
后端
Georgewu2 小时前
【智能体】OpenJiuWen开源智能体开发框架讲解
ai编程
小超同学你好2 小时前
Langgraph 17. Skills 三级加载与 Token 优化(含代码示例)
人工智能·语言模型·langchain