20 min · 四种实现形态、写入/清洗策略、一个最容易翻车的维度:作用域
🎒 预备知识:完成上一课「A5 上下文工程」(零基础入口:第 0 课)
L1 讲过:模型无状态,权重冻结。"记忆"在 agent 里完全是工程的造物—— 本质就一句话:把过去的什么信息,以什么形式,重新放进现在的上下文。 拆开是三个决策:存什么(写入策略)、放在哪(存储形态)、怎么取回(检索策略)。 新手只想着第三个,前两个才是事故高发区。
| 形态 | 怎么做 | 失败模式 |
|---|---|---|
| 窗口内 | 历史 messages 每轮全量重发(L4 模式一) | 撑爆窗口;长对话必死 |
| 压缩 | 窗口快满时 LLM 生成摘要替换旧史 | 摘要丢细节——关键约束被压没 |
| 文件 | 写 markdown,每轮读回 | 什么都记 → 流水账淹没有效信息 |
| 检索 | 向量化 + 相似度召回(把文本变向量按相似度找;A8 详述) | 召回不到=忘了;专有名词检索烂 |
压缩的工作原理(OpenClaw 的做法,正课 L18 逐行看):窗口超阈值时, 让 LLM 把旧史生成结构化摘要 → 摘要作为追加条目进历史(原文不删!只是后续轮不再重发) → 保留最近 20000 token 的原文 → 继续跑。要点:最近的消息保原文,远的保摘要—— 当前任务通常依赖近期细节。
文件是最被低估的形态:人类可读可编辑、git 可版本化、模型读得懂、无召回风险。 Easel 的账号长期记忆就是六个 markdown 文件,没有数据库。选择树:语料小(几十 KB 内) 且结构清晰 → 文件;海量无结构 → 检索(A8 的决策树)。
长期记忆的崩溃往往不是技术故障,是垃圾进垃圾出。看 Easel AGENTS.md 的沉淀标准 (正课 L03 逐条精读)——只有真正可复用的偏好、红线、方法、归因才沉淀,且要用户确认:
值得沉淀:用户明确偏好/禁区;反复认可的封面/开场/配音方法;
发布后验证有效或失效的选题结构
不沉淀: 一次性规格、临时参数、流水账、Key/token/路径
判据一句话:沉淀"会改变未来决策的事实",不沉淀"只属于这次任务的细节"。 写入方式是增量合并(去重、不覆盖无关内容),不是整文件重写—— 注意与 transcript 的严格只追加不同:记忆文件允许增量合并,但要保留冲突痕迹、拒绝静默覆盖。写入时机上,Easel 要求"任务结束时询问用户 同意后才写"——记忆写入本身是个需要授权的动作(写错人设比不写更糟)。
只写不清的记忆三个月后必然腐化:过时的"用户偏好 XX 工具"还占着位置, 新偏好被旧偏好稀释。两个机制:① 定期审计——让模型通读记忆文件并逐条标注 "仍被近期行为支持 / 已过时 / 相互矛盾",人工确认后清理;② 冲突处理规则—— 新偏好与旧偏好冲突时,新胜旧且保留冲突痕迹("3 月曾说偏好 A,7 月改为 B"—— 历史比干净更有信息量)。Easel 的做法是沉淀时"去重合并,不覆盖无关内容" (skill-profile-manager),把清洗留给显式动作而不是静默覆盖。
设两个并行会话:A 绑美食账号画像,B 绑科技账号画像,共享一份全局记忆文件。
t1 A 轮结束:沉淀"受众爱看探店" → 写入全局记忆
t2 B 开始新任务:读全局记忆 → 看到"受众爱看探店"
t3 B 给科技号写探店文案 → 串味,且用户无法定位原因
Easel 的答案:记忆按画像分域,每个会话只绑自己的 memory.md, 全局 MEMORY.md 刻意留空禁读写(正课 L05 看 persona.py 的三句话前缀怎么声明作用域)。 一般化原则:记忆作用域 ≥ 需要它的决策范围,绝不超过。个人助理=单人一份; 多租户=每租户一份;多角色=每角色一份。
坑 1:什么都记。每轮对话都总结写文件——一周后记忆几万字,噪声淹没信号。
价值密度比数量重要一百倍。
坑 2:记忆只写不清洗。过时偏好永不下岗——要定期审计 + 新旧冲突规则。
坑 3:向量化一切。六份画像文件也建向量库——引入召回失败风险去解决不存在的问题。语料小就整读。
坑 4:写入不授权。静默记用户的"偏好"记错了,用户连哪里出错都找不到——写入要可见可拒。
为"个人助理 agent"设计记忆方案,必须回答五问:① 什么进窗口、什么写文件、什么建索引? ② 什么才触发沉淀(给出你的判据)?③ 作用域怎么划?④ 清洗机制怎么设计? ⑤ 跨设备同步时哪种形态最先出问题?(提示:从四种形态各自“活在哪里”想——哪些只存在于一台机器的窗口或磁盘上?)发到对话里我批改。