当公共尺子都断了:从 SWE-bench Pro 30% 废题率到自建私有评测基础设施

SWE-bench Verified 因数据污染被 OpenAI 弃用,SWE-bench Pro 又被审计出 27-34% 废题——公共评测基准的公信力正在连环崩塌。本文给出不依赖任何公共榜单、从零搭建私有评测基础设施的完整工程方案。

工程实践 评测基准 SWE-bench 私有评测 数据污染 LLM-as-Judge CI/CD 质量保障 Agent评测

2026 年 7 月,AI 行业投入了一年半时间建立的公共评测基准信任体系,在一个月内连环崩塌。

一、尺子断了:公共评测基准的信任崩塌

7 月 8 日,OpenAI 发布了一篇名为《Separating signal from noise in coding evaluations》的博客,对 SWE-bench Pro 731 道公开题目做了逐题审计。结论令人震惊:27.4% 至 34.1% 的任务是坏的——要么测试规定的行为从未在题目描述里提及(“过度严格测试”,占 14.4%),要么题目描述模糊到连人类工程师也不知道该做什么(占 7.5%),要么测试覆盖不够导致错误实现也能通过(占 9.4%)。

OpenAI 的原话很直白:“Improvements on SWE-bench Verified no longer reflect meaningful improvements in models’ real-world software development abilities.” 这家公司不仅弃用了 Verified,还收回了之前推荐 Pro 的表态。

这不是孤立事件。把时间轴拉长,2026 年上半年评测基准领域至少发生了五次重大崩塌:

时间事件影响
2026-02OpenAI 弃用 SWE-bench Verified被检出全面数据污染,前沿模型可逐字复现解
2026-05ICSE 2026 PATCHDIFF 研究SWE-bench “通过” 的补丁中 29.6% 语义不正确,得分虚高 6.2 个百分点
2026-06ACL 2026 “Test of Time” 论文时序污染信号高度依赖于题目构造方式,LLM 改写可消除时序特征
2026-06”Reliability Gap” 论文 (arXiv:2606.03305)335 次评测中仅 201 次正确,检测方法在分布迁移和规模受限下系统性失效
2026-07-08OpenAI 审计 SWE-bench Pro27-34% 任务破损,撤回 Pro 推荐
2026-07-09Poisoned Chalice 竞赛报告 (FSE-AIWare 2026)污染检测方法不够可靠,无法替代透明的数据溯源

六次崩塌形成一个清晰的结论:公共评测基准不只是一个有噪声的信号——它们正在变成一个系统性误导的信号。 模型在榜单上越跑越高,但每一轮审计都发现分数的提升中混入了不可忽略的污染溢价和测试缺陷。

同一天,Databricks 发布了一组截然不同的评测结果:他们用自己的生产代码库(数百万行 Python、Go、TypeScript、Scala 代码的真实合并 PR)作为评测集,测试执行决定正确性,没有 LLM 判官,也没有污染风险——因为这些任务从未公开过。结果是 GLM 5.2 和 Claude Opus 4.8 在任务质量上统计打平,但前者每个任务成本 $1.28,后者 $1.94。当公共尺子不可靠时,那些真正关心答案的企业正在自己造尺子。

二、行业三条自救路线

面对基准信任危机,2026 年 7 月并行出现了三条自救路径:

路线一:推理时修复。 ACL 2026 论文 DeconIEP(Chai, Zhe, Sakuma et al.)提出在推理阶段对输入嵌入施加微小有界扰动(ℓ∞\ell_\infty 约束,ζ≤10−3\zeta \leq 10^{-3}),以”参考模型”为锚引导被评估模型远离记忆捷径。实验表明:在 Llama 3 / Mistral / Qwen2.5 上,DeconIEP 可将污染残余降至接近零,而对干净输入的 benign utility drop 仅 0.009-0.041。局限是白盒方法——需要访问嵌入空间和梯度,对闭源 API 无效。

