3078 字
约 10 分钟
21
S21-A07 · Agent 记忆设计:存什么、忘什么、怎么用

“加了记忆功能之后,模型开始胡编。”这通常不是记忆模块写错,而是边界没定:什么进长期存储、什么只活一轮、写进去的事实凭什么被信任。三者没定,记忆库就成了装满猜测的黑箱,而检索每次都会忠实地把猜测喂回去。

记忆不是“让模型更懂我”,而是一个带容量、带过期、带错误率的数据系统,与缓存同构。按顺序拆:存什么 → 何时写 → 如何存 → 如何忘 → 如何取 → 如何评估。


1. 四种记忆与各自的载体

形态 内容 生命周期 载体 失效模式
工作记忆 当前推理所需的中间结论 单次任务 上下文窗口 被后续内容挤掉
会话记忆 本次对话的意图、已确认条件 单会话 会话状态 + 摘要 摘要把限定条件丢掉
长期事实记忆 跨会话稳定的事实(偏好、约束、实体属性) 周/月 结构化库 + 向量索引 过时、冲突、污染
流程经验 某类任务的做法(步骤、工具偏好、坑) 长期 提示片段 / 工作流模板 过拟合到旧场景

四者混在一个存储里是最常见的起点错误:读写频率、一致性要求、清理策略都不同。

2. “存什么”的判据是下次会不会用到

不是“信息有没有价值”,而是下一次任务是否可能用到它。有价值但不复用的信息,存了只会污染检索。

信息 有价值 会复用 结论
输出格式偏好(表格/要点) 是 是 存,作为稳定偏好
项目技术约束(版本、禁用项) 是 是 存,带 scope
用户今天的情绪 是 否 不存
一次性的临时口径 是 否 只进会话记忆
写入门槛(三条同时满足)
1 可复用:同类任务未来还会出现
2 可验证:有来源或用户确认过
3 可作用:会改变下一次的输出或动作

第三条最易被忽略:不改变任何决策的事实只是占容量的噪声。

3. 写入时机:显式指令与自动抽取

方式 精度 召回 噪声来源 适用
显式指令(“记住…”) 高 低 几乎无 用户主动设定的偏好与约束
自动抽取 低 高 把闲聊、假设、模型自己的推测当事实 需要覆盖大量隐式信息时

自动抽取的问题不在抽得少,而在抽得随意:假设句、反问、模型自己的推测,都会被写成肯定陈述。折中是两级流水线:先写候选池,满足重复出现或用户确认才晋升。

对话 → 抽取器 → 候选池(未生效)
        ├ 重复 ≥ 2 次   → 晋升
        ├ 用户确认       → 晋升
        └ 超期未确认     → 淘汰
# 记忆写入策略(按实现核对字段名)
extract:
  mode: candidate            # off | candidate | direct
  require_source: true
  max_candidates_per_turn: 3
promote:
  min_observations: 2
  require_confirmation: false
  ttl_days: 30

4. 事实记忆的结构

一条事实至少要有五个字段,缺一个就会在某个场景失效。

字段 作用 缺失后果
subject 归属主体(用户/项目/团队) 张冠李戴
predicate + value 断言内容 无法比较新旧
valid_from / valid_to 生效区间 旧规则覆盖新规则
source 来源(对话/文档/系统) 无法判权威、无法纠错
confidence 置信度 低质事实与确认事实同权
{
  "subject": "user:u1024",
  "predicate": "preferred_output_format",
  "value": "markdown_table",
  "valid_from": "2026-03-01",
  "source": "explicit_instruction",
  "confidence": 0.95,
  "scope": "project:clarity"
}

scope 是实践中救场最多的字段:同一人在不同项目的约束常常相反,没有 scope 必然串味。

5. 冲突处理:覆盖需要判据

情形 处理 理由
用户显式更正 新事实生效,旧的写 valid_to 显式指令优先级最高
同一 predicate 两个值,来源不同 按来源权威排序(系统 > 文档 > 对话推断) 权威差异是真实存在的
来源相同、时间不同 取时间晚者,保留历史 时间是最便宜的判据
来源与时间都相同 并列保留,降低置信度 无法裁决时不要伪造裁决
值互相矛盾但 scope 不同 各归其 scope,不视为冲突 大部分“矛盾”其实是串域

最常见的事故是后写覆盖:没有判据,最后写入的永远赢,一次口误就能永久污染一个事实。

6. 遗忘机制:三种策略各有代价

策略 触发 代价 适用
容量淘汰 每主体条目上限 挤掉低频但关键的事实 个人助手类,容量压力大
时间过期 TTL / valid_to 长期有效的偏好被误删 时效性强的事实(职位、价格)
纠错删除 显式删除或负反馈 需要产品入口与审计 错误事实、敏感信息
retention:
  max_items_per_subject: 200       # 典型量级,按实测容量调
  ttl_default_days: 180
  ttl_override: {preference: never, employment: 365}
  decay:
    enabled: true
    half_life_days: 90
    keep_floor: 0.3                # 低于此值只降权不删

