Agent 真正的记忆,不是保存,而是想对

本文是对第三章《用户记忆和知识库》的学习整理。它不是逐节摘要,而是试着回答一个更实际的问题:Agent 怎样才能在需要时,想起正确的信息?

上一篇:第二章学习笔记:上下文工程:不是把信息塞满,而是让 Agent 在正确时刻看见正确的事。

写在前面:记住越多,真的越聪明吗?

假设我先告诉 Agent:“我住在北京。”几个月后又说:“我搬到上海了。”

一个最简单的记忆系统会把两句话都保存下来。问题随之而来:下次订酒店时,它该以哪个城市为出发地?如果只取相似度最高的一条,旧地址可能胜出;如果两条都塞进上下文,模型又要临时猜测哪条有效。

这让我意识到,Agent 的记忆问题从来不只是“存没存”,而是至少包含四个连续动作:

从交互中提取事实 → 组织并保留来源 → 在需要时准确找回 → 用新证据安全更新

少了任何一环,所谓“长期记忆”都可能退化成一座越堆越大的数据仓库。第三章真正讨论的,正是这条知识生命周期。

一条主线:用户记忆与知识库,其实是同一道题

用户记忆服务于单个用户,知识库服务于一群用户;一个追求个性化,一个追求领域覆盖。它们的尺度不同,底层难题却高度一致:

问题 用户记忆 共享知识库
信息从哪里来 历史会话、工具结果、用户行为 文档、网页、业务规则、案例数据
怎样表示 Notes、JSON Cards、可执行状态 文本块、层次摘要、知识图谱
怎样找回 按用户、时间、实体和语义检索 BM25、向量检索、混合检索
怎样处理变化 偏好改变、身份变更、事实冲突 新版政策、失效条款、文档修订
最大风险 隐私泄露、记错人、使用过期事实 越权检索、知识投毒、错误版本

所以这一章前半部分讲“如何记住一个人”,后半部分讲“如何使用一座知识库”,最后又汇合到同一个答案:少量结构化概览常驻上下文,大量原始细节按需检索。

先别谈技术:怎样才算“记得好”

第三章把记忆能力分成三个层次。我很喜欢这个顺序,因为它把“记忆”从模糊体验变成了可以测试的能力。

第一层:基础回忆

用户明确说过“会员号是 12345”,系统之后能够准确取回。这里考验的是最基本的写入与读取,重点是不能编、不能串用户,也不能把关键标识记错。

第二层:多会话检索

相关信息散落在多次沟通中,Agent 必须全部找齐再判断。比如用户说“帮我的车预约保养”,而历史记录里有一辆本田和一辆特斯拉。真正合格的行为不是挑一辆最像的,而是识别歧义并追问。

第三层:主动服务

系统需要发现用户没有直接指出的关联。例如订国际航班时,主动联想到几个月前保存的护照有效期,并提示潜在风险。

这三层背后的难度并非线性增长:

准确找回单条事实
        ↓
拼接跨会话、跨对象的信息
        ↓
在全局记忆中发现尚未被提问的关联

第三层最难的地方,不是“搜索更多次”,而是 Agent 必须先拥有全局视野,才知道应该搜索什么。

记忆的三个维度:放哪里、怎么存、存什么

这一章同时使用了几套分类,刚读时很容易混在一起。我把它们整理成三个互不替代的问题。

1. 放哪里:轨迹、长期记忆与业务状态

  • **轨迹(Trajectory)**是单次运行的原始事件序列,包含用户消息、模型回复和工具结果,适合审计与回放;
  • 用户长期记忆是跨会话提炼出的稳定信息,会被合并、修订和淘汰;
  • 业务状态记录任务进行到哪个阶段,例如“等待付款”或“需要澄清”。

轨迹像流水账,长期记忆像档案,业务状态像工单看板。三者用途不同,不该用一份聊天摘要全部代替。

2. 怎么存:从 Notes 到可执行状态

格式 优点 代价 适合什么
Simple Notes 便宜、简单、易追加 关系容易被拆散 大量低风险事实
Enhanced Notes 保留完整叙事 冗余高、更新麻烦 需要上下文的事件
JSON Cards 字段稳定、可局部更新 分类刚性 结构明确的用户属性
Advanced JSON Cards 带人物、关系、来源与时间 生成维护成本高 关键身份、关系与高价值事实
可执行状态 可做聚合、冲突检测和规则校验 需要类型设计与测试 高风险、强约束业务

最打动我的不是某一种格式“胜出”,而是混合策略:关键且少量的信息用强结构保存,大量普通事实用低成本形式留存。把所有内容都塞进最复杂的 Schema,和把所有内容都写成散乱便签一样,都会制造新的问题。

