别再用榜分决定要不要把活交给模型,先给你的回归集分层

举报
霍格沃兹测试开发 发表于 2026/09/15 16:18:53 2026/09/15
【摘要】 同一批模型,在两个都叫 SWE-bench 的榜单上,顶分差出了十几个百分点:Verified 上 Claude Opus 5 登顶,头部口径在 96%—97% 之间;Pro(Public)的顶分只有 80.30。两个数字都是真的。错的是把它们当成同一把尺子来读。一、先分清:Verified 和 Pro 不是同一张卷子SWE-bench 家族的共同做法是从真实开源仓库里捞 issue,把 i...

同一批模型,在两个都叫 SWE-bench 的榜单上,顶分差出了十几个百分点:Verified 上 Claude Opus 5 登顶,头部口径在 96%—97% 之间;Pro(Public)的顶分只有 80.30。

两个数字都是真的。错的是把它们当成同一把尺子来读。

一、先分清:Verified 和 Pro 不是同一张卷子

SWE-bench 家族的共同做法是从真实开源仓库里捞 issue,把 issue 描述和当时的代码快照交给模型,让它提交补丁,再用项目自带的测试套件判定通没通过。分歧出在题目怎么筛、筛完留下什么。

Verified 是经过人工复核的子集:题目可解性被确认过,描述被清理干净,判定链路可靠。它的价值在于可信,代价在于——它是一份被人修过边的卷子。

Pro(Public)走的是另一条路:题目直接取自真实的大型仓库,issue 原文更长,涉及的代码面更广,没有为了「好判」而把上下文削薄。

所以 96%—97% 和 80.30 之间的落差,主要不是模型能力的落差,而是口径的落差。

这里有一起真实发生过的误读值得记一笔:有人看到 Pro 公开榜顶分 80.30,转头就下了结论——「Verified 顶分才 79% 左右,榜上根本没有 Opus 5」。两个数字都真实存在,拼出来的判断完全是假的。做质量的人对这个错误应该很熟,它就是我们天天在防的跨口径对比,只不过这次翻车的是读榜的人,不是写代码的人。

二、口径差在四个维度上

把两边摊开对照,差别不是「难一点」,而是四件事同时变了:

维度

SWE-bench Verified

SWE-bench Pro(Public)

头部成绩

Claude Opus 5 登顶,头部口径 96%—97%

顶分 80.30(Claude Fable 5 深度思考)

题面来源

真实仓库 issue,经人工复核筛选

真实大仓 issue,保留原始复杂度

题面长度与信息密度

短、聚焦,可解性已确认

长、噪声多,跨文件跨模块

被针对性优化的难度

分布稳定、题目公开,容易被反复打磨

上下文长、路径多,难以押题

对测试团队的读法

看模型在干净题面上的能力上限

看模型在脏题面上的可用性下限




最后一行才是重点。同一个分数,在两个榜上回答的是两个不同的问题:一个回答「它最好能做到什么」,一个回答「它在真实噪声里还能不能用」。拿前者去做后者的决策,是选型阶段最贵的一种错。

三、为什么短题面天然更容易被优化

题面越短、越干净,模型和它背后的工程链路能发力的地方就越集中:把 issue 读准,定位到那一两个文件,改对那一处逻辑,让项目自带测试通过。这是一条窄路,而窄路是可以被反复打磨的——公开题目、稳定分布、明确判定,三个条件凑齐,针对性优化就有了着力点。

题面一旦变长变脏,情况就完全不同。真实大仓里的 issue 常常同时夹着复现步骤不全、依赖版本不一致、报错信息误导、需要跨好几个模块才能定位。模型要先在一大堆文字里挑出真正相关的几十行,还要在长上下文中不丢掉关键约束。这已经不是同一种难度的任务。

所以 Pro 顶分只有 80.30,不代表模型退步了,而是它终于被放到了一条没法押题的路上。一个榜单最值钱的地方,往往不是它的顶分有多高,而是它还能不能被针对性优化。

再补第三个数字作旁证:LiveCodeBench 顶分 92.00,来自 Gemini 3.0 Pro Preview。它是竞赛题口径,题目短、输入输出边界清楚、判定确定。于是我们手上有了三个数:96%—97%、92.00、80.30。

