Files changed (3) hide show
  1. README.md +44 -26
  2. index.html +204 -195
  3. script.py +41 -17
README.md CHANGED
@@ -1,26 +1,44 @@
1
- ---
2
- title: Leaderboard
3
- emoji: 🏆
4
- colorFrom: green
5
- colorTo: blue
6
- sdk: static
7
- pinned: false
8
- license: apache-2.0
9
- ---
10
-
11
- Model performance across Bench Labs' benchmark suite — Effortless, Easy, Mid, and AGI.
12
- Reads from `models.json`, no backend required.
13
-
14
- ## Evaluate a model
15
-
16
- One script, every benchmark, per-category/subcategory results:
17
-
18
- ```bash
19
- curl -sLO https://huggingface.co/spaces/bench-labs/BenchLabs-Leaderboard/resolve/main/script.py
20
- pip install torch transformers
21
- python script.py --model your/model
22
- ```
23
-
24
- Writes `results.json` (full breakdown), per-sample CSVs, and `leaderboard.json` — a ready-to-paste entry for `models.json`. Run `python script.py --help` for all options.
25
-
26
- all rights reserved @bench-labs
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: Leaderboard
3
+ emoji: 🏆
4
+ colorFrom: green
5
+ colorTo: blue
6
+ sdk: static
7
+ pinned: false
8
+ license: apache-2.0
9
+ ---
10
+
11
+ Model performance across Bench Labs' benchmark suite — Effortless, Easy, Mid, and AGI.
12
+ Reads from `models.json`, no backend required.
13
+
14
+ ## Evaluate a model
15
+
16
+ One script, every benchmark, per-category/subcategory results:
17
+
18
+ ```bash
19
+ curl -sLO https://huggingface.co/spaces/bench-labs/BenchLabs-Leaderboard/resolve/main/script.py
20
+ pip install torch transformers
21
+ python script.py --model your/model
22
+ ```
23
+
24
+ Writes `results.json` (full breakdown), per-sample CSVs, and `leaderboard.json` — a ready-to-paste entry for `models.json`. Run `python script.py --help` for all options.
25
+
26
+ ### Reasoning / CoT models
27
+
28
+ Models that think in `<think>…</think>` blocks are supported: the script strips the
29
+ reasoning block and scores only the text after the final `</think>`. Two things to know:
30
+
31
+ - Raise the generation budget — `--max-new-tokens 2048` or more. The default 32 is sized
32
+ for direct-answer models; a thinking model burns it inside the block, and a generation
33
+ cut off mid-think (unclosed `<think>`) scores as an empty answer.
34
+ - `bench-mid-6-2026` is scored by log-likelihood over the answer choices with no
35
+ generation, so thinking never runs there.
36
+
37
+ ### Provenance
38
+
39
+ `leaderboard.json` pins the run to exact bytes: `model_revision` is the Hub commit of the
40
+ weights the script actually loaded (recorded by `from_pretrained`, not re-resolved after
41
+ the fact), and `script_sha256` is the hash of the script file that produced the numbers.
42
+ Local checkpoints have no Hub revision and honestly report `null`.
43
+
44
+ all rights reserved @bench-labs
index.html CHANGED
@@ -1,195 +1,204 @@
1
- <!doctype html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="utf-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1">
6
- <title>Bench Labs Leaderboard</title>
7
- <meta name="description" content="Model performance across Bench Labs' benchmark suite: Effortless, Easy, and Mid.">
8
- <link rel="stylesheet" href="style.css">
9
- </head>
10
- <body>
11
- <script src="background.js" defer></script>
12
-
13
- <div class="background"></div>
14
-
15
- <main class="container">
16
-
17
- <header class="hero">
18
- <div class="eyebrow">
19
- <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M8 21h8M12 17v4M17 3H7a2 2 0 0 0-2 2v6a7 7 0 0 0 14 0V5a2 2 0 0 0-2-2Z"/></svg>
20
- <a href="https://huggingface.co/bench-labs" target="_blank" rel="noopener">bench-labs</a>
21
- </div>
22
- <h1>Leaderboard</h1>
23
- <p class="subtitle">
24
- Every evaluated model, every benchmark score, one table. Pulled straight from <code>models.json</code>.
25
- </p>
26
- </header>
27
-
28
- <div class="controls">
29
- <div class="filter-wrap">
30
- <button
31
- type="button"
32
- class="search-circle-btn filter-btn tooltip"
33
- id="params-filter-btn"
34
- aria-label="Filter by parameter count"
35
- aria-expanded="false"
36
- data-tooltip="Filter by parameter count">
37
- <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round">
38
- <line x1="4" y1="6" x2="20" y2="6"/><circle cx="9" cy="6" r="2"/>
39
- <line x1="4" y1="12" x2="20" y2="12"/><circle cx="16" cy="12" r="2"/>
40
- <line x1="4" y1="18" x2="20" y2="18"/><circle cx="7" cy="18" r="2"/>
41
- </svg>
42
- </button>
43
-
44
- <div class="filter-popup" id="params-filter-popup" hidden>
45
- <div class="filter-popup-title">Parameters (B)</div>
46
- <div class="range-slider" id="params-range-slider">
47
- <div class="range-slider-track"></div>
48
- <div class="range-slider-fill" id="params-range-fill"></div>
49
- <input type="range" id="params-range-min" class="range-thumb range-thumb-min" min="0" max="1000" step="1" value="0" aria-label="Minimum parameters in billions">
50
- <input type="range" id="params-range-max" class="range-thumb range-thumb-max" min="0" max="1000" step="1" value="1000" aria-label="Maximum parameters in billions">
51
- </div>
52
- <div class="range-slider-values">
53
- <span id="params-range-min-label">0B</span>
54
- <span id="params-range-max-label">1000B+</span>
55
- </div>
56
- <button type="button" class="filter-reset" id="params-filter-reset">Reset</button>
57
- </div>
58
- </div>
59
-
60
- <div class="search-pill">
61
- <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><circle cx="11" cy="11" r="6"/><line x1="20" y1="20" x2="15.5" y2="15.5"/></svg>
62
- <input type="search" id="model-search" placeholder="Search models or orgs…" aria-label="Search models">
63
- </div>
64
-
65
- <div class="sort-wrap">
66
- <button
67
- type="button"
68
- class="sort-trigger"
69
- id="sort-trigger"
70
- aria-haspopup="listbox"
71
- aria-expanded="false">
72
- <span class="sort-trigger-label" id="sort-trigger-label">Avg score: High → Low</span>
73
- <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" class="sort-trigger-arrow"><polyline points="6 9 12 15 18 9"/></svg>
74
- </button>
75
-
76
- <ul class="sort-menu" id="sort-menu" role="listbox" aria-label="Sort order" hidden>
77
- <li role="option" data-value="avg-desc" aria-selected="true">Avg score: High → Low</li>
78
- <li role="option" data-value="avg-asc" aria-selected="false">Avg score: Low → High</li>
79
- <li role="option" data-value="params-asc" aria-selected="false">Params: Small → Large</li>
80
- <li role="option" data-value="params-desc" aria-selected="false">Params: Large → Small</li>
81
- <li role="option" data-value="name-asc" aria-selected="false">Name: A → Z</li>
82
- </ul>
83
- </div>
84
- </div>
85
-
86
- <p class="results-count" id="results-count"></p>
87
-
88
- <!-- A single flat table: one row per model, one plain column per benchmark's
89
- headline score. No grouped/rowspan headers, no separate detail panel —
90
- models with a category breakdown get an inline expand row using the
91
- same row styling as everything else. -->
92
- <div class="table-scroll" id="table-scroll">
93
- <table class="leaderboard" id="leaderboard-table">
94
- <thead id="leaderboard-head">
95
- <!-- populated by script.js: exactly one header row -->
96
- </thead>
97
- <tbody id="leaderboard-body">
98
- <!-- populated by script.js -->
99
- </tbody>
100
- </table>
101
- </div>
102
-
103
- <!-- Mobile: the same data as the table, one card per model. -->
104
- <div class="model-cards" id="model-cards"></div>
105
-
106
- <div class="empty-state" id="empty-state" hidden>
107
- <svg width="34" height="34" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6"><circle cx="11" cy="11" r="7"/><line x1="21" y1="21" x2="16.5" y2="16.5"/></svg>
108
- <p>No models match your search or filters.</p>
109
- </div>
110
-
111
- <section class="submit-panel" aria-label="Submission rules">
112
- <button class="submit-toggle" id="submit-toggle" aria-expanded="false" aria-controls="submit-body">
113
- <span class="submit-toggle-left">
114
- <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5v14M5 12h14"/></svg>
115
- <span>Submit a model</span>
116
- </span>
117
- <span class="submit-toggle-arrow">▼</span>
118
- </button>
119
-
120
- <div class="submit-body" id="submit-body" hidden>
121
- <p class="submit-intro">
122
- There's no submission form — the leaderboard <em>is</em> <code>models.json</code>.
123
- Add your entry and open a PR against this Space.
124
- </p>
125
-
126
- <h3>Rules</h3>
127
- <ul class="rules-list">
128
- <li>Model must be public on the Hugging Face Hub, with a link in <code>url</code>.</li>
129
- <li>Evaluated on at least one Bench Labs benchmark using the method described in that dataset's README (lm-eval loglikelihood for <code>bench-mid-6-2026</code>, normalized exact-match for <code>bench-effortless-6-2026</code> / <code>bench-easy-6-2026</code>).</li>
130
- <li>Include <code>n</code> (sample count) for every benchmark you report a score for.</li>
131
- <li>If reporting a <code>bench-mid-6-2026</code> result, include the full <code>categories</code> breakdown — powers the row's expand arrow.</li>
132
- <li>Link to your eval run or write-up in <code>eval_source</code> (a blog post, a script, a notebook anything reproducible).</li>
133
- <li>Only submit models you've actually run — don't add placeholder rows with no scores.</li>
134
- </ul>
135
-
136
- <h3>How to evaluate</h3>
137
- <p class="submit-intro">
138
- One universal script runs every benchmark and reports per-category / subcategory results.
139
- </p>
140
- <ol class="steps-list">
141
- <li>Download the script from this Space:
142
- <pre><code>curl -sLO https://huggingface.co/spaces/bench-labs/BenchLabs-Leaderboard/resolve/main/script.py</code></pre></li>
143
- <li>Install the two dependencies: <pre><code>pip install torch transformers</code></pre></li>
144
- <li>Run it against your model: <pre><code>python script.py --model org/ModelName</code></pre>
145
- Options: <code>--benchmarks effortless,easy,mid</code> · <code>--device cuda</code> · <code>--limit 10</code> for a smoke test.</li>
146
- <li>It writes <code>results.json</code> (full category/subcategory report), per-sample CSVs, and <code>leaderboard.json</code> — a ready-made entry for <code>models.json</code>.</li>
147
- </ol>
148
-
149
- <h3>How to submit</h3>
150
- <ol class="steps-list">
151
- <li>Create a PR on this space via the web UI or CLI.</li>
152
- <li>Add an object to the <code>models</code> array in <code>models.json</code>, following the existing entries' shape (see <code>schema</code> below). The script's <code>leaderboard.json</code> output is already in this shape.</li>
153
- <li>Leave <code>score: null</code> for any benchmark tier you haven't run yet; don't omit the key.</li>
154
- <li>Submit the PR here with your eval source linked in the description.</li>
155
- <li>We verify reproducibility before merging. Once merged, it shows up here automatically. Nothing else to deploy.</li>
156
- </ol>
157
-
158
- <h3>Entry schema</h3>
159
- <pre><code id="schema-snippet">{
160
- "id": "your-model-slug",
161
- "name": "org/ModelName",
162
- "org": "org",
163
- "params_b": 1.5,
164
- "license": "apache-2.0",
165
- "architecture": "Transformer decoder, dense",
166
- "url": "https://huggingface.co/org/ModelName",
167
- "eval_source": "https://…",
168
- "runs": {
169
- "bench-effortless-6-2026": { "score": 0.0, "n": 240, "notes": "" },
170
- "bench-easy-6-2026": { "score": 0.0, "n": 300, "notes": "" },
171
- "bench-mid-6-2026": { "score": null, "n": null, "notes": "" }
172
- }
173
- }</code></pre>
174
-
175
- <a class="pr-link" href="https://huggingface.co/spaces/bench-labs/leaderboard/discussions" target="_blank" rel="noopener">
176
- Open a PR on the Space
177
- <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M7 17 17 7M9 7h8v8"/></svg>
178
- </a>
179
- </div>
180
- </section>
181
-
182
- <footer class="page-footer">
183
- <span>Data from <a href="models.json">models.json</a> · loaded client-side, no build step.</span>
184
- <span>
185
- <a href="https://huggingface.co/bench-labs" target="_blank" rel="noopener">org</a> ·
186
- <a href="https://huggingface.co/spaces/bench-labs/blog" target="_blank" rel="noopener">blog</a> ·
187
- <a href="https://huggingface.co/spaces/bench-labs/Members" target="_blank" rel="noopener">members</a>
188
- </span>
189
- </footer>
190
-
191
- </main>
192
-
193
- <script src="script.js" defer></script>
194
- </body>
195
- </html>
 
 
 
 
 
 
 
 
 
 
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <title>Bench Labs Leaderboard</title>
7
+ <meta name="description" content="Model performance across Bench Labs' benchmark suite: Effortless, Easy, and Mid.">
8
+ <link rel="stylesheet" href="style.css">
9
+ </head>
10
+ <body>
11
+ <script src="background.js" defer></script>
12
+
13
+ <div class="background"></div>
14
+
15
+ <main class="container">
16
+
17
+ <header class="hero">
18
+ <div class="eyebrow">
19
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M8 21h8M12 17v4M17 3H7a2 2 0 0 0-2 2v6a7 7 0 0 0 14 0V5a2 2 0 0 0-2-2Z"/></svg>
20
+ <a href="https://huggingface.co/bench-labs" target="_blank" rel="noopener">bench-labs</a>
21
+ </div>
22
+ <h1>Leaderboard</h1>
23
+ <p class="subtitle">
24
+ Every evaluated model, every benchmark score, one table. Pulled straight from <code>models.json</code>.
25
+ </p>
26
+ </header>
27
+
28
+ <div class="controls">
29
+ <div class="filter-wrap">
30
+ <button
31
+ type="button"
32
+ class="search-circle-btn filter-btn tooltip"
33
+ id="params-filter-btn"
34
+ aria-label="Filter by parameter count"
35
+ aria-expanded="false"
36
+ data-tooltip="Filter by parameter count">
37
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round">
38
+ <line x1="4" y1="6" x2="20" y2="6"/><circle cx="9" cy="6" r="2"/>
39
+ <line x1="4" y1="12" x2="20" y2="12"/><circle cx="16" cy="12" r="2"/>
40
+ <line x1="4" y1="18" x2="20" y2="18"/><circle cx="7" cy="18" r="2"/>
41
+ </svg>
42
+ </button>
43
+
44
+ <div class="filter-popup" id="params-filter-popup" hidden>
45
+ <div class="filter-popup-title">Parameters (B)</div>
46
+ <div class="range-slider" id="params-range-slider">
47
+ <div class="range-slider-track"></div>
48
+ <div class="range-slider-fill" id="params-range-fill"></div>
49
+ <input type="range" id="params-range-min" class="range-thumb range-thumb-min" min="0" max="1000" step="1" value="0" aria-label="Minimum parameters in billions">
50
+ <input type="range" id="params-range-max" class="range-thumb range-thumb-max" min="0" max="1000" step="1" value="1000" aria-label="Maximum parameters in billions">
51
+ </div>
52
+ <div class="range-slider-values">
53
+ <span id="params-range-min-label">0B</span>
54
+ <span id="params-range-max-label">1000B+</span>
55
+ </div>
56
+ <button type="button" class="filter-reset" id="params-filter-reset">Reset</button>
57
+ </div>
58
+ </div>
59
+
60
+ <div class="search-pill">
61
+ <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><circle cx="11" cy="11" r="6"/><line x1="20" y1="20" x2="15.5" y2="15.5"/></svg>
62
+ <input type="search" id="model-search" placeholder="Search models or orgs…" aria-label="Search models">
63
+ </div>
64
+
65
+ <div class="sort-wrap">
66
+ <button
67
+ type="button"
68
+ class="sort-trigger"
69
+ id="sort-trigger"
70
+ aria-haspopup="listbox"
71
+ aria-expanded="false">
72
+ <span class="sort-trigger-label" id="sort-trigger-label">Avg score: High → Low</span>
73
+ <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" class="sort-trigger-arrow"><polyline points="6 9 12 15 18 9"/></svg>
74
+ </button>
75
+
76
+ <ul class="sort-menu" id="sort-menu" role="listbox" aria-label="Sort order" hidden>
77
+ <li role="option" data-value="avg-desc" aria-selected="true">Avg score: High → Low</li>
78
+ <li role="option" data-value="avg-asc" aria-selected="false">Avg score: Low → High</li>
79
+ <li role="option" data-value="params-asc" aria-selected="false">Params: Small → Large</li>
80
+ <li role="option" data-value="params-desc" aria-selected="false">Params: Large → Small</li>
81
+ <li role="option" data-value="name-asc" aria-selected="false">Name: A → Z</li>
82
+ </ul>
83
+ </div>
84
+ </div>
85
+
86
+ <p class="results-count" id="results-count"></p>
87
+
88
+ <!-- A single flat table: one row per model, one plain column per benchmark's
89
+ headline score. No grouped/rowspan headers, no separate detail panel —
90
+ models with a category breakdown get an inline expand row using the
91
+ same row styling as everything else. -->
92
+ <div class="table-scroll" id="table-scroll">
93
+ <table class="leaderboard" id="leaderboard-table">
94
+ <thead id="leaderboard-head">
95
+ <!-- populated by script.js: exactly one header row -->
96
+ </thead>
97
+ <tbody id="leaderboard-body">
98
+ <!-- populated by script.js -->
99
+ </tbody>
100
+ </table>
101
+ </div>
102
+
103
+ <!-- Mobile: the same data as the table, one card per model. -->
104
+ <div class="model-cards" id="model-cards"></div>
105
+
106
+ <div class="empty-state" id="empty-state" hidden>
107
+ <svg width="34" height="34" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6"><circle cx="11" cy="11" r="7"/><line x1="21" y1="21" x2="16.5" y2="16.5"/></svg>
108
+ <p>No models match your search or filters.</p>
109
+ </div>
110
+
111
+ <section class="submit-panel" aria-label="Submission rules">
112
+ <button class="submit-toggle" id="submit-toggle" aria-expanded="false" aria-controls="submit-body">
113
+ <span class="submit-toggle-left">
114
+ <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5v14M5 12h14"/></svg>
115
+ <span>Submit a model</span>
116
+ </span>
117
+ <span class="submit-toggle-arrow">▼</span>
118
+ </button>
119
+
120
+ <div class="submit-body" id="submit-body" hidden>
121
+ <p class="submit-intro">
122
+ There's no submission form — the leaderboard <em>is</em> <code>models.json</code>.
123
+ Add your entry and open a PR against this Space.
124
+ </p>
125
+
126
+ <h3>Rules</h3>
127
+ <ul class="rules-list">
128
+ <li>Model must be public on the Hugging Face Hub, with a link in <code>url</code>.</li>
129
+ <li>Evaluated on at least one Bench Labs benchmark using the method described in that dataset's README (lm-eval loglikelihood for <code>bench-mid-6-2026</code>, normalized exact-match for <code>bench-effortless-6-2026</code> / <code>bench-easy-6-2026</code>).</li>
130
+ <li>Include <code>n</code> (sample count) for every benchmark you report a score for.</li>
131
+ <li>If reporting a <code>bench-mid-6-2026</code> result, include the full <code>categories</code> breakdown — powers the row's expand arrow.</li>
132
+ <li>Provenance is pinned automatically: <code>leaderboard.json</code> carries <code>model_revision</code> (the Hub commit of the weights the script actually loaded) and <code>script_sha256</code> (hash of the exact script that produced the numbers). Keep both in your entry, and link your eval run or write-up in the PR description.</li>
133
+ <li>Only submit models you've actually run — don't add placeholder rows with no scores.</li>
134
+ </ul>
135
+
136
+ <h3>How to evaluate</h3>
137
+ <p class="submit-intro">
138
+ One universal script runs every benchmark and reports per-category / subcategory results.
139
+ </p>
140
+ <ol class="steps-list">
141
+ <li>Download the script from this Space:
142
+ <pre><code>curl -sLO https://huggingface.co/spaces/bench-labs/BenchLabs-Leaderboard/resolve/main/script.py</code></pre></li>
143
+ <li>Install the two dependencies: <pre><code>pip install torch transformers</code></pre></li>
144
+ <li>Run it against your model: <pre><code>python script.py --model org/ModelName</code></pre>
145
+ Options: <code>--benchmarks effortless,easy,mid</code> · <code>--device cuda</code> · <code>--limit 10</code> for a smoke test.</li>
146
+ <li>It writes <code>results.json</code> (full category/subcategory report), per-sample CSVs, and <code>leaderboard.json</code> — a ready-made entry for <code>models.json</code>.</li>
147
+ </ol>
148
+ <p class="submit-intro">
149
+ Reasoning models that think in <code>&lt;think&gt;…&lt;/think&gt;</code> blocks are supported:
150
+ the script strips the reasoning and scores only the text after the final <code>&lt;/think&gt;</code>.
151
+ Give them room to finish run with <code>--max-new-tokens 2048</code> or more (the default 32
152
+ is sized for direct-answer models; a generation cut off mid-think scores as an empty answer).
153
+ <code>bench-mid-6-2026</code> is scored by log-likelihood over the answer choices with no
154
+ generation, so thinking never runs there.
155
+ </p>
156
+
157
+ <h3>How to submit</h3>
158
+ <ol class="steps-list">
159
+ <li>Create a PR on this space via the web UI or CLI.</li>
160
+ <li>Add an object to the <code>models</code> array in <code>models.json</code>, following the existing entries' shape (see <code>schema</code> below). The script's <code>leaderboard.json</code> output is already in this shape.</li>
161
+ <li>Leave <code>score: null</code> for any benchmark tier you haven't run yet; don't omit the key.</li>
162
+ <li>Submit the PR here with your eval source linked in the description.</li>
163
+ <li>We verify reproducibility before merging. Once merged, it shows up here automatically. Nothing else to deploy.</li>
164
+ </ol>
165
+
166
+ <h3>Entry schema</h3>
167
+ <pre><code id="schema-snippet">{
168
+ "id": "your-model-slug",
169
+ "name": "org/ModelName",
170
+ "org": "org",
171
+ "params_b": 1.5,
172
+ "license": "apache-2.0",
173
+ "architecture": "Transformer decoder, dense",
174
+ "url": "https://huggingface.co/org/ModelName",
175
+ "model_revision": "hub commit sha the script loaded",
176
+ "script_sha256": "sha256 of the script.py that ran",
177
+ "runs": {
178
+ "bench-effortless-6-2026": { "score": 0.0, "n": 240, "notes": "" },
179
+ "bench-easy-6-2026": { "score": 0.0, "n": 300, "notes": "" },
180
+ "bench-mid-6-2026": { "score": null, "n": null, "notes": "" }
181
+ }
182
+ }</code></pre>
183
+
184
+ <a class="pr-link" href="https://huggingface.co/spaces/bench-labs/leaderboard/discussions" target="_blank" rel="noopener">
185
+ Open a PR on the Space
186
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M7 17 17 7M9 7h8v8"/></svg>
187
+ </a>
188
+ </div>
189
+ </section>
190
+
191
+ <footer class="page-footer">
192
+ <span>Data from <a href="models.json">models.json</a> · loaded client-side, no build step.</span>
193
+ <span>
194
+ <a href="https://huggingface.co/bench-labs" target="_blank" rel="noopener">org</a> ·
195
+ <a href="https://huggingface.co/spaces/bench-labs/blog" target="_blank" rel="noopener">blog</a> ·
196
+ <a href="https://huggingface.co/spaces/bench-labs/Members" target="_blank" rel="noopener">members</a>
197
+ </span>
198
+ </footer>
199
+
200
+ </main>
201
+
202
+ <script src="script.js" defer></script>
203
+ </body>
204
+ </html>
script.py CHANGED
@@ -44,6 +44,14 @@ Scoring conventions
44
  Headline score = soft_score_norm, matching the leaderboard.
