返回 DeepSeek-Reasonix
select_subset.py
根目录 / benchmarks / swebench / select_subset.py
1 #!/usr/bin/env python3
2 """Select the published SWE-bench Verified subset.
3
4 Deterministic by construction: no random seed, no hand-picking. Re-running this
5 against the same dataset revision reproduces subset.json byte for byte, so the
6 sample cannot be quietly tuned after seeing results.
7
8 Rules:
9 1. Repos get slots in proportion to their share of the full 500, largest
10 remainder first, so the sample keeps the benchmark's real composition
11 (django is ~46% of SWE-bench Verified and stays ~46% here).
12 2. Within a repo, instances are ordered by (difficulty, instance_id) and
13 picked at evenly spaced indices, which spreads the sample across the
14 repo's own difficulty mix instead of clustering on easy ones.
15
16 Nothing is excluded. psf/requests instances exercise a test suite that makes
17 live network calls and can exhaust the grader timeout; such a run is reported
18 as eval_timeout rather than dropped, because silently removing the instances a
19 harness handles badly is how a benchmark stops meaning anything.
20 """
21
22 import json
23 import sys
24 from datasets import load_dataset
25
26 TOTAL = 50
27 DIFFICULTY_ORDER = {"<15 min fix": 0, "15 min - 1 hour": 1, "1-4 hours": 2, ">4 hours": 3}
28
29
30 def allocate(counts, total):
31 """Largest-remainder apportionment of `total` slots across repo counts."""
32 population = sum(counts.values())
33 exact = {repo: n * total / population for repo, n in counts.items()}
34 floors = {repo: int(v) for repo, v in exact.items()}
35 remaining = total - sum(floors.values())
36 order = sorted(exact, key=lambda r: (-(exact[r] - floors[r]), r))
37 for repo in order[:remaining]:
38 floors[repo] += 1
39 return floors
40
41
42 def evenly_spaced(items, k):
43 if k <= 0:
44 return []
45 if k >= len(items):
46 return items
47 return [items[(2 * i + 1) * len(items) // (2 * k)] for i in range(k)]
48
49
50 def main():
51 ds = load_dataset("princeton-nlp/SWE-bench_Verified", split="test")
52 by_repo = {}
53 for row in ds:
54 by_repo.setdefault(row["repo"], []).append(row)
55
56 slots = allocate({repo: len(rows) for repo, rows in by_repo.items()}, TOTAL)
57
58 selected = []
59 for repo in sorted(by_repo):
60 rows = sorted(
61 by_repo[repo],
62 key=lambda r: (DIFFICULTY_ORDER.get(r["difficulty"], 9), r["instance_id"]),
63 )
64 selected.extend(evenly_spaced(rows, slots[repo]))
65
66 selected.sort(key=lambda r: r["instance_id"])
67 out = [
68 {
69 "instance_id": r["instance_id"],
70 "repo": r["repo"],
71 "base_commit": r["base_commit"],
72 "problem_statement": r["problem_statement"],
73 "difficulty": r["difficulty"],
74 }
75 for r in selected
76 ]
77 with open("benchmarks/swebench/subset.json", "w", encoding="utf-8") as f:
78 json.dump(out, f, indent=2, ensure_ascii=False)
79 f.write("\n")
80
81 print(f"selected {len(out)} of {len(ds)}", file=sys.stderr)
82 for repo in sorted(by_repo):
83 share = 100 * len(by_repo[repo]) / len(ds)
84 print(f" {slots[repo]:2d} {repo:32s} (full set {share:4.1f}%)", file=sys.stderr)
85
86
87 if __name__ == "__main__":
88 main()
89
89 lines PYTHON