路线二:动态演进基准。 MMBench-Live(Liu, Zhao, Zhou et al., arXiv:2607.01813)用多 Agent 驱动自动化流水线实现基准的持续演化,每次更新成本约 $30、耗时 1-2 小时,通过”分布一致更新策略”保持跨版本可比性。SWE-bench-Live 同样以 RepoLaunch Agent 自动构建管道实现月度更新。问题在于:流水线本身也有维护成本,且”防污染”不等于”题目质量好”——SWE-bench Pro 的动态性并没有阻止它产生 30% 废题。

路线三:自建私有评测。 Databricks 范式:用团队自身的生产代码库构建从不公开的评测集,正确性由执行结果而非 LLM 判断,成本与质量同时可衡量。这是最务实的路线,也是本文工程实战的核心。

三条路线不互斥。推理时修复可以作为公共基准的辅助验证手段;动态基准适合学术跟踪趋势;私有评测则是生产决策的基础。一个成熟团队的评测策略应该同时覆盖这三层。

三、工程实战:从零搭建私有评测基础设施

下面给出一个不依赖任何公共榜单、可落地的私有评测管道架构。核心原则只有三条:任务私有(永不公开)、评判可执行(不靠 LLM 主观打分的尽量不靠)、成本可量化。

3.1 整体架构

[生产代码库/线上日志] ──→ [任务采集层] ──→ [评测执行层] ──→ [结果分析层]──→ [CI门禁]
       │                       │                  │                 │
       │                  - Bug修复合集        - 模型调用        - 通过率计算
       │                  - 线上badcase        - Harness适配     - 成本统计
       │                  - 功能需求           - 沙箱执行        - 回归检测
       │                                       - 测试执行        - 趋势面板
       │
  [污染检测层] ←────────────────────────────────── 持续运行 ─────→
   定期扫描训练集与评测集的 n-gram / 语义重叠

3.2 任务采集:让生产代码库自己”出题”

私有评测的核心难点不是执行,而是任务采集的可持续性。没有持续的 new tasks,私有基准会在 3-6 个月内沦为另一个静态集。

方案 A:Bug 修复类任务(推荐起点)

从已合并的 Bug 修复 PR 中提取任务。每个任务包含:修复前的代码状态、Issue 描述(或 PR 描述)、通过的测试用例。

# scripts/collect_bugfix_tasks.py
import subprocess, json, re
from pathlib import Path

def extract_task_from_pr(pr_number: str, repo_path: str) -> dict:
    """从已合并的 Bug 修复 PR 提取评测任务"""
    # 1. 获取 PR 的 base commit(修复前状态)
    base = subprocess.run(
        ["gh", "pr", "view", pr_number, "--json", "baseRefOid", "-q", ".baseRefOid"],
        capture_output=True, text=True, cwd=repo_path
    ).stdout.strip()

    # 2. 获取 PR 改动的文件列表(仅 .py/.ts/.go 等业务代码)
    changed = subprocess.run(
        ["gh", "pr", "view", pr_number, "--json", "files", "-q",
         "[.files[].path] | join(\" \")"],
        capture_output=True, text=True, cwd=repo_path
    ).stdout.strip().split()

    # 3. 提取 PR 描述作为 issue 描述
    body = subprocess.run(
        ["gh", "pr", "view", pr_number, "--json", "body", "-q", ".body"],
        capture_output=True, text=True, cwd=repo_path
    ).stdout.strip()

    # 4. 找关联的测试文件
    test_files = [f for f in changed if "test" in f.lower()]

    return {
        "task_id": f"PR-{pr_number}",
        "repo": repo_path,
        "base_commit": base,
        "issue_description": body[:2000],  # 截断避免过长
        "changed_files": changed,
        "test_files": test_files,
        "created_at": subprocess.run(
            ["gh", "pr", "view", pr_number, "--json", "mergedAt", "-q", ".mergedAt"],
            capture_output=True, text=True, cwd=repo_path
        ).stdout.strip()
    }

