3010 字
8 分钟
评测不是打分:SAGE 的 Context、Memory、RAG、Harness 怎么量
2026-07-25

做 Agent 做久了会遇到一个尴尬的事:一个任务跑成功了,你很难说清它是为什么成功的。

是因为模型足够强?是因为上下文恰好没爆?是因为预算没卡住所以一路堆 token 堆过去的?还是因为记忆恰好命中了?如果分不清,下一次失败你也不知道该改哪里。

评测的意义不在于给系统打一个分数,而在于让结果可解释—成功是因为什么,失败是因为什么,改了某一处会怎样。这篇文章记录我在给 SAGE 设计评测时遇到的核心难处,以及四层边界各自该怎么量。

四层水平地层剖面,一把测量卡尺探向地层,左侧带有刻度
四层边界像地质剖面:评测不是给整体打分,而是逐层量出每一层的控制是否忠实、能力是否够强。

四层各评什么#

SAGE 的运行底座可以分成四层,每一层都容易混淆“评了什么”和“该评什么”:

容易评的该评的
Context上下文用了多少 token预算控制是否因果—超预算的调用有没有真的被挡住
Memory状态机是否正确记忆是否真的有用—能不能召回“上次怎么解决的”
RAG能不能检索到答案检索不到时是否诚实 abstain,答案是否被证据支撑
Harness能不能跑起来、能不能确定性跑能不能解决问题

四层共同的坑是:把“控制层是否正确”当成了“能力层是否够强”。状态机正确不等于记忆有用,检索能命中不等于生成诚实,能跑起来不等于能解决问题。

Context:预算是不是因果的#

Context 层最该评的是预算的因果性。一个任务在预算内完成,和“预算控制真的生效了”是两回事。我在评估时发现四个值得量的边界:

边界现象
多套预算并存字符计的上下文管理、字符计的投影截断、token 计的累计预算三套系统,单位、强制力(报告/投影/事后检查)、作用域(每次调用/累计全程)都不同,无单一权威
事后预算运行预算在模型响应返回后才累加用量再检查,超预算的那次调用已经发生、已经计费;是防失控的护栏,不是真正的预算控制
用量缺失归零供应商不返回用量元数据时按零计,门禁静默失效—不报错、不停机,只是悄悄变成空操作
压缩只在回合开始压缩阈值只在用户回合开始触发,单回合内连续多次工具调用可中途失控;相同任务仅因回合结构不同,成功率就剧烈变化

这几个边界都不是 bug,而是设计权衡。但如果不评,它们就会把能力分数污染掉:你可能测出“模型在 A 任务上成功率 80%”,却不知道其中一部分是靠超预算堆出来的。

Memory:状态机正确不等于记忆有用#

Memory 层是我觉得反差最大的一层。

SAGE 的记忆生命周期设计得很扎实:写入有 CAS 乐观锁、提案有审批、运行之间有隔离、事实变更有冲突检测。作为状态机,它经得起确定性测试—状态转移、隔离、审批不变量都能锁住。这在 Agent 系统里其实少见,很多框架的记忆连基础的并发隔离都做不到。

但状态机正确,和记忆“有用”,是两回事。

我去翻实际产出的情景记忆,发现里面主要是元数据:这次运行用了哪些工具、终端状态是什么、证据有几条。它记录了“发生了什么”,没有记录“学到了什么”—哪个方案试过失败了、哪个坑踩过、哪个 workaround 管用。

于是出现一个错位:生命周期测试全部通过,但你问记忆“我们以前遇到过这个问题吗”,它召回不出来有用的经验。

所以 Memory 该评的不是生命周期,而是经验内容质量。我的做法是设计一个探针任务:先跑一个“方案 A 失败、找到 workaround”的任务,过一段时间再让 Agent 遇到同类问题,看它能不能从记忆里召回那个 workaround。这测的是记忆的智能,不是状态机的正确。更进一步,还可以做受控三臂对比:

检索方法
no-memory不启用记忆
current词法 + 近因
hybrid词法 + 近因 + embedding

三臂固定模型、工具、token 预算、延迟和数据切分,唯一变量是检索方法—这样记忆带来的增益才说得清。

RAG:评错了层#

RAG 层的问题更直接:它评错了层。

现有的知识评测只评检索—给定问题,能不能检索到正确片段。而且有一组“无答案”问题,准确率是零。

但“无答案准确率零”是个语义不明的数字。它可能意味着系统总是硬编一个答案(该 abstain 的时候不 abstain),也可能意味着系统 abstain 了但评测把它判错了。没有弃答指标,你分不清。而用户真正关心的不是“能不能检索到”,是“检索不到的时候,系统会不会老老实实说不知道,而不是编一个”。这是诚实性,不是召回率。

