"让记忆在睡眠中生长"
暨 MolaGPT 开发日志 - 其(十五)
mola
去年我写过一篇 Beyond Amnesia 介绍了 MolaGPT Tracks 的双轨记忆系统:事件记忆向量检索,人格洞察定期 LLM 分析,两条线各司其职,再通过 Prompt 注入统一交给模型。
这套系统运行了快一年,随着真实进入它的数据量越来越大,设计上的粗糙感变得越来越明显,并且这一年多来我也一直在关注行业里其他人是怎么做 Agent 记忆的,看到了不少让我重新审视自己方案的思路。最终我决定把旧的 MolaGPT Tracks 进行一次大的升级。
这篇文章聊聊旧系统的问题、新系统的设计,以及我在这个过程中的一些思考。
旧系统的结构
旧 MolaGPT Tracks 的事件记忆走的是最经典的 RAG 方式:每轮对话结束后,把内容切成切片后再 Embedding 进入向量库。下次聊天的时候,系统拿新问题作为 query 去向量库里检索最相似的片段,然后格式化构造之后注入到模型的上下文里。

RAG 的效率先不谈,这条线最大的问题是不分场合,不管你发什么,它都会完整走一遍存储流程。粘贴一篇论文让 MolaGPT 总结,那篇论文也会被切块、向量化之后当成的记忆保存。下次聊天的时候如果相似度碰巧够高,模型就会莫名其妙地把那篇论文的内容当作关于用户的记忆来引用。如果还要加上效率的话,开启 MolaGPT Tracks 之后,每一轮对话都要进行一次 Embedding 加向量检索加相似度打分,即使用户只是说了句你好,后面也有一次 RAG 在等待,直接拖慢了首 Token 到达的速度。
在内部 Benchmark 中,我使用了 5,782 个会话作为数据。测试结果显示,旧 MolaGPT Tracks 系统的向量库里只有 597 个分片,覆盖率只有 10% 出头,且检索命中率极低。在相同的 Bench 中进一步调查发现,旧的 MolaGPT Tracks 系统在 12 次采样里 83% 返回空结果。

另一条线是洞察系统,思路其实更好一些:定期把新产生的对话文本拼在一起让 LLM 通读,提炼出关于用户的结构化理解,每条洞察带置信度和半衰期,会随时间自然衰减。
它的问题是:分类框架是我手动定义的八个固定类别,LLM 必须在这个框架里做归类,能理解的维度实际上被限死了,并且洞察的演化也只有新建、强化、驳斥、改写四种操作,粒度偏粗。
站在一年之后我对旧 MolaGPT Tracks 的评价是:事件记忆和洞察完全割裂,一边在无差别地做嵌入,一边在做看起来很灵活实则死板的框架式归纳,两者之间没有一点点信息流动,不过我当时把它称为双轨驱动其实也能说得过去吧。
行业在怎么做
这一年多来 AI 记忆这个方向卷得很快,大致可以分成三条路线:最简单的是直接在提示词里维护一块记忆区域,存放用户偏好和历史摘要。现在主流模型普遍支持百万级上下文窗口,缓存也越来越便宜,往提示词塞东西反而成了最大巧不工的策略;再进一步的是渐进式披露,维护一份记忆索引常驻在上下文,模型觉得需要更多细节的时候再去读取完整内容,既控制了上下文膨胀,又保留了按需调取的能力。
还有社区(不管是 Coding 亦还是酒馆人机恋)各种多层 memory 方案,把记忆拆成短期、长期、情景、语义实体好几层,配上向量检索和 RAG。但是这些记忆的生命周期管理和失效策略往往比记忆本身更难设计,过于自动化的记忆容易成为一个不好调试的黑箱,多层检索还会引入排序、去重、冲突解决等一系列工程问题,很多时候简单的系统,其效果反而好更好。
MolaGPT Tracks 2.0 的设计更偏向前两种路线:常驻上下文提供核心记忆,按需检索补充长尾,但其最大的不同在于记忆的产生方式。
Dream
新系统的核心想法来自人类的睡眠记忆巩固。白天经历的事情并不是实时写入长期记忆的,大脑会在夜间的不同睡眠阶段对这些经历做筛选和整合,重要的巩固下来,不重要的自然遗忘。我觉得这个思路特别适合用来解决旧系统那个不分场合的问题:白天聊天的时候什么都不做,到了晚上再统一处理。
所以 Tracks 2.0 的记忆产生方式跟旧系统完全相反。聊天过程中没有 Embedding 计算,所以自然也没有任何额外的请求拖慢对话。每天到了凌晨,系统会自动运行,像做梦一样把白天的对话消化成记忆,这个流程分成浅睡、深睡、周巩固三个阶段,对应不同层次的处理。
浅睡:摄入
这一过程每天进行一次,从当天的对话里筛选出值得记住的内容,在此我用了一个被严格约束的 LLM 来做判断,第一步看整段对话的性质,如果这是一场角色扮演、文档翻译或者代码调试,整段跳过不做提取,这就直接解决了旧系统把翻译论文当作记忆存起来的问题。第二步对正常对话里的每条消息做精细提取,要求 LLM 同时给出用户的原话引用和一条规范化的事实陈述,原话引用很重要,后面的巩固阶段会拿它回原始对话里做比对,对不上的直接拒掉,这是整套系统防止 LLM 在提取阶段就开始产生幻觉的第一道保障。
在内部 Benchmark 中,浅睡 phase 累计 triage 了 4,084 场对话,跳过了其中 1,320 场,有 32.3% 的对话被跳过,数据显示,这其中有 822 场被判定为 document(粘贴论文、网页等),415 场是 coding(纯调试),还有 23 场 roleplay(会扰乱记忆系统的判断),这些对话类型对记忆系统来说是一种很大的噪音。

