DeepCode SWE-bench 评测 Harness 实战:从 Docker-free 本地基线到官方 Verified 50 的完整闭环
2026/9/14 12:12:38 网站建设 项目流程

DeepCode SWE-bench 评测 Harness 实战:从 Docker-free 本地基线到官方 Verified 50 的完整闭环

【免费下载链接】DeepCode"DeepCode: Open Agentic Coding (Agent Harness & Loop Engineering & Multi-Agent Orchestration)"项目地址: https://gitcode.com/GitHub_Trending/deepc/DeepCode

本文系统讲解 DeepCode 仓库中eval/swebench评测工具链的设计与使用:它如何把"Agent 能否解决真实 GitHub issue"这一终极问题拆解为 Predict(预测补丁)与 Score(官方评分)两个可独立演进的阶段,如何在无 Docker 环境下用内置 benchmark 快速冒烟验证整条管线,以及如何对接官方 SWE-bench_Verified 数据集产出可复现的 P2 基线。读完本文,你将掌握该 harness 的全部 CLI 用法、实例数据结构、补丁捕获与评分规则,以及如何把它接入发布前的回归门禁。

背景:为什么把 SWE-bench 作为 P2 exit gate

SWE-bench 是评估编码型 Agent 的行业标准任务集:给定一个真实 GitHub issue 与仓库在base_commit时刻的快照,Agent 需要产出一份能修复该 issue 的补丁(model_patch)。修复是否成立由隐藏测试判定——FAIL_TO_PASS中的测试必须从失败翻转为通过,同时PASS_TO_PASS中的既有测试必须保持绿色。这就是"修好 bug 且不破坏邻居"的经典评测形态。

在 DeepCode 中,该 harness 被明确定位为P2 exit gate(见 eval/swebench/README.md):用真实 GitHub issue 度量 DeepCode Agent 的修复能力,为每个发布周期守住"解决率"这条质量底线。

架构核心:Predict 与 Score 两阶段分离

harness 遵循"各司其职"的分层设计,只做 DeepCode 该做的事,绝不重复造轮子:

阶段执行者产出/位置
Predict:在base_commit检出仓库,对 issue 运行deepcode exec,把git diff捕获为model_patchDeepCodepredict.py
Score:应用补丁、运行测试、判定是否 resolved官方swebenchDocker harness(Verified 集)/ 本地 scorer(开发用)evaluate.py(本地)

关键原则:不重新实现官方评分器。对 Verified 集,harness 只负责产出符合 SWE-bench schema 的predictions.jsonl,然后移交swebench.harness.run_evaluation完成评分。这样做既避免了与官方结果产生偏差,也把"预测"这一真正属于 Agent 能力的环节留在仓库内持续打磨。

模式一:Local 模式(无需 Docker,随处可跑)

快速上手

python -m eval.swebench.run --mode local --model gpt-5.4 --report report.json

该模式内置一个自包含 benchmark——三个真实 bug(off-by-one、大小写敏感、缺少空值守卫),每个实例还附带一个与 bug 无关的正确函数,完整复刻 SWE-bench "修好 bug、不碰邻居"的形态。它以端到端方式跑完整条管线(prepare → agent → apply → test → score)并打印真实解决率。

README 记录的在当前机器上(Poegpt-5.4)的运行结果为3/3 resolved(100%)——每个实例的FAIL_TO_PASS都成功翻转且PASS_TO_PASS保持绿色。需要强调的是,这验证的是"prepare → agent → apply → test → score 全链路对真实模型可用",属于冒烟基线(smoke baseline),而非官方 Verified 数字

三个内置实例详解

内置 benchmark 以声明式规格(declarative spec)定义在 instance.py 的_LOCAL_SPECS中,每个实例包含:待修复的 buggy 文件、测试文件、issue 文案、必须翻转/保持绿色的测试列表:

instance_idbug 类型FAIL_TO_PASSPASS_TO_PASS
local__mathlib-inclusive-sum区间求和range(a, b)漏掉上界 b(off-by-one)test_mathlib.py::test_sum_inclusivetest_mathlib.py::test_factorial
local__stringutil-palindrome-caseis_palindrome大小写敏感比较test_stringutil.py::test_palindrome_ignores_casetest_stringutil.py::test_reverse
local__listutil-empty-guardfirst_or_none对空列表无条件索引xs[0]IndexErrortest_listutil.py::test_first_or_none_emptytest_listutil.py::test_length