3. 存什么:情景、语义与程序记忆

  • 情景记忆回答“发生过什么”,例如上周订过一张去东京的机票;
  • 语义记忆回答“用户通常是什么样”,例如偏好靠窗、需要素食餐;
  • 程序记忆回答“通常怎样做”,例如用户订票时习惯先筛直飞,再确认座位。

这组来自认知科学的分类,提醒我不能把所有历史都压缩成“用户画像”。事件、稳定事实和行为模式,是三种不同的信息资产。

RAG 的本质:不是让模型知道更多,而是让它此刻看到对的内容

当记忆与知识多到无法全部放入上下文,就需要 RAG。最小流程可以写成:

问题 → 检索相关片段 → 注入上下文 → 基于证据生成答案

看起来简单,真正影响质量的却是前面的每一步。

分块决定了“可被找到的最小单位”

块太小,代词、时间和主题容易丢失;块太大,又会混入多个主题,让嵌入向量失焦,还浪费上下文窗口。因此固定大小、结构感知与语义切分都只是起点,最终要根据真实查询集评估。

我现在更愿意把 Chunking 理解为一种知识建模决策:你怎样切,决定系统将来能怎样想起。

稠密与稀疏检索,各自只解决一半问题

  • 稠密检索擅长语义相近的表达,能理解“猫咪”和“feline”相关,却可能漏掉错误码、产品编号和人名;
  • BM25 等稀疏检索擅长精确关键词,能抓住 HTTP-403,却不理解同义改写。

生产级管线因此通常采用:

稠密召回 ─┐
           ├→ 结果融合(如 RRF)→ 神经重排序 → Top-K 上下文
稀疏召回 ─┘

融合负责把候选汇到一起,重排序负责更细致地判断查询与候选是否真正匹配。两者不是一回事,也不能因为加了重排序就忽视召回质量。

比“用了哪种向量数据库”更值得追踪的是检索指标:该找的内容有没有进入前 k 项、第一条正确结果排得多靠前、整个排序是否合理。RAG 的问题应该先在检索层度量,而不是只看最终回答“读起来像不像对的”。

为什么“把资料都存进向量库”还不够

第三章用了两个非常有启发的例子。

如果知识库中有 90 个黑猫案例、10 个白猫案例,而检索只返回 20 条,模型无法从局部样本准确算出总体比例。再比如,一项优惠的适用边界分散在几百张客服工单里,最近邻只能返回若干个案,却无法凭空生成“哪些人适用、哪些人明确不适用”的完整规则。

这暴露了一个常被忽略的前提:检索只能找到已经被表达出来的知识,不能保证从零散案例中现场归纳出全局规律。

因此,知识进入索引前往往还需要整理:

  • 用 RAPTOR 建立从细节到摘要的树状层次,适合“先看全局,再钻细节”;
  • 用 GraphRAG 表达实体与关系,适合多跳查询和实体消歧;
  • 用带链接的 Markdown 与目录建立可读、可版本控制的轻量知识网络;
  • 对案例数据做结构化提取与统计分析,把隐含模式转成可查询的规则或原型。

这也意味着结构化索引不是免费午餐。它增加索引成本、LLM 调用和维护复杂度。对于“退款政策是什么”这类定位型问题,混合检索通常已经足够;只有频繁出现跨文档综合、层次导航或多跳关系时,更复杂的结构才值得投入。

Agentic RAG:把搜索从管道变成工具

传统 RAG 只搜索一次,然后立即回答。Agentic RAG 则把知识库搜索暴露为工具,让 Agent 在 ReAct 循环中自己决定:

  1. 当前问题需要拆成哪些子问题;
  2. 第一轮应该搜索什么;
  3. 结果是否充分、是否互相矛盾;
  4. 是否需要换关键词、继续搜索或交叉验证;
  5. 什么时候证据已经足够,可以停止。

它更像研究员,而不是搜索框。但这里也有一个需要克制的判断:简单问题不必 Agentic。 单次检索能解决的问题,多轮循环只会增加延迟与成本。Agentic RAG 的价值主要出现在复杂、多跳、信息不完备的任务中。

更重要的是,检索到的文档属于外部数据,不是系统指令。恶意网页和被投毒的知识条目可能携带间接提示注入,因此检索内容必须标记来源,高风险动作也不能仅凭检索文本自动触发。

上下文感知检索:给每个碎片找回“身份证”

“该公司第二季度收入增长了 3%”是一个典型的坏分块:句子本身没有说明是哪家公司、哪一年、来自哪份报告。

上下文感知检索的做法,是在索引前让 LLM 为每个块生成简短前缀,例如:

本段来自 ACME 公司 2025 年第二季度财报的关键业绩章节。