需要特别注意的是,涉及健康状况、宗教信仰、密码凭证之类的敏感内容会被 MolaGPT Tracks 自动跳过。
深睡:巩固与整理
深睡是记忆真正被写入的环节,浅睡产出的候选先按主题做聚类,跟已有的记忆条目对比,找出哪些是全新的、哪些跟已有记忆矛盾,然后生成一段简短的叙事追加到 DREAMS.md 里,可以理解为一篇梦境日记。

接下来,每条候选要过一轮打分,综合考虑这件事是用户主动提到的还是随口带过的、是不是在多次对话里反复出现过、内容具不具体、时效性如何,以及用户有没有给过明确的反馈。
对于已经出现迹象但是用户又没有明确反馈的候选会被暂存在一个池子里,如果同一件事后来又被提到了,之后巩固的时候就会被补充进记忆中。所有候选写入前都会回到原始对话做回溯校验,确认用户确实说过这些话,防止 LLM 在提取阶段就产生幻觉。
除了每晚的巩固之外,系统每周还会固定进行一次整理,把到期的、长期没被提到的记忆淘汰掉,重复的合并,过时的修正,确保即使用户很久没跟 MolaGPT 聊天,那些过时的记忆不会影响到用户的即时情景。
记忆怎么被使用
旧的 MolaGPT Tracks 每轮对话都要跑一次向量检索,新系统反过来了。所有活跃的记忆会被实时渲染成一份 MEMORY.md,每次对话时直接放进模型的上下文里,不需要任何检索动作。没被收进常驻上下文的长尾记忆,模型可以通过一个检索工具按需调取。

从之前的被动检索到按需 Recall,大幅改善了在启用 MolaGPT Tracks 之后日常聊天的延迟,Benchmark 显示,MolaGPT Tracks 2.0 更新后,用户日常聊天的性能提升了约 489 倍。
记忆中心

这次也上线了一个前端的记忆中心页面,用户可以在里面看到 MolaGPT 记住了哪些事情,每条记忆的置信度和来源,还可以对单条记忆做认同、存疑、拒绝的反馈。这些反馈会直接影响下一次深睡巩固时的打分,不想被记住的东西删掉就是真的删掉了。

我会对其继续进行微调。您可以启用 MolaGPT Tracks 进行广泛体验,去感受其对您的「感受」!

发表回复