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 循环中自己决定:
- 当前问题需要拆成哪些子问题;
- 第一轮应该搜索什么;
- 结果是否充分、是否互相矛盾;
- 是否需要换关键词、继续搜索或交叉验证;
- 什么时候证据已经足够,可以停止。
它更像研究员,而不是搜索框。但这里也有一个需要克制的判断:简单问题不必 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%,多会话检索是四种表示共同的主要薄弱点。