Cxin Blog

Back

Memory System:记忆系统的那些事

上一篇提到,记忆系统是为了解决模型上下文限制而出现的一类方法。

但如果把问题再往前推一步,会发现“记忆”并不只是把旧信息存起来。它真正要解决的是:什么值得留下,什么时候应该取回,以及新旧信息冲突时该相信谁。

1. 记忆系统只回答一个问题#

1.1 LLM 的缺陷#

模型有两个基本约束:

  1. 无状态:一次调用结束后,模型不会自动保留这次交互;
  2. 上下文有限:能够放进当前上下文的内容始终有限。即使上下文窗口足够大,模型对其中所有内容的注意力也不可能完全均匀。

1.2 三个动作#

所有记忆系统这件事可以分为三个动作:

  1. 写:什么内容值得脱离当前上下文,进入长期存储?
  2. 取:在当前任务中,什么内容应该重新回到上下文?
  3. 改:新旧内容发生冲突时,保留、覆盖,还是并存?应该相信哪一条?

其中最难的是“改”。因为一旦修改本身出错,系统不仅会记错,还可能失去追溯和恢复的能力。

所有论文、项目、产品,都是在这三个动作间做出的取舍。

2. 原点#

我们把时间拨回 2023 年

2.1 经历流#

Generative Agents(2023-4)是这条线的起点,这个解法是如何让agent 像一个有连续人生的人

简单说下它是如何做的:每发生一件事,就用自然语言将这段经历追加进一个 memory stream(写);需要的时候,就对每条记录按相关度、新近度、重要度三项进行打分,取 top-k,另外,当近期积累的重要度超过阈值时触发一次reflection,把一堆碎片信息合成一条更高层的判断。

这个方案看起来合理:每次检索都综合考虑相关度、新近度和重要度,再取 top-k。

但问题也在这里。时间只是三个评分因素之一。当新旧消息发生冲突时,旧消息可能因为相关度或重要度更高,仍然被检索出来。系统于是会非常“自信”地取出一条已经过时的信息。

2.2 上下文管理#

MemGPT(2023-10)走的是完全相反的路。它不关心”agent 的人生”,它关心”上下文塞不下怎么办”。方案是把主上下文当内存、外部存储当磁盘(写),然后让模型自己用函数调用决定:读哪段进来、写什么出去、驱逐谁(取、改)。

这种设计的风险也很明显:如果把读取、写入、驱逐和改写都交给 LLM,那么一旦模型改错,谁负责恢复?

更关键的是,改写通常是覆盖式的。原始内容被替换之后,系统很难知道自己改了什么,也很难回到之前的状态。

2.3 三条支线#

  1. MemoryBank 是第一个明确对用户画像建模的:同时维护对话事件和用户画像,并用艾宾浩斯遗忘曲线按时间和重要度做衰减与强化——“遗忘”第一次成为机制而不是缺陷。
  2. Reflexion 把失败变成可复用的语言反思,任务反馈之后写一条”下次别这么干”。
  3. Voyager 把技能做成可执行代码入库、跨任务复用——这是”经验沉淀”这条线的祖先。

2.4 缺口#

我们做个简单的收敛:在这个时期的memory 都无法完美表达**“过时”**

只增的系统(Generative Agents)里,一条三月份的旧偏好和一条八月份的新偏好会平等地躺在流水账里,系统只能靠打分把旧的那条压下去——运气不好就压不下去,或者两条一起取出来自相矛盾。而 MemGPT 那套”模型自己改写”,改写是覆盖式的,没有版本概念,改错了无从追溯。

2.5 收获#

这一阶段留下了三条重要经验。

第一,记忆不只是存储问题。Generative Agents 证明了“经历流 + 检索 + 反思”可以产生连续性,但也暴露出过时信息和冲突信息的问题。

第二,记忆系统必须区分原始经历、抽象结论和可执行技能。它们的生命周期不同,不能用同一种方式管理。

第三,写入和改写必须能够追溯。只要系统允许覆盖旧信息,就必须同时回答一个问题:如果这次更新错了,能不能恢复?