每个 spec 在运行时会通过_materialize()落盘为真实的 git 仓库:写文件 →git init→ 提交为 "base: buggy state",并把 HEAD 记录为该实例的base_commit。也就是说,本地实例和官方实例共享同一套"以 git 仓库为基准"的工作模型,Agent 见到的就是一个处于 buggy 状态的代码库。

本地评分器的判定规则

本地评分逻辑在 evaluate.py 中实现,忠实于 SWE-bench 的 resolution 规则、但去掉了容器:

  1. 把 model_patch 应用到干净的新检出(clean checkout atbase_commit)——度量的是补丁本身,而非 Agent 在 scratch 目录里留下的其他改动;
  2. pytest分别运行FAIL_TO_PASSPASS_TO_PASS节点;
  3. 判定 resolved 的充要条件:所有fail_to_pass测试通过,所有pass_to_pass测试仍然通过。

应用补丁使用git apply --whitespace=nowarn;补丁为空或应用失败都会直接判为 unresolved 并给出明确原因("empty patch"/"patch did not apply")。

结果报告

local 模式会输出汇总行与可选 JSON 报告(report.py):

SWE-bench [local] gpt-5.4: 3/3 resolved (100.0%)

--report report.json会把逐实例结果行(resolved、fail_to_pass_ok、pass_to_pass_ok、patch_generated、detail)与聚合的resolved_rate一并写出。从 run.py 的源码可见,local 模式在没有任何实例 resolved 时会以非零码退出,因此可以直接被 CI 当作门禁使用。

模式二:Official Verified 50(需要 Docker)

生成预测

对官方 50 实例确定性子集生成预测:

# 需要 `datasets` 包 + 网络以流式下载数据集并 clone 仓库 uv run --with-requirements requirements.txt --with datasets \ python -m eval.swebench.run --mode predict --limit 50 --out predictions.jsonl

确定性子集的选择机制

子集的"可复现性"来自 dataset.py 的实现而非随机种子:select_subset()先把全部 Verified 记录按instance_id字典序排序,再取前 N 条。字典序在每次运行、每台机器上都稳定,因此同一 50 实例集合天然可复现,无需跟踪任何 RNG seed。对应的单元测试test_select_subset_is_deterministic_and_sized(tests/test_swebench_harness.py)专门验证了"打乱输入顺序、输出子集不变"这一性质。

load_verified()是仓库中唯一依赖datasets包与网络的入口,被刻意隔离,使得子集选择与 record→Instance映射这些确定性逻辑保持纯净、可离线单测;若未安装datasets,它会抛出附带安装指引的RuntimeError。SWE-bench 记录中的FAIL_TO_PASS/PASS_TO_PASS字段以 JSON 编码字符串存储,_parse_test_list()负责将其解析为测试节点列表(兼容 list 与 JSON 字符串两种形态)。

用官方 Docker harness 评分

predict 运行结束时会在终端打印官方评分命令:

python -m swebench.harness.run_evaluation \ --dataset_name princeton-nlp/SWE-bench_Verified \ --predictions_path predictions.jsonl \ --max_workers 4 --run_id deepcode-p2

评分前置条件:运行中的 Docker daemon 与已安装的swebench包。该评分环节不在本仓库内复现(这是刻意的架构决策,见上文"两阶段分离")。官方报告出的 resolved rate 即 P2 基线,应在每个发布前重跑,确保该数字永不静默回退。

源码级剖析:预测阶段的核心机制

1. Instance 数据模型

instance.py 中的Instancedataclass 对齐 SWE-bench schema,承载 harness 所需的全部字段:

  • instance_id/problem_statement:issue 标识与交给 Agent 的 issue 文案;
  • base_commit/repo:仓库在 buggy 时刻的快照定位(官方实例为owner/name,本地实例 repo 为空);
  • fail_to_pass/pass_to_pass:决定 resolution 的测试节点列表;
  • test_cmd:默认python -m pytest -q
  • repo_path:仅本地模式使用,指向已就绪的 buggy git 仓库。

2. Workspace 准备与 Agent 驱动

predict.py 的prepare_workspace()负责把实例检出到 scratch workspace:本地实例从repo_path离线 clone,官方实例 clonehttps://github.com/<repo>.git,随后 checkout 到base_commit——保证后续git diff恰好等于模型的改动。

