benchkit-cli 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (149) hide show
  1. benchkit/__init__.py +1 -0
  2. benchkit/_pi_proxy.py +219 -0
  3. benchkit/answer_key_guard.ts +49 -0
  4. benchkit/artifacts.py +87 -0
  5. benchkit/benchmarks/__init__.py +105 -0
  6. benchkit/benchmarks/aider_polyglot.py +405 -0
  7. benchkit/benchmarks/arc.py +52 -0
  8. benchkit/benchmarks/banking77.py +149 -0
  9. benchkit/benchmarks/base.py +19 -0
  10. benchkit/benchmarks/boolq.py +49 -0
  11. benchkit/benchmarks/chartqa.py +133 -0
  12. benchkit/benchmarks/code_verifier.py +77 -0
  13. benchkit/benchmarks/downloads.py +166 -0
  14. benchkit/benchmarks/evalplus.py +288 -0
  15. benchkit/benchmarks/git_surgery.py +485 -0
  16. benchkit/benchmarks/gpqa.py +56 -0
  17. benchkit/benchmarks/gsm8k.py +97 -0
  18. benchkit/benchmarks/hellaswag.py +49 -0
  19. benchkit/benchmarks/humaneval.py +103 -0
  20. benchkit/benchmarks/ifeval.py +56 -0
  21. benchkit/benchmarks/ifeval_instructions.py +477 -0
  22. benchkit/benchmarks/mbpp.py +60 -0
  23. benchkit/benchmarks/mc_arena.py +479 -0
  24. benchkit/benchmarks/mcq.py +94 -0
  25. benchkit/benchmarks/medfailbench.py +537 -0
  26. benchkit/benchmarks/mmlu.py +54 -0
  27. benchkit/benchmarks/mmlu_pro.py +62 -0
  28. benchkit/benchmarks/mmvp.py +115 -0
  29. benchkit/benchmarks/ocrbench.py +96 -0
  30. benchkit/benchmarks/openbookqa.py +52 -0
  31. benchkit/benchmarks/patcheval.py +929 -0
  32. benchkit/benchmarks/piqa.py +52 -0
  33. benchkit/benchmarks/ruler.py +172 -0
  34. benchkit/benchmarks/ruler_generator.py +535 -0
  35. benchkit/benchmarks/sanity.py +174 -0
  36. benchkit/benchmarks/treejs_arena.py +268 -0
  37. benchkit/benchmarks/truthfulqa.py +52 -0
  38. benchkit/benchmarks/utils.py +25 -0
  39. benchkit/benchmarks/vision.py +230 -0
  40. benchkit/benchmarks/vstar.py +108 -0
  41. benchkit/benchmarks/winogrande.py +52 -0
  42. benchkit/benchmarks/xstest.py +116 -0
  43. benchkit/browser.py +429 -0
  44. benchkit/catalog.py +121 -0
  45. benchkit/cli.py +1000 -0
  46. benchkit/client.py +1413 -0
  47. benchkit/controls.py +87 -0
  48. benchkit/datasets/MMLU_LICENSE.txt +21 -0
  49. benchkit/datasets/README.md +142 -0
  50. benchkit/datasets/arc_challenge.jsonl +1172 -0
  51. benchkit/datasets/banking77.jsonl +3080 -0
  52. benchkit/datasets/banking77_intents.json +79 -0
  53. benchkit/datasets/boolq.jsonl +3270 -0
  54. benchkit/datasets/code_verifier.jsonl +500 -0
  55. benchkit/datasets/gpqa_diamond.jsonl +198 -0
  56. benchkit/datasets/gsm8k.jsonl +1319 -0
  57. benchkit/datasets/hellaswag.jsonl +1000 -0
  58. benchkit/datasets/humaneval.jsonl +164 -0
  59. benchkit/datasets/ifeval.jsonl +541 -0
  60. benchkit/datasets/mbpp.jsonl +500 -0
  61. benchkit/datasets/mc_blocks_1_20_1.jsonl +1003 -0
  62. benchkit/datasets/medfailbench_hard30.jsonl +30 -0
  63. benchkit/datasets/medfailbench_hard30.md +13 -0
  64. benchkit/datasets/openbookqa.jsonl +500 -0
  65. benchkit/datasets/piqa.jsonl +1838 -0
  66. benchkit/datasets/sanity_code.jsonl +6 -0
  67. benchkit/datasets/truthfulqa.jsonl +817 -0
  68. benchkit/datasets/winogrande.jsonl +1267 -0
  69. benchkit/datasets/xstest.csv +451 -0
  70. benchkit/decision.py +194 -0
  71. benchkit/demo.py +451 -0
  72. benchkit/dockerfiles.py +247 -0
  73. benchkit/engine.py +1270 -0
  74. benchkit/evaluation.py +195 -0
  75. benchkit/events.py +141 -0
  76. benchkit/executor.py +96 -0
  77. benchkit/git_surgery/backport-release-stack/setup.sh +328 -0
  78. benchkit/git_surgery/backport-release-stack/verify.sh +119 -0
  79. benchkit/git_surgery/bisect-the-regression/setup.sh +49 -0
  80. benchkit/git_surgery/bisect-the-regression/verify.sh +34 -0
  81. benchkit/git_surgery/rebase-conflict-chain/setup.sh +65 -0
  82. benchkit/git_surgery/rebase-conflict-chain/verify.sh +43 -0
  83. benchkit/git_surgery/recover-complex-stash/setup.sh +152 -0
  84. benchkit/git_surgery/recover-complex-stash/verify.sh +95 -0
  85. benchkit/git_surgery/recover-lost-work/setup.sh +40 -0
  86. benchkit/git_surgery/recover-lost-work/verify.sh +36 -0
  87. benchkit/git_surgery/repair-force-pushed-remote/setup.sh +171 -0
  88. benchkit/git_surgery/repair-force-pushed-remote/verify.sh +83 -0
  89. benchkit/git_surgery/revert-merge-with-followups/setup.sh +198 -0
  90. benchkit/git_surgery/revert-merge-with-followups/verify.sh +98 -0
  91. benchkit/git_surgery/secret-in-history/README.md +27 -0
  92. benchkit/git_surgery/secret-in-history/setup.sh +107 -0
  93. benchkit/git_surgery/secret-in-history/verify.sh +106 -0
  94. benchkit/git_surgery/split-the-mega-commit/setup.sh +50 -0
  95. benchkit/git_surgery/split-the-mega-commit/verify.sh +48 -0
  96. benchkit/git_surgery/untangle-nested-submodules/setup.sh +193 -0
  97. benchkit/git_surgery/untangle-nested-submodules/verify.sh +90 -0
  98. benchkit/history.py +474 -0
  99. benchkit/jobs.py +332 -0
  100. benchkit/leakage.py +51 -0
  101. benchkit/looping.py +873 -0
  102. benchkit/mc_render.py +274 -0
  103. benchkit/mc_viewer/dist/atlas.png +0 -0
  104. benchkit/mc_viewer/dist/blockStates.json.gz +0 -0
  105. benchkit/mc_viewer/dist/version.json +4 -0
  106. benchkit/mc_viewer/dist/viewer.html +23 -0
  107. benchkit/mc_viewer/dist/viewer.js +2 -0
  108. benchkit/mc_viewer/dist/viewer.js.LICENSE.txt +25 -0
  109. benchkit/mc_viewer/dist/worker.js +2 -0
  110. benchkit/mc_viewer/dist/worker.js.LICENSE.txt +19 -0
  111. benchkit/metrics.py +100 -0
  112. benchkit/ollama.py +60 -0
  113. benchkit/perf.py +353 -0
  114. benchkit/perf_report.py +207 -0
  115. benchkit/perturbations.py +208 -0
  116. benchkit/pi_agent.py +476 -0
  117. benchkit/pi_package/package-lock.json +1827 -0
  118. benchkit/pi_package/package.json +8 -0
  119. benchkit/report.py +142 -0
  120. benchkit/report_markdown.py +645 -0
  121. benchkit/results.py +688 -0
  122. benchkit/retry.py +163 -0
  123. benchkit/runner.py +769 -0
  124. benchkit/sandbox.py +1167 -0
  125. benchkit/template_check.py +291 -0
  126. benchkit/templates/arena.html +504 -0
  127. benchkit/templates/history.html +58 -0
  128. benchkit/templates/perf.html +509 -0
  129. benchkit/templates/report.html +769 -0
  130. benchkit/tui/__init__.py +5 -0
  131. benchkit/tui/app.py +87 -0
  132. benchkit/tui/app.tcss +512 -0
  133. benchkit/tui/formatting.py +84 -0
  134. benchkit/tui/screens/__init__.py +1 -0
  135. benchkit/tui/screens/connect.py +191 -0
  136. benchkit/tui/screens/detail.py +288 -0
  137. benchkit/tui/screens/help.py +84 -0
  138. benchkit/tui/screens/modals.py +544 -0
  139. benchkit/tui/screens/results.py +361 -0
  140. benchkit/tui/screens/run.py +988 -0
  141. benchkit/tui/screens/setup.py +733 -0
  142. benchkit/tui/theme.py +135 -0
  143. benchkit/tui/widgets.py +120 -0
  144. benchkit_cli-0.1.0.dist-info/METADATA +294 -0
  145. benchkit_cli-0.1.0.dist-info/RECORD +149 -0
  146. benchkit_cli-0.1.0.dist-info/WHEEL +5 -0
  147. benchkit_cli-0.1.0.dist-info/entry_points.txt +3 -0
  148. benchkit_cli-0.1.0.dist-info/licenses/LICENSE +201 -0
  149. benchkit_cli-0.1.0.dist-info/top_level.txt +1 -0
