跳到主要内容

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

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

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

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

如果容器里的仓库还能看到「未来」的提交和 tag,模型 agent 就可能偷看到答案。make_repo_script_list_pyswebench/harness/test_spec/python.py:264-317)在克隆后做了一串清理:

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

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

4.1.2 clean diff:用一次空提交锚定基线

安装步骤可能顺手改动仓库文件,导致后面 git diff 把环境改动也算进去。解决办法是建仓脚本结尾打一次空提交(python.py:309-315):

# 真实源码节选
git config --global user.email setup@swebench.config
git config --global user.name SWE-bench
git commit --allow-empty -am SWE-bench

这是它在干嘛:把「环境就绪」固化成一个干净的 HEAD,之后 git diff 就只反映模型补丁带来的改动,基线一致、可复现。

4.1.3 内容哈希当缓存键(见第 2 章 2.3.1)

环境脚本/docker_specs 的 sha256 当镜像 tag(test_spec.py:89-104):脚本变→key 变→自动重建,脚本不变→命中复用。正确性来自内容寻址,省时又防陈旧缓存。

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

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

4.1.5 新文件 vs 改文件,还原方式不同(一个真实 bug 的修法)

eval 脚本还原测试时,对已存在文件git checkout base_commit <file>、对新增文件rm -fpython.py:417-423,注释里点名 issue #518)。原因:若对没有文件参数地 git checkout base_commit,会把整个工作树都 reset 掉、连环境改动一起抹了。get_modified_files/get_new_filesutils.py:339-362)靠 unidiff 判断补丁里源文件是不是 /dev/null 来区分。

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。支持的语言由 constants/ 下的文件枚举:c / go / java / javascript / php / python / ruby / rustMAP_REPO_TO_EXTconstants/__init__.py:158-167)。加一门语言/一个仓库,本质是补三处映射表:

要补什么在哪
安装/测试配方 MAP_REPO_VERSION_TO_SPECSconstants/<lang>.py
日志解析器 MAP_REPO_TO_PARSERlog_parsers/<lang>.py
脚本/ Dockerfile 模板(如非 common 可复用)test_spec/<lang>.pydockerfiles/<lang>.py

脚本生成默认走 *_commontest_spec/create_scripts.py)。专门实现的分布并不均匀:建仓/装环境脚本只有 Python 有专门分支,JS 的专门实现仅限 eval 脚本make_eval_script_list_js,见 2.2),其余路径仍走 common——所以新语言常常先复用 common 路径。

4.4 边界与局限(诚实)

  • 强依赖 Docker 与算力:README 建议 x86_64、≥120GB 磁盘、≥16GB 内存;ARM/Mac 需本地构建镜像(慢)。这不是轻量评测。
  • 判分依赖日志格式:解析器是按框架/仓库手写的正则。测试框架升级、输出格式变了,解析可能失准(源码里多处 TODO,如 grading.py:49python.py:93-99 的 Django 特例)。
  • Multimodal test 不可本地评测:被刻意私有化以防刷分,只能走 sb-cli 云端提交(run_evaluation.py:496-501)。
  • 「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/harness/constants/__init__.pySWEbenchInstance, FAIL_TO_PASS, PASS_TO_PASS, TestStatus, ResolvedStatus
评测顶层入口swebench/harness/run_evaluation.pymain, get_dataset_from_preds, run_instances, run_instance, GIT_APPLY_CMDS
题→脚本编译swebench/harness/test_spec/test_spec.pyTestSpec, make_test_spec, env_image_key, instance_image_key
脚本生成(按语言分派)swebench/harness/test_spec/create_scripts.pymake_repo_script_list, make_env_script_list, make_eval_script_list
Python 脚本/防泄漏/clean diffswebench/harness/test_spec/python.pymake_repo_script_list_py, make_eval_script_list_py, get_test_directives
三层镜像构建swebench/harness/docker_build.pybuild_base_images, build_env_images, build_instance_image, build_container, build_image
Dockerfile 模板swebench/harness/dockerfiles/python.py_DOCKERFILE_BASE_PY, _DOCKERFILE_ENV_PY, _DOCKERFILE_INSTANCE_PY
容器执行/超时/缓存清理swebench/harness/docker_utils.pyexec_run_with_timeout, should_remove, clean_images
判分内核swebench/harness/grading.pyget_logs_eval, get_eval_tests_report, compute_fail_to_pass, get_resolution_status, get_eval_report
日志解析器映射swebench/harness/log_parsers/__init__.pyMAP_REPO_TO_PARSER
pytest/Django 解析器swebench/harness/log_parsers/python.pyparse_log_pytest, parse_log_django
最终汇总报告swebench/harness/reporting.pymake_run_report
工具:预测加载/线程池/patch 分析swebench/harness/utils.pyget_predictions_from_file, run_threadpool, load_swebench_dataset, get_modified_files, get_new_files
数据采集swebench/collect/build_dataset.pycreate_instance, is_valid_pull, is_valid_instance, has_test_patch
安装/测试配方表swebench/harness/constants/python.pyMAP_REPO_VERSION_TO_SPECS_PY, TEST_PYTEST, TEST_DJANGO
inference:输入/检索/跑模型swebench/inference/make_datasets/create_instance.py, bm25_retrieval.py, swebench/inference/run_api.pyPROMPT_FUNCTIONS, prompt_style_2, make_index, MODEL_LIMITS