所以 RAG 该评三层:

  1. 检索协议本身:能不能召回正确片段,用 nDCG、Recall 这类标准检索指标,并补人工标注的相关性。
  2. 弃答诚实性:无答案时是 abstain 还是幻觉。这一层要先消歧—把“无答案准确率零”拆成“总是幻觉”还是“abstain 被判错”。
  3. 生成质量:给出的答案有没有被检索到的证据真正支撑,引用是不是站得住。

把检索和生成拆开评,才能定位问题出在哪一层。否则一个端到端的“准确率”会同时掩盖检索召回不足、弃答失败和生成幻觉三种完全不同的问题。

Harness:有“能跑”的门禁,缺“能解决”的门禁#

Harness 层其实已经有了一个扎实的发布门禁:它会检查新旧运行时是否一致、真实供应商能不能跑通、浏览器、时间线、沙箱、回滚。这是运行时层面的门禁,做得很好—它保证系统不会退化成跑不起来。

另外还有一套确定性场景 runner,用脚本化的客户端跑十几个固定路径—但它是 informational 的,明确不作门禁。它证明的是“系统能不能确定性跑”,不是“系统能不能解决问题”。

缺的恰恰是第三种:能力门禁。用真实模型跑真实任务,看它到底解不解决得了问题。这部分要借助外部基准:状态管理用 STATE-Bench,工具调用用 BFCL,轨迹质量看工具选择准不准、有没有冗余调用、工具报错后能不能恢复。安全上还要做红队—经工具结果的提示注入、权限边界、沙箱逃逸,用 garak 这类工具压一遍。

怎么让结果可解释:契约层和智能层交叉标签#

讲完四层各自该评什么,核心方法其实就一句话:把契约层和智能层分开评,再用交叉标签做归因。

契约层(确定性,CI 可跑,不依赖模型)智能层(真实模型 / LLM 判官)
Context超预算调用比例、用量缺失放过比例、中途失控回合频率任务成功率
Memory状态机、隔离、冲突检测经验召回率
RAG检索 nDCG、Recall答案正确性、引用蕴含
Harness运行时一致性、沙箱、回滚真实任务解决率

契约层测的不是模型能力,是控制层是否忠实;智能层测的才是能力。两层分开还不够,关键是用交叉标签把它们连起来。每跑一次真实任务,都打上这次运行触发了哪些契约层缺陷。于是任务成功率可以被切成两半:

任务成功率
├─ 未触发任何契约缺陷的成功率 ← 这是真正的能力
└─ 触发了预算/记忆/检索缺陷的成功率 ← 这是靠失控换来的

前者是真正的能力,后者是靠失控换来的。这就是因果可解释:你不是得到一个“80% 成功率”的黑箱数字,而是知道其中多少是能力、多少是控制层失守。没有这一步,所有能力评测都会被控制缺陷污染成噪声。

顺序:先修破坏因果的部分,再测剩余的#

最后一个判断是顺序问题:先建评测适配器,还是先修预算语义?

我的结论是先做最小的预算修复,再建评测。原因是:如果在“事后预算、用量缺失归零”这种破损语义上包一层评测 runner,测出来的数字会把模型能力和控制缺陷缠在一起—正是要避免的不可解释。

但“全部修好再测”也不对,那是无测量地盲改。所以解法是:只修掉破坏因果性的两个廉价缺陷—用量缺失时不归零(要么 fail-closed 要么用 tokenizer 估算),把事后检查改成调用前的预算预估—其余边界原样保留,转成契约层里可观测的指标。修完因果性的部分,再建评测 runner(我选 Inspect AI 作为外层 runner,它包装 SAGE 现有运行时,不替换它),让它顺便把预算边界的事件记下来。

这样评测从一开始就不报告混淆数字,而那些没修的边界也没有被藏起来—它们变成了仪表盘上的读数,而不是黑箱里的噪声。

收尾#

给 Agent 做评测,最大的诱惑是早点跑出一个分数。但一个混了能力和控制的分数,比没有分数更危险—它会让你自信地改错地方。

Context 评预算的因果性,Memory 评经验的有用性,RAG 评检索不到时的诚实,Harness 评解决问题的关键能力。用契约层让缺陷可见,用智能层测能力,用交叉标签把两者连起来归因。评估的目的从来不是打分,是让每一次成功和失败都说得清原因。

References / 相关链接#

分享

如果这篇文章对你有帮助,欢迎分享给更多人!

评测不是打分:SAGE 的 Context、Memory、RAG、Harness 怎么量
https://blog.sagecompanion.top/posts/agent-evaluation-four-layers/
作者
ZeroMadLife
发布于
2026-07-25
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时

目录