评估记忆质量

M7
深入解析 · 记忆与上下文工程

评估记忆质量——以及它能捕获的陷阱。

记忆系统会静默失效。智能体仍在回答、仍在行动、在演示里仍看着没问题——而它在悄悄回忆一条过期事实、服从一条被毒化的记忆,或在压缩中遗忘了一条约束。你无法调优你没有度量的东西。本文定义记忆特有的指标,以及它们存在所要捕获的失效模式。

STEP 1

为什么通用评估漏掉记忆缺陷。

端到端的任务成功率评估最终会捕获一个损坏的记忆系统,但很晚、很嘈杂,且不告诉你哪一层坏了。记忆失效是弥散的:第 12 轮一次错误回忆,会在第 30 轮表现为一个糟糕动作。你需要把记忆栈与智能体推理隔离开的评估,并对每个操作设置定向探针:写入、回忆、压缩、更新。

原则:每一个可能丢失或扭曲信息的记忆操作,都有它自己的数据集和它自己的指标。聚合任务成功率是集成测试;这些是单元测试。

STEP 2

核心记忆指标。

  • Recall@k(记忆)——给定一条 N 轮前写入的已知事实,以及一个本应浮现它的查询,它在前 k 个里吗?最重要的单个数字。把它作为存储规模和轮次距离的函数来跟踪——一个在 100 条记忆时正常、在 5 万条时损坏的系统,是常态失效轨迹。
  • 回忆精度/干扰率——被注入上下文的记忆中,真正相关的比例是多少?高召回配低精度,会用看着自信的垃圾毒化推理。
  • 约束存活——一次压缩后,所有硬约束在结果状态中是否仍成立?以每约束每压缩的严格通过/失败来度量。
  • 过期率——当一个事实已被更新,后续回忆中返回值的比例是多少?直接度量更新路径。
  • 写入精度——写入长期记忆的一切中,真正值得持久的比例是多少?低写入精度是未来回忆崩塌的领先指标。
# eval/memory_eval.py
def recall_at_k(mem, probes, k=5) -> float:
    # probe = (fact_id, query, turns_ago) injected earlier
    hit = 0
    for p in probes:
        got = mem.recall(p.query, k=k)
        hit += int(p.fact_id in {g.id for g in got})
    return hit / len(probes)

def staleness_rate(mem, updates) -> float:
    # update = (key, old_val, new_val); recall after update
    stale = 0
    for u in updates:
        v = mem.recall(u.key, k=1)[0].text
        stale += int(u.old_val in v and u.new_val not in v)
    return stale / len(updates)

在每次对记忆栈的改动上,针对一条合成的长时程轨迹(数百轮,植入的事实、植入的更新、植入的约束)运行这些。这就是 retrieval-augmented-memory 中的权重调优和 context-compaction 中的触发器所针对的评估框架。

STEP 3

陷阱:上下文毒化。

一条错误的、幻觉的或对抗性的陈述被写入长期记忆,随后被以与真实记忆同等的权威性回忆出来,并传播开——智能体据它推理,产出与它一致的输出,而那输出本身可能又被写回。一个自我强化的谬误。

  • 给写入路径设门控:不要在没有落地依据的情况下,把模型生成的论断作为语义事实持久化。一个推断被存为推断,而非事实(即 retrieval-augmented-memory 中的来源标注)。
  • 绝不把回忆到的记忆放进权威系统块:它是证据,不是策略。毒化一个提示可恢复;毒化一条指令是服从。
  • 评估探针:注入一条已知为假的记忆,然后度量它在答案中浮现的频率,以及智能体是否曾把一个派生谬误写回。无法传播回存储的毒化即被控制住。
STEP 4

陷阱:过期记忆。

一个事实在写入时为真、现在错了——用户换了团队、API 版本升级了、策略改了。记忆系统自信地回忆出那个过时值。这正是仅追加向量库必然导致、而就地键值更新(memory-stores)能防止的失效。

  • 语义记忆就地更新:一个键,一个当前值。新观察覆盖它,而非累积。
  • 带时间戳、冲突时偏好较新者:当两条记忆相左时,时近性打破平局,并把分歧暴露出来,而不是静默挑一个。
  • 评估探针:上面的过期率指标。非零的过期率意味着更新路径坏了——P0,因为智能体现在自信地错着。
STEP 5

陷阱:检索漂移与压缩失忆。

两种共享一个特征的失效——系统看起来健康,因为它仍返回貌似合理的结果——因此没有定向探针就不可见。

  • 检索漂移:一个在任务开始时构造一次的线索,持续回忆早期、如今已无关的记忆,而任务已经向前推进。通过度量 recall@k 作为进入任务的轮次距离的函数来捕获,而不只是在第 1 轮。一条在任务中途衰减的曲线就是漂移。修复:每轮从当前状态重建线索。
  • 压缩失忆:一条约束或未闭合回路在摘要中被丢弃,智能体当它从未存在过般继续推进。通过 context-compaction 中的约束存活与未闭合回路存活检查来捕获。修复:为硬约束和活跃回路设一个钉住的、永不压缩的块。
memory eval report  (synthetic 300-turn trajectory)
  recall@5 @ store=1k        0.91   ok
  recall@5 @ store=50k       0.58   FAIL  ← redundancy collapse
  recall@5 by turn-distance: t1 0.94  t150 0.61  FAIL ← drift
  staleness rate             0.00   ok    (kv in-place update)
  constraint survival        18/20  FAIL  ← compaction dropped 2
  write precision            0.41   WARN  ← tighten write gate

这份报告就是交付物。一个记忆系统不是在十轮演示里能用就"完成"了——它是在你将真正投入生产运行的存储规模和任务长度下,这些数字在一条合成长时程轨迹上仍然成立时才完成。先度量;本节其他每篇文章都是你针对这块仪表盘去拧的旋钮。