方案 B:线上 Badcase 转评测任务

从生产环境的用户负反馈中提取。输入:用户提问 + Agent 回复 + 用户标记的”不满意”信号。

# task-schema.yaml — 评测任务的标准结构
task_id: "bc-20260730-0042"
source: "production_badcase"  # or "bugfix_pr" / "feature_req"
difficulty: "medium"
context:
  repo: "payment-service"
  language: "go"
prompt: |
  用户报告:在并发退款场景下,order_refund 接口偶现
  "duplicate refund" 错误。请定位 root cause 并修复。
expected_behavior:
  - 并发退款请求必须幂等
  - 不应在无锁情况下修改 refund_status 字段
verification:
  type: "test_execution"  # 而非 LLM-as-Judge
  test_command: "go test ./internal/service/ -run TestConcurrentRefund -count=10"
  timeout_seconds: 120
  expected_exit_code: 0
excluded_patterns:  # 禁止使用的实现方式
  - "sync.Mutex.*refund_status"  # 如果用锁实现则判错(业务要求用乐观锁)

3.3 评测执行:Harness 适配与沙箱隔离

# scripts/run_private_eval.py
import subprocess, json, time, os
from dataclasses import dataclass
from pathlib import Path

@dataclass
class EvalResult:
    task_id: str
    model: str
    passed: bool
    cost_usd: float
    latency_seconds: float
    output_tokens: int
    error_log: str = ""

def evaluate_task(task: dict, model_config: dict) -> EvalResult:
    """在隔离沙箱中执行单任务评测"""
    import docker

    client = docker.from_env()
    start = time.time()

    # 1. 构建包含任务代码的沙箱镜像
    sandbox = client.containers.run(
        image=model_config["harness_image"],
        command="sleep 3600",  # 保持运行
        detach=True,
        environment={
            "TASK_JSON": json.dumps(task),
            "MODEL_NAME": model_config["name"],
            "API_KEY": os.environ["MODEL_API_KEY"],
            "API_BASE": model_config["api_base"],
        },
        volumes={f"{task['repo']}": {"bind": "/repo", "mode": "ro"}},
        network_mode="none"  # 关键:禁止外网访问,防止数据泄露
    )

    try:
        # 2. 执行 agent harness
        exec_result = sandbox.exec_run(
            f"python /harness/run.py --task /tmp/task.json --max-tokens {model_config['budget_tokens']}",
            stdout=True, stderr=True
        )

        # 3. 运行验证测试
        test_result = sandbox.exec_run(
            task["verification"]["test_command"],
            stdout=True, stderr=True
        )

        elapsed = time.time() - start
        return EvalResult(
            task_id=task["task_id"],
            model=model_config["name"],
            passed=(test_result.exit_code == task["verification"]["expected_exit_code"]),
            cost_usd=model_config["price_per_1k_tokens"] * 0.001 * estimate_tokens(exec_result.output),
            latency_seconds=elapsed,
            error_log=test_result.stderr.decode()[:500] if test_result.exit_code != 0 else ""
        )
    finally:
        sandbox.remove(force=True)

3.4 LLM-as-Judge 的正确用法:只在不得不主观评分时用

对于无法用测试断言验证的维度(如回复的”语气是否恰当""解释是否清晰”),才引入 LLM-as-Judge。但必须保证 Judge 本身经过校准:

# Judge 校准检查清单
class JudgeCalibration:
    @staticmethod
    def human_alignment(judge_scores: list, human_scores: list) -> dict:
        """计算 Cohen's Kappa,阈值 < 0.6 则 Judge 不可用"""
        from sklearn.metrics import cohen_kappa_score
        kappa = cohen_kappa_score(judge_scores, human_scores)
        return {
            "kappa": kappa,
            "usable": kappa >= 0.6,
            "action": "recalibrate" if kappa < 0.6 else "ok"
        }

    @staticmethod
    def positional_bias_check(judge_responses: list) -> bool:
        """检测位置偏差:A/B 对比中是否倾向选择靠前的选项"""
        first_wins = sum(1 for r in judge_responses if r == "A")
        return abs(first_wins / len(judge_responses) - 0.5) > 0.15  # 偏差超过 15% 则告警

