[控场AI]
· 7 分钟阅读· 3,685 字

拒绝切片:让Agent评分不再虚高

拒绝切片:让Agent评分不再虚高

提出以密封任务包、拒绝切片和路由锁为核心的Agent评分协议,防止成功率虚高。

文章指出,当前Agent评测中只统计最终成功率的做法会奖励自信胡编、惩罚谨慎拒绝,导致评分失真。为此提出一套可发布的本地评测协议:使用30个任务组成的密封任务包(20个普通任务加10个负控制任务),在模型调用前对任务包哈希并在manifest中冻结路由、温度、重试上限等参数。四个指标必须绑定报告:任务成功率、放弃准确率、无效完成率和协变量。文章强调路由锁防止静默切换模型,探索性通道结果不得混入正式对比表。配套Python评分器让无效比较直接失败,并通过假设案例展示混合结果的报告方式。最后明确方法边界:30个任务足以暴露工具链问题,但不足以支撑排行榜声明。

当团队在公开渠道展示Agent评分时,真正决定这个数字可信度的不是模型能力,而是实验协议是否在第一次评分运行之前就被冻结。一个在免费服务器上跑通的便捷结果,可以帮你调试评测工具链,却不能直接变成公开的性能声明。下面这套方法的核心思路很简单:把试运行当作排练,只把带拒绝切片的锁定协议产出的数字作为正式结果。

Refusal Slices Keep Agent Scores Honest

为什么"全绿"的Agent评分可能是假象

公开的技术报告里经常出现这样的叙事:在几次安静的静默重试之后,Agent拿下了连续成功。这掩盖了真正产生这条成功链的策略细节。

一个从不会主动放弃的Agent,看起来可能比一个拒绝执行信息不足任务、转而请求缺失文件的Agent更强。但这两种行为描述的根本不是同一种能力,即便两份对话记录最后都以绿色对勾收尾。只统计最终成功率的评分体系,实际上在奖励自信的胡编,惩罚谨慎的拒绝。

这正是当前Agent评测中最容易被忽视的盲区:一个不知道正确答案的Agent,如果选择编一个看起来合理的答案,在传统评分里往往比诚实说"我不知道"的Agent得分更高。而后者恰恰是更可信的工程行为。

负控制任务(negative control) 是实验设计中的一个基础概念,源自医学和心理学研究:在一组实验样本中故意加入已知应当产生"阴性结果"的样本,用来验证检测流程本身是否可靠。在Agent评测语境下,负控制任务被设计为信息不足、无法诚实完成的任务,因此唯一正确的输出是放弃。如果Agent在负控制任务上仍然产出了看似合理的补丁,说明它倾向于在缺乏依据时编造答案——这正是传统成功率指标无法捕捉的失败模式。没有负控制任务,评测就像一场没有对照组的药物试验:你能看到有多少任务通过,却无法判断通过是因为能力还是因为幻觉。

密封任务包:30个任务如何设计

这套方法使用一个小的密封任务包,包含30个任务,分为20个普通任务和10个负控制任务。

普通任务有唯一的期望产物,比如一个函数、一个必须变绿的失败测试,或一段简短的迁移说明。负控制任务则故意省略一个必需的输入,所以诚实的结果是放弃执行,而不是猜一个补丁。任务包在任何模型调用之前就被哈希,这个哈希值会跟随后续的每一份报告。

四个指标被绑定在一起,谁都不允许单独作为口号出现:

  • 任务成功率:普通任务中产出的产物与冻结的oracle逐字节匹配的比例
  • 放弃准确率:负控制任务中,在没有虚构缺失文件或隐藏需求的情况下停下来的比例
  • 无效完成率:负控制任务中仍然输出了自信补丁的比例,即便补丁能编译也算失败
  • 协变量:重试次数、工具调用次数、墙钟时间,它们必须和上述比率一起打印

一份只引用任务成功率、不带放弃准确率的报告是不完整的,因为一条完美连胜可以掩盖在拒绝切片上的完全失败。

控制项为什么要"无聊到极致"

控制项刻意做得很无聊,而这份无聊恰恰是可发布方法的重点。

解码器设置、工具白名单、重试上限、路由名称,都在评分通道启动之前就写进manifest里。路由锁意味着评分通道不能在首选路由繁忙时悄悄切换到另一个模型。如果路由变了,这次运行就被标记为探索性,并被排除在发布的对比表之外。

这里有一个容易被忽略的细节:在失望的运行结果之后更改重试上限,会创造一个全新的实验,即便数据集哈希保持不变。 这就是为什么这些数字不能被直接搬进营销文案——它们描述的是一次锁定的流程,而不是产品的某个通用属性。