这些经验后来分别发展成了三条改造线:更可靠的写入、更精细的检索与更新,以及更完整的生命周期治理。

3. 三条改造线(24-25)#

3.1 写#

代表是Mem0和A-MEM:

Mem0(v2)的做法可以简单概括为**“抽取-评估-更新”**,从对话抽取出“显著信息”,在决定怎么并入已有信息。但它仍然依赖一个脆弱的前提:LLM 能够稳定地从对话中判断哪些信息真正值得长期保存。换句话说,系统只是把“记什么”的判断交给了模型,抽取错误仍然可能直接进入长期记忆。

A-MEM 借 Zettelkasten 卡片笔记法:新记忆生成一张结构化卡片,然后触发两件事,一是与已有卡片建链接,二是 memory evolution,回头修改既有卡片的表示。注意第二件事——这是”改”第一次被正面设计,但方式是改写旧内容,跟 MemGPT 问题一模一样:改错了无从追溯。

3.2 取和改#

代表是 HippoRAG 与 Zep:

HippoRAG 把检索从”向量相似度 top-k”换成知识图谱上的 Personalized PageRank,解决多跳——A 和 C 之间没有字面相似度,但通过 B 连着。

Zep 是多层次(近期原始对话,长期记忆摘要,语义相关记忆)取,后端异步改:消息积累到一定数量,自动调用轻量级 LLM将旧消息更新合并到长期 summary中。

3.3 治理#

代表是 MemoryOS 和 MemOS:

MemoryOS 把存储分三层(短期/中期/长期个人记忆),对话按 FIFO 往上推,是最明确把”稳定的 persona”当长期存储一等公民的设计。

MemOS 提出 MemCube 统一封装,把记忆分成明文、激活、参数三类,重点在生命周期与治理词汇。

4. 从“记住事实”到“贴合习性”:记忆问题进入二阶阶段#

到了 2026 年,研究重点开始发生变化。系统不再只关心“以前说过什么”,还开始关心“这个人通常怎么做,以及这种习性是否正在变化”。

先看 LoCoMo 和 LongMemEval 那一代,测的是事实召回:很久以前说过的那个点,你还找得回来吗。而 DynamicMem、IBA-Bench、Setoka 这一批开始测习性、偏好演化和隐式线索。换测量对象不是小事,它把问题从一阶变成了二阶:

事实是一阶的。 「用户在八月改了技术栈」是一个点,对或错,存下来取出来就完事。

习性是二阶的。 「用户偏好简洁的界面」不是任何人说过的一句话,它是从一堆小事里推断出来的结论。这就带来三个新麻烦。

第一,它是推断出来的,不是被告知的。DynamicMem 特别强调这点:证据很少被明说,散落在不同应用里的小动作里,等着系统自己去归纳。而且它把画像拆成属性、习性、偏好三类——因为这三者变化的快慢不一样。属性(职业、常住城市)几年才动一次,习性(作息、工作方式)按月漂移,偏好可能一周就翻。变化还常由外部语境驱动:换季、换工作、搬家。

第二,推断必须挂在证据上,否则你没法修正它。PGMem 把这件事叫”记忆-画像有效性缺口”:既有系统把画像存成一张和事件脱钩的扁平 profile,于是画像一旦写歪,你既验证不了它、也追不回它是从哪来的。它的解法是用带类型的 provenance / evidence 边,把画像节点和支撑它的事件节点连起来,检索时按证据是否仍然有效排序。HERO 走的是同一个方向,理由更直白:压缩和改写会造成信息损失和语义漂移,所以它宁可保留原始对话文本。

第三,也是最容易被忽略的一条:“知道”不等于”做到”。IBA-Bench 给这个起了名字,叫知识-行动缺口。用户的历史被准确检索到了,偏好也被正确归纳出来了,不等于 agent 在真正做事的时候会照着做。Setoka 从另一侧说同一件事:显式事实检索不等于理解用户,它把用户理解分了四个层次,从显式事实一路到抽象人格特征。

这一节可以压缩成一句话:二阶问题会把一阶问题中的所有机制重新打开一遍。