Agent 调用被设计为可注入的ExecRunner(签名(workspace, prompt, model) -> bool),默认实现default_exec_runner()用当前解释器以子进程方式驱动:

python -m cli.exec_cli --workspace <ws> --json [--model <model>] <problem_statement>

选择sys.executable运行,是为了让评测环境(代理、依赖、配置)自然流入 Agent 进程。它解析子进程 stdout 中最终 NDJSON 事件的stop_reason,仅当为completed才视为本轮完成;单实例超时上限_EXEC_TIMEOUT_S = 900秒(predict.py)。你可以在 cli/exec_cli.py 中看到该 CLI 的prompt--workspace--model参数定义及task_complete事件的输出。

3. 补丁捕获与产物排除(关键细节)

Agent 在调试时会运行测试,留下__pycache__/*.pyc等字节码/缓存垃圾。若这些二进制内容混入model_patchgit apply会因二进制 hunks 拒绝整个补丁。因此capture_patch()采用git add -A+git diff --cached(一次性捕获新增/修改/删除/重命名)并显式排除:

**/__pycache__/**、**/*.pyc、**/*.pyo、**/.pytest_cache/**、**/*.egg-info/**

(见 predict.py 的_DIFF_EXCLUDES。)该设计有专门的回归测试守护:test_patch_excludes_pytest_artifacts_and_resolves用"修复 bug 后又跑过 pytest"的 fake agent 复现曾经的__pycache__污染场景,断言model_patch中不含__pycache__.pyc且补丁仍可干净应用、实例 resolved。

generate_prediction()最终产出符合 SWE-bench predictions schema 的字典(外加私有的_completed诊断标志):

{"instance_id": "...", "model_name_or_path": "...", "model_patch": "diff --git ..."}

predict 模式对单个实例失败(如 clone 失败)采取容错策略:捕获异常、写入空补丁继续下一个实例,避免一次失败拖垮整批。

CLI 参数速查

以下参数由 run.py 的argparse定义:

参数取值/默认说明
--modelocal(默认)/predict运行模式:本地冒烟 or 官方预测
--model默认空串模型 id;留空则使用配置默认
--limit默认50predict 模式实例数量
--out默认predictions.jsonlpredict 模式输出路径
--report默认空本地模式 JSON 报告写出路径

local 模式在TemporaryDirectory中运行,结束即清理;CI 门禁语义为"至少有一个实例 resolved 才返回 0"。

测试保障:无模型也能验证整条管线

test_swebench_harness.py 是该 harness 的离线测试套件(真实 git + pytest,无需模型),覆盖:

  • 纯逻辑:子集选择的确定性与数量、JSON 测试列表解析、record→Instance 字段映射;
  • 本地实例物化:三个实例均为真实 git 仓库、base_commit有效、F2P/P2P 非空;
  • 端到端:注入确定性 fake agent(按 marker 文件改写 bug)跑通 prepare → predict → evaluate,验证正确修复可 resolved、空补丁不 resolved;
  • 回归守护:捕获补丁包含编辑内容、排除 pytest 产物。

由于ExecRunner可注入,harness 自身的逻辑无需真实模型即可被完整验证——这正是"机制优先于硬编码"设计意图的体现。

接入发布流程的最佳实践

  1. 日常开发用 local 模式:每次改动 agent/工具链后先跑--mode local,用真实模型确认全链路没有断裂;
  2. 发布前跑 Verified 50:用--mode predict生成predictions.jsonl,交给官方 Docker harness 评分,记录 resolved rate 作为 P2 基线;
  3. 让数字永不静默回退:把官方评分结果与上次基线对比,或在 CI 中对 local 模式结果设置最低 resolved 阈值(该模式已内置非零退出码门禁);
  4. 记住两条边界:local 的 100% 只是冒烟基线,官方 Verified 数字才代表真实水平;datasets依赖与 Docker 仅存在于 predict/score 环节,本地迭代保持零重量依赖。

通过这条 Predict/Score 分离的 harness,DeepCode 把"Agent 能否修好真实 bug"这一抽象问题,落成了可复现、可门禁、可回归的具体数字。

【免费下载链接】DeepCode"DeepCode: Open Agentic Coding (Agent Harness & Loop Engineering & Multi-Agent Orchestration)"项目地址: https://gitcode.com/GitHub_Trending/deepc/DeepCode

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询