45
  Multiple-choice prompt format: "Q: {input}\nA:" with candidates " {choice}".
46
 
 
 
 
 
 
 
 
 
47
  Bench Labs - Simple, Reliable, Open sourced
48
  """
49
 
@@ -123,6 +131,12 @@ ANSWER_PREFIXES = re.compile(
123
  r"^(the answer is|answer\s*[:=]|final answer\s*[:=]?|it is|it's)\s*", re.IGNORECASE
124
  )
125
 
 
 
 
 
 
 
126
  # --------------------------------------------------------------------------- #
127
  # Text normalization and scoring
128
  # --------------------------------------------------------------------------- #
@@ -137,8 +151,18 @@ def normalize(text: str) -> str:
137
 
138
 
139
  def extract_answer(text: str) -> str:
140
- """First line of the generation, minus boilerplate answer prefixes."""
141
- text = str(text).strip()
 
 
 
 
 
 
 
 
 
 
142
  if "\n" in text:
143
  text = text.split("\n", 1)[0]
144
  text = ANSWER_PREFIXES.sub("", text.strip())
@@ -278,21 +302,19 @@ class HFModel:
278
  print(f" chat template: {'yes' if self.use_chat else 'no (plain QA prompt)'}")
279
 
280
  # -- resolved model provenance ------------------------------------ #
281
- # Prefer the Hub's actual commit SHA for the given name/revision; this
282
- # is what ties a leaderboard entry to the exact weights that were run,
283
- # rather than to a mutable name or branch like "main".
284
- self.resolved_revision: Optional[str] = None
285
- try:
286
- from huggingface_hub import HfApi
287
- if "/" in name and not Path(name).exists():
 
 
 
288
  self.resolved_revision = HfApi().model_info(name).sha
289
- except Exception:
290
- pass
291
- if self.resolved_revision is None:
292
- # Fall back to whatever transformers recorded when resolving the
293
- # model (works for hub ids pinned via --revision, no-ops for
294
- # local checkpoints, which legitimately have no hub revision).
295
- self.resolved_revision = getattr(self.model.config, "_commit_hash", None)
296
 
297
  # -- generation -------------------------------------------------------- #
298
 
@@ -630,7 +652,9 @@ def parse_args(argv: Optional[Sequence[str]] = None) -> argparse.Namespace:
630
  p.add_argument("--device", default="auto", help="auto | cuda | cpu | mps")
631
  p.add_argument("--dtype", default="auto", help="auto | float16 | bfloat16 | float32")
632
  p.add_argument("--batch-size", type=int, default=8)
633
- p.add_argument("--max-new-tokens", type=int, default=32)
 
 
634
  p.add_argument("--limit", type=int, default=None, help="cap rows per benchmark (smoke test)")
635
  p.add_argument("--output-dir", default=None,
636
  help="default: benchlabs_results/<model-name>")
 
44
  Headline score = soft_score_norm, matching the leaderboard.
45
  Multiple-choice prompt format: "Q: {input}\nA:" with candidates " {choice}".
46
 
47
+ Reasoning / CoT models
48
+ <think>...</think> blocks are stripped before answer extraction: only the
49
+ text after the final </think> is scored. Raise --max-new-tokens (2048+) so
50
+ the model can finish thinking -- the default 32 is sized for direct-answer
51
+ models. A generation cut off mid-think (unclosed <think>) scores as an
52
+ empty answer. Mid is scored by log-likelihood over the answer choices with
53
+ no generation at all, so thinking never happens there.
54
+
55
  Bench Labs - Simple, Reliable, Open sourced
56
  """