然后把前缀和原块一起交给 BM25 与嵌入模型。这样既补充了精确关键词,也恢复了语义背景。

我把它理解为:普通分块切下了一张纸条,上下文感知检索则给纸条补上来源、时间和主题这张“身份证”。它发生在索引期,是给知识做加法;不要和运行期压缩会话历史的“上下文感知压缩”混为一谈。

最终汇合:双层记忆架构

第三章最值得带走的设计,不是某个检索算法,而是这套双层结构:

层次 保存什么 怎样使用
结构化概览层 少量关键事实、人物关系、时间与状态 常驻上下文,帮助发现关联与规划检索
原始细节层 大量历史对话、事件与证据 通过上下文感知 RAG 按需召回、核验细节

只有概览层,细节会被压缩掉;只有检索层,Agent 又缺少全局视野,不知道哪些旧事实值得联想。两层配合后,才有机会从“用户订了国际航班”联想到“护照即将过期”,再回到原始对话核实日期。

这套架构也解释了“主动服务”为什么昂贵:它不是一次搜索,而是概览触发关联、检索补齐证据、推理形成建议的完整链条。

记忆必须会更新,也必须接受审查

知识会过期,偏好会改变,摘要会逐渐偏离原始证据。因此一个长期运行的记忆系统需要两条更新路径:

  • 增量更新:新证据到来时,做小范围、低延迟的修改;
  • 定期整理:从全局重新去重、合并、解决冲突、调整目录与重建索引。

第三章提出了一个很工程化的类比:把知识库当代码库,把每次知识修改当 Pull Request。

原始证据(只增不改)
        ↓
Proposer 提出最小 diff
        ↓
Reviewer 对照原始证据审核
        ↓
格式、链接、权限与测试检查
        ↓
合入知识库,再重建派生索引

这里最重要的边界是:索引只是可重建的服务层,经过审核的知识与原始证据才是事实来源。Reviewer 也不应只看 Proposer 挑出来的几段文字,否则双方可能共享同一个盲区。

对于“北京”和“上海”这样的冲突,系统不能机械地永远保留最新值。先要确认它们是否描述不同时间、不同对象或不同场景;证据不足时,应保留冲突与待确认状态,而不是强行制造一个确定答案。

隐私与权限,不是上线前再补的功能

用户记忆天然会接触地址、账号、健康信息和私人关系。越个性化,泄露后的损害越具体。

我会把本章里的安全要求压缩成四条底线:

  • 敏感日志优先在本地脱敏,不要为了脱敏先把原文发送到第三方;
  • 检索必须在调用者权限范围内执行,越权文档不应进入模型上下文;
  • 不同租户的索引和元数据必须隔离,避免检索“串味”;
  • 每条关键记忆都应带来源、时间与适用范围,便于追溯和撤销。

隐私不是“最后把名字打码”这么简单,它决定了哪些数据能被保存、谁能检索、模型能看到什么,以及多久以后必须删除。

我的长期记忆系统检查清单

如果现在要为 Agent 增加长期记忆,我会先检查:

  • 是否把原始轨迹、长期记忆和业务状态分开了?
  • 哪些信息值得长期保存,哪些只是本次任务的短期细节?
  • 关键事实是否带来源、人物、时间和适用场景?
  • 冲突信息是被覆盖、并存,还是标记为待确认?
  • 是否同时评估基础回忆、多会话检索与主动服务?
  • 稠密、稀疏与重排序各自解决了什么问题?
  • 分块离开原文后,是否仍能看懂实体、时间和指代?
  • 简单问题是否走低成本路径,复杂问题才启用 Agentic RAG?
  • 检索前是否执行用户、权限与租户过滤?
  • 知识修改能否审查、回滚,并追溯到原始证据?
  • 是否有定期去重、失效下线和全量重建机制?
  • 评估的是检索与任务完成证据,还是只凭最终答案观感?

写在最后

读完第三章,我对“Agent 有记忆”这句话变得更谨慎了。

保存过,不等于记住了;检索到,不等于找全了;写进上下文,也不等于模型用对了。真正可靠的记忆系统,必须让每条知识都能回答四个问题:它从哪里来、现在是否有效、为什么在此刻相关、出错后怎样撤回。

所以,Agent 真正的记忆能力不是无限积累,而是有选择地提炼、有依据地检索、有边界地使用,再用新的证据持续修正自己。

这和人的好记性其实很像:重要的从来不是把一切都背下来,而是在正确的时刻,想起正确的事。

第三章配套实验记录

实验3-1:用三层次框架评估记忆系统

60 个跨会话用例、四种记忆表示共完成 240 个评测单元;enhanced_notes 的总体通过率最高,为 86.7%,多会话检索是四种表示共同的主要薄弱点。

查看完整实验记录