跳到主要内容

数据截至 (上游 commit 7a21e0577295)

第 4 章 · 巧妙之处、边界与代码地图

前三章讲了主线。本章收拢「值得带走的精华」、诚实的局限,以及给人/agent 用的跳转表。

4.1 巧妙之处(可借鉴的技术)

4.1.1 防数据泄漏:把 base_commit 之后的历史从仓库里剪掉

如果容器里的仓库还能看到「未来」的提交和 tag,模型 agent 就可能偷看到答案。这套清理由 git_clone_timesafeswebench/image_builder/docker_utils.py:58-78)在镜像构建期完成(重构后它从评测时挪到了建镜像时):

  • git remote remove origin——断开远程,模型拿不到新提交(:69)。
  • base_commit 的时间戳,删掉所有指向更晚提交的 tag:71)。
  • git reflog expire + git gc --prune=now --aggressive 抹掉悬空对象(:72-73)。
  • 校验:统计 base 时间戳之后的提交数,若不为 0 直接 exit 1:74-76)。

妙在哪:把「不许偷看未来」做成了构建期硬校验,而不是口头约定。

4.1.2 clean diff:跑测试前先把工作树扫干净

安装/执行步骤可能顺手改动仓库文件,导致后面 git diff 把环境改动也算进去。新版的做法简单粗暴:跑 eval.sh 之前先 git checkout -- . ; git clean -fdrun_evaluation.py:306)——把容器里的工作树强制扫回基线,之后跑出来的 diff 就只反映模型补丁带来的改动。

4.1.3 镜像复用:从「内容哈希缓存键」到「预建镜像注册表」(见第 2 章 2.3)

旧版靠「环境脚本内容的 sha256 当镜像 tag」做本机复用。2026 年中重构后,镜像按题扁平命名(sweb.eval.<arch>.<instance_id>,见 image_builder/image_spec.py:37-44),默认直接从 DockerHub 拉官方预建镜像——复用从「本机跨次跑」升级成「全网共享预建镜像」,内容寻址的复杂度随之退役。

4.1.4 多级 patch fallback(见第 2 章 2.4)

GIT_APPLY_CMDSrun_evaluation.py:54-58)从严到宽三连:git applygit apply --rejectpatch --fuzz=5。容忍模型补丁的轻微行号偏移,同时保留「全失败即判失败」的底线。

4.1.5 测试还原逻辑搬到了数据侧

旧版 eval 脚本由 harness 现场生成,还原测试时对已存在文件git checkout base_commit <file>、对新增文件rm -f(修过 issue #518:无文件参数的 checkout 会把整个工作树 reset 掉)。2026 年中重构后 eval 脚本由数据集自带eval_script 字段),这套区分逻辑内嵌在数据侧生成的脚本里,harness 不再现场拼装。

4.2 inference 子系统:模型怎么拿到题、怎么交补丁

虽然评测不强制用本仓库跑模型,但 inference/ 提供了完整链路:

  • 构造输入PROMPT_FUNCTIONSswebench/inference/make_datasets/create_instance.py:296)把 issue + 仓库代码 + 「请输出一个能 git apply 的补丁」拼成 prompt(如 prompt_style_2:165-190)。
  • 检索:仓库往往太大塞不进上下文,bm25_retrieval.py 用 Pyserini/Lucene 建索引(make_index:196),按 BM25 召回最相关的文件再喂给模型。
  • 跑模型run_api.py 走 OpenAI/Anthropic API(MODEL_LIMITS 里登记各模型上下文上限,:32-45),run_llama.py 跑本地权重;都把模型回复里的补丁抽出来(extract_diff)写成 predictions。

4.3 多语言扩展点

SWE-bench 已不止 Python。支持的语言各有专属日志解析器:c / go / java / javascript / php / python / ruby / rustharness/log_parsers/<lang>.py)。2026 年中重构后,「安装/测试配方表」与「脚本/Dockerfile 模板」两层随现场脚本生成体系一起退役——加一门语言,现在的主战场是给它的数据集构建出镜像与 eval 脚本(数据侧),再给 harness 补一个日志解析器

要补什么在哪
日志解析器 MAP_REPO_TO_PARSER_<LANG>harness/log_parsers/<lang>.py
该语言数据集的镜像与 eval 脚本数据侧(collect/task/

4.4 边界与局限(诚实)

  • 强依赖 Docker 与算力:README 建议 x86_64、≥120GB 磁盘、≥16GB 内存;ARM/Mac 需本地构建镜像(慢)。这不是轻量评测。
  • 判分依赖日志格式:解析器是按框架/仓库手写的正则。测试框架升级、输出格式变了,解析可能失准(源码里多处特例注释,如 log_parsers/python.py:111:144 的 Django 特例)。
  • Multimodal test 不可本地评测:被刻意私有化以防刷分,只能走 sb-cli 云端提交(run_evaluation.py:719)。
  • 「resolved」不等于「写法和人一样好」:只要 F2P/P2P 满足即算解决,不评估补丁的可读性/最优性——它测的是「修对了吗」,不是「修得漂亮吗」。
  • 数据可能随时间偏差:题来自历史 PR,新模型的训练数据可能已包含这些仓库的后续提交,存在潜在记忆/泄漏风险(这也是 4.1.1 那套构建期防护存在的原因,但只能防容器内偷看,防不了训练集污染)。

4.5 横向对比(同 shelf 视角)

SWE-bench 属于 evals-observability + coding-agents 交叉地带,与「跑模型的 agent」是上下游关系:

  • vs 编码 agent(如 SWE-agent):agent 负责「生成补丁」,SWE-bench 负责「给补丁判分」。SWE-agent 正是为刷 SWE-bench 而生的兄弟项目(README News)。本仓库 inference/ 是一个最简 baseline 式的「生成器」。
  • 判分哲学:相比「LLM 当裁判」或「文本相似度」的评测,SWE-bench 走的是**可执行裁判(真测试)**路线——客观、抗刷分,代价是工程复杂、跑得慢。

4.6 代码地图(导航索引)

主题文件路径关键符号
题目数据结构swebench/types.pySWEbenchInstance, TestSpec
评测常量swebench/harness/constants/__init__.pyFAIL_TO_PASS, TestStatus, ResolvedStatus, START_TEST_OUTPUT, FAIL_ONLY_REPOS
评测顶层入口swebench/harness/run_evaluation.pymain, get_dataset_from_preds, run_instance, GIT_APPLY_CMDS
读 TestSpecswebench/harness/utils.pymake_test_spec, parse_eval_script, get_predictions_from_file
镜像规格/命名swebench/image_builder/image_spec.pyImageSpec, name, is_remote_image
本地镜像构建swebench/image_builder/docker_build.pybuild_instance_images, build_instance_image, build_image
判分内核swebench/harness/grading.pyget_logs_eval, get_eval_tests_report, compute_fail_to_pass, get_resolution_status, get_eval_report
日志解析器(按语言)swebench/harness/log_parsers/<lang>.pyparse_log_pytest, parse_log_django, MAP_REPO_TO_PARSER_*
最终汇总报告swebench/harness/reporting.pymake_run_report
任务包格式swebench/task/repo.pyeval_scripteval.sh 映射
数据采集swebench/collect/build_dataset.pycreate_instance, is_valid_pull, is_valid_instance, has_test_patch
inference:输入/检索/跑模型swebench/inference/make_datasets/create_instance.py, bm25_retrieval.py, swebench/inference/run_api.pyPROMPT_FUNCTIONS, prompt_style_2, make_index, MODEL_LIMITS