No Formulas · Flow Only

遗忘机制与倒排索引 · 流程详解

不用公式,用流程图 + 具体例子,解释 OpenClaw 记忆是怎么被记住、怎么被遗忘、怎么被找回来的。

Part 1

记忆是怎么被记住和遗忘的?

用一条记忆的完整生命周期,解释遗忘机制。

📖 一条记忆的完整生命周期
Step 1 · 记忆诞生
用户说:"我喜欢用 TypeScript,代码格式用 Prettier"
📄 memory/user.md 自动写入
用户偏好使用 TypeScript,代码格式偏好 Prettier
⏰ 创建时间: 今天 10:00 🔢 访问次数: 0
Step 2 · 记忆被调用
3天后,用户问:"这个项目用什么语言?"
👤
这个项目用什么语言?
🤖
搜索 memory/user.md,找到偏好记录,确认使用 TypeScript
访问次数: 0 → 1(+1)
📄 更新后的 memory/user.md
⏰ 创建时间: 今天 10:00 🔢 访问次数: 1
Step 3 · 记忆随时间"褪色"
时间流逝,记忆的"强度"逐渐下降:
第 7 天
84%
第 30 天
50%
第 90 天
12%
💡 不删除文件:只是检索时排名下降,文件永远保留
Step 4 · 被再次访问,记忆"强化"
第 35 天,用户又问类似问题:
👤
我的代码风格偏好是什么?
🔄
访问次数: 1 → 2,记忆被"唤醒",获得 boost
💡 效果
这条记忆被重新唤醒,分数暂时提升,不会继续衰减了。经常用的记忆永远不会忘,不用的自然会淡出。
Step 5 · 上下文快满时,自动保存
会话太长了,上下文要压缩了:
上下文快满了(176,000 tokens),触发"预压缩提醒"
🤖
收到提醒:把重要信息写进 memory/2026-05-08.md!
📁
所有重要信息被写入今日日志,会话结束后仍然存在
⚠️ 压缩后上下文会清空,但记忆文件不受影响,只是 Agent 暂时"失忆"
🔑 遗忘机制一句话总结

不是"删除文件",而是"降低排名"——记忆文件永远在磁盘上,只是检索时:

  • 越老的记忆 → 排名越靠后 → 越难被找到
  • 越常用的记忆 → 排名越靠前 → 越容易被找到
  • 上下文压缩前 → 自动把重要信息写入文件 → 不丢失

就像书架上的书:最近读的书放前面,经常翻的永远在前排,很久没动的书被挤到后面,但你没有扔掉它。

Part 2

倒排索引是怎么工作的?

用具体的数据,展示"从关键词到记忆"的完整查找流程。

📚 先看原始记忆(正向索引)

假设你的记忆文件里有这 4 条记忆:

文档 内容 包含的词
Doc 1 用户偏好使用 TypeScript 和 Prettier 用户、偏好、TypeScript、和、Prettier
Doc 2 项目使用 PostgreSQL 数据库 项目、使用、PostgreSQL、数据库
Doc 3 TypeScript 配置参考 Prettier 规范 TypeScript、配置、参考、Prettier、规范
Doc 4 数据库连接池大小配置 数据库、连接池、大小、配置

📖 正向索引:从文档 → 找它包含哪些词(人看很自然,但找东西要一个个翻)

🔄 翻过来,变成倒排索引

OpenClaw 把上面那个表"翻"过来,变成:

关键词 出现在哪些文档 文档数量
typescript Doc 1 Doc 3 2 个文档
prettier Doc 1 Doc 3 2 个文档
数据库 Doc 2 Doc 4 2 个文档
配置 Doc 3 Doc 4 2 个文档
用户 Doc 1 1 个文档
postgresql Doc 2 1 个文档

🔍 倒排索引:从词 → 一秒找到所有包含它的文档(就像书的索引目录)

🔍 完整搜索流程:用户问 "TypeScript 配置"
1