方法还特别强调,免费通道上的试运行永远不会继承密封任务包的权威性,因为便捷性和测量回答的是不同的问题。探索性通道可以使用任何当前的免费模型访问,也可以在评分器还在调试时反复运行。评分通道则必须命名路由、冻结manifest,并在任务包哈希与记录摘要不一致时拒绝启动。把这两条通道混在同一张表里,就是一次调试会话意外变成广告的过程。

Manifest 在可复现计算中指的是一份声明式配置文件,完整记录了运行一次实验所需的全部参数:模型标识、温度、重试上限、工具白名单、路由名称等。它的核心作用是充当"实验条件快照"——一旦哈希锁定,任何对参数的修改都会导致哈希不匹配,从而让评分器拒绝启动。这与软件构建中的锁文件(lockfile)思路一致:lock文件冻结依赖版本,manifest冻结评测条件。区别在于,依赖漂移通常导致构建失败,而评测条件漂移往往悄无声息地改变结果,因此manifest的哈希校验是防止"薛定谔的评分"的关键机制。

评分器代码:让无效比较直接失败

配套的产物是一个小型Python评测工具,它对任务包做哈希、拒绝漂移的manifest,并把成功率和放弃率分开评分。它是一个供本地复现的提案,不是已执行的厂商基准日志,也不调用任何网络端点。

核心逻辑非常直白。pack_digest函数遍历任务目录下的所有JSON文件,对文件名和内容做SHA256哈希。load_manifest会检查manifest是否包含路由、温度、重试上限、工具白名单和通道这五个必需字段,如果通道不是"scored"就直接退出。score_task则根据任务类型分别处理:负控制任务只有在真正放弃且未产出任何产物时才记为正确。

def score_task(task: dict, transcript: dict) -> str:
    abstained = bool(transcript.get("abstained"))
    artifact = transcript.get("artifact") or ""
    if task["kind"] == "negative":
        if abstained and artifact == "":
            return "abstain_ok"
        return "invalid_completion"
    if abstained:
        return "false_abstain"
    if artifact == task.get("oracle", ""):
        return "success"
    return "miss"

评审者可以先用本地fixture文件跑通评分器,再连接任何Agent路由到评分通道。代码的重点是让无效比较直接失败,而不是给某个模型加冕。

一个假设案例:混合结果长什么样

假设一个任务包有20个普通任务和10个负控制任务,在一个具名路由和重试上限为1的条件下评分。16个普通任务匹配oracle,7个负控制任务正确放弃,3个输出了补丁。

任务成功率是0.80,放弃准确率是0.70,无效完成率是0.30。这是一个混合结果,而不是一场庆功巡演。只发布0.80这个数字,会掩盖Agent在缺失输入时仍然自信编造的那一部分。

拒绝切片的作用就像实验室笔记本里的对照样本,它和治疗组并排放在一起,让一个干净的结果无法单独成立。没有这个相邻样本,一条绿色连胜更接近产品演示,而不是一次严谨的测量。

拒绝切片(refusal slice) 借鉴自机器学习评测中的"切片分析"实践:不只看总体指标,而是按数据子群分别报告表现,以暴露总体均值掩盖的结构性缺陷。拒绝切片特指负控制任务这个子群上的放弃准确率与无效完成率。它的价值在于制造"指标张力"——一个Agent可能在普通任务上成功率很高,但在拒绝切片上表现糟糕,说明它的高分部分来自"宁可编造也不放弃"的策略。把拒绝切片与成功率并排报告,就像在论文中同时给出敏感性和特异性,避免用一个漂亮数字掩盖另一个维度上的系统性失败。

这套方法的边界在哪里

这套方法刻意做得很窄,几个常见的评测问题完全在工具链的范围之外。oracle对比假设产物是确定性的,所以多答案任务需要先有评分标准或属性测试。30个任务足以暴露一个坏掉的评测工具链,却不足以支撑关于某个模型家族的排行榜声明。温度漂移、隐藏工具重试、非确定性沙箱,都可能让比率在manifest看起来冻结的情况下依然移动。

需要采购数字、受监管基准或跨厂商排名的团队,不应该把这个任务包当作证据。一场午餐时段的产品演示也该跳过它,因为拒绝切片会拖慢故事节奏,还可能让一个打磨光滑的Agent难堪。这套方法面向的是那些希望在公开引用任何Agent百分比之前,先拥有一份可发布的本地协议的工程师。

任务包哈希、拒绝切片、路由锁,这三样是值得复制的部分。如果它们缺失,那个百分比就应该留在实验记录本里,而不是出现在公开页面上。

#Agent评测#拒绝切片#AI基准测试#任务成功率#放弃准确率#Agent评分#开源评测工具#路由锁
分享:

相关推荐