3.5 CI 门禁:让坏模型无法上线

# .github/workflows/model-eval-gate.yml
name: Model Evaluation Gate

on:
  pull_request:
    paths:
      - 'config/model_config.yaml'  # 模型切换配置变更时触发

jobs:
  eval-gate:
    runs-on: [self-hosted, gpu]
    steps:
      - uses: actions/checkout@v4

      - name: Run Private Benchmark
        run: |
          python scripts/run_private_eval.py \
            --tasks tasks/manifest.yaml \
            --model ${{ vars.CANDIDATE_MODEL }} \
            --baseline ${{ vars.PRODUCTION_MODEL }} \
            --output results/candidate.json

      - name: Gate Check
        run: |
          python scripts/gate_check.py \
            --results results/candidate.json \
            --rules config/eval_gates.yaml
        # gate_rules.yaml 示例:
        # rules:
        #   - metric: pass_rate
        #     threshold: ">= baseline - 0.02"  # 允许 2pp 退化
        #   - metric: cost_per_task
        #     threshold: "<= baseline * 1.3"   # 成本增幅不超过 30%
        #   - metric: p50_latency
        #     threshold: "<= baseline * 1.5"   # 延迟增幅不超过 50%

      - name: Block if Failed
        if: failure()
        run: |
          echo "::error::评测门禁未通过,禁止合并此 PR。"
          echo "详情见 results/candidate.json 和 results/regression_report.md"
          exit 1

3.6 成本账:私有评测到底有多贵?

以 Databricks 公布的内部评测为参考,给出一个典型的中型团队(50 人工程团队)私有评测的月度成本估算:

成本项月度估算说明
任务维护(人工)8 人天每月新增 ~30 个任务 + 淘汰过时任务
评测执行(API 调用)$200-500假设 500 个任务 × 2 模型 × 每次 $0.20-0.50
GPU 服务器(如私有部署)$800-1500自建 harness 运行环境,按需弹性
Judge 校准(人工复核)2 人天/月每月抽取 100 个 judge 评分人工复核
总计$2200-4000/月约合一个初级工程师薪资的 25-45%

对比收益:避免一次因模型质量退化导致的生产事故,其损失通常在数万到数十万美元级别。私有评测的成本是保险,不是开支。

四、四条踩坑经验

坑 1:任务采集比执行难 10 倍

私有评测的瓶颈不在 GPU 或 API 调用——在任务供给。Bug 修复 PR 会枯竭(好 bug 都被修完了),线上 badcase 偏向简单任务(用户只会在简单问题出错时才点”不满意”)。对策:建立”任务新鲜度”指标,当过去 3 个月新增任务占比低于 30% 时触发告警,要求团队从 feature request / 重构 PR / 外部安全报告等渠道补充。

坑 2:私有基准也会”污染”

即便评测集从未公开,模型也可能通过其他渠道接触类似代码——比如相同的开源依赖库、相同的 Stack Overflow 答案被重写进了训练集。对策:定期用 n-gram 重叠检测(4-gram 以上匹配率 > 5% 标黄,> 15% 标红)+ 语义嵌入相似度(cosine similarity > 0.85 标记)做自查。

坑 3:LLM-as-Judge 偷懒

Judge 模型会在续行中直接给 5 分(完美分数),跳过推理步骤。这会导致平均分系统性偏高。对策:强制 CoT(Chain-of-Thought)打分——Judge 必须输出”评分理由 → 分数”,直接给分无理由的判为无效。在笔者团队的实际使用中,这个改动让 Judge 分数的方差从 0.3 提升到 1.1,校准后的 Kappa 从 0.48 提升到 0.72。