57
 
 
131
  r"^(the answer is|answer\s*[:=]|final answer\s*[:=]?|it is|it's)\s*", re.IGNORECASE
132
  )
133
 
134
+ # Reasoning-model tags. THINK_CLOSE also matches a bare closing tag: some chat
135
+ # templates open <think> inside the prompt, so the generation contains only
136
+ # the reasoning and a </think>.
137
+ THINK_CLOSE = re.compile(r"</think(?:ing)?>\s*", re.IGNORECASE)
138
+ THINK_OPEN = re.compile(r"<think(?:ing)?>.*", re.IGNORECASE | re.DOTALL)
139
+
140
  # --------------------------------------------------------------------------- #
141
  # Text normalization and scoring
142
  # --------------------------------------------------------------------------- #
 
151
 
152
 
153
  def extract_answer(text: str) -> str:
154
+ """First line of the generation after any <think> block, minus boilerplate prefixes.
155
+
156
+ Only text after the final </think> is scored. An unclosed <think> means the
157
+ generation ran out of budget mid-reasoning, so there is no answer to extract.
158
+ """
159
+ text = str(text)
160
+ parts = THINK_CLOSE.split(text)
161
+ if len(parts) > 1:
162
+ text = parts[-1]
163
+ else:
164
+ text = THINK_OPEN.sub("", text)
165
+ text = text.strip()
166
  if "\n" in text:
167
  text = text.split("\n", 1)[0]
168
  text = ANSWER_PREFIXES.sub("", text.strip())
 
302
  print(f" chat template: {'yes' if self.use_chat else 'no (plain QA prompt)'}")
303
 
304
  # -- resolved model provenance ------------------------------------ #
305
+ # The weights already carry their commit: from_pretrained records the
306
+ # snapshot it actually loaded in config._commit_hash, no second Hub
307
+ # lookup. Asking the Hub afterwards can pin a different commit if the
308
+ # branch moved between load and lookup, so _commit_hash is primary.
309
+ self.resolved_revision: Optional[str] = getattr(self.model.config, "_commit_hash", None)
310
+ if self.resolved_revision is None and "/" in name and not Path(name).exists():
311
+ # Fallback for transformers versions that don't record it. Local
312
+ # checkpoints stay None, which is honest: they have no hub revision.
313
+ try:
314
+ from huggingface_hub import HfApi
315
  self.resolved_revision = HfApi().model_info(name).sha
316
+ except Exception:
317
+ pass
 
 
 
 
 
318
 
319
  # -- generation -------------------------------------------------------- #
320
 
 
652
  p.add_argument("--device", default="auto", help="auto | cuda | cpu | mps")
653
  p.add_argument("--dtype", default="auto", help="auto | float16 | bfloat16 | float32")
654
  p.add_argument("--batch-size", type=int, default=8)
655
+ p.add_argument("--max-new-tokens", type=int, default=32,
656
+ help="generation budget; raise to 2048+ for reasoning models "
657
+ "that emit <think> blocks (default: 32)")
658
  p.add_argument("--limit", type=int, default=None, help="cap rows per benchmark (smoke test)")
659
  p.add_argument("--output-dir", default=None,
660
  help="default: benchlabs_results/<model-name>")