遗忘的目的不是省空间,而是缩短错误事实的存活时间。容量与 TTL 是手段,纠错入口才根治——大部分错误来自抽取,不会自己过期。

7. 检索记忆:三种方式,错一种就串味

方式 适合 风险
按时间(最近 N 条) 会话续接、短期上下文 久远但关键的约束被漏掉
按相似度(向量) 事实语义模糊、需模糊匹配 相似但不同主体/项目的事实被拉进来
按结构化查询(键值、条件) 明确 predicate(偏好、版本) 需要 schema,冷启动成本高

“检索错记忆比没有记忆更糟”:没有记忆时模型会问一句,检索错了它不问,直接按错约束执行。顺序必须是先 scope 后相似度,阈值宁高不低。

recall(subject, query):
  pool = store.where(subject == s AND scope IN {global, current_scope})
  key = pool.exact(predicate_of(query))          # 结构化优先
  return key if key else pool.vector(query, top=5, min_score=0.8)

8. 记忆污染与纠错入口

污染是自我强化的:错误事实写入 → 下次命中 → 据此生成 → 生成内容又被抽成新事实。三轮之后原始来源已不可见。

环节 必须留下的东西
写入 source、写入时的原始片段 id
检索 本次命中了哪些记忆 id(进日志)
生成 输出是否依赖记忆(可标注)
纠错 用户可查看、可删除、可更正
纠错入口(最小可用)
1  用户侧:列出"关于我的事实",逐条可删/可改
2  运营侧:按 source=candidate 批量清理
3  数据侧:删除时写 tombstone,防止重新抽取复活

第 3 条最易漏:删了事实但保留原对话,下一轮抽取会把它原样写回。删除必须带墓碑。

9. 隐私与隔离

类别 处理
证件号、银行卡、健康信息 不进长期记忆;需要时即时取用,用完不落库
第三方的个人信息 不进长期记忆(不属于该用户可授权范围)
密钥、口令 不进记忆,走凭据服务
多用户环境 namespace = tenant + user,检索前强制过滤

隔离失效的典型症状是“A 用户问出了 B 的偏好”——测试环境几乎不出现,因为测试数据常只有一个人。

10. 记忆与上下文的预算竞争

预算项 建议占比 挤占后果
系统提示与工具定义 固定 削减会破坏行为一致性
记忆片段 小且固定上限 过大则挤压检索结果
检索证据 主要弹性项 被挤压 → 答非所问
历史对话 可压缩(摘要) 压缩过度丢限定条件
输出预留 固定 不足则回答被截断

记忆高置信、低覆盖,证据低置信、高覆盖。紧张时优先保记忆,但不能让它吃掉检索空间——约束对了、事实没有,照样错。

11. 评估:有/无记忆的对照

指标 含义 对照做法
首轮正确率 不需要用户重复说明的比例 同一批任务,开/关记忆各跑一遍
重复说明次数 用户重申同一约束的次数 统计会话内重复率
纠正次数 用户纠正模型的比例 纠正是负向信号,绝对值看趋势
判定表
开记忆后首轮正确率↑ 且 纠正次数↓ → 记忆有效
开记忆后正确率持平 但 纠正次数↑   → 记忆在引入错误约束
两者都无变化                        → 记忆没被用上,删掉它

最后一行值得写进决策记录:从不被命中的记忆,成本是存储、延迟与污染风险,收益为零。

12. 排错:六种“记忆引起的怪事”

现象 原因 处理
模型突然用上没提过的偏好 旧事实未过期、scope 未过滤 检查 valid_to 与 scope 条件
同一问题两次会话答案不同 记忆检索结果不稳定(阈值附近) 提高阈值,或改结构化优先
用户说“我没这么说过” 抽取把假设句写成事实 关闭 direct 模式,走候选池
删了记忆但行为不变 原对话仍在,被重新抽取 写 tombstone,排除已删来源
记忆越多回答越慢 检索记忆挤占了证据预算 给记忆设固定小配额
A 用户看到 B 的偏好 namespace 过滤缺失 检索前强制 tenant+user 过滤

13. 边界:什么时候不要做记忆

场景 更合适的做法
会话很短、任务不重复 把上下文管好就够了
事实极少且稳定 写进系统提示
强合规场景 事实由系统录入,不由对话抽取

判断标准只有一句:记忆的收益来自复用。没有复用,它只是把上下文问题搬到了更难排查的地方。


14. 自测

  1. 用户说“记住我用表格输出”,这条该进哪一层记忆?为什么不是会话记忆?
  2. 自动抽取为什么必须先进候选池?不进会发生什么?
  3. 同一 predicate 出现两个值,按什么顺序裁决?都裁不了时怎么办?
  4. 删除一条事实后行为没变,最可能漏了哪一步?
  5. 为什么“先 scope 过滤再相似度”不能反过来?
  6. 开记忆后首轮正确率不变、纠正次数上升,说明什么?
S21-A07 · Agent 记忆设计:存什么、忘什么、怎么用
https://www.clxhxhhr.top/posts/6161/
作者
clxstart
发布于
2024-12-31
许可协议
CC BY-NC-SA 4.0
评论
0 条
还没有评论,先写一条吧。