拆词

把问题拆成关键词:typescript + 配置

2

查倒排索引

"typescript" → Doc 1, Doc 3
"配置" → Doc 3, Doc 4

3

合并候选集

两个词都包含的文档:Doc 3 ← 最佳匹配!
只含一个词的:Doc 1 Doc 4

4

打分排序

Doc 3:含 2 个词 → 最高分
Doc 1:含 1 个词 → 中等分
Doc 4:含 1 个词 → 中等分

5

返回结果

第 1 名 → Doc 3:"TypeScript 配置参考 Prettier 规范"
第 2 名 → Doc 1:"用户偏好使用 TypeScript 和 Prettier"

🔀 实际用的是"混合搜索":关键词 + 语义

纯关键词搜索有个问题:用户问"网关主机"就找不到"router",因为不是同一个词。

🔤
关键词搜索
BM25:必须完全匹配词
"gateway" ≠ "router"
+
🧠
语义搜索
向量相似度:意思相近就算
"gateway" ≈ "router" ✓

OpenClaw 把两种方法的结果加起来:70% 语义分 + 30% 关键词分。
这样既能找到"意思相近"的,也能找到"精确匹配"的。

🗂️ 去重:MMR 算法

问题:如果 Doc 1 和 Doc 3 内容高度相似(比如都是讲 TypeScript 的),只保留一个就够了。

❌ 没有 MMR(重复内容多):
1
Doc 1:TypeScript + Prettier 偏好
2
Doc 3:TypeScript + Prettier 规范(❌ 和 Doc1 内容重叠!)
✅ 有 MMR(结果更多样):
1
Doc 1:TypeScript + Prettier 偏好
2
Doc 4:数据库连接池配置(✨ 和 Doc1 不重叠!)
3
Doc 3:TypeScript 配置规范

💡 MMR 逻辑:选了 Doc 1 后,和 Doc 1 太像的 Doc 3 会被扣分,让其他不同方向的记忆有机会冒头。

Part 3

记忆 + 遗忘 + 检索,完整串联

一个完整的对话场景,展示三个机制如何协同工作。

🎬 场景:用户在不同时间问同样的问题
⏳ 3 个月后(第 90 天)

记忆已经很"老"了:

1
最近的工作进展(上周)— 访问次数: 5
2
项目架构决策(上月)— 访问次数: 3
3
TypeScript 偏好(3个月前)— 访问次数: 1
⚠️ 分数被衰减了很多,排名第3
🌟 昨天刚设置过偏好

记忆很"新鲜":

1
TypeScript 偏好(昨天设置)— 访问次数: 2
✅ 分数很高,排名第1
2
最近的工作进展(上周)
3
项目架构决策(上月)
💡 结论
同一条记忆,新旧程度不同,排名完全不同。
但文件内容一模一样,只是检索时的"分数"不同。

🌿 遗忘机制

  • 记忆文件永远存在,不删除
  • 越老的记忆,检索时排名越靠后
  • 被访问的记忆,排名会提升
  • 上下文快满时,自动写入文件保存
  • 就像书架:常用的在前,不用的在后

🔍 倒排索引

  • 预先建好"词 → 文档"的目录
  • 搜索时直接翻目录,不用逐个翻文档
  • BM25 处理精确关键词匹配
  • 向量处理意思相近的词
  • 两种结果混合:70% 语义 + 30% 关键词

🗂️ MMR 去重

  • 避免相似内容重复出现
  • 选了 A 后,和 A 相似的 B 会扣分
  • 让不同方向的内容都有机会展示
  • 提升结果的多样性和覆盖度

⚡ 完整流程

  • 用户提问 → 拆词
  • 查倒排索引 + 向量搜索 → 得候选集
  • 混合加权 → 得综合分数
  • MMR 去重 → 得最终列表
  • 应用时间衰减 → 返回排序结果
OpenClaw Memory System · Flow Guide · 2026