坑 4:Harness 成本的 2× 差异

Databricks 的评测发现了被很多团队忽视的一件事:同一个底层模型,通过不同的 Agent Harness 路由,成本差异可以超过 2 倍,而输出质量几乎没有差别。如果你的评测只换模型不换 Harness,你测量的是”模型 + Harness”的组合效果,而非模型的裸能力。对策:为每个候选模型至少测试 2 种 Harness 配置,报告中同时展示模型-成本和质量-成本散点图。

五、总结

2026 年 7 月的评测基准崩塌不是偶然事件——它是过去一年半榜单军备竞赛的必然结果。当 SWE-bench Verified 从评估工具变成了公关工具,当实验室开始围绕固定题集做定向优化,基准的公信力就已经在缓慢失血。

三条务实结论:

  1. 不信任任何一个公共基准的绝对值。 用它做趋势跟踪可以,用它做模型选择决策不可以。OpenAI 的建议值得重复:即使模型通过了某个基准任务,也不意味着它真的解决了问题——去读具体的输出。

  2. 自建私有评测不是可选项,是必选项。 只要你的团队在生产环境中使用 AI 写代码、处理数据或与用户交互,你就需要一个从你的生产代码库出发、以你的业务指标为评判标准的私有评测集。

  3. 把评测成本视作工程质量投资,而非研发开销。 每月 $2000-4000 的私有评测管道,抵得上一次生产事故的零头。这不是评测团队的预算申请——这是工程团队的保险单。

当公共尺子都断了的时候,唯一不会欺骗你的,是你自己做的尺子。

关联内容

文章 ⬆️ 前置
别让评测分数骗了你:从静态刷榜到动态抗污染评测管道实战
当 78% 的 CodeForces 题目存在训练集软污染,当 NIST 闭源评测引发争议,传统静态基准的公信力正在崩塌。本文以 BeyondBench、StressEval、Claw-Eval-Live 为蓝本,给出从污染检测到动态生成评测管道的完整工程方案
文章 🔍 深入
从 88 到 24 的祛魅之旅:代码智能的 2026 年 7 月「成人礼」
Senior SWE-Bench 揭示最强模型真实通过率仅 24%,OpenAI 审计发现 SWE-bench Pro 约 30% 题目是废题,同月 Ornith-1.0 和 SWE-1.7 在自搭脚手架和 RL 天花板两个方向上双双突破——代码智能正在撕掉榜单上的泡沫,直面真实世界的复杂。
文章 ⬆️ 前置
LLM-as-Judge 不是魔法,是工程:从评测漂移到 CI 门禁,构建可信任的生产级评测管道
LLM-as-Judge 是 2026 年最主流的 AI 质量评测范式,但 80% 的团队低估了它的工程复杂度。本文给出从 Golden Dataset 构建、Rubric 工程化、Judge 校准到 CI/CD 门禁的完整工程方案,附可复制的代码模板和踩坑清单。
文章 🔗 相关
当评测器比模型更不靠谱:Agent 评测管道的 18.5% 幻觉率与工程自救指南
最新研究发现 Agent 工具调用评测的误对齐率高达 18.5%,同一配置重复跑分差 18.9 个百分点。本文拆解评测器的五种失灵模式,给出从污染检测、可复现管道到分解式评测的三层工程自救方案。
文章 ⬆️ 前置
修一个 Bug 容易,演进一个系统难:SWE 基准从静态到动态的范式跃迁
从 SWE-bench Verified 到 SWE-EVO、SWE-bench-Live、Vibe Code Bench,代码智能基准正从单 Issue 修复走向长周期软件演化和零到一应用构建,GPT-5 在 SWE-EVO 上仅 21% 解决率揭示能力鸿沟