Forgetting as a Feature: Why Your Agent Memory System Needs to Forget
长期记忆系统的核心困境不是"记不住",而是"忘不掉"。从信息检索的底层原理出发,看遗忘机制如何反向提升 agent 记忆质量。
去年看了一篇神经科学的科普:人类大脑每天产生的记忆大约 74GB,但意识能调用的带宽只有 10-50 bit/s。你的大脑每天做的最关键的工作,不是存储,而是主动遗忘。
这听起来反直觉——我们总觉得遗忘是缺陷。但从信息系统的角度看,遗忘是最高效的压缩策略。回到第一性原理:任何存储系统的有效容量不是它装了多少,而是它能精准召回多少。当你把所有东西都记住,检索就变成了在一个不断膨胀的噪声池里捞针。
存储不是问题,检索才是
构建长时记忆 agent 时,最自然的直觉是:把 agent 经历过的所有交互都存下来,需要时用语义相似度搜一下。
这条路径有两个致命问题。
第一,信噪比会随时间指数衰减。 假设 agent 每天产生 100 条记忆片段,一周后池子里就有 700 条。其中大量是日常例行操作——检查邮箱、确认时间、重试失败请求。这些记忆可能 embedding 上跟当前 query 相似("邮件"的 embedding 和"写邮件"的 embedding 距离很近),但语义上完全无关。检索结果 top-10 里可能 8 条都是噪声,只因为数量和嵌入空间的重叠把信号淹没了。
第二,检索延迟随数据量线性增长。 向量数据库的 ANN 搜索不是严格线性的,但索引维护成本、内存占用、每次查询的 IO 开销都会增长。这不是理论问题——在长期运行的生产 agent 中,记忆池从 1000 条膨胀到 10000 条时,延时的跳升肉眼可见。
这两个问题指向同一个结论:记忆系统的瓶颈不在写入,而在读取。 存储 10000 条很容易,但从 10000 条里找到那 1 条有用的,难得多。
四种遗忘策略的工程取舍
既然遗忘是必要的,怎么忘?以下是我梳理的四种策略,各有场景和代价。
1. 基于时间的衰减(Recency-based Decay)
最简单:给每条记忆打时间戳,检索时按 recency 加权。刚发生的记忆权重高,旧记忆逐渐沉底。
- 优点:实现极其简单,一个时间戳字段就够了
- 问题:很多重要知识是长期有效的。你今天学会怎么调 API,下周依然有用。Recency decay 会把这种有价值的长周期信息一并埋掉
- 适用:会话级别的短期记忆,或者 agent 状态恢复(重启后从最近 checkpoint 恢复)
2. 基于访问频率的衰减(Frequency-based Forgetting)
记录每条记忆被检索的次数。低频访问的记忆自动降级,最终被归档或丢弃。
- 优点:接近真实认知机制——你经常回忆的事情更清晰
- 问题:冷启动阶段所有记忆都是低频的,系统还没建立起"重要度"判别,就会在一开始错误地丢弃大量信息。另外,存在一种"幸存的活"现象——一次检索成功会稍微提升该记忆的权重,使得这条记忆更容易被再次检索到,形成正反馈循环,反而降低了多样性
- 适用:需要长期稳态运行的 agent,有足够长的 warm-up 窗口
3. 基于重要性的加权(Importance-weighted Retention)
给每条记忆附一个"重要性"分数(由 agent 自身在写入时评估),检索时作为排序因子。
- 优点:让 agent 自己决定什么是值得记住的
- 问题:谁来定义"重要性"?如果让 LLM 打分,每个写入都多一次调用,成本线性增长。而且 agent 对"重要"的判断可能不准确——当事后视角来看,很多最初以为不重要的细节恰恰是解决问题的线索
- 适用:与人类协作的场景,用户明确标记"这条重要"时配合使用
4. 基于检索结果的反馈(Retrieval-aware Forgetting)
这是我觉得最有意思的方向。不靠启发式规则,而是让遗忘决策和检索结果挂钩:一条记忆如果连续被检索到但从未被实际使用(agent 执行完任务后回看时发现该记忆未被采纳),就降低其权重。
本质上,这是把遗忘变成了一个在线学习问题:每次检索+使用就是一个训练样本,模型(遗忘策略)根据反馈持续调整。
- 优点:自适应的,不需要预先定义重要规则
- 问题:循环依赖。要判断"是否被使用",需要 agent 在完成任务后主动做一次记忆审计——这本身就是一个工程挑战。而且反馈信号是稀疏且延迟的,agent 可能半天做不出一个能产生有效反馈的动作
- 适用:长期运行且有明确任务周期的 agent(比如每天收工做一次记忆审计)
在实践中怎么组合
我目前在项目中尝试的分层策略:
短期记忆层 (Buffer)
├─ 纯 recency 衰减,最多保留 50 条
├─ 用于当前会话上下文
└─ 会话结束时有价值片段 → 压缩后进入长期层
长期记忆层 (Store)
├─ 结合 frequency + retrieval-aware 衰减
├─ 每条记忆存 3 个字段:内容(embedding+原文)、access_count、access_sequence
├─ 每月做一次"记忆审计":遍历所有记忆,计算每条的使用率
└─ 使用率低于阈值?不是删除,而是降级到"归档"——不出现在检索结果中,
但可以通过明确引用还原(类似 macOS 的"隐藏"而非"删除")
这个方案不是完美的,但它的好处是:保留了降级路径而不是直接删除。遗忘不应该是 irreversible 的 delete,而是 soft demotion。因为 agent 的记忆不像人脑——它没有"突然想起来"的能力。一旦删除就真的没了。但降级+归档,给了你一条后悔的路径。
核心收获
回到第一性原理:记忆系统的瓶颈在读取不在写入。遗忘不是存储空间的妥协,而是检索精度的提升策略。选择遗忘策略时,思考顺序应该是:
- 检索失败的主要诱因是信噪比还是延迟?
- 遗忘是 reversible 还是 irreversible?
- 反馈信号是做什么样的 loop 用?
从这个角度看,遗忘不是退路,是捷径。
评论
发表评论