当公共尺子都断了:从 SWE-bench Pro 30% 废题率到自建私有评测基础设施
SWE-bench Verified 因数据污染被 OpenAI 弃用,SWE-bench Pro 又被审计出 27-34% 废题——公共评测基准的公信力正在连环崩塌。本文给出不依赖任何公共榜单、从零搭建私有评测基础设施的完整工程方案。
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-02 | OpenAI 弃用 SWE-bench Verified | 被检出全面数据污染,前沿模型可逐字复现解 |
| 2026-05 | ICSE 2026 PATCHDIFF 研究 | SWE-bench “通过” 的补丁中 29.6% 语义不正确,得分虚高 6.2 个百分点 |
| 2026-06 | ACL 2026 “Test of Time” 论文 | 时序污染信号高度依赖于题目构造方式,LLM 改写可消除时序特征 |
| 2026-06 | ”Reliability Gap” 论文 (arXiv:2606.03305) | 335 次评测中仅 201 次正确,检测方法在分布迁移和规模受限下系统性失效 |
| 2026-07-08 | OpenAI 审计 SWE-bench Pro | 27-34% 任务破损,撤回 Pro 推荐 |
| 2026-07-09 | Poisoned 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.)提出在推理阶段对输入嵌入施加微小有界扰动( 约束,),以”参考模型”为锚引导被评估模型远离记忆捷径。实验表明:在 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 从评估工具变成了公关工具,当实验室开始围绕固定题集做定向优化,基准的公信力就已经在缓慢失血。
三条务实结论:
-
不信任任何一个公共基准的绝对值。 用它做趋势跟踪可以,用它做模型选择决策不可以。OpenAI 的建议值得重复:即使模型通过了某个基准任务,也不意味着它真的解决了问题——去读具体的输出。
-
自建私有评测不是可选项,是必选项。 只要你的团队在生产环境中使用 AI 写代码、处理数据或与用户交互,你就需要一个从你的生产代码库出发、以你的业务指标为评判标准的私有评测集。
-
把评测成本视作工程质量投资,而非研发开销。 每月 $2000-4000 的私有评测管道,抵得上一次生产事故的零头。这不是评测团队的预算申请——这是工程团队的保险单。
当公共尺子都断了的时候,唯一不会欺骗你的,是你自己做的尺子。