这三个数不是三个能力值,是三种口径。你只能竖着读同一列,不能斜着读。

跨口径比较,是数据造假里最便宜的一种形式——它甚至不需要篡改任何一个数字。

四、测试团队读榜的三条规矩

第一条,先看口径,再看分数。打开任何一个榜,先找三件事:题目从哪来、题面多长、判定用的是谁的测试。这三件事没弄清之前,分数只是发布会素材。

第二条,把「顶分差」当信息,不要当排名。Verified 与 Pro 之间那十几分的落差,本身就是一个测量结果:它告诉你,从干净题面走到真实大仓题面,模型的可用水位会掉多少。这个落差比任何单个分数都更贴近你项目的真实处境,因为它量的是「环境变脏的代价」,而你的项目环境从来都是脏的。

第三条,只把榜单当上限,不要当预期。公开榜的分数是在最优条件下跑出来的:题目被筛过、环境被冻结、失败没有任何生产后果、还可以多次采样取最好的一次。你的仓库不具备其中任何一条。

一句话:「登顶」是市场的语言,「分层落差」才是工程的语言。 测试团队的价值,就是把前者翻译成后者。

五、把公开榜结论映射到自建回归集:先分层,再对号

大多数团队的动作是这样的:看到榜分 → 决定要不要把某类活交给模型。中间跳过了一个关键步骤——把你自己的回归集按题面难度分层,再让每一层去对榜上口径最接近的那一档。

自建回归集分层

典型特征

口径最接近的公开榜

可参考的顶分

该做的动作

L1 单元级

单函数、单文件、断言明确

LiveCodeBench(竞赛题口径)

92.00

可较高比例交给模型改,人只审断言

L2 单 issue 级

单模块缺陷、有明确复现步骤

SWE-bench Verified

96%—97%

模型可自主提交,回归集当闸口

L3 跨模块级

长上下文、跨服务、需求半口头

SWE-bench Pro(Public)

80.30

模型产出必须人工复核,别只靠测试兜

L4 生产环境级

依赖真实数据、配置、灰度状态

公开榜无对应口径

不引用

自建判据,任何榜分都不作依据

注意 L4 那一行:不是分数低,而是没有对应口径。这一层去借榜,等于拿别人的卷子给自己打分。

分层真正的产出也不是「哪些用例能过」,而是评审强度。L1、L2 的口径接近公开榜的干净题面,模型产出可以走轻评审:人只看断言写得对不对,测试跑绿就放行。L3 必须走重评审:diff 逐段过、跨模块的调用链要有人复核一遍,测试通过只是入场券。L4 则根本不该由榜分参与决策,它的判据只能来自你自己的灰度数据与回滚记录。把评审强度绑在分层上,比把通过率绑在榜分上靠谱得多。

下面这段脚本做的事很朴素:给用例打标 → 算各层占比 → 输出每层可借的口径,最后给一个「榜分对你还有多少参考价值」的判据。

# bench_map.py
# 用途:把公开榜口径映射到自建回归集分层,输出「可借榜程度」判据
# 用法:python bench_map.py tests/regression --meta case_meta.json
# case_meta.json 示例:
# [{"id": "TC-001", "files": ["service/refund.py"], "steps": 3,
#   "cross_module": false, "needs_prod_data": false}, ...]
import json, argparse, pathlib, collections

# 口径锚点:分数只作「参考水位」,禁止跨层混用
BENCH_ANCHOR = {
    "L1_unit":         {"bench": "LiveCodeBench(竞赛题口径)", "top": "92.00"},
    "L2_single_issue": {"bench": "SWE-bench Verified",          "top": "96%—97%(登顶·区间口径)"},
    "L3_cross_module": {"bench": "SWE-bench Pro(Public)",     "top": "80.30"},
    "L4_prod_env":     {"bench": "无公开对应口径",               "top": "不引用"},
}

def classify(case: dict) -> str:
    """打标优先级:生产数据 > 跨模块 > 单文件短步骤 > 其余归 L2"""
    if case.get("needs_prod_data"):
        return "L4_prod_env"
    if case.get("cross_module") or len(case.get("files", [])) > 3:
        return "L3_cross_module"
    if len(case.get("files", [])) == 1 and case.get("steps", 0) <= 3:
        return "L1_unit"
    return "L2_single_issue"