benchkit/__init__.py ADDED
@@ -0,0 +1 @@
1
+ """Benchmark local LLMs with real eval suites."""
benchkit/_pi_proxy.py ADDED
@@ -0,0 +1,219 @@
1
+ """Restricted inference proxy used by the Pi task sandbox.
2
+
3
+ The Pi container lives on an internal Docker network with no direct egress.
4
+ This small process runs in a separate container attached to both that network
5
+ and Docker's bridge network, forwards only OpenAI-compatible inference routes,
6
+ and keeps the upstream API key out of the agent's filesystem and environment.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import hashlib
12
+ import http.client
13
+ import json
14
+ import os
15
+ from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
16
+ from urllib.parse import urlsplit
17
+
18
+ ALLOWED_PATHS = ("/v1/chat/completions", "/v1/models")
19
+ MAX_BODY_BYTES = 32 * 1024 * 1024
20
+ SCAFFOLD_PATH = "/tmp/benchkit_pi_scaffold.json"
21
+ HOP_BY_HOP = {
22
+ "connection",
23
+ "keep-alive",
24
+ "proxy-authenticate",
25
+ "proxy-authorization",
26
+ "te",
27
+ "trailers",
28
+ "transfer-encoding",
29
+ "upgrade",
30
+ }
31
+
32
+
33
+ def _message_text(content: object) -> str:
34
+ if isinstance(content, str):
35
+ return content
36
+ if not isinstance(content, list):
37
+ return ""
38
+ return "".join(
39
+ str(part.get("text") or "")
40
+ for part in content
41
+ if isinstance(part, dict) and part.get("type") in {"text", "input_text"}
42
+ )
43
+
44
+
45
+ def _capture_scaffold(request_data: dict) -> None:
46
+ """Persist the exact scaffold sent by Pi on the first model request."""
47
+ if os.path.exists(SCAFFOLD_PATH):
48
+ return
49
+ messages = request_data.get("messages") or []
50
+ system_prompt = "\n\n".join(
51
+ _message_text(message.get("content"))
52
+ for message in messages
53
+ if isinstance(message, dict) and message.get("role") in {"system", "developer"}
54
+ )
55
+ tools = request_data.get("tools") or []
56
+ tool_names = [
57
+ str(tool.get("function", {}).get("name") or "")
58
+ for tool in tools
59
+ if isinstance(tool, dict) and isinstance(tool.get("function"), dict)
60
+ ]
61
+ tool_names = [name for name in tool_names if name]
62
+ tool_schema = json.dumps(tools, ensure_ascii=False, sort_keys=True)
63
+ payload = {
64
+ "system_prompt": system_prompt,
65
+ "system_prompt_sha256": hashlib.sha256(system_prompt.encode()).hexdigest(),
66
+ "system_prompt_chars": len(system_prompt),
67
+ "tools_available": tool_names,
68
+ "tool_schema_sha256": hashlib.sha256(tool_schema.encode()).hexdigest(),
69
+ }
70
+ for field in ("max_completion_tokens", "max_tokens"):
71
+ value = request_data.get(field)
72
+ if isinstance(value, int) and value > 0:
73
+ payload["max_output_tokens"] = value
74
+ payload["max_output_tokens_field"] = field
75
+ break
76
+ try:
77
+ with open(SCAFFOLD_PATH, "x", encoding="utf-8") as handle:
78
+ json.dump(payload, handle, ensure_ascii=False)
79
+ except FileExistsError:
80
+ pass
81
+
82
+
83
+ def _upstream_target(path: str) -> tuple[str, str, int, str]:
84
+ base = os.environ["BENCHKIT_UPSTREAM"].rstrip("/")
85
+ parsed = urlsplit(base)
86
+ request = urlsplit(path)
87
+ suffix = request.path[3:] if request.path.startswith("/v1") else request.path
88
+ prefix = parsed.path.rstrip("/")
89
+ target = f"{prefix}{suffix}" or "/"
90
+ query = "&".join(part for part in (parsed.query, request.query) if part)
91
+ if query:
92
+ target += f"?{query}"
93
+ port = parsed.port or (443 if parsed.scheme == "https" else 80)
94
+ return parsed.scheme, parsed.hostname or "", port, target
95
+
96
+
97
+ def _models_payload() -> bytes:
98
+ model = os.environ["BENCHKIT_MODEL"]
99
+ return json.dumps(
100
+ {"object": "list", "data": [{"id": model, "object": "model"}]}
101
+ ).encode()
102
+
103
+
104
+ def _upstream_timeout() -> float:
105
+ try:
106
+ return max(0.1, float(os.environ.get("BENCHKIT_UPSTREAM_TIMEOUT", "600")))
107
+ except ValueError:
108
+ return 600.0
109
+
110
+
111
+ class ProxyHandler(BaseHTTPRequestHandler):
112
+ """Stream a deliberately tiny subset of an OpenAI-compatible API."""
113
+
114
+ protocol_version = "HTTP/1.1"
115
+
116
+ def do_GET(self) -> None:
117
+ if self.path == "/health":
118
+ self._plain(200, b"ok")
119
+ return
120
+ self._forward()
121
+
122
+ def do_POST(self) -> None:
123
+ self._forward()
124
+
125
+ def _forward(self) -> None:
126
+ route = self.path.split("?", 1)[0]
127
+ if route not in ALLOWED_PATHS:
128
+ self._plain(404, b"route unavailable")
129
+ return
130
+ if route == "/v1/models":
131
+ if self.command != "GET":
132
+ self._plain(405, b"method unavailable")
133
+ return
134
+ self._json(200, _models_payload())
135
+ return
136
+ if self.command != "POST":
137
+ self._plain(405, b"method unavailable")
138
+ return
139
+
140
+ length = int(self.headers.get("content-length", "0") or 0)
141
+ if length > MAX_BODY_BYTES:
142
+ self._plain(413, b"request too large")
143
+ return
144
+ body = self.rfile.read(length) if length else None
145
+ try:
146
+ request_data = json.loads(body or b"{}")
147
+ except (json.JSONDecodeError, UnicodeDecodeError):
148
+ self._plain(400, b"invalid JSON")
149
+ return
150
+ _capture_scaffold(request_data)
151
+ if request_data.get("model") != os.environ["BENCHKIT_MODEL"]:
152
+ self._plain(403, b"model unavailable")
153
+ return
154
+
155
+ scheme, host, port, target = _upstream_target(self.path)
156
+ connection_type = (
157
+ http.client.HTTPSConnection
158
+ if scheme == "https"
159
+ else http.client.HTTPConnection
160
+ )
161
+ connection = connection_type(host, port, timeout=_upstream_timeout())
162
+ headers = {
163
+ key: value
164
+ for key, value in self.headers.items()
165
+ if key.lower() not in HOP_BY_HOP | {"host", "authorization"}
166
+ }
167
+ if api_key := os.environ.get("BENCHKIT_UPSTREAM_API_KEY"):
168
+ headers["Authorization"] = f"Bearer {api_key}"
169
+
170
+ response_started = False
171
+ try:
172
+ connection.request(self.command, target, body=body, headers=headers)
173
+ response = connection.getresponse()
174
+ self.send_response(response.status, response.reason)
175
+ for key, value in response.getheaders():
176
+ if key.lower() not in HOP_BY_HOP | {"content-length"}:
177
+ self.send_header(key, value)
178
+ self.send_header("Connection", "close")
179
+ self.end_headers()
180
+ response_started = True
181
+ while chunk := response.read(64 * 1024):
182
+ self.wfile.write(chunk)
183
+ self.wfile.flush()
184
+ except (OSError, http.client.HTTPException) as exc:
185
+ if not response_started and not self.wfile.closed:
186
+ self._plain(502, f"upstream error: {exc}".encode())
187
+ finally:
188
+ connection.close()
189
+ self.close_connection = True
190
+
191
+ def _plain(self, status: int, body: bytes) -> None:
192
+ self.send_response(status)
193
+ self.send_header("Content-Type", "text/plain; charset=utf-8")
194
+ self.send_header("Content-Length", str(len(body)))
195
+ self.send_header("Connection", "close")
196
+ self.end_headers()
197
+ self.wfile.write(body)
198
+ self.close_connection = True
199
+
200
+ def _json(self, status: int, body: bytes) -> None:
201
+ self.send_response(status)
202
+ self.send_header("Content-Type", "application/json")
203
+ self.send_header("Content-Length", str(len(body)))
204
+ self.send_header("Connection", "close")
205
+ self.end_headers()
206
+ self.wfile.write(body)
207
+ self.close_connection = True
208
+
209
+ def log_message(self, _format: str, *_args: object) -> None:
210
+ return
211
+
212
+
213
+ def main() -> None:
214
+ server = ThreadingHTTPServer(("0.0.0.0", 8080), ProxyHandler)
215
+ server.serve_forever()
216
+
217
+
218
+ if __name__ == "__main__":
219
+ main()
@@ -0,0 +1,49 @@
1
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
+ import { appendFileSync, realpathSync } from "node:fs";
3
+ import { isAbsolute, normalize, resolve } from "node:path";
4
+
5
+ const AUDIT_LOG = "/tmp/benchkit-answer-key-guard.jsonl";
6
+ const ANSWER_COMPONENT = /(^|[\\/])\.(meta|approaches)([\\/]|$)/i;
7
+ const ANSWER_NAME = /(^|[\\/])[^\\/]*(example|reference|proof)[^\\/]*([\\/]|$)/i;
8
+
9
+ function forbidden(value: unknown, cwd: string): boolean {
10
+ if (typeof value !== "string" || !value.trim()) return false;
11
+ const candidate = value.trim();
12
+ const normalized = normalize(isAbsolute(candidate) ? candidate : resolve(cwd, candidate));
13
+ let resolved = normalized;
14
+ try { resolved = realpathSync(normalized); } catch { /* missing/glob path */ }
15
+ return ANSWER_COMPONENT.test(candidate) || ANSWER_NAME.test(candidate)
16
+ || ANSWER_COMPONENT.test(normalized) || ANSWER_NAME.test(normalized)
17
+ || ANSWER_COMPONENT.test(resolved) || ANSWER_NAME.test(resolved);
18
+ }
19
+
20
+ function inspectedValues(toolName: string, input: Record<string, unknown>): string[] {
21
+ if (toolName === "bash") return [String(input.command ?? "")];
22
+ if (["read", "grep", "find", "ls"].includes(toolName)) {
23
+ return ["path", "pattern", "glob", "query"]
24
+ .map((key) => input[key])
25
+ .filter((value): value is string => typeof value === "string");
26
+ }
27
+ return [];
28
+ }
29
+
30
+ export default function answerKeyGuard(pi: ExtensionAPI) {
31
+ pi.on("tool_call", async (event, ctx) => {
32
+ const input = event.input as Record<string, unknown>;
33
+ const matches = inspectedValues(event.toolName, input).filter((value) =>
34
+ forbidden(value, ctx.cwd),
35
+ );
36
+ if (!matches.length) return undefined;
37
+
38
+ appendFileSync(AUDIT_LOG, JSON.stringify({
39
+ tool: event.toolName,
40
+ arguments: input,
41
+ matches,
42
+ cwd: ctx.cwd,
43
+ }) + "\n", { encoding: "utf8", mode: 0o600 });
44
+ return {
45
+ block: true,
46
+ reason: "BenchKit denied access to an answer-key path",
47
+ };
48
+ });
49
+ }
benchkit/artifacts.py ADDED
@@ -0,0 +1,87 @@
1
+ """Run-scoped staging for per-task binary artifacts.
2
+
3
+ Benchmarks produce screenshots and generated pages while a run is still in
4
+ flight, but the results directory only exists once :func:`benchkit.report.save`
5
+ stamps it. Artifacts are therefore written to a staging directory keyed by the
6
+ process, and collected into the results directory at save time with the paths
7
+ in each task record rewritten to be relative to the report.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import contextlib
13
+ import re
14
+ import shutil
15
+ import uuid
16
+ from pathlib import Path
17
+
18
+ STAGING_ROOT = Path("results") / ".artifacts"
19
+ _RUN_ID = uuid.uuid4().hex[:12]
20
+ _COUNTER = 0
21
+
22
+ # Artifact keys in a task's ``workspace`` payload, and where they are collected.
23
+ COLLECTED = (
24
+ ("screenshot", "screenshots", ".png"),
25
+ ("screenshot_thumbnail", "screenshots", ".jpg"),
26
+ # mc-arena photographs one build from three fixed cameras; the plain
27
+ # ``screenshot`` above is the three of them side by side.
28
+ ("screenshot_iso", "screenshots", "-iso.png"),
29
+ ("screenshot_side", "screenshots", "-side.png"),
30
+ ("screenshot_top", "screenshots", "-top.png"),
31
+ ("page_html", "pages", ".html"),
32
+ ("response_text", "pages", ".txt"),
33
+ ("script_py", "builds", ".py"),
34
+ ("blocks_json", "builds", ".json"),
35
+ )
36
+
37
+
38
+ def staging_root() -> Path:
39
+ return STAGING_ROOT / _RUN_ID
40
+
41
+
42
+ def task_dir(prefix: str) -> Path:
43
+ """Create a fresh directory for one evaluation's artifacts."""
44
+ global _COUNTER
45
+ _COUNTER += 1
46
+ directory = staging_root() / f"{_slug(prefix)}-{_COUNTER:04d}"
47
+ directory.mkdir(parents=True, exist_ok=True)
48
+ # Absolute, so a path recorded mid-run still resolves at report time.
49
+ return directory.resolve()
50
+
51
+
52
+ def _slug(value: str) -> str:
53
+ text = re.sub(r"[^A-Za-z0-9._-]+", "-", str(value)).strip("-")
54
+ return text[:80] or "artifact"
55
+
56
+
57
+ def collect(out: Path, results: list[dict]) -> None:
58
+ """Move staged artifacts into the report and relativize their paths."""
59
+ root = staging_root().resolve()
60
+ for result in results:
61
+ model = _slug(str(result.get("model") or "model"))
62
+ for task in result.get("tasks") or []:
63
+ workspace = task.get("workspace")
64
+ if not isinstance(workspace, dict):
65
+ continue
66
+ for key, subdir, suffix in COLLECTED:
67
+ source = workspace.get(key)
68
+ if not isinstance(source, str) or not source:
69
+ continue
70
+ path = Path(source)
71
+ if not path.is_absolute() or not path.is_file():
72
+ workspace.pop(key, None)
73
+ continue
74
+ if root not in path.resolve().parents:
75
+ continue
76
+ name = f"{model}__{_slug(str(task.get('task_id') or 'task'))}{suffix}"
77
+ target = out / subdir / name
78
+ target.parent.mkdir(parents=True, exist_ok=True)
79
+ shutil.copyfile(path, target)
80
+ workspace[key] = f"{subdir}/{name}"
81
+
82
+
83
+ def cleanup() -> None:
84
+ """Remove this process's staging directory, and the root when it empties."""
85
+ shutil.rmtree(staging_root(), ignore_errors=True)
86
+ with contextlib.suppress(OSError):
87
+ STAGING_ROOT.rmdir()
@@ -0,0 +1,105 @@
1
+ """Available benchmarks."""
2
+
3
+ from benchkit.benchmarks.aider_polyglot import AiderPolyglot
4
+ from benchkit.benchmarks.arc import ARC
5
+ from benchkit.benchmarks.banking77 import Banking77
6
+ from benchkit.benchmarks.boolq import BoolQ
7
+ from benchkit.benchmarks.chartqa import ChartQA
8
+ from benchkit.benchmarks.code_verifier import CodeVerifier
9
+ from benchkit.benchmarks.evalplus import HumanEvalPlus, MBPPPlus
10
+ from benchkit.benchmarks.git_surgery import GitSurgery
11
+ from benchkit.benchmarks.gpqa import GPQA
12
+ from benchkit.benchmarks.gsm8k import GSM8K
13
+ from benchkit.benchmarks.hellaswag import HellaSwag
14
+ from benchkit.benchmarks.humaneval import HumanEval
15
+ from benchkit.benchmarks.ifeval import IFEval
16
+ from benchkit.benchmarks.mbpp import MBPP
17
+ from benchkit.benchmarks.mc_arena import MCArena
18
+ from benchkit.benchmarks.medfailbench import MedFailBench
19
+ from benchkit.benchmarks.mmlu import MMLU
20
+ from benchkit.benchmarks.mmlu_pro import MMLUPro
21
+ from benchkit.benchmarks.mmvp import MMVP
22
+ from benchkit.benchmarks.ocrbench import OCRBench
23
+ from benchkit.benchmarks.openbookqa import OpenBookQA
24
+ from benchkit.benchmarks.patcheval import PatchEval
25
+ from benchkit.benchmarks.piqa import PIQA
26
+ from benchkit.benchmarks.ruler import RULER, RULERFull
27
+ from benchkit.benchmarks.sanity import Sanity
28
+ from benchkit.benchmarks.treejs_arena import TreeJSArena
29
+ from benchkit.benchmarks.truthfulqa import TruthfulQA
30
+ from benchkit.benchmarks.vstar import VStar
31
+ from benchkit.benchmarks.winogrande import WinoGrande
32
+ from benchkit.benchmarks.xstest import XSTest
33
+
34
+ REGISTRY: dict[str, type] = {
35
+ # Generative suites first, then the multiple-choice ones.
36
+ "aider-polyglot": AiderPolyglot,
37
+ "git-surgery": GitSurgery,
38
+ "patcheval": PatchEval,
39
+ "sanity": Sanity,
40
+ "mc-arena": MCArena,
41
+ "treejs-arena": TreeJSArena,
42
+ "humaneval": HumanEval,
43
+ "humaneval-plus": HumanEvalPlus,
44
+ "mbpp": MBPP,
45
+ "mbpp-plus": MBPPPlus,
46
+ "gsm8k": GSM8K,
47
+ "ifeval": IFEval,
48
+ "ruler": RULER,
49
+ "ruler-full": RULERFull,
50
+ "xstest": XSTest,
51
+ "medfailbench": MedFailBench,
52
+ "gpqa": GPQA,
53
+ "mmlu-pro": MMLUPro,
54
+ "banking77": Banking77,
55
+ "code-verifier": CodeVerifier,
56
+ # Vision suites send images and run on the direct harness only.
57
+ "ocrbench": OCRBench,
58
+ "chartqa": ChartQA,
59
+ "mmvp": MMVP,
60
+ "vstar": VStar,
61
+ # Multiple-choice suites.
62
+ "mmlu": MMLU,
63
+ "arc": ARC,
64
+ "openbookqa": OpenBookQA,
65
+ "winogrande": WinoGrande,
66
+ "piqa": PIQA,
67
+ "boolq": BoolQ,
68
+ "truthfulqa": TruthfulQA,
69
+ "hellaswag": HellaSwag,
70
+ }
71
+
72
+ DESCRIPTIONS: dict[str, str] = {
73
+ "aider-polyglot": "repository editing across six languages with the Pi agent",
74
+ "git-surgery": "stateful Git operations in isolated repositories with Pi",
75
+ "patcheval": "real Python bug fixes with externally isolated hidden tests",
76
+ "mc-arena": "frozen Minecraft build prompts, scored on the block list a generated script prints",
77
+ "treejs-arena": "frozen creative three.js scenes, scored only on whether they render",
78
+ "sanity": "25 curated checks across code, math, instructions, science, and commonsense",
79
+ "humaneval": "Python function completions with the original unit tests",
80
+ "humaneval-plus": "HumanEval with 122k+ tougher EvalPlus test inputs",
81
+ "mbpp": "short Python functions from natural-language specifications",
82
+ "mbpp-plus": "sanitized MBPP tasks with 39k+ EvalPlus test inputs",
83
+ "gsm8k": "multi-step grade-school math problems with exact numeric answers",
84
+ "ifeval": "prompts with code-checkable instruction-following constraints",
85
+ "ruler": "practical long-context retrieval across all 13 RULER task families",
86
+ "ruler-full": "research-scale RULER with 500 samples per task and context",
87
+ "xstest": "safe compliance and unsafe refusal using an offline string matcher",
88
+ "medfailbench": "clinical safety screening with deterministic offline rules",
89
+ "arc": "challenging grade-school science questions with four choices",
90
+ "gpqa": "expert-written graduate science questions designed to resist search",
91
+ "mmlu-pro": "harder MMLU successor: ten options and reasoning-heavy questions",
92
+ "banking77": "route a banking customer message to one of 77 intents",
93
+ "code-verifier": "judge whether a model-written HumanEval+ solution passes its tests",
94
+ "ocrbench": "text recognition and text-centric VQA across ten image categories",
95
+ "chartqa": "questions about real charts, scored with 5% relaxed numeric accuracy",
96
+ "mmvp": "pairs of look-alike images that differ in one detail, two options",
97
+ "vstar": "small details in high-resolution images, two or four options",
98
+ "mmlu": "zero-shot coverage of 57 academic and professional subjects",
99
+ "openbookqa": "elementary science questions requiring facts plus reasoning",
100
+ "winogrande": "commonsense pronoun resolution in ambiguous sentences",
101
+ "piqa": "choose the most physically plausible solution to everyday tasks",
102
+ "boolq": "answer yes/no questions using evidence from a passage",
103
+ "truthfulqa": "avoid common misconceptions and select the truthful answer",
104
+ "hellaswag": "choose the most plausible continuation of a real-world scenario",
105
+ }