KEEL · 龙骨 · A CURRICULUM FOR THE AI ERA
09. 怎样证明记忆真的有用? — keel 龙骨
演示中,Agent 能说出用户偏好中文,很容易让人产生“记忆已经完成”的感觉。但一个生产系统还要证明:该记的内容被发现了,不该记的没有写入,相关内容能够被找到,最终任务确实改善,而且没有跨用户泄露。
演示中,Agent 能说出用户偏好中文,很容易让人产生“记忆已经完成”的感觉。但一个生产系统还要证明:该记的内容被发现了,不该记的没有写入,相关内容能够被找到,最终任务确实改善,而且没有跨用户泄露。
评估时要拆开链路,否则最终答案出错时,你无法判断问题发生在哪里。
1. 先画出需要分别评估的四层
flowchart LR
A[会话/工具事实] --> B[候选抽取与写入]
B --> C[存储和生命周期]
C --> D[检索与上下文装配]
D --> E[最终任务结果]
模型回答流畅不能证明 B、C、D 正确。每一层都需要自己的样本和指标。
2. 写入质量:系统记对了吗
准备一组人工标注的会话片段,标明:
- 是否应该产生候选;
- 候选属于哪种记忆;
- 是否包含敏感信息;
- 是否需要用户或业务确认;
- 标准化后的事实是什么。
示例数据可以写成 JSONL:
{"text":"以后报告使用中文","candidates":["semantic"],"needs_confirmation":true}
{"text":"今天先查支付服务","candidates":[]}
{"text":"验证码是731204","candidates":[],"sensitive":true}
至少观察:
- 写入精确率:被建议保存的内容中有多少确实值得保存;
- 写入召回率:应该保存的内容中有多少被发现;
- 敏感误写率:敏感样本中有多少穿过写入门;
- 重复率:有多少候选只是已有记录的重复改写;
- 未确认写入率:需要确认的信息有多少被自动保存。
错误记忆会持续影响未来会话,早期系统通常应优先控制误写,而不是追求把所有可能信息都记住。
3. 检索质量:需要的内容找到了吗
为每个查询标记一个或多个相关记忆,再计算:
Recall@k:相关记忆是否出现在前 k 条;Precision@k:前 k 条里有多少真正相关;MRR:第一条相关结果排得有多靠前;nDCG:当相关程度不同时,高价值记录是否排在前面;- 跨作用域泄露率:是否返回其他租户或用户的记录,目标必须是 0。
测试查询不要只是原文复制。应该包含同义改写、否定表达、词面相似但语义不同、多语言输入、过期事实和新旧冲突。
4. 上下文装配:找到以后用对了吗
Retriever 找到相关记录,不代表 Context Builder 一定正确。每次运行应能记录:
- 召回了哪些记忆 ID;
- 最终采用了哪些 ID 和版本;
- 哪些被去重、因冲突丢弃或超出预算;
- 记忆占用了多少 token;
- 是否混入过期、deleted 或 restricted 内容;
- 模型回答是否把历史线索误写成当前事实。
这组信息也是调试“为什么 Agent 忘了”或“为什么 Agent 记错了”的基础。
5. 最终任务:有记忆真的更好吗
对同一批任务运行两组实验:
基线组:关闭长期记忆
实验组:启用完整记忆读路径
比较任务正确率、用户修正次数、完成时间、工具调用数量和 token 成本。只有改善可以重复出现,并且没有带来不可接受的隐私或错误风险,记忆系统才真正有价值。
例如在故障诊断场景中,可以观察:
- 是否正确使用了用户的报告格式偏好;
- 是否找到了相似历史事故;
- 是否仍然查询当前监控数据,而不是照搬旧结论;
- 是否减少了重复询问;
- 是否因错误记忆增加了误诊。
6. 在线运行还要观察什么
| 阶段 | 需要观察的指标 |
|---|---|
| 候选抽取 | 成功率、解析失败率、P50/P95 延迟 |
| 写入策略 | 保存、待确认、拒绝的数量和原因 |
| embedding | 模型版本、吞吐、失败率、重建进度 |
| 检索 | P95 延迟、零结果率、候选数量 |
| Context Builder | 注入条数、token 占用、丢弃原因 |
| 更新和删除 | 各副本完成率、处理时间、失败重试 |
| 端到端 | 有无记忆的任务成功率和用户纠正率 |
候选抽取可以异步;检索处在回答热路径,应该有严格超时和无记忆降级。所有指标都要按模型版本、embedding 版本和策略版本区分,否则升级后的回归难以定位。
7. 用一个结课项目把所有概念连起来
完成一个故障诊断助手,按下面顺序实现,不要同时搭建所有基础设施。
第一阶段:手动记忆
- 保存用户确认的报告语言偏好;
- 第二次独立运行能够读取;
- Alice 和 Bob 的记录严格隔离;
- 用户能够修改和删除偏好。
第二阶段:Ollama 候选抽取
- 从自然语言中提取语义和情景候选;
- 验证 Structured Outputs;
- 不保存访问令牌、验证码和临时命令;
- 用户偏好在确认后才正式写入。
第三阶段:语义检索和上下文
- 使用
qwen3-embedding:8b建立向量; - 用不同措辞召回相似事故;
- 检索结果带有来源和记忆 ID;
- 在预算内装配少量上下文;
- 历史事故只作为线索,不覆盖当前监控事实。
第四阶段:生产边界
- 新偏好替代旧偏好;
- 删除后主记录和向量都不可检索;
- 记忆服务超时时以无记忆模式回答;
- 恶意记忆不能绕过工具审批;
- 使用固定数据集比较开启和关闭记忆的效果。
完成这四个阶段后,你已经能够参与真实项目中的数据契约、Harness 接口、检索链路、生命周期、安全测试和离线评估,而不只是知道“Agent 可以有记忆”。
8. 这些概念来自哪里
下面的资料分别支撑不同概念,而不是作为装饰性的链接列表:
- LangGraph Memory区分 thread 级短期状态与跨 session 的长期 store,可用来核对第一章的边界;
- Google ADK Memory区分 Session/State 与可搜索的 MemoryService,展示了另一套框架中的相同问题;
- MemGPT讨论有限上下文下的分层记忆管理,帮助理解外部记忆和上下文预算;
- Generative Agents展示经验、反思和检索怎样影响后续行为,适合理解情景记忆与检索的研究背景;
- Ollama Structured Outputs和 Ollama Embeddings是本地代码使用的官方接口依据。
研究论文会探索更广泛的认知架构;生产项目还必须补上身份、权限、来源、删除和审计。两者有关联,但不能互相替代。
9. 最后的自检
- 我能区分 history、context、state、checkpoint 和 memory
- 我知道语义、情景和程序性记忆的权限差异
- 我不会让模型填写用户作用域和真实来源
- 我能解释候选为什么不等于正式记录
- 我先做作用域过滤,再做向量排序
- 我知道检索结果还要经过 Context Builder
- 我能处理更新、过期、删除和多副本遗忘
- 我不会让记忆绕过工具权限
- 我能分别评估写入、检索、装配和最终任务
- 我能在记忆服务不可用时安全降级