def report(meta_path: pathlib.Path, threshold: float = 0.4):
    cases = json.loads(meta_path.read_text(encoding="utf-8"))
    buckets = collections.Counter(classify(c) for c in cases)
    total = len(cases) or 1

    print(f"{'分层':<18}{'用例数':>7}{'占比':>8}  {'可借口径':<28}{'参考顶分'}")
    for layer, anchor in BENCH_ANCHOR.items():
        n = buckets.get(layer, 0)
        print(f"{layer:<18}{n:>7}{n / total:>8.0%}  "
              f"{anchor['bench']:<28}{anchor['top']}")

    # 关键判据:L3+L4 占比越高,公开榜对你的参考价值越低
    hard = buckets.get("L3_cross_module", 0) + buckets.get("L4_prod_env", 0)
    ratio = hard / total
    verdict = ("榜分参考价值低:别用榜分做放行依据,L3 必须人工复核"
               if ratio >= threshold
               else "L1/L2 口径可作有限参考,仍不代表你的成功率")
    print(f"\nL3+L4 占比 {ratio:.0%}(阈值 {threshold:.0%},经验起手值需按项目校准)")
    print(f"判据 → {verdict}")

if __name__ == "__main__":
    p = argparse.ArgumentParser()
    p.add_argument("target", help="回归集目录,仅作记录,实际读取 --meta")
    p.add_argument("--meta", required=True, help="用例元数据 JSON")
    p.add_argument("--threshold", type=float, default=0.4)
    a = p.parse_args()
    report(pathlib.Path(a.meta), a.threshold)

三个实现上的提醒:

第一,打标数据不要靠人手填。 files 可以直接从 git 变更文件数拿,steps 可以用用例步骤数或断言数近似,needs_prod_data 看用例是否连生产库或读线上配置。手工打标撑不过三个月。

第二,0.4 这个阈值是经验起手值【推断】,不是行业标准。 正确做法是拿你过去半年的线上事故去校准:把出过事故的那批变更按同样规则打标,看它们落在哪一层,再把阈值压到那条线附近。

第三,top 字段只能打印,不能进判据。 一旦你把 96%—97% 或 80.30 写进 if 条件里当放行门槛,你就完成了本篇开头那起误读的同款操作——只是这次是代码替你错的。

六、映射时最容易犯的三种错位

错位一:把 Pro 的 80.30 读成「模型只能修好八成的 bug」。 80.30 是在 Pro 那批特定题目、特定判定下跑出来的,你的缺陷分布和它没有任何统计关系。它是口径水位,不是你的成功率。

错位二:把 Verified 的 96%—97% 当成自己项目的预期值。 Verified 的题目已经被人工确认可解。你的 backlog 里有多少 issue 是描述不清、根本复现不了的?那部分既不该由模型背锅,也不该由榜分背书——它该由你的需求流程负责。

错位三:给 L4 层也找一个榜来靠。 生产环境层没有公开口径,任何「某模型在生产级任务上表现如何」的说法,都必须由你自己的数据支撑。这一层最需要的是自建判据,而不是一个更好看的引用来源。

最后补一句流程上的提醒:榜单会更新,分数会变。今天写下的 96%—97% 与 80.30,发布前都应该回到 DataLearner 代码榜再核一遍区间,尤其是「登顶」这种带时效性的表述。把来源固定下来、把复核动作写进流程,比记住某个具体数字重要得多。

七、写在最后

同一批模型在两个榜上差出十几分,这不是矛盾,这是两把尺子;同一条 bug 落在你的 L2 和 L4 上,也该差出两套判据,这不是麻烦,这是分层。

分不清口径的人,永远只能读别人写好的结论;分得清口径的人,才有资格决定哪些活可以交出去。

关于我们

本文部分内容参考了霍格沃兹测试开发学社整理的相关技术资料,主要涉及软件测试、自动化测试、测试开发及 AI 测试等内容,侧重测试实践、工具应用与工程经验整理。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。