写入时,需要判断哪些行为足以形成稳定习性;检索时,需要让结果对用户本人敏感;更新时,需要保留证据并处理习性的变化;执行时,还要验证 agent 是否真的按照这些记忆行动。——写入时机、证据来源、淘汰策略、以及怎么证明它真的生效。PPRO 的做法就是把画像反过来当成检索的显式先验,让检索”对这个人敏感”,而不是只”对问题敏感”。

5. 分数高不等于好#

先说结论,在这个领域里”我的记忆系统比对手强 X%“的数字,都不能横向比较。

5.1 全是自报,没有独立复现#

每篇论文用自己的 harness、自己的裁判模型、自己写的benchmark。你看到的都是”我的方法在我的考卷上比对手好”,而不是”这个方法在同一个考场里更好”。尤其当裁判是 LLM 的时候——用一个模型给一批回答打分,这个打分器和被测系统、甚至和作者,往往是一家人。

5.2 检索预算不同#

给对手 5 条检索结果和 2K token,给自己 50 条结果和 30K token,然后宣布提升了 20%。嗯,拿出来的都是真的!

5.3 同一个名字下可能有几个不同的东西#

最典型的是 mem0:它自己的 README 里注明,托管版分数包含了闭源优化,开源 SDK 只是”方向性接近”。也就是说”mem0 的分数”取决于你问的是哪一版。论文版的机制和开源实现已经分叉了——论文做抽取-评估-更新,2026 年的开源实现改成纯 ADD。引用时必须说清是哪一版。

5.4 负面结论是最可信的证据#

LoCoMo 和 LongMemEval 里最有价值的数字是那一条:商业助手和长上下文模型在持续交互中准确率下降约 30%。为什么它比那些正向数字硬?因为”我的方法在我的考卷上赢了”这件事本身有利益驱动,而”这份考卷上大家都不及格”证明的是问题真的存在——它不依赖谁的方法更好。问题存在,才轮得到解决方案。

顺带说,LongMemEval 最有工程价值的地方甚至不是那个数字,是它把记忆设计拆成了索引、检索、阅读三段。有了这个拆法,你的系统坏掉的时候可以定位到具体哪一段,而不是笼统地说”记忆不好用”。

6. 趋势#

最后呢,做个收敛

6.1 混合检索(yin)#

BM25 + 稠密向量 + RRF 融合 + 可选 rerank,在 mem0、memsearch、TencentDB、ReMe、SimpleMem 里反复出现,实现细节几乎一致。

原因很简单,便宜且稳定。

6.2 蒸馏在离开在线路径#

留在每轮用户等待路径上的只剩 mem0 和 memsearch,而且都压到一次调用。

其余全在任务结束、会话提交、后台队列或离线周期里做。

6.3 文件是事实,索引是影子#

ReMe、memsearch、EverOS、Acontext、memU、OpenViking 六个项目独立走到了同一个结论——Markdown 或事件日志是 source of truth,向量库是可重建的索引。

原因也很实际:Markdown 或事件日志方便人看,也方便以后换索引。

6.4 冲突处理#

各种互不兼容的方案,从”只增不改”到”整块重写画像”都有,而且都是活跃项目的当前选择。

7. 收束#

这些趋势共同指向一个变化:记忆系统正在从“把信息存起来”转向“维护一套可审计、可更新、可迁移的用户状态”。

混合检索解决的是“怎么更稳定地找到内容”;后台蒸馏解决的是“怎么把复杂处理移出在线路径”;文件作为事实来源解决的是“怎么审计和迁移”;冲突处理则直接面对“新旧信息到底应该相信谁”。

但最后一个问题仍然没有统一答案。不同系统在只增不改、局部更新、整块重写和版本化治理之间做出了不同选择。也许这正是接下来几年最值得继续观察的主线:记忆系统最终会更像数据库、版本控制系统,还是更像一个持续变化的个人模型。

Memory System:记忆系统的那些事
http://127.0.0.1:4321/blog/memory-system
Author Cxin
Published at 2026年9月14日