对应 Maps to:Stanford CS329Z Engineering AI Agents(Fall 2026),Lecture 7 · Wed Oct 14 · Agent Memory Architectures(Diyi Yang、Michael Ryan、John Yang)。阅读材料:Packer et al., MemGPT: Towards LLMs as Operating Systems(2023)/ Letta 博客;Chhikara et al., Mem0(2025);Park et al., Generative Agents(UIST 2023)。 依据说明:本讲以原课第 7 讲的公开 slides 为主线(为什么需要记忆、记忆的类型、记忆架构的四种模式、评估记忆、挑战与开放问题),结合三篇阅读材料和 slides 引用的论文:CoALA、Voyager、AWM、MemoryOS、Reflexion、睡眠时计算、A-Mem、Zep、LoCoMo、PersonaMem、LongMemEval-v2、MemoryArena 等。凡是引用数字的都核对过原文摘要或 slides 上的图表(从图上读的会注明”约”)。全部实验是本讲义自己设计的,不代表课堂上讲了什么。 配套代码 Code:
code/lecture07/(只用 Python 标准库,含sqlite3;8 个脚本 + 3 个模块 + 1 个可选脚本;不需要 API key;每个脚本约 1 秒) 预计阅读时间:3–4 小时(含运行代码)
0. 本讲导航 · How to read this lecture
0.1 学习目标 Learning goals
slides 给这一讲定了三个目标:认识到记忆在多会话、面向用户的智能体系统里的重要性;根据设计模式区分不同的记忆架构;识别智能体记忆仍在面对的挑战。展开来说,学完这一讲你应该能够:
- 说出没有记忆会丢掉的三样东西(程序、知识、进展)和有了记忆能得到的三样东西(个性化、从经验中学习、有状态)。
- 用 CoALA 的分类(工作 / 情景 / 语义 / 程序性记忆)和”参数记忆 vs 上下文记忆”描述任何一个记忆系统;回答设计记忆的三个问题:存什么、什么时候存取、怎样存取(文件系统、数据库、知识图谱)。
- 区分四种记忆架构模式——从经验中学习程序(Voyager、AWM)、分层记忆(MemGPT)、反思式整合(生成式智能体)、记忆维护(Mem0、睡眠时计算)——并说出每种的代价。
- 用”真实、长上下文、有挑战、可验证”四条要求评价一个记忆基准;理解”取回了记忆却用不好”。
- 讨论该记住什么、该忘掉什么,以及记忆带来的投毒、隐私、过度个性化问题。
0.2 先修与本讲范围 Prerequisites & scope
| 默认你已经会 Assumed | 本讲只给直觉,后面再展开 Previewed only |
|---|---|
| 第 1 讲 §3.5:三种记忆(情景 / 语义 / 程序性)、Reflexion | 多智能体之间的记忆共享(第 8 讲) |
| 第 3 讲:BM25、检索评估——记忆的检索就是 RAG | 用记忆数据做训练(第 10–11 讲) |
| 第 5 讲 §4:OpenClaw 的 MEMORY.md 与夜间整理;第 6 讲 §4:上下文管理的五种模式(记忆卸载是其中之一) | 隐私评估(PrivacyLens)、提示词注入(第 14 讲) |
| 前置讲 P4:间接注入、来源标记;SQL 参数化 | 评估方法论与统计(第 12 讲) |
0.3 本讲地图 Map
§0.6 开场:两个"失忆"的例子
§1 为什么需要记忆:丢掉什么、得到什么 ← 代码 01
§2 记忆的类型:CoALA 的四种记忆;参数记忆 vs 上下文记忆 ← 代码 01
§3 三个问题:存什么、什么时候、怎样存(文件系统、数据库、知识图谱) ← 代码 02
§4 四种架构模式:学习程序(Voyager、AWM)、分层(MemGPT)、反思(生成式智能体)、维护(Mem0、睡眠时计算) ← 代码 03–06
§5 评估记忆:四条要求;LoCoMo、PersonaMem、LongMemEval-v2、MemoryArena ← 代码 07
§6 挑战与开放问题:记什么忘什么、信任与隐私、用对记忆 ← 代码 08
§7 用真实模型试一试 ← 代码 09(可选)
§8 小结 §9 常见误区 §10 练习 §11 延伸阅读 §12 下一讲预告
0.4 术语 Terms
| 术语 | 本讲里的意思 |
|---|---|
| 工作记忆(working memory) | 智能体当前”看得见”的东西——通常就是上下文窗口 |
| 情景记忆(episodic) | 过去发生了什么的原始记录:轨迹、以前的对话 |
| 语义记忆(semantic) | 关于世界和用户的事实:偏好、细节、常识 |
| 程序性记忆(procedural) | 怎样做事:规则、技能、工作流 |
| 参数记忆 / 上下文记忆 | 写在模型权重里的 / 在需要时被放进上下文里的 |
| 抽取(extraction) | 用 LLM 从对话里提炼出事实再存起来(写入路径的一步) |
| 整合(consolidation) | 把新记忆和旧记忆合并:去重、解决冲突、更新、提炼 |
| 有效期(validity interval) | 一条事实从什么时候起成立、到什么时候失效(双时间知识图谱) |
| 分层记忆(tiered memory) | 主上下文(小、快、总在眼前)+ 外部存储(大、要检索)——像内存和磁盘 |
| 记忆投毒(memory poisoning) | 不可信的内容被写进记忆,之后在别的任务里生效 |
0.5 本讲的代码
代码围绕一个模拟用户(user_world.py):40 个会话,约 1.2 万 token 的对话(我们的近似计数),大多数是闲聊;里面散落着静态事实(狗的名字、过敏、生日)、会变的偏好(住的城市、工作、早上喝什么、饮食、航空公司、跑步目标——每次变化都带原因)、旅行和预约、关于姐妹的事实,以及”同事的狗、朋友搬家、侄子的过敏”这类干扰项。陈述有不同的说法:有的带关键词,有的不带;说起变化时有的提到旧值,有的没有。会话结束后问 28 道题,分 7 种题型。每个实验用 20 个这样的用户。
和前几讲一样的提醒:抽取器和阅读器的行为(漏抽、错记、读错、被干扰项带偏、上下文腐烂……)是旋钮(
memory_systems.KNOBS),所以准确率的具体数字由旋钮决定。机制性的部分不依赖旋钮:记忆库里实际存了什么(包括被污染的、被覆盖的)、检索和查询、MemGPT 的队列与换出、记忆流的打分、token 和调用次数。
0.6 开场:两个”失忆”的例子
slides 用两个真实的例子开场:一篇 Andon Labs 的博客(关于让 AI 当”老板”的实验),以及一条社交媒体帖子里用户给智能体的叮嘱——“Check this inbox too and suggest what you would archive or delete, don’t action until I tell you to.”(把这个收件箱也看一看,建议哪些可以归档或删除,我说了再动手。)
这句叮嘱正好说明了记忆为什么不是”锦上添花”:它是一条约束。如果它在长会话里被挤出上下文、被压缩掉了,智能体就会在用户不知情的情况下做出可能无法撤销的动作。slides 的结论:对长时间运行、多会话的智能体来说,记忆必不可少。今天介绍智能体记忆的类型和几种具体的记忆架构。
1. 为什么需要记忆 · Motivating agent memory
1.1 没有记忆会丢掉什么
slides 列了三样:
- 程序(loss of procedure):每次都要重新教智能体怎么完成这件事;
- 知识(loss of knowledge):重要的事实、规则和偏好在会话之间丢失;
- 进展(loss of progress):会话一长,智能体就忘了自己做过什么、早先的目标和指示(§0.6 的例子)。
1.2 有了记忆能得到什么
- 个性化:智能体能学会你的个人偏好(例子:PersonaMem,Jiang et al., 2025);
- 从经验中学习:在一个会话里学会的技能,以后能用上(例子:Agent Workflow Memory,Wang et al., 2024);
- 有状态:新的对话能接着上次的地方继续——“把我们上次在写的提案再打开”(例子:Du et al., 2025)。
1.3 在模拟用户上量一量
代码 01 演示 1 比较”没有记忆”和”每个会话结束后抽取事实、写进记忆”两种系统(20 个用户 × 28 题):
| 系统 | 知识(事实、偏好、事件) | 进展(变化、原因) |
|---|---|---|
| 没有记忆 | 6.2% | 1.9% |
| 抽取事实、写进记忆 | 83.2% | 73.8% |
没有记忆的 6% 全靠瞎猜碰上。程序的丢失更隐蔽:用户在第 7 个会话左右说过”摘要请用 bullet points”;之后每 5 个会话要一次摘要,共 8 次——没有记忆时,这 8 次都要用户重新说明(或者第一稿格式不对、来回改一轮)。用户不会每次都抱怨,只会觉得”它每次都要我重新教”。
为什么不干脆把所有对话都塞进上下文? 代码 01 演示 3:全部对话每个会话约 304 token、随会话数线性增长,约 26 个会话就超出 8K 的窗口,约 657 个会话超出 200K——一个每天用几次的助手,一年就到了。而且就算放得下,上下文越长越容易漏看(第 6 讲 §4),每次调用都要为整段历史付钱。记忆系统的思路是把历史放在上下文之外,每次只取回相关的一小部分——这就是第 3 讲 RAG 的思想,用在”自己的过去”上。
2. 记忆的类型 · Types of agent memory
2.1 CoALA 的四种记忆
slides 采用 CoALA(Cognitive Architectures for Language Agents,Sumers et al., 2024)的框架。CoALA 把一个语言智能体描述成三部分:模块化的记忆、一个和内部记忆及外部环境交互的结构化动作空间、一个选择动作的决策过程。记忆分四种:
| 记忆 | 是什么(slides) | 本讲义里的例子 |
|---|---|---|
| 工作记忆 | 通常就是上下文窗口:智能体当前看到、正在推理的东西——观察、目标、用户输入、内部推理 | 第 1 讲的消息列表;第 2、6 讲的上下文管理 |
| 情景记忆 | 智能体过去行为的序列(轨迹);在聊天机器人里就是以前所有对话的存储;通常是”发生了什么”的原始日志 | 第 1 讲 Reflexion 的轨迹;本讲的原始对话检索、MemGPT 的回忆存储 |
| 语义记忆 | 关于世界的事实:用户的细节、偏好、常识……人们说”聊天机器人的记忆”时通常指的就是它 | 本讲的事实抽取、Mem0、知识图谱;第 3 讲的文档库 |
| 程序性记忆 | 一组作用在工作记忆上、决定智能体行为的规则——本质上是智能体的技能:“怎样”完成任务的知识 | 系统提示、第 6 讲 Pi 的技能文件;本讲代码 05 的工作流和技能库 |
2.2 参数记忆 vs 上下文记忆
slides 的另一个维度:记忆写在哪里。
| 参数记忆(写在模型权重里) | 上下文记忆(被放进模型的上下文里) | |
|---|---|---|
| 语义 | 预训练学到的知识 | 检索回来的事实 |
| 程序性 | 指令遵循等能力 | 检索回来的技能 |
| 情景 | 不适用 | 检索回来的以前的对话 |
| 怎样增加 / 管理 | 可以通过微调加入更多知识或技能 | 由上下文管理器取出合适的记忆 |
本讲讨论的几乎都是上下文记忆:记忆存在模型外面,在需要的时候被取回、放进上下文。第 9、10 讲会讨论把经验写进权重(微调、蒸馏)。
3. 三个问题:存什么、什么时候、怎样存 · What, when, and how
slides 把记忆设计归结为三个问题:
- 存什么 / 取什么(What):事实(具体的和一般的)、程序、对话的进展……
- 什么时候触发存储 / 检索(When):由智能体通过工具按需调用;由后台任务做;由事件驱动……
- 怎样存、怎样取(How):文件系统、数据库(检索)、知识图谱……
前两个问题贯穿 §4 的四种架构模式。这一节先回答第三个问题。
3.1 文件系统
每条记忆是一个文件;可以让智能体自己管理它的记忆;天然有层级;grep、ls 这些 bash 命令就是记忆工具。slides 的例子是 LangChain 的 Agent Builder:智能体的记忆就是一组它自己读写的文件。第 5 讲的 OpenClaw(MEMORY.md、USER.md)、第 6 讲 Pi 的技能文件也是这个思路。
3.2 数据库
可以建一个向量数据库、按语义检索记忆;想按元数据(时间、类型、人)查时,常用 SQLite;要精确的词查找,用 BM25。slides 的提醒:“回想一下我们的 RAG 那一讲!“——记忆的检索就是 RAG,只是语料换成了智能体自己的过去。
3.3 知识图谱
实体是节点、关系是边。slides 的例子是 Zep(Rasmussen et al., 2025):它把记忆存成一个带时间的知识图谱——每条边记着这个事实什么时候开始成立、什么时候失效。新事实出现时,旧边不删除,而是被标记为”失效”——于是”现在住哪”和”三月份住哪”都能直接查。
3.4 同一批记忆,三种存法
代码 02 把一个模拟用户的全部事实(直接用标准答案,不经过抽取——这里只比较存储)存进三种后端:真的在临时目录里写 markdown 文件(profile.md、preferences.md 带日期的行、people/姐妹名.md、events/日期-事件.md);标准库 sqlite3 里一张带 valid_from / valid_to 的事实表;一个边带有效期的知识图谱。然后回答七类问题:
| 问题 | 文件系统 | SQLite | 知识图谱 |
|---|---|---|---|
| 1 精确查找:狗叫什么 | 1 次 grep | 1 句 SELECT | 1 次邻居查询 |
| 2 最新值:现在住哪 | 1 次 grep,模型自己挑最新的那行 | valid_to IS NULL | 当前成立的边 |
| 3 某一天的值:3 月 1 日住哪 | 1 次 grep,模型自己比较日期 | valid_from ≤ 日期 < valid_to | 那一天成立的边 |
| 4 历史:按顺序住过哪些城市 | 1 次 grep,排序 | ORDER BY valid_from | 边的历史 |
| 5 两跳:姐妹住哪 | grep 出名字 + cat 她的文件(2 次) | 1 句自连接 | 沿两条边走(2 次) |
| 6 关键词:提过 legroom 吗 | 1 次 grep(天然的全文搜索) | LIKE(没有全文索引时慢) | 扫描所有边的属性 |
| 7 换了说法:“坐哪家的飞机”(库里存的是 airline) | ✗ | ✗ | ✗ |
前六类三种后端都答对了,差别在由谁来做推理:SQLite 和图谱把”时间”做成了查询条件;文件系统把带日期的行全 grep 出来,再由模型自己比较日期——这一步正是 LLM 会出错的地方。两跳是图谱的强项。关键词是 grep 的强项。第七类三种都失败:它们都按字面匹配名字(“fly” ≠ “airline”)。要么由 LLM 先把问题翻译成存储里的名字(text-to-SQL、选对文件),要么加一层语义检索(第 3 讲的稠密向量)。真实系统常常组合使用:向量检索找候选、元数据过滤时间和人、BM25 补精确词。
文件系统还有一个优点:智能体自己能管理——用它本来就会的工具,记忆还是人能读懂、能改的 markdown。slides 引用的 LongMemEval-v2 结果显示,“文件系统式”的记忆在长轨迹上胜过检索式记忆(§5.4,不过它配的模型也更强)。
4. 四种记忆架构模式 · Agent memory architectures
slides 把具体的记忆架构归成四种模式:
| 模式 | 存什么 | 什么时候写 | 什么时候读 | 主要的取舍 |
|---|---|---|---|---|
| 从经验中学习程序 | 可复用的代码、工作流、程序 | 有用的轨迹之后,或者离线归纳 | 相关的任务需要一个程序时 | 复用省力,但程序会过时 |
| 分层记忆 | 紧凑的活跃信息 + 外部的细节 | 信息进来、上下文压力变大时 | 活跃记忆一直在读;外部记忆按需读 | 上下文变小了,但需要可靠的记忆管理 |
| 反思式整合 | 从经验里提炼出的教训和更高层的推断 | 收到反馈之后,或者积累了足够多的观察之后 | 相关的推理和规划时 | 抽象提高了复用,但可能引入没有根据的结论 |
| 记忆维护 | 修订过的事实、链接、索引、预先准备好的表示 | 有新证据时、写入时、或者后台 | 通过维护好的存储 | 组织得更好要花计算,而且可能丢信息 |
(这张表是 slides 的总结页。)下面逐一展开,每种配一个实验。
4.1 从经验中学习程序:Voyager、AWM、技能文件
Voyager(Wang et al., 2023)是一个在 Minecraft 里自己探索的智能体,三个组件:一个最大化探索的自动课程;一个不断增长的、由可执行代码组成的技能库,用来存储和检索复杂的行为;一种结合了环境反馈、执行错误和自我验证的迭代提示机制。摘要报告:比之前最好的方法多拿到 3.3 倍的独特物品、走了 2.3 倍远、解锁关键科技树节点快了最多 15.3 倍。slides 特别指出:有技能库时,Voyager 在 102 次提示迭代内造出了钻石工具;没有技能库时,这从来没做到过。
AWM(Agent Workflow Memory,Wang et al., 2024)从成功的网页任务轨迹里归纳出可复用的”工作流”(例如”在某网站上搜索商品并加入购物车”的一般步骤),把它们放进系统提示,解新任务时作为上下文。摘要报告:在 Mind2Web 和 WebArena 上相对基线的成功率分别提升 24.6% 和 51.1%;训练和测试任务的分布差距越大,它领先得越多(8.9 到 14.0 个绝对百分点)。slides 上的表(WebArena 跨模板子集):AWM 总成功率 33.2%,高于 BrowserGym 的 20.5%、AutoEval 的 23.2%,甚至略高于用了人工设计工作流的 SteP(32.1%);学习曲线显示大约 40 个例子之后从”快速学习期”进入”稳定推理期”。
技能文件(Anthropic 的 Agent Skills):一个文件夹里放说明和脚本,元数据进系统提示,正文需要时再读(第 6 讲的渐进披露)。它是通用的、面向用户的助手里程序性记忆的常见形式——而且可以更新。
局限:slides 引用 Cao et al.(2026)指出,这类程序性记忆在动态环境里不稳健——网站改版了、API 换了,存下来的程序就过时了。
代码 05 在一个玩具”办公门户”里量了这件事:8 个子程序(登录、导出报表、开工单……),每个要按顺序点 3–5 个按钮(每步 4 个可选);60 个任务,每个由 2–3 个子程序组成;第 30 个任务之后门户改版,3 个子程序里各有一步换了位置。20 次独立运行的平均:
| 系统 | 改版前:步数 | LLM 调用 | 成功 | 改版后:步数 | LLM 调用 | 成功 |
|---|---|---|---|---|---|---|
| 没有记忆 | 18.5 | 18.5 | 100% | 18.7 | 18.7 | 100% |
| 工作流记忆(AWM 式) | 11.1 | 11.1 | 100% | 47.4 | 6.2 | 25% |
| 技能库(Voyager 式:一次调用执行一个技能) | 11.0 | 4.2 | 100% | 47.4 | 1.8 | 25% |
| 工作流记忆 + 出错就修 | 11.0 | 11.0 | 100% | 10.4 | 10.4 | 100% |
| 技能库 + 出错就修 | 11.0 | 4.2 | 100% | 10.4 | 2.7 | 100% |
- 学过的子程序不用再探索:步数 18.5 → 11.1。技能库再把 LLM 调用从 11.1 降到 4.2——一个技能是一段代码,一次调用执行完(第 6 讲 CodeAct 的道理)。只从成功的任务里归纳,免得把错误的做法存进去(Voyager 的自我验证)。
- 学习曲线:第一组 5 个任务平均 14.8 步,第二组 11.0,之后走平在 10 步左右——“快速学习 → 稳定”的形状。
- 改版之后,不会修的记忆变成了负担:照着过时的步骤反复出错,成功率掉到 25%,比没有记忆还差。
- 出错就退回探索、修好那一步并更新记忆:成功率 100%、10.4 步,和改版前差不多。程序性记忆要配上验证(执行有没有成功)和维护(§4.4)。
4.2 分层记忆:MemGPT
MemGPT(Packer et al., 2023)的关键洞见:给 LLM 工具,让它自己管理自己的记忆。它借用了操作系统的分层内存:
主上下文("内存",在 LLM 的上下文窗口里)
├─ 系统指令(只读)
├─ 工作上下文(working context,可读写:关于用户和自己的要点)
└─ FIFO 消息队列(最近的消息;队列管理器负责换出)
外部上下文("磁盘",在上下文窗口外面)
├─ 回忆存储(recall storage:全部对话原文,可按文字 / 日期搜索)
└─ 档案存储(archival storage:任意文本,向量检索)
- 队列管理器:上下文快满时(70%)给模型发一条”内存压力”警告,模型可以趁机把重要的东西存进工作上下文或档案;满了(100%)就把最早的一半消息换出(它们仍在回忆存储里),换成一段递归摘要。
- 函数:
working_context.append / replace、archival_storage.insert / search、recall_storage.search;搜索结果分页返回。slides:“不需要搜索工作记忆,因为它就在上下文里。” - 中断与控制流:MemGPT 用中断(事件)在用户和自己之间切换控制流。论文在两个领域评估:超出上下文窗口的长文档分析,以及多会话聊天。
slides 引用的结果(深度记忆检索 DMR:问以前会话里的细节):
| 模型 | 准确率 | ROUGE-L(R) |
|---|---|---|
| GPT-3.5 Turbo | 38.7% | 0.394 |
| + MemGPT | 66.9% | 0.629 |
| GPT-4 | 32.1% | 0.296 |
| + MemGPT | 92.5% | 0.814 |
| GPT-4 Turbo | 35.3% | 0.359 |
| + MemGPT | 93.4% | 0.827 |
另一张图(文档问答)显示:把更多文档塞进固定上下文的模型,准确率先升后降;MemGPT 的表现不受上下文长度影响。
代码 03 用模拟用户把主上下文的机制跑了一遍(队列容量 3,000 token,70% 时警告)。演示 1 是一个用户的事件流:第 7 个会话时队列到了 71%,模型收到警告,把过敏、工作、早上喝什么、狗的名字、姐妹的名字等写进工作上下文(working_context.replace('allergy', ...));第 10 个会话队列满了,最早的 62 条消息被换出,递归摘要里留下 4 条事实……40 个会话之后,回忆存储里有全部 480 条消息。
演示 2:问很久以前说过的事(20 个用户;单跳、历史、原因、时间四类题):
| 做法 | 准确率 | 每题输入 token | 每题 LLM 调用 |
|---|---|---|---|
| 固定上下文(队列满了就丢) | 6.2% | 2,524 | 1.00 |
| 固定上下文 + 递归摘要 | 39.7% | 2,622 | 1.00 |
| MemGPT(摘要 + 工作上下文 + 外部存储) | 85.6% | 2,788 | 1.65 |
- 固定上下文:很久以前的事几乎都答不上来。
- 递归摘要留住了一部分,但摘要是有损的,每递归一次旧事实又丢一些——越早的事越模糊。
- MemGPT:内存压力警告给了模型”趁还在、赶紧存”的机会;工作上下文答不了时调用搜索函数,去回忆存储里翻原文(演示 3 的轨迹:问”搬家前住哪”,工作上下文里只有现在的城市,模型调用
recall_storage.search找到了”I live in Ashmere.”)。代价是每题多 0.65 次调用。形状和论文的 DMR 结果一致。
分层记忆把”上下文里放什么”变成了模型自己的决策——这既是它的力量,也是它新的失败方式:模型要知道自己不知道才会去搜。slides 还介绍了 MemoryOS(Kang et al., 2025):像操作系统一样分短期、中期、长期(人格)记忆,按热度在层与层之间迁移。
4.3 反思式整合:Reflexion 与生成式智能体
Reflexion 回顾(第 1 讲 §5.7、第 6 讲 §3.2):把评价和反思写成”记忆”,放进执行者的上下文——起作用的是反思,不只是看过以前的轨迹。
生成式智能体(Park et al., UIST 2023):25 个智能体住在一个小镇里;用户只给一个智能体(Isabella)一个想法——办一场情人节派对——智能体们在接下来两天里自己发邀请、结识新朋友、约对方一起去,并在正确的时间到场。它的记忆架构:
- 记忆流(memory stream):智能体全部经历的自然语言记录,每条带时间戳(“desk is idle""Isabella is writing in her journal”……大量琐碎的观察)。
- 检索:要回答”你现在最期待什么?“时,按三项打分取回最合适的几条:
- 新近:距离上次被取用过了多久,按每(游戏里的)小时 0.995 指数衰减;
- 重要:写入时让 LLM 打 1–10 分(“刷牙”是 1,“分手、被大学录取”是 10);
- 相关:和当前问题的嵌入余弦相似度;
- 三项各自归一化后相加。slides 上的例子:“Isabella 正兴奋地计划在 Hobbs Cafe 办情人节派对”得分 2.34 = 0.91(新近)+ 0.63(重要)+ 0.80(相关),排第一;“订派对的装饰”2.21 = 0.87 + 0.63 + 0.71。
- 反思:最近事件的重要性加起来超过一个阈值(论文是 150)时,智能体从最近的记忆里提出几个高层问题,检索证据,写出更抽象的”洞见”(带着引用),洞见本身也存回记忆流。
代码 04 把记忆流用在模拟用户身上(每句话一条观察;重要性按事实类型打分再加 ±1 的噪声,模拟 LLM 打分的不一致;相关性用”词 + 概念”的余弦代替嵌入),20 个用户 × 3 个请求(“今晚给你订晚饭,有什么要注意的?“要取回过敏和饮食;“帮我订机票”要取回航空公司;“姐妹下周来”要取回姐妹),看取前 5 条能不能把要紧的记忆取全:
| 打分方式 | 要紧的记忆全部取回 |
|---|---|
| 只看新近(每天衰减 0.98) | 0.0% |
| 只看重要 | 11.7% |
| 只看相关 | 55.0% |
| 新近 + 相关(每天 0.98) | 1.7% |
| 三项相加,论文的衰减(每小时 0.995) | 48.3% |
| 三项相加,每天 0.98 | 36.7% |
| 三项相加,长期属性不衰减 | 78.3% |
这张表的结论和”照搬论文”的预期不同,值得仔细读:
- 单项各有各的毛病:只看新近,取回的是最近几次的闲聊;只看重要,总是那几条最重要的、和问题无关时也一样;只看相关,会被关键词像的闲聊和干扰项(同事的狗、侄子的过敏)带偏。
- 照搬论文的参数,在半年的时间尺度上反而不如只看相关。新近度对”几个月前说过、至今成立”的事实(过敏、饮食)一律给接近 0 的分,却把最近的闲聊推到前面;换成更温和的按天衰减更糟——最近几周的闲聊都还有可观的新近度。论文的参数是给两天的小镇模拟调的。超参数随时间尺度而变。
- 让”长期属性”(过敏、饮食、住址……)不衰减、只让闲聊和事件衰减:78.3%。哪些记忆该随时间淡去、哪些不该,本身就是记忆设计的一部分(§6.1)。
- “订机票”是另一种失败:新的偏好用了不同的说法(“X from now on”),旧的那句(“Booked another trip on Y”)和”订机票”更像——20 个用户里最多 4 个取回了现在坐的航空公司。检索式记忆在这里几乎总是取回旧版本,这正是 §4.4 的”按属性整合、新值覆盖旧值”要解决的问题。
反思(演示 3、4):用户 0 的 240 条观察里,重要性累计超过 150 时触发反思,写出了 4 条洞见,例如”The user cares about health and fitness: sleep, running and diet come up often.”,引用了”改喝热巧克力(因为医生的建议)""报名马拉松""遛狗”几条观察。抽象的问题——“推荐一个我周末会喜欢的活动”——和任何一条具体的观察都不太像:
| 记忆流 | 取 1 条 | 取 2 条 | 取 3 条 | 取 5 条 |
|---|---|---|---|---|
| 没有反思 | 0% | 0% | 90% | 100% |
| 有反思 | 95% | 100% | 100% | 100% |
(表里是”前 k 条里已经有成型线索”的用户比例:一条相关的洞见,或 ≥ 3 条相关的观察。)有反思时,一条洞见就够了——同样的信息,更少的上下文。代价是 slides 总结表里那句:抽象可能引入没有根据的结论,而错的洞见会被反复取回、反复误导。
4.4 记忆维护:睡眠时计算、A-Mem、Mem0
睡眠时计算(Lin et al., 2025):在用户不在的时候(“睡觉时”),预先把上下文想一遍——推出可能被问到的结论、整理好表示——测试时就能用更少的计算答对。摘要报告:在 Stateful GSM-Symbolic 和 Stateful AIME 上,达到同样准确率所需的测试时计算减少约 5 倍;加大睡眠时计算还能把准确率再提高最多 13% 和 18%;同一份上下文上有多个相关问题时,把睡眠时计算分摊开,每个问题的平均成本降 2.5 倍。slides 上的图显示,在 o3-mini、Claude 3.7 Sonnet、DeepSeek R1 等模型上,睡眠时计算的曲线普遍压过了”测试时多采样(pass@k)“的曲线。
A-Mem(Xu et al., 2025)的关键想法:专门造一个只管记忆的智能体——每条新记忆写成一张带关键词、标签、描述的”笔记”,和相关的旧笔记建立链接,旧笔记也会随新信息”演化”(受卡片盒笔记法启发)。
Mem0(Chhikara et al., 2025):一个后台的记忆 workflow。抽取阶段:从新消息(加上对话摘要和最近的消息)里抽出候选事实;更新阶段:对每条候选事实,检索语义上相似的已有记忆,让 LLM 在四种操作里选一种——ADD(新信息)、UPDATE(补充或修正已有记忆)、DELETE(和新信息矛盾的旧记忆)、NOOP(什么都不做)。它的图版本(Mem0ᵍ)把记忆存成实体–关系图,冲突检测器发现矛盾的旧关系时把它标为无效。摘要报告:在 LoCoMo 上 LLM 评审的得分比 OpenAI 的记忆功能相对高 26%;和”全部塞进上下文”相比,p95 延迟低 91%、token 成本省 90% 以上;图版本的总分再高约 2%。
代码 06 实现了两种 Mem0 式更新(覆盖旧值 / 把旧值移进历史)并和”只追加”比较(20 个用户,40 个会话;三种做法共用同一份抽取结果):
| 做法 | 40 个会话后的条数 | 写入时的 LLM 调用 | latest | history | reason | 每题读取 token |
|---|---|---|---|---|---|---|
| 只追加 | 24.6 | 40 | 81.7% | 61.2% | 77.5% | 185 |
| Mem0 式:覆盖 | 16.4 | 65 | 80.8% | 35.0% | 75.0% | 176 |
| Mem0 式:保留历史 | 23.8 | 65 | 74.2% | 60.0% | 77.5% | 184 |
(Mem0 式:每个用户平均 ADD 16.4、UPDATE 7.3、NOOP 0.8 次。)
- 整合要花计算:每条新事实都要和已有记忆比较一次,写入时的调用从 40 涨到 65。
- 覆盖会丢信息:历史题从 60% 掉到 35%——只有用户自己说出”从 A 换到 B”时,旧值才碰巧留在新事实里。保留历史(像 Zep 那样给每条事实记有效期)两头都照顾,代价是存得多一点;同一件事的版本多了,挑最新值时也更容易挑错(latest 74.2%)。
- 维护会放大写入时的错误:抽取器偶尔把干扰项(同事的狗)错记成用户的事实。只追加时,错的和对的并存,阅读器还有机会挑对;覆盖时,错的值直接取代了正确的当前值——每个用户平均 0.60 条”当前值”是被污染的。写入路径上的错误比读取路径上的更难补救(§6.2 的投毒是它的恶意版本)。
- 睡眠时计算是一个摊销问题(演示 4 的成本模型):每晚花约 4,000 个输入 token 把记忆整理成一份”档案”(现在的偏好、推出来的事实……),之后每个问题只读档案、输出也短。这组参数下,每天超过约 4.4 个问题才划算。另外两点不在成本表里:延迟更低(读一份短档案);但白天刚改的偏好昨晚的档案里还没有——档案要和当前会话的上下文一起用。
5. 评估记忆 · Evaluating agent memory
5.1 四条要求
slides 给好的记忆评估列了四条:
- 真实:记忆的来源(“干草堆”)和问题都要反映真实场景;
- 长上下文:短对话不需要记忆,没必要在上面评;
- 有挑战:太容易就区分不出系统的失败;
- 可验证:要知道系统什么时候成功、什么时候失败。
5.2 LoCoMo
LoCoMo(Maharana et al., ACL 2024):在很多段很长的模拟对话上做多任务评估,对话由扮演用户的智能体生成(用的正是生成式智能体的架构)。slides 上的 RAG 结果表(gpt-3.5-turbo):不检索时答案 F1 总分 22.4;以对话轮次为单位检索前 50 条时,检索召回率 82.7%,答案 F1 只有 40.5;以”观察”(从对话里提炼的事实)为单位检索前 5 条时 F1 最高(43.3)。slides 的红字:“就算模型拿到了正确的记忆,也不一定用得好。“按四条要求:真实 ✗(用户和用户之间的模拟对话,不是我们真正关心的场景);长上下文 ✓(每段约 16.6K token);有挑战 ✓(多任务、对抗题);可验证 ✓(问答有标准答案)。
5.3 PersonaMem
人会有很多次对话,偏好也会随时间变——于是 PersonaMem(Jiang et al., 2025)模拟用户和助手之间的多次对话,偏好不断演化,用多选题考七类问题(回顾偏好变化的原因、追踪偏好的完整演化、给出符合偏好的推荐、回忆用户说过的事实、认出最新的偏好、把理由推广到新场景、提出新点子)。slides 上的图(32K token 上下文):GPT-4o 平均约 0.39,加上 Mem0 涨了约 19 个百分点,加上 RAG 涨了约 26 个百分点;slides 的结论:“记忆 / RAG 必不可少,Mem0 对偏好演化和最近的偏好有帮助。“按四条要求:真实 △(用户和助手的对话更像,但多选题不像智能体真正使用信息的方式);长上下文 ✓(一段对话最长接近 100 万 token);有挑战 ✗(多选题有干扰项,但可以猜);可验证 ✓。
5.4 LongMemEval-v2
如果记忆的对象不是对话、而是智能体的轨迹呢?LongMemEval-v2(Wu et al., 2026)的构造:用 Codex(GPT-5.2 和 GPT-5-mini)在四个 WebArena 环境里跑出轨迹;人工整理五类问题;保证只有少数几条轨迹能回答某个问题;再配上 100–500 条不含答案的轨迹作为”干草堆”。slides 上的结果图:基于检索的记忆(配 Qwen3.5 9B)准确率约 0.51–0.59;基于文件系统的记忆(配 GPT-5.4-mini)在小规模集上最高约 0.75——“文件系统记忆在这里胜过检索,虽然它的模型也更强”。按四条要求:真实 ✓(智能体轨迹更真实,但问的仍然是关于旧观察的多选题);长上下文 ✓(几亿 token 的轨迹);有挑战 ✓(巨大的干草堆里只有少数轨迹有答案);可验证 ✓。
5.5 MemoryArena
能不能直接测智能体解决真实、多样的问题,而不是做多选题?MemoryArena(He et al., 2026):四个环境(打包网购、团体旅行规划、渐进式网页搜索、形式推理),子任务逐步构建、互相依赖,约束可以验证。slides 上的表(任务智能体 gpt-5.1-mini):所有方法的平均成功率都很低——长上下文 0.09–0.19,记忆智能体(Letta、Mem0、Mirix、Reasoning Bank)0.12–0.14,RAG(BM25、嵌入、MemoRAG、GraphRAG)0.17–0.20。slides 的红字:“记忆控制器在这里是最弱的方法。还有很大的提升空间!因为这是真实而复杂的任务,失败不能全部归因于记忆。“四条要求全部满足。
5.6 在模拟用户上做一个迷你基准
代码 07 在 20 个模拟用户上(每人 28 题,7 种题型)比较了 7 种记忆系统:
| 系统 | single | latest | history | reason | temporal | multihop | abstain | 总体 | 每题读取 token | 每用户写入调用 |
|---|---|---|---|---|---|---|---|---|---|---|
| 没有记忆 | 8% | 11% | 4% | 0% | 0% | 0% | 93% | 14.3% | 150 | 0 |
| 全塞进上下文(8K 窗口) | 19% | 79% | 40% | 59% | 66% | 0% | 90% | 53.6% | 8,139 | 0 |
| 原始对话 + BM25 检索 5 轮 | 52% | 38% | 41% | 69% | 72% | 0% | 93% | 53.4% | 201 | 0 |
| 抽取事实,只追加 | 88% | 82% | 61% | 78% | 86% | 72% | 92% | 80.4% | 185 | 40 |
| Mem0 式:覆盖 | 83% | 81% | 35% | 75% | 90% | 80% | 93% | 76.4% | 176 | 65 |
| Mem0 式:保留历史 | 86% | 74% | 60% | 78% | 88% | 80% | 90% | 78.8% | 184 | 65 |
| MemGPT 式:核心 + 档案 + 回忆 | 78% | 78% | 66% | 82% | 80% | 70% | 87% | 77.5% | 504 | 40 |
- 没有一种系统在所有题型上都最好。长上下文只记得最近的事:最新值还行,早期的单跳事实和两跳几乎全丢。原始对话 + BM25 怕换说法(“Finally settled in X”里没有 city、live 这些词)和两跳(第二跳那句话和问题没有共同的词)。抽取事实的几种系统总体最好,每题只读两百个左右的 token。
- 抽取式记忆的代价在写入端:每个会话至少一次 LLM 调用,Mem0 式还要为每条新事实再调用一次;漏抽、错抽在写入时就发生了,读的时候补不回来。
证据在上下文里 ≠ 用得上(演示 2):把最近的对话塞满窗口,窗口从 2K 开到 16K:
| 窗口 | 证据在上下文里 | 答对 | 每题读取 token |
|---|---|---|---|
| 2K | 6% | 6% | 2,137 |
| 4K | 26% | 23% | 4,138 |
| 8K | 53% | 52% | 8,139 |
| 16K(整段对话都放得下) | 100% | 79% | 12,328 |
整段对话都放得下时,证据 100% 在上下文里,答对的却只有 79%——大约每五道题就有一道,答案明明就在上下文里却答错了(上下文太长漏看了、拿了旧版本、被干扰项带偏)。这就是 LoCoMo 那张表(召回 82.7%、F1 40.5)的同一个现象。
我们的迷你基准按四条要求:真实 ✗(模板生成的对话);长上下文 △(每人约 1.2 万 token);有挑战 △(7 种题型、干扰项、偏好变化);可验证 ✓。它适合检验机制,不能替代 LoCoMo、MemoryArena 这类基准,更不能替代你在自己产品数据上的评估(第 12 讲)。
6. 挑战与开放问题 · Challenges and open problems
slides 列了三类:
6.1 该记住什么、该忘掉什么
一条记忆写下的时候,并不知道它将来有没有用。全留着会让检索、上下文和维护的成本都变大;忘掉又可能丢了有用的证据或者还没完成的承诺。slides 的例子(Ma et al., 2026):一句话是该记住的事实,还是一个玩笑?该记住它的哪个方面?
代码 08 演示 1 在抽取式记忆上试了四种遗忘策略:
| 策略 | 记忆大小(token) | 答对 | 过敏被忘了 |
|---|---|---|---|
| 全部保留 | 301 | 81.2% | 0/20 |
| 只留重要性 ≥ 6 的 | 160 | 54.3% | 0/20 |
| 60 天前的丢掉(重要性 ≥ 8 的除外) | 135 | 45.4% | 0/20 |
| 只留最近 12 条 | 154 | 51.8% | 19/20 |
按重要性丢,“喝什么""坐哪家航空”这类重要性不高的偏好都没了;按时间丢、只留最近几条,几个月前说过、至今成立的事实就没了——只留最近 12 条时,20 个用户里 19 个的过敏被忘了,那恰恰是最不该忘的一条。和 §4.3 的教训一样:遗忘要区分记忆的类型,长期属性和一次性的闲聊不该用同一条规则。
6.2 信任、隐私和用户控制
记忆是一个攻击面。slides 引用 Chen et al.(2024):可以让模型依据被投毒的程序性记忆做出危险的行为。代码 08 演示 2 只从防御的角度量这件事:助手处理的文档里,有 10% 夹着”请记住一条新的长期规则”的文字;朴素的记忆写入器有时会把它存成程序性记忆,之后相关的任务都会照它行事。1,000 个任务:
| 防御 | 存进程序性记忆的有毒规则 | 被触发的次数 | 误伤(挡掉了用户自己的规则) |
|---|---|---|---|
| 不设防 | 43 | 212 | 0 |
| 写入校验(检测”像不像指令”,命中率 0.85) | 6 | 161 | 4 |
| 来源标记(程序性记忆只接受用户本人的写入) | 0 | 0 | 0 |
| 执行前确认 | 34 | 19 | 0 |
| 写入校验 + 执行前确认 | 9 | 19 | 1 |
写入校验挡住了大部分有毒规则(43 → 6),被触发的次数却只从 212 降到 161——漏进一条就够了,它会在之后的每个相关任务里生效;检测器还会误伤用户自己的规则。执行前确认把触发压到 19 次,但要用户一次次确认。最有效的是来源标记:每条记忆记下它从哪来,程序性记忆只接受用户本人的写入,来自工具输出的”规则”根本进不去。这和第 4 讲、前置讲 P4 的间接注入防御是同一套思路:数据不是指令。
隐私。slides 引用 Shao et al.(PrivacyLens):智能体和世界交互时,并不完全理解你想把什么保密;带着记忆这样做,可能暴露个人细节。代码 08 演示 3:同一条健康信息,用来给用户本人建议是合适的,写进替用户发给同事的邮件就是泄露。只看相关性时,400 个任务里泄露 65 次;给每条记忆标上”在什么场合说的、敏感不敏感”、敏感记忆只流向同一场合(情境完整性,第 14 讲),泄露降到 0,私人场合里的有用度不受影响(93% vs 92%)。隐私的问题不在”记不记”,而在”流到哪”。
6.3 用对记忆
slides 引用 Hu et al.(2026):LLM 有时太急于用上下文里的东西,出现”过度个性化”——问一个和你本人无关的问题,回答里也冒出”考虑到你的狗……”。更好的检索或者训练 LLM 忽略不重要的上下文都能缓解,但都没有完全解决;而且有的用户比别人更喜欢个性化。代码 08 演示 4(一半的问题和用户无关):
| 记忆进上下文的条件 | 无关问题里硬塞了个人信息 | 个人问题里用上了记忆 |
|---|---|---|
| 不门控(每次都塞前 3 条) | 56% | 87% |
| 相关性 ≥ 0.3 | 21% | 89% |
| 相关性 ≥ 0.5 | 8% | 77% |
| 相关性 ≥ 0.7 | 1% | 53% |
门控越严,误用越少,但该个性化的问题也漏得越多——阈值是一个产品决定,可能需要让用户自己调。
7. 用真实模型试一试 · Try it on a real model
代码 09(可选)让真实的 Claude 当抽取器(从每个会话里抽出关于用户和家人的事实,忽略同事、朋友等人)和阅读器(按 Mem0 式更新、保留历史之后,回答 28 道题):
pip install anthropic
python3 09_real_llm.py
--toy 不联网,用模拟的抽取器和阅读器跑同样的流程(模拟抽取器在用户 0 身上:24 条标准事实,抽出 22 条,对上 21 条,召回 88%、精确率 95%,把别人的事记成用户的 1 次)。值得看的是:真实模型会不会把”同事的狗""朋友搬家”记成用户的;history 和 reason 题——它抽的时候有没有保留原因;abstain 题——它会不会老实说 unknown。
8. 小结 · Summary
- 为什么需要记忆:没有记忆会丢掉程序、知识和进展;有了记忆能个性化、从经验中学习、保持状态。全塞进上下文撑不了多久,而且就算放得下也用不好。
- 记忆的类型:CoALA 的工作、情景、语义、程序性记忆;参数记忆 vs 上下文记忆。设计记忆要回答存什么、什么时候、怎样存——文件系统(智能体自己能管、人能读、grep 即检索)、数据库(向量 / SQLite / BM25)、知识图谱(关系和时间是一等公民)。
- 四种架构模式:学习程序(Voyager 的技能库、AWM 的工作流、技能文件——复用省力,但会过时,要验证和修);分层记忆(MemGPT 让模型自己管理主上下文和外部存储——上下文小了,但模型要知道自己不知道);反思式整合(生成式智能体的三项打分与反思——超参数随时间尺度而变;洞见压缩了信息,也可能概括错);记忆维护(Mem0 的 ADD / UPDATE / DELETE / NOOP、睡眠时计算、A-Mem——组织得更好要花计算,覆盖会丢历史、会放大抽取错误)。
- 评估:真实、长上下文、有挑战、可验证;LoCoMo、PersonaMem、LongMemEval-v2、MemoryArena 各满足其中几条;证据在上下文里不等于用得上;今天的记忆控制器在真实任务上还有很大的提升空间。
- 挑战:未来的相关性未知(遗忘要分类型);记忆是攻击面(来源标记最有效、漏一条就够了);隐私在于流向(情境完整性);过度个性化(按相关性门控,阈值是产品决定)。
9. 常见误区 · Common pitfalls
- “上下文窗口够大,就不需要记忆了。” 历史线性增长,几百个会话就超出 200K;就算放得下,答案在上下文里也有约五分之一答错(代码 07)。
- “记忆就是把对话存下来、需要时检索。” 原始对话检索怕换说法、怕两跳,而且新旧版本混在一起(代码 07:53.4%)。抽取、整合、带时间的结构各有用处。
- “新值覆盖旧值,记忆就干净了。” 也就丢掉了”以前是什么、为什么变”(历史题 60% → 35%),而且一条错记的值会直接取代正确的值。
- “照搬论文的记忆参数就行。” 生成式智能体的衰减参数是给两天的模拟调的,放到半年的助手上反而不如只看相关(48.3% vs 55.0%)。
- “程序性记忆学会了就一劳永逸。” 环境一变,过时的程序比没有记忆还糟(25% vs 100%);要验证、要修。
- “让 LLM 打重要性分,重要的就不会忘。” 按重要性丢掉的是”喝什么”这类不重要但会被问到的偏好;按时间丢掉的可能正是最重要的过敏。
- “写入时加一个检测器,投毒就挡住了。” 漏一条就够了(触发次数 212 → 161);用来源标记让不可信来源根本写不进程序性记忆。
- “敏感信息不记就安全了。” 很多场合需要记住它们(给用户本人的建议);问题在于它们流向哪里。
- “记住了就该用上。” 和用户无关的问题里硬塞个人信息是过度个性化;按相关性门控。
- “在 LoCoMo 上分数高,就说明记忆系统好。” 看基准满足哪几条要求;MemoryArena 这样的真实任务上,今天的记忆控制器还不如简单的 RAG。
10. 练习 · Exercises
练习 1(分类):把下面每一项归到 CoALA 的四种记忆之一,并说明它是参数记忆还是上下文记忆:(a) 模型知道巴黎是法国首都;(b) 助手的 MEMORY.md 里写着”用户对花生过敏”;(c) 第 6 讲 Pi 的 python-testing 技能文件;(d) 上周那次对话的完整记录;(e) 当前会话里用户刚说的话;(f) Voyager 技能库里的 craftDiamondPickaxe()。
参考答案
(a) 语义,参数;(b) 语义,上下文;(c) 程序性,上下文;(d) 情景,上下文(检索回来时);(e) 工作记忆(上下文本身);(f) 程序性,上下文(作为代码被检索并执行)。注意 (c) 和 (f) 的区别:技能文件是说明,模型读了之后自己执行;技能库里的是可执行代码,调用一次就执行完。练习 2(三个问题):为一个”帮用户管理日程”的助手设计记忆:分别回答存什么、什么时候写 / 读、存在哪。至少区分三类信息。
参考答案(之一)
(1) 承诺和预约("5 月 14 日看牙医"):语义记忆中的事件,带日期;用户提到时立即写(事件驱动),每天早上和临近时读(后台任务),存在带时间字段的数据库里(SQLite,按日期查)。(2) 偏好("上午 9–11 点别安排会"):语义记忆,带有效期;对话结束后抽取并整合(Mem0 式 UPDATE + 保留历史),安排日程时读;存成带有效期的事实或知识图谱的边。(3) 怎样处理冲突("有冲突时先问我,不要自动挪"):程序性记忆,**只接受用户本人写入**(§6.2 的来源标记),放进系统提示或技能文件。此外原始对话存进情景记忆,用于回答"我上周说过什么"。练习 3(SQL 与有效期):用代码 02 的 facts 表(about、attr、value、valid_from、valid_to),写出:(a) 用户在 2026-03-01 喝什么;(b) 用户换过几次航空公司;(c) 用户的姐妹现在在哪工作。
参考答案
(a) `SELECT value FROM facts WHERE about='user' AND attr='drink' AND valid_from <= '2026-03-01' AND (valid_to IS NULL OR '2026-03-01' < valid_to)`;(b) `SELECT COUNT(*) - 1 FROM facts WHERE about='user' AND attr='airline'`(版本数减一);(c) `SELECT f2.value FROM facts f1 JOIN facts f2 ON f2.about = f1.value WHERE f1.about='user' AND f1.attr='sister' AND f1.valid_to IS NULL AND f2.attr='employer' AND f2.valid_to IS NULL`。都用占位符传参数更好(前置讲 P4 §2)。练习 4(MemGPT 的内存压力):MemGPT 在队列到 70% 时发警告、100% 时换出一半。(a) 如果把警告的阈值提到 95%,会发生什么?(b) 如果模型收到警告时什么都不存,换出之后还剩什么?(c) 为什么”回忆存储”保留全部原文这么重要?
参考答案
(a) 模型保存重要信息的窗口变窄:从警告到换出之间只剩 5% 的空间,很可能来不及存(或者一次要处理的内容太多)。(b) 只剩递归摘要——有损、而且越早的事越模糊(代码 03:递归摘要 39.7%)。(c) 它是兜底:工作上下文和摘要漏掉的事实,还能通过搜索原文找回(代码 03 演示 3 就是靠它答对"搬家前住哪"的)。代价是存储和检索成本,以及模型要知道去搜。练习 5(记忆流的打分):一条记忆的新近度、重要性、相关性(归一化后)分别是 0.10、0.90、0.60;另一条是 0.95、0.10、0.55。(a) 等权重相加谁排前面?(b) 如果问题是”今晚订什么外卖”,第一条是”对花生过敏”,第二条是”昨晚做了扁豆汤”,你希望谁排前面?(c) 怎样改打分规则?
参考答案
(a) 第一条 1.60,第二条 1.60——打平(实际取决于更细的数值)。(b) 当然是过敏那条——它是"长期成立"的属性,和时间无关。(c) 按记忆类型区分衰减:长期属性(过敏、饮食、住址)不衰减,闲聊和一次性事件才衰减(代码 04:48.3% → 78.3%);或者提高重要性的权重;或者对安全相关的记忆(过敏)设"必取"规则。重要的是用自己场景的数据去调这些超参数。练习 6(覆盖与历史):用户在第 5 个会话说”我住在 A”,第 20 个会话说”终于在 B 安顿下来了”(没提 A)。(a) Mem0 式覆盖之后,“我搬家前住哪”能答吗?(b) 怎样改写入逻辑才能回答?(c) 这样做的代价是什么?
参考答案
(a) 不能:UPDATE 把 A 覆盖成 B,新的那句话里也没有 A。(b) UPDATE 时把旧值移进历史(或者给旧事实填上失效日期,Zep 式),而不是删掉;或者在新事实里自动记下"previously: A"。(c) 存储多一些;检索时同一件事有多个版本,阅读器更容易挑错最新值(代码 06:latest 80.8% → 74.2%),所以检索时要带上有效期、让"当前值"一眼可辨。练习 7(睡眠时计算):代码 06 的成本模型里,每晚预计算花 4,000 个输入 token 和 600 个输出 token;查询时现想每题 900 输入 + 250 输出,有档案时每题 350 输入 + 40 输出(输入每百万 5 美元、输出 25 美元)。(a) 推出盈亏点(每天几个问题)。(b) 如果输出价格翻倍,盈亏点怎样变?
参考答案
(a) 每晚成本 = (4000 × 5 + 600 × 25) / 10⁶ = 0.035 美元;每题省下 (900 × 5 + 250 × 25 − 350 × 5 − 40 × 25) / 10⁶ = (4500 + 6250 − 1750 − 1000) / 10⁶ = 0.008 美元;盈亏点 0.035 / 0.008 ≈ 4.4 个问题 / 天。(b) 输出 50 美元:每晚 (20000 + 30000) / 10⁶ = 0.05;每题省 (4500 + 12500 − 1750 − 2000) / 10⁶ = 0.01325;盈亏点 ≈ 3.8——查询时现想的输出(推理)更贵了,预计算更划算。练习 8(基准的四条要求):你要评估一个”帮工程师记住代码库约定”的编程助手的记忆。设计一个评估,并逐条说明它怎样满足真实、长上下文、有挑战、可验证。
参考答案(之一)
真实:用真实的代码库和真实的工程师会话(或其回放),问题来自真实的 code review 意见("这个仓库的日志要用结构化格式")。长上下文:跨几十个会话、上万次工具调用的轨迹,约定散落在其中。有挑战:约定会变(旧约定被废弃)、有相似但不同的约定(不同子目录不同)、有只出现一次的约定。可验证:不问多选题,而是让助手完成会被约定影响的任务(写一个函数),用 lint 规则 / 测试 / 结构化检查来判断有没有遵守约定——像 MemoryArena 那样考"用得对不对",而不只是"记不记得"。练习 9(投毒的防御):解释为什么代码 08 里”写入校验”挡住了 86% 的有毒规则,被触发的次数却只降了约 24%。由此说明防御应该放在写入路径的哪一层。
参考答案
因为一条有毒规则一旦写进去,就会在之后的每个相关任务里生效:触发次数 ≈ 存在的有毒规则 × 之后相关任务的数量。只要有一条漏网,后面几百个任务都会受影响——伤害和"有没有漏网"有关,而不只和"漏了几条"成比例。所以防御要放在**最前面**,并且是确定性的:来源标记让不可信来源的内容根本不能写进程序性记忆(0 次);检测器这种概率性的防御只能作为补充,再配上执行前确认和定期审查记忆(让用户看得见、改得了自己的记忆)。练习 10(开放题:HW1 的跨会话记忆):原课 HW1 要求实现跨会话记忆。结合本讲,写出你的设计:分哪几层、写入和读取的时机、遗忘规则、防投毒和隐私的措施,以及你会怎样评估它。
参考答案(之一)
三层:(1) 核心记忆(总在系统提示里,≤ 500 token):用户的长期属性和明确的偏好,只能由用户本人的陈述写入(来源标记);(2) 事实存储(SQLite,带有效期和来源):每个会话结束后后台抽取、Mem0 式整合并保留历史;(3) 情景存储(原始对话,BM25 + 日期过滤):兜底。读取:核心记忆每次都在;问题涉及历史 / 时间 / 不在核心里的东西时,智能体调用 search_memory 工具。遗忘:闲聊不进事实存储;事实永久保留但带有效期;情景存储按时间衰减检索权重而不删除。安全:工具输出里的内容不能写进核心记忆和程序性规则;敏感事实标注场合,对外的工具调用前检查流向。评估:按 4 元组(第 12 讲)造一组跨会话的任务——单跳、最新值、历史、两跳、该说不知道的,外加投毒和隐私的对抗用例;同时记录写入和读取的成本。11. 延伸阅读 · Further reading
本讲的阅读材料
- C. Packer et al., MemGPT: Towards LLMs as Operating Systems, 2023;Letta 的博客(MemGPT 的后续工程化)。
- P. Chhikara et al., Mem0: Building Production-Ready AI Agents with Scalable Long-Term Memory, 2025.
- J. S. Park et al., Generative Agents: Interactive Simulacra of Human Behavior, UIST 2023.
记忆的分类
- T. Sumers et al., Cognitive Architectures for Language Agents(CoALA),TMLR 2024.
架构
- G. Wang et al., Voyager: An Open-Ended Embodied Agent with Large Language Models, 2023.
- Z. Z. Wang et al., Agent Workflow Memory, 2024.
- J. Kang et al., Memory OS of AI Agent(MemoryOS),2025.
- K. Lin et al., Sleep-time Compute: Beyond Inference Scaling at Test-time, 2025.
- W. Xu et al., A-MEM: Agentic Memory for LLM Agents, 2025.
- P. Rasmussen et al., Zep: A Temporal Knowledge Graph Architecture for Agent Memory, 2025.
- Anthropic, Agent Skills 文档。
评估
- A. Maharana et al., Evaluating Very Long-Term Conversational Memory of LLM Agents(LoCoMo),ACL 2024.
- B. Jiang et al., Know Me, Respond to Me: Benchmarking LLMs for Dynamic User Profiling and Personalized Responses at Scale(PersonaMem),2025.
- LongMemEval-v2(Wu et al., 2026);MemoryArena(He et al., 2026)。
挑战
- Z. Chen et al., AgentPoison: Red-teaming LLM Agents via Poisoning Memory or Knowledge Bases, NeurIPS 2024.
- Y. Shao et al., PrivacyLens: Evaluating Privacy Norm Awareness of Language Models in Action, NeurIPS D&B 2024(第 14 讲的阅读材料)。
12. 下一讲预告 · Next lecture
第 8 讲 多智能体系统:第 6 讲把”上下文隔离”(子智能体)列为一种上下文管理模式,本讲的代码 07 又一次看到”交接会丢东西”。下一讲正面讨论多个智能体:什么时候一个智能体就够了(“不要小看单智能体系统”),什么时候值得拆成好几个;编排的几种拓扑(orchestrator–workers、顺序交接、群聊、辩论)和 AutoGen 式的”可对话的智能体”;交接与状态传递时的信息损失;多智能体辩论什么时候有用;动态选择团队成员(DyLAN);以及 Why Do Multi-Agent LLM Systems Fail? 归纳的 14 种失败模式。配套代码会在同一组任务上比较单智能体和多种多智能体拓扑的准确率、token 和延迟,量化交接中的信息损失,并复现失败模式的分类。