简体中文
评估
本页定义 eyeful 的评估实验。实验方案已冻结在研究方案里;本页和方案不一致时,以方案为准。eval/ 里的脚本已经写好,运行还没有做(见路线图)。结果等主实验跑完再补上。
研究问题
与更简单的 LLM 审查者相比,带规划的多专家审查加上基于执行的验证,能否找到更多要紧的缺陷、噪声更少、并给出维护者可以核对的证据?代价是多少?
| 问题 | 问的是 |
|---|---|
| RQ1,检出 | 规划出的专家组是否比使用相同模型和 skill 的单个 agent 找到更多已知缺陷、更多类别的问题? |
| RQ2,噪声 | 在每种验证条件下,报告的发现里有多大比例是成立的? |
| RQ3,可验证性与代价 | 执行能复现并修复多少发现,漏掉多少真实缺陷,代价是多少? |
RQ2 不预设方向。如果只读验证下的发现大多已经成立,执行的价值就体现在 RQ3。
数据集
一个被试是一个缺陷已知的改动,来自公开的测试集。只有 SWE-bench 的测试能运行,所以 RQ3 只靠它回答。不对任何输出做人工标注。
| 数据集 | 被试 | 已知缺陷 | 回答 |
|---|---|---|---|
| SWE-bench Verified,回退版 | 七个 Python 项目里的约 30 个任务 | 任务本身,由它自己的测试判定 | RQ1、RQ2、RQ3 |
| Code Review Bench,离线 | 50 个 pull request | 173 条人工审查者确认的评论 | RQ1、RQ2 |
| ReviewBench | 219 个 pull request 中的 50 个,按语言从开发未用过的 194 个里抽取 | 基准认可的 golden 发现 | RQ1、RQ2 |
- SWE-bench 被试把参考修复放进基准,再在改动里把它去掉。它用任务自带的 Docker 镜像构建,镜像名是中性的,issue 文本不提供,测试在任务的容器里无网络运行。这七个项目是
subjects.py有测试运行器的那些。 - ReviewBench 的 25 个测试 pull request 是 eyeful 开发时用的,永不抽取。50 个名额按各语言在其余 194 个里的占比分配,再按哈希挑选,所以每次抽到的都一样。
- 数据集放在
.eval/下,被 git 忽略。被试的描述指明了缺陷,它和仓库分开存放,每次审查都在只能读取该仓库的沙箱里运行。agent 读了仓库之外内容的运行会被排除并计数。
配置与条件
配置决定谁来找问题,条件决定发现怎样被验证。
| 配置 | 运行方式 | 谁来审查 |
|---|---|---|
| panel | eyeful review | 规划器给改动分组,Go 挑选专家 |
| single | eyeful review generalist | 一个拥有全部 skill 的 agent(见名册) |
| fixed | eyeful review correctness security | 两个指定的专家,没有规划器,用于消融 |
| 条件 | 报告哪些 |
|---|---|
| none | 全部发现 |
| read-only | 裁判没有否定的发现 |
| execution | 已复现的发现,以及没有复现、裁判也没有否定的发现 |
三种条件验证的是同一份发现存档,所以唯一的差别就是验证。计数单位是评论:合并成一个问题的发现只算一次。没有能运行的测试时,execution 等同于 read-only,所以在 Code Review Bench 和 ReviewBench 上只比较 read-only 和 none。
实验步骤
采用被试内设计。每个被试都由专家组和单 agent 各审查三次。execution 先运行,其他条件复用它的发现。fixed 配置只在 SWE-bench 和 Code Review Bench 上运行一次,与专家组的第一次运行比较。合计约 860 次审查。失败的审查最多重试三次。
所有 agent 和裁判都用 DeepSeek V4.1 Flash,基准的官方裁判也一样,所以结果是内部比较,不是排行榜分数。提示词、预算和本方案在主实验开始前固定。
指标与分析
一条发现是否成立,由数据集自己的评分器决定:
| 数据集 | 已知缺陷算作找到的条件 | 评分脚本 |
|---|---|---|
| SWE-bench | 官方 harness 用修复 agent 为某条报告的发现写的修复解决了该任务:FAIL_TO_PASS 和 PASS_TO_PASS 测试都通过 | resolve.py |
| Code Review Bench | 基准的裁判在默认的 Core 配置下判定某条发现就是该 golden 评论 | match.py |
| ReviewBench | 基准的裁判把某条发现匹配到该 golden 发现;它的分类器还会认可没有匹配上但成立的发现 | reviewbench.py |
| 问题 | 指标 | 分析方法 |
|---|---|---|
| RQ1 | 召回率:一个已知缺陷在某配置的三次运行中有两次找到才算。找到的类别数,用各基准自己的标签 | McNemar 精确检验 |
| RQ2 | 精确率:报告的发现中解决了 SWE-bench 任务或匹配到 Code Review Bench golden 评论的比例;ReviewBench 用其 augmented precision | 按被试的配对 bootstrap |
| RQ3 | 可验证率:被执行的发现中,复现通过全部六道关卡的比例。验证损失:解决了 SWE-bench 任务、执行却没有确认的发现所占比例。token、费用、秒数 | 按被试的 bootstrap |
专家组还会与单 agent 三次运行的并集比较,后者的花费大约等于一次专家组运行。每个估计都附带 95% 区间,由对整个被试做 10,000 次重抽样得到。
消融
去掉后测量结果没有任何变化的部分,会从 eyeful 中移除。
| 去掉的部分 | 运行方式 | 预期效果 |
|---|---|---|
| 规划器 | fixed 配置,与专家组的第一次运行比较 | 混合改动上的召回率下降,或者没有变化 |
| oracle 分级 | 对存档的复现重新打分,允许每一条都阻断 | 阻断的发现更多,它们的精确率下降 |
效度威胁
- LLM 裁判可能偏宽松。
- golden 集不完整,所以精确率是下界。
- 同一个模型既是审查者,又是裁判和评分者。
- SWE-bench 的项目早于模型的知识截止时间,模型可能知道这个 issue;而在回退版被试上,被去掉的代码就在 diff 里。
- RQ3 只靠约 30 个 Python 被试。
工具
eval/ 里的脚本只用 Python 标准库。resolve.py 用 uv 运行 SWE-bench 的 harness,match.py 和 ReviewBench 的裁判在各基准自己的检出目录里运行。mise run test 会运行这些脚本的测试。
| 脚本 | 作用 |
|---|---|
subjects.py | 从 SWE-bench 的行或 Code Review Bench 的 golden 评论构建被试 |
reviewbench.py | 构建 ReviewBench 样本,把每次审查报告的评论交给基准的裁判,再读回分数 |
run.py | 用 eyeful 审查每个被试:每种配置先找问题,再由各个条件验证 |
confine.py | 在 macOS 沙箱里启动 pi,只允许读取被审查的仓库,用户的其他内容一概不能读 |
audit.py | 列出审查者的 agent 在仓库之外打开过什么 |
resolve.py | 把每个修复交给 SWE-bench 的 harness 运行,并给 SWE-bench 的审查打分 |
match.py | 在审查上运行 Code Review Bench 的裁判,并按 Core 配置打分 |
analyze.py | 根据审查和分数计算各项指标,一次一个数据集 |
revmux.py | 用 revmux 审查每个被试,这是可选的扩展,在 Code Review Bench 上打分 |
