--- name: memory-system description: 为 Agent 设计、实现或评估用户记忆系统时使用——涵盖记忆能力三层次评估框架、轨迹与长期记忆分层、Simple Notes 到 Advanced JSON Cards 及可执行代码的存储格式选型、Mem0/Memobase 框架取舍、记忆压缩整理与隐私脱敏,以及何时该用记忆而非 RAG 的判断。 --- # 用户记忆系统 ## 何时使用 - 为 Agent 设计跨会话的用户记忆(记住偏好、身份、历史交互) - 选型记忆存储格式(Simple Notes / Enhanced Notes / JSON Cards / Advanced JSON Cards / 可执行代码) - 评估记忆系统好坏(对照三层次框架或 LoCoMo 基准) - 集成、改造或对比 Mem0、Memobase 等记忆框架 - 处理记忆冲突、过期、膨胀、压缩与隐私脱敏 - 判断某类信息该进用户记忆还是共享知识库 - 设计记忆的压缩与定期整理策略 ## 核心原则 - 记忆与 RAG 的边界:**单个用户的个性化信息**(偏好、身份、关系、历史)走用户记忆;**面向所有用户共享的集体知识**(行业法规、公司流程、专业文档)走 RAG 知识库。两者尺度不同但底层技术相通(向量检索、知识压缩),也面临同样的麻烦:信息冲突、知识过期、检索不准。用户记忆同样可以反过来用 RAG 技术增强召回。 - 记忆不是逐句存档:会话结束后用一次专门的 LLM 调用提取,提取结果须同时满足三条规则——**选择性**(丢弃"搜索返回 3 个选项"这类短期细节)、**抽象化**(把本次"靠窗座位"归纳为长期偏好)、**结构化**(用可检索字段保存事实)。 - 先立评估标尺再设计。记忆能力可归纳为八项:个人信息保留、偏好追踪、上下文切换、记忆更新、多会话连续性、复杂思考、时间感知、冲突解决。工程上按三层次验收: - **L1 基础回忆**:精确存取用户直接给出的结构化事实("我的会员号是 12345")。 - **L2 多会话检索**:跨对象、跨时期找全相关信息并主动澄清(用户有两辆车时问"为哪辆预约",而不是猜一辆)。 - **L3 主动服务**:综合很久以前的记忆给出预见性帮助(订国际航班时关联数月前存储的护照信息并预警临期)。 - 公开基准可参考 **LoCoMo**(平均约 300 轮、最多 35 个会话的超长多轮对话)。 - 三个正交维度分开决策,勿混淆:**放哪里**(轨迹 / 用户长期记忆 / 业务状态)、**怎么存**(四种格式)、**存什么**(情景 / 语义 / 程序记忆)。三者可自由组合。 - 轨迹(Trajectory)是单次运行的 append-only 原始流水,供追溯调试审计;运行时上下文可对它压缩重组。用户长期记忆是跨会话持久化、与用户 ID 绑定的档案,会被反复改写、合并、淘汰。前者是流水账,后者是档案。 - 认知类型指导"存什么":情景记忆记具体事件(订了哪班航班),语义记忆存提炼出的稳定特征(用户是素食者),程序记忆学行为流程(先搜直飞→确认座位→用常旅客号)。 - 选格式看工程需求(简单性与表达力的取舍),选类型看业务场景(需要记住事实、事件还是流程)——两套体系正交,分别决策。 - 格式选型按关键性与数量: - **Simple Notes**:最小不可分事实,开销最低、O(1) 操作,但关联性丢失,综合查询需重新拼凑碎片。 - **Enhanced Notes**:完整上下文段落,语义丰富,但存储冗余、更新需重写多个段落。 - **JSON Cards**:类别→子类别→键值对三层嵌套,支持部分更新、可预测可扩展,但强制单一归类会丢失多维性("周末用 Python 开发个人项目"同时是时间/技术/活动偏好)。 - **Advanced JSON Cards**:事实之外加 backstory(为何存储)、person、relationship(为谁存储)和时间戳,解决同名实体消歧(用户自己的牙科张医生 vs 父亲的心脏科张医生)。 - 经验法则:**关键且少量**(偏好、关键人物关系)用 Advanced JSON Cards;**大量且非关键**的对话事实用 Simple Notes;生产系统多为混合模式,不同类别走不同路径。 四种格式速查: | 格式 | 结构 | 优势 | 代价 | |------|------|------|------| | Simple Notes | 最小不可分事实 | 开销极低、O(1) 操作 | 关联性丢失,综合查询需重新拼凑 | | Enhanced Notes | 完整上下文段落 | 叙事结构、语义丰富 | 存储冗余、属性变化需重写多段 | | JSON Cards | 类别→子类别→键值对 | 部分更新、可预测可扩展 | 刚性归类丢失多维性 | | Advanced JSON Cards | 事实 + backstory/person/relationship/时间戳 | 同名实体消歧、多身份区分 | 生成与维护成本高 | - 需要聚合统计、冲突检测、约束执行等确定性推理时,把记忆升级为**可执行代码**(User as Code):事实先进只增日志,再定期重建带类型状态;规则写成普通函数(如国际行程出发前护照有效期不足 180 天即告警),让"表示"和"推理"共用可验证介质。 - 记忆库不是越大越好。三层压缩:重要性评分筛选(访问频率、时间衰减、情感强度、信息独特性四因素综合,低于阈值标记为可压缩或可删除)→ 相似记忆聚类生成代表性摘要(多次天气对话压成"用户经常询问天气,特别关心降雨",原始细节存档二级存储)→ 从情景记忆抽象泛化为语义/程序记忆(从多次购物对话学到"偏好性价比高的产品,重视用户评价")。 - 业务状态("需要澄清"/"处理请求中"/"等待付款")是开发者定义的高层任务阶段抽象,与轨迹、长期记忆并列,在事件驱动架构中尤为重要;多数系统先实现轨迹 + 长期记忆两层即可。 ## 实践模式 - 标准生命周期:读取相关记忆 → 会话结束后后台提取候选事实 → 来源与策略核验 → 更新(增/改/删/合并)。提取与对话主循环分离,不阻塞响应。 - 记忆不是一次建成:随交互持续积累,靠"增量吸收 + 定期整理"双路径维护,整理规则与共享知识库一致(见 `book/chapter3.md`「知识应该如何更新」)。 - 框架取舍: - **Mem0**:v3 用单次 LLM 调用抽取事实且只做 ADD,写入时不消歧;查询时融合语义相似度、BM25 关键词和实体匹配,并结合时间信息排序。优点是不会因错误 UPDATE/DELETE 丢失历史、LLM 调用少(LoCoMo 71.4→92.5,LongMemEval 67.8→94.4)。注意:Mem0-g 图记忆是历史设计,OSS v3 已移除外部图存储与 `relations` 返回值,实体链接仅用于内部检索加权。v2 及 2025 论文则在写入阶段做 ADD/UPDATE/DELETE/NOOP 决策,记忆库始终简洁但一次误更新即不可逆。 - **Memobase**:聚焦"用户画像"形态——开发者可配置的 Profile 槽位(主题→子主题两级,如 basic_info→姓名、work→职位)+ 按时间线的 Event Memory(回答"上次讨论预算是什么时候")。缓冲批处理:对话先在缓冲区累积,达规模或时限后统一触发一次提取,摊薄 LLM 成本并保证查询低延迟。 - **自建参考架构**:情景/语义/程序三类长期记忆 + 显式保留工作记忆层(管理当前任务、与长期记忆双向交互)。工作记忆是经筛选激活的动态子集,与 append-only 的轨迹不同。按业务取舍,不必追求大而全。 - 记忆量上千条后,用检索技术增强召回(RAG 管道与结构化索引同样适用于记忆条目)。最高阶形态是**双层记忆架构**:少量关键事实用 Advanced JSON Cards 结构化后常驻上下文(全局概览),海量原始对话经上下文增强后按需召回(精确细节)——只靠常驻会丢细节,只靠检索看不到跨会话隐藏关联。 - 隐私保护:脱敏优先本地小模型(如 Ollama 跑 Qwen3 0.6B,CPU 可跑,可升 1.7b/4b)——日志送云端脱敏违背初衷;识别结构化(证件号/银行卡号)、半结构化(地址)与自然语言敏感内容("我的密码是 abc123"),经 JSON Schema 输出类型/位置/置信度,LLM 脱敏召回率 95% 以上;超高吞吐场景用"正则快筛 + LLM 深析"混合策略。 - 前沿备忘(多模态记忆):脸孔、嗓音等难用文字描述的信息有三条思路——存原始数据 + 文本描述(检索到图片后再读原图比对);存嵌入(每张脸约 1 token,1000 token 上下文可容纳 1000 张人脸,效率极高但需常驻);写入预训练模型的 Engram 哈希 N-gram 槽位(扩展性强但依赖特定模型、查准率可能不如存嵌入)。训练每用户 fact-LoRA 直接复述尚可,间接推理会失灵。 - 评估方法:每层约 20 个用例,L1 用例通常由单个会话构成,L2/L3 用例由多个跨时间、跨对象的会话构成(每个用例合计约 50 轮沟通)。评估时要求被测 Agent 根据第一个会话生成记忆,再根据记忆和下一个会话修改记忆——全程仅能访问记忆、不可回看原始对话;记忆生成完毕后回答一个新的用户问题,用 LLM-as-a-judge 对比参考答案打分。 - 三层次框架与技术的对应关系(选型时的标尺):L1 靠可靠的存取即可满足;L2 需要检索技术找全跨会话信息并判断何时该主动澄清;L3 最难,要求系统同时握有"全局概览"(常驻结构化事实)和"精确细节"(按需召回原始对话)两种视角。 - 记忆写入的工程细节:提取在后台进行,不阻塞对话响应;写入前先检索相近记忆再决定增/改/删/合并,避免无限堆积;带时间信息保存事实,让"搬家到上海"和"住在北京"能按时间排序而非互相覆盖。 ## 常见陷阱 - 把短期细节当长期记忆存入,记忆库噪声膨胀、检索被稀释。 - 只存事实不存情境:脱离了"为谁存储、为何存储"的 backstory,"张医生"这类同名实体必然混淆。 - 一种格式通吃:Simple Notes 割裂关联、Enhanced Notes 冗余难更新、JSON Cards 丢失多维性。 - 写入时激进 UPDATE/DELETE:一次误判即不可逆丢失历史;或只 ADD 从不整理,矛盾事实无限堆积。 - 只更新不整理:同一事实散落多处、新旧说法并存、摘要偏离原始证据;定期整理必须回到原始证据核查,不能在旧摘要间相互改写。 - 冲突时简单"保留最新一条"或让模型猜:应追溯各自原始信息源,检查是否在不同时间/对象/条件下分别成立,把适用场景写入知识;证据不足则保留待确认状态。 - 把轨迹当长期记忆直接检索:原始流水只增不改、噪声大,跨会话记忆必须先提炼再入库。 - 敏感信息原样进入 LLM 上下文和系统日志。 - 脱敏用云端 API:日志本身可能含敏感信息,送云端脱敏违背隐私保护初衷。 ## 配套代码 - `chapter3/user-memory/` — 统一接口实现四种记忆模式(notes/enhanced notes/JSON cards/advanced JSON cards),对话与后台记忆处理分离,可切换模式对比同一用例的记忆产物。 - `chapter3/mem0/` — Mem0 v3 ADD-only 提取 + 混合检索,跑 LoCoMo 长上下文多会话场景。 - `chapter3/memobase/` — 真实 Memobase SDK 的 Profile + Event 演示,外加 Memobase 风格自研记忆 Agent(情景/语义/程序/工作四类记忆、重要性衰减与聚类)。 - `chapter3/user-memory-evaluation/` — 实验 3-1 三层评测集(每层 20 用例、50+ 轮),LLM-as-Judge 多维打分,含离线 keyword-recall 对照。 ## 深度阅读 - `book/chapter3.md`「用户记忆系统」