一、基于丢弃与保留的策略(最直接、最常用)
这类方法的核心是判断哪些记忆值得保留,哪些可以直接扔掉。
- 滑动窗口
-
- 原理:只保留最近N轮对话或最近K个时间步的记忆,更早的直接丢弃。
- 特点:实现极简单,适合短期任务(如客服对话、单回合代码调试)。缺陷是丢失了所有长期信息,无法回答"昨天你提到了什么?"这类问题。
- 变体 :重要窗口------保留最近N条 + 额外保留几个特定的全局重要记忆。
- 重要性/相关性评分
-
- 原理:每产生一条新记忆(如一次环境反馈),用一个小型模型(或LLM自身)评估其"重要性分数"(如0-1分)。低于阈值的丢弃。相关性基于当前任务目标判断。
- 代表工作 :Generative Agents(斯坦福小镇论文)中,每个Agent会定时反思:"最近的经历中,哪些是重要的?" 只保留重要事件。
- 实现提示:可以用GPT-4给少量样例打标,然后微调一个BERT-size的小模型来做实时评分,成本远低于让大模型逐条判断。
- 遗忘曲线模型
-
- 原理:模拟人类艾宾浩斯遗忘曲线。记忆的"存活概率"随时间和访问次数衰减。长期未访问且非重要的记忆会被优先丢弃。
- 场景:教育类Agent、长期陪伴型Agent,它比简单窗口更自然。
二、基于摘要与重构的方法(信息蒸馏)
不丢弃内容,而是把多条记忆合并成更紧凑的表述。
- 滚动摘要
-
- 原理:每当对话或记忆序列达到一定长度(如3000词),调用一次LLM生成一段摘要,然后清空原始细节,把摘要当作后续对话的上下文前缀。
- 经典模式 :
[系统提示] + [历史摘要] + [最近5轮对话]。 - 问题:摘要会越写越长,且丢失细节(例如,"用户曾输入过身份证号后四位"在摘要中通常不体现)。
- 改进 :双层摘要------高层摘要(周总结)+ 低层事件列表(带时间戳的关键事件)。
- 分层次摘要树(MemGPT / 递归摘要)
-
- 原理:将记忆组织成树状结构。叶子节点是原始事件;父节点是其子节点的摘要;根节点是全局摘要。当内存不足时,从最深层的叶子开始向上合并压缩。
- 代表:MemGPT(专门为LLM设计分层记忆架构)。Agent可以像操作系统管理"内存-磁盘"一样,将近期记忆放在快速上下文,把旧记忆压缩成摘要存入外部存储,需要时再解压部分回来。
- 优势:保留多粒度信息,且支持随机访问。
- 指令微调式的压缩
-
- 原理:训练一个专门的"压缩器"模型,输入是一段记忆序列,输出是一个固定长度的向量(或特殊token序列)。这个向量能被LLM直接理解(作为soft prompt)。
- 特点:压缩比极高(例如1:100),但需要额外训练且跨任务泛化性有挑战。类似Gist Token、AutoCompressors的思路。
三、基于向量数据库与检索的方法(存算分离)
这是目前工业界最主流的长期记忆方案。本质上不是"压缩",而是"外部化+索引",但能达到压缩上下文的目的。
- 基础流程
-
- 每段记忆(事件、观察、反思)被embedding成向量 → 存入向量数据库。
- 每次Agent决策时,将当前状态(如用户问题、环境观察)作为查询向量 → 检索Top-K最相似的记忆 → 将检索到的记忆内容拼接到提示词中。
- 上下文窗口只包含检索结果,而非全量历史------这就是"上下文压缩"的体现。
- 关键的压缩增强技巧
-
- 重排序(Re-ranking) :向量检索后,用更精密的交叉编码器对Top-50记忆重新打分,只取Top-3/5。进一步压缩。
- 最大边际相关性(MMR) :避免检索出内容重复的记忆,提高信息密度。
- 时间衰减加权 :检索相似度 =
cos_sim(向量) * exp(-λ * 时间差)。让旧记忆被检索到的概率降低,变相压缩长期稀疏信息。
- Agent特有:反思式压缩
-
- 原理:Agent定期(如每10个交互轮次)触发反思:"总结我最近做了什么?学到了什么?哪些记忆其实可以合并?"
- 输出:生成更高级的"反思记忆"(如"用户讨厌红色"),然后删除引发该反思的原始琐碎记忆(如"用户说我不喜欢那个红按钮")。
- 代表 :Generative Agents 中的反思模块,以及 Voyager(游戏Agent)中的技能库构建。
四、基于学习型压缩(模型层面)
改动LLM本身或引入可训练的压缩模块。
- Landmark Tokens(地标token)
-
- 原理 :在LLM的词表中加入一些特殊token(如
<|mem|>)。训练模型学会:看到<|mem|>时,去一个外部内存矩阵中读取或写入。 - 效果 :模型自己决定何时压缩记忆。例如处理完20个数字后,模型输出
<|mem|>,表示"我已将这20个数字压缩为一个内部表征"。
- 原理 :在LLM的词表中加入一些特殊token(如
- Transformer-XL 式片段递归
-
- 原理:在处理长序列时,前一片段的隐藏状态(hidden states)会被缓存,并作为下一片段的上下文。这相当于模型层面的"压缩"。
- 局限:在Agent场景中,记忆跨越多个不同任务片段时,这种连续缓存的迁移学习能力会下降。
五、方法选择的实用建议
| 场景 | 推荐方法 | 理由 |
|---|---|---|
| 简单客服/闲聊Agent | 滑动窗口 + 重要事件白名单 | 成本低,够用 |
| 代码辅助Agent(会话短) | 向量检索(只存代码片段+报错信息) | 精确检索比摘要更重要 |
| 复杂游戏/机器人控制 | 滚动摘要 + 反思式压缩 | 需要抽象出策略层级 |
| 长时间陪伴/心理支持 | 遗忘曲线 + 分层次摘要树 | 既有长期记忆,又不像记仇一样全保留 |
| 预算无限、追求最佳 | MemGPT架构 + 向量检索 + 定期反思 | 最像人类记忆系统 |
一个被忽视的要点:写入时的压缩
绝大多数方法关注读取/检索时 的压缩。但更高效的做法是在写入记忆时就先压缩:
- 实体提取 :不是存"用户说他的狗叫旺财,今年5岁",而是存
{实体:狗,名称:旺财,属性:年龄=5,关联:用户}。 - 去重合并:若已有"用户喜欢咖啡",新来"用户点了一杯美式",则更新为"用户喜欢咖啡(偏好:美式)",而非新增一条。
- 异常值保留:只有违反已有模式的信息才保留原文(例如用户突然说"我讨厌咖啡")。
总结 :Agent记忆压缩没有万能解。实际系统常采用混合策略:短期用滑动窗口,中期用向量检索,长期用摘要树,并辅以写入时的结构化压缩。核心评价指标是:压缩后,Agent在关键任务上的决策质量下降不超过5%,而上下文长度减少80%以上。
面试回答
第一,摘要式压缩。 这是最直观的。比如每隔N轮对话,让LLM自己把之前的对话总结成一段短文本,替换掉原始对话。缺点是可能丢失细节,而且摘要本身也会越来越长。改进版是分层摘要------每小时总结一次,每天再把小时的摘要再总结一次,像金字塔一样。
第二,滑动窗口 + 重要度评分。 比如只保留最近10轮完整对话,更早的就只保留关键词或实体。那怎么判断哪些信息重要?可以用注意力分数 (Transformer自带的attention权重)或者专门训练一个小模型来打分,分数高的记忆留到下一个窗口。
第三,向量检索 + 压缩存储。 这个在RAG里很常见。不是存原始文本,而是把每条记忆embedding成向量,存到向量数据库里。需要回忆时,用当前问题去检索最相关的Top-K条记忆。这本身就是一种压缩------从海量对话变成几十个向量和对应的原始片段。
第四,使用专门的压缩模型。 像AutoCompressors或者ICAE(In-Context Autoencoder),它们会训练一个模型把长上下文压缩成几十个虚拟token(比如叫记忆token)。这些token再喂给主Agent。这个方法效果比较好,但需要额外训练。
第五,结构化记忆。 把对话抽成(实体, 关系, 时间)的三元组,存到图数据库里。比如'用户喜欢喝美式,不喜欢加糖'。这种结构化表示比原始文本短得多,而且方便逻辑推理。
实际落地时,通常混合使用: 短期用滑动窗口保证响应快,中期用摘要保留脉络,长期用向量库或者图数据库存结构化事实。另外要定期重写记忆------因为用户偏好会变,比如以前喜欢猫,后来养狗了,旧记忆要降权甚至删除。