Martico2432 commited on
Commit
c988c4f
·
verified ·
1 Parent(s): fb181d0

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +816 -19
index.html CHANGED
@@ -1,19 +1,816 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en" class="dark">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>SLM Leaderboard - Small Language Model Benchmarks</title>
7
+ <!-- Tailwind CSS -->
8
+ <script src="https://cdn.tailwindcss.com"></script>
9
+ <!-- Chart.js -->
10
+ <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
11
+ <!-- FontAwesome Icons -->
12
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
13
+
14
+ <script>
15
+ tailwind.config = {
16
+ darkMode: 'class',
17
+ theme: {
18
+ extend: {
19
+ colors: {
20
+ brand: {
21
+ 50: '#f0fdf4',
22
+ 500: '#22c55e',
23
+ 600: '#16a34a',
24
+ 900: '#14532d',
25
+ },
26
+ darkbg: '#0b0f17',
27
+ darkcard: '#111827',
28
+ darkborder: '#1f2937'
29
+ }
30
+ }
31
+ }
32
+ }
33
+ </script>
34
+ <style>
35
+ /* Custom Scrollbar */
36
+ ::-webkit-scrollbar {
37
+ width: 8px;
38
+ height: 8px;
39
+ }
40
+ ::-webkit-scrollbar-track {
41
+ background: #0b0f17;
42
+ }
43
+ ::-webkit-scrollbar-thumb {
44
+ background: #374151;
45
+ border-radius: 4px;
46
+ }
47
+ ::-webkit-scrollbar-thumb:hover {
48
+ background: #4b5563;
49
+ }
50
+ </style>
51
+ </head>
52
+ <body class="bg-darkbg text-slate-100 font-sans min-h-screen antialiased selection:bg-brand-500 selection:text-white">
53
+
54
+ <!-- Top Navigation Header -->
55
+ <header class="border-b border-darkborder bg-darkcard/80 backdrop-blur sticky top-0 z-50">
56
+ <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 h-16 flex items-center justify-between">
57
+ <div class="flex items-center gap-3">
58
+ <div class="h-9 w-9 rounded-lg bg-gradient-to-br from-brand-500 to-emerald-700 flex items-center justify-center text-white shadow-lg shadow-brand-500/20">
59
+ <i class="fa-solid fa-microchip text-lg"></i>
60
+ </div>
61
+ <div>
62
+ <h1 class="font-bold text-lg leading-none tracking-tight">SLM Leaderboard</h1>
63
+ <p class="text-xs text-slate-400 mt-0.5">Small Language Model Performance & Efficiency Index</p>
64
+ </div>
65
+ </div>
66
+
67
+ <div class="flex items-center gap-3">
68
+ <a href="#submit-guide" onclick="toggleSubmitModal()" class="inline-flex items-center gap-2 bg-brand-600 hover:bg-brand-500 text-white text-xs font-semibold px-3.5 py-2 rounded-lg transition shadow-md shadow-brand-500/10">
69
+ <i class="fa-solid fa-code-pull-request"></i>
70
+ <span>Submit Model (PR)</span>
71
+ </a>
72
+ </div>
73
+ </div>
74
+ </header>
75
+
76
+ <main class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8 space-y-12">
77
+
78
+ <!-- Summary & Info Cards -->
79
+ <section class="grid grid-cols-1 md:grid-cols-4 gap-4">
80
+ <div class="bg-darkcard border border-darkborder rounded-xl p-5 relative overflow-hidden">
81
+ <div class="text-slate-400 text-xs font-medium uppercase tracking-wider">Total Evaluated SLMs</div>
82
+ <div id="stat-total-models" class="text-3xl font-extrabold mt-2 text-slate-100">0</div>
83
+ <div class="text-xs text-emerald-400 mt-1"><i class="fa-solid fa-arrow-up text-[10px]"></i> Active Community Leaderboard</div>
84
+ </div>
85
+ <div class="bg-darkcard border border-darkborder rounded-xl p-5 relative overflow-hidden">
86
+ <div class="text-slate-400 text-xs font-medium uppercase tracking-wider">Top Intelligence Score</div>
87
+ <div id="stat-top-score" class="text-3xl font-extrabold mt-2 text-brand-500">0.0%</div>
88
+ <div id="stat-top-model" class="text-xs text-slate-400 mt-1 truncate">-</div>
89
+ </div>
90
+ <div class="bg-darkcard border border-darkborder rounded-xl p-5 relative overflow-hidden">
91
+ <div class="text-slate-400 text-xs font-medium uppercase tracking-wider">Evaluation Suite</div>
92
+ <div class="text-3xl font-extrabold mt-2 text-slate-100">5 Benchmarks</div>
93
+ <div class="text-xs text-slate-400 mt-1">lm-evaluation-harness weighted standard</div>
94
+ </div>
95
+ <div class="bg-darkcard border border-darkborder rounded-xl p-5 relative overflow-hidden">
96
+ <div class="text-slate-400 text-xs font-medium uppercase tracking-wider">Parameter Cap</div>
97
+ <div class="text-3xl font-extrabold mt-2 text-slate-100">&lt; 8.0 Billion</div>
98
+ <div class="text-xs text-slate-400 mt-1">Focused strictly on sub-8B edge & small AI</div>
99
+ </div>
100
+ </section>
101
+
102
+ <!-- SECTION 1: Leaderboard Table -->
103
+ <section class="bg-darkcard border border-darkborder rounded-xl p-6 shadow-xl">
104
+ <div class="flex flex-col lg:flex-row lg:items-center justify-between gap-4 mb-6">
105
+ <div>
106
+ <h2 class="text-xl font-bold flex items-center gap-2">
107
+ <i class="fa-solid fa-list-ol text-brand-500"></i> Benchmark Leaderboard
108
+ </h2>
109
+ <p class="text-sm text-slate-400">Sort by weighted overall score or individual benchmark metrics.</p>
110
+ </div>
111
+
112
+ <!-- Filters & Search -->
113
+ <div class="flex flex-wrap items-center gap-3">
114
+ <!-- Search input -->
115
+ <div class="relative min-w-[220px]">
116
+ <i class="fa-solid fa-magnifying-glass absolute left-3 top-1/2 -translate-y-1/2 text-slate-500 text-xs"></i>
117
+ <input type="text" id="search-input" placeholder="Search model or creator..." class="w-full bg-darkbg border border-darkborder rounded-lg pl-9 pr-3 py-1.5 text-xs text-slate-200 placeholder-slate-500 focus:outline-none focus:border-brand-500">
118
+ </div>
119
+
120
+ <!-- Size Filter -->
121
+ <div class="flex items-center gap-1 bg-darkbg p-1 border border-darkborder rounded-lg" id="size-filters">
122
+ <button data-size="all" class="size-filter-btn active text-xs px-2.5 py-1 rounded-md font-medium transition bg-brand-600 text-white">All</button>
123
+ <button data-size="1M" class="size-filter-btn text-xs px-2.5 py-1 rounded-md font-medium text-slate-400 hover:text-white transition">&lt;1M</button>
124
+ <button data-size="10M" class="size-filter-btn text-xs px-2.5 py-1 rounded-md font-medium text-slate-400 hover:text-white transition">&lt;10M</button>
125
+ <button data-size="100M" class="size-filter-btn text-xs px-2.5 py-1 rounded-md font-medium text-slate-400 hover:text-white transition">&lt;100M</button>
126
+ <button data-size="1B" class="size-filter-btn text-xs px-2.5 py-1 rounded-md font-medium text-slate-400 hover:text-white transition">&lt;1B</button>
127
+ <button data-size="3B" class="size-filter-btn text-xs px-2.5 py-1 rounded-md font-medium text-slate-400 hover:text-white transition">&lt;3B</button>
128
+ </div>
129
+ </div>
130
+ </div>
131
+
132
+ <!-- Table -->
133
+ <div class="overflow-x-auto">
134
+ <table class="w-full text-left border-collapse text-sm">
135
+ <thead>
136
+ <tr class="border-b border-darkborder text-slate-400 text-xs uppercase bg-darkbg/50">
137
+ <th class="py-3 px-3 w-12 text-center">Rank</th>
138
+ <th class="py-3 px-3">Model</th>
139
+ <th class="py-3 px-3">Creator / Org</th>
140
+ <th class="py-3 px-3 text-right">Params</th>
141
+ <th class="py-3 px-3 text-right cursor-pointer hover:text-white font-bold text-brand-400" onclick="sortTable('overall')">
142
+ Overall Index <i class="fa-solid fa-sort ml-1 text-[10px]"></i>
143
+ </th>
144
+ <th class="py-3 px-3 text-right cursor-pointer hover:text-white" onclick="sortTable('AIME 2026')">
145
+ AIME 2026 <span class="text-[10px] text-slate-500">(1.5x)</span> <i class="fa-solid fa-sort ml-1 text-[10px]"></i>
146
+ </th>
147
+ <th class="py-3 px-3 text-right cursor-pointer hover:text-white" onclick="sortTable('Arc_easy')">
148
+ ARC-E <span class="text-[10px] text-slate-500">(1.0x)</span> <i class="fa-solid fa-sort ml-1 text-[10px]"></i>
149
+ </th>
150
+ <th class="py-3 px-3 text-right cursor-pointer hover:text-white" onclick="sortTable('Arc_challenge')">
151
+ ARC-C <span class="text-[10px] text-slate-500">(0.5x)</span> <i class="fa-solid fa-sort ml-1 text-[10px]"></i>
152
+ </th>
153
+ <th class="py-3 px-3 text-right cursor-pointer hover:text-white" onclick="sortTable('PIQA')">
154
+ PIQA <span class="text-[10px] text-slate-500">(1.0x)</span> <i class="fa-solid fa-sort ml-1 text-[10px]"></i>
155
+ </th>
156
+ <th class="py-3 px-3 text-right cursor-pointer hover:text-white" onclick="sortTable('HellaSwag')">
157
+ HellaSwag <span class="text-[10px] text-slate-500">(1.0x)</span> <i class="fa-solid fa-sort ml-1 text-[10px]"></i>
158
+ </th>
159
+ <th class="py-3 px-3 text-center">Card</th>
160
+ </tr>
161
+ </thead>
162
+ <tbody id="leaderboard-body" class="divide-y divide-darkborder font-mono text-xs">
163
+ <!-- Populated dynamically -->
164
+ </tbody>
165
+ </table>
166
+ </div>
167
+ </section>
168
+
169
+ <!-- SECTION 2: Visual Charts Grid -->
170
+ <div class="grid grid-cols-1 lg:grid-cols-3 gap-8">
171
+
172
+ <!-- Chart 1: Intelligence Index vs Parameters (Log Scale) -->
173
+ <div class="lg:col-span-2 bg-darkcard border border-darkborder rounded-xl p-6 shadow-xl">
174
+ <div class="flex items-center justify-between mb-4">
175
+ <div>
176
+ <h3 class="text-lg font-bold flex items-center gap-2">
177
+ <i class="fa-solid fa-chart-line text-brand-500"></i> Intelligence Index vs. Parameter Count
178
+ </h3>
179
+ <p class="text-xs text-slate-400">Logarithmic scale X-axis with average trend vs Top-10% efficiency frontier.</p>
180
+ </div>
181
+ </div>
182
+ <div class="h-[360px] w-full relative">
183
+ <canvas id="scatterChart"></canvas>
184
+ </div>
185
+ </div>
186
+
187
+ <!-- Chart 2: Org/User Leaderboard Share -->
188
+ <div class="bg-darkcard border border-darkborder rounded-xl p-6 shadow-xl flex flex-col justify-between">
189
+ <div>
190
+ <h3 class="text-lg font-bold flex items-center gap-2 mb-1">
191
+ <i class="fa-solid fa-pie-chart text-brand-500"></i> Creator / Org Share
192
+ </h3>
193
+ <p class="text-xs text-slate-400 mb-4">Distribution of submitted SLMs by organization or individual creator.</p>
194
+ </div>
195
+ <div class="h-[280px] w-full relative my-auto">
196
+ <canvas id="shareChart"></canvas>
197
+ </div>
198
+ </div>
199
+ </div>
200
+
201
+ <!-- SECTION 3: Per-Model Insights Section -->
202
+ <section class="bg-darkcard border border-darkborder rounded-xl p-6 shadow-xl">
203
+ <div class="flex flex-col md:flex-row md:items-center justify-between gap-4 mb-6">
204
+ <div>
205
+ <h2 class="text-xl font-bold flex items-center gap-2">
206
+ <i class="fa-solid fa-magnifying-glass-chart text-brand-500"></i> Per-Model Radar & Skill Insights
207
+ </h2>
208
+ <p class="text-sm text-slate-400">Analyze benchmark strengths/weaknesses compared against the overall SLM average.</p>
209
+ </div>
210
+
211
+ <!-- Model Selector Dropdown -->
212
+ <div class="min-w-[280px]">
213
+ <label for="insight-model-select" class="block text-xs font-medium text-slate-400 mb-1">Select Model to Inspect:</label>
214
+ <select id="insight-model-select" class="w-full bg-darkbg border border-darkborder rounded-lg px-3 py-2 text-xs text-slate-200 focus:outline-none focus:border-brand-500">
215
+ <!-- Populated dynamically -->
216
+ </select>
217
+ </div>
218
+ </div>
219
+
220
+ <div class="grid grid-cols-1 lg:grid-cols-12 gap-8 items-center">
221
+ <!-- Radar Chart -->
222
+ <div class="lg:col-span-6 h-[340px] relative">
223
+ <canvas id="radarChart"></canvas>
224
+ </div>
225
+
226
+ <!-- Breakdown Cards -->
227
+ <div class="lg:col-span-6 space-y-4">
228
+ <div id="insight-model-header" class="p-4 bg-darkbg border border-darkborder rounded-lg flex items-center justify-between">
229
+ <!-- Dynamic Content -->
230
+ </div>
231
+
232
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
233
+ <div class="bg-darkbg/70 border border-emerald-900/30 p-4 rounded-lg">
234
+ <h4 class="text-xs font-bold text-emerald-400 uppercase tracking-wider mb-2 flex items-center gap-1.5">
235
+ <i class="fa-solid fa-circle-check"></i> Benchmark Strengths
236
+ </h4>
237
+ <ul id="insight-strengths" class="text-xs space-y-1.5 text-slate-300">
238
+ <!-- Dynamic -->
239
+ </ul>
240
+ </div>
241
+ <div class="bg-darkbg/70 border border-rose-900/30 p-4 rounded-lg">
242
+ <h4 class="text-xs font-bold text-rose-400 uppercase tracking-wider mb-2 flex items-center gap-1.5">
243
+ <i class="fa-solid fa-triangle-exclamation"></i> Optimization Opportunities
244
+ </h4>
245
+ <ul id="insight-weaknesses" class="text-xs space-y-1.5 text-slate-300">
246
+ <!-- Dynamic -->
247
+ </ul>
248
+ </div>
249
+ </div>
250
+ </div>
251
+ </div>
252
+ </section>
253
+
254
+ </main>
255
+
256
+ <!-- Submission Modal Guide -->
257
+ <div id="submit-modal" class="fixed inset-0 bg-black/70 backdrop-blur-sm z-50 flex items-center justify-center hidden p-4">
258
+ <div class="bg-darkcard border border-darkborder rounded-xl max-w-2xl w-full p-6 relative shadow-2xl">
259
+ <button onclick="toggleSubmitModal()" class="absolute top-4 right-4 text-slate-400 hover:text-white">
260
+ <i class="fa-solid fa-xmark text-lg"></i>
261
+ </button>
262
+ <h3 class="text-xl font-bold text-slate-100 flex items-center gap-2 mb-2">
263
+ <i class="fa-solid fa-code-pull-request text-brand-500"></i> How to Submit Your SLM via PR
264
+ </h3>
265
+ <p class="text-xs text-slate-400 mb-4">
266
+ To add your model or configure your Organization/User color, edit the script dictionaries in this HTML file and open a Pull Request on Hugging Face Spaces!
267
+ </p>
268
+
269
+ <div class="space-y-3 bg-darkbg p-4 rounded-lg border border-darkborder text-xs font-mono text-slate-300 overflow-x-auto">
270
+ <p class="text-slate-400">// 1. Add your Org/User Color to CREATOR_COLORS:</p>
271
+ <p class="text-emerald-400">"YourName": "#FF5733",</p>
272
+
273
+ <p class="text-slate-400 mt-2">// 2. Add your Model entry to MODELS_DATA:</p>
274
+ <pre class="text-brand-400">
275
+ {
276
+ name: "My-Custom-SLM-1B",
277
+ creator: "YourName",
278
+ params: 1000000000, // exact parameter count integer
279
+ card_url: "https://huggingface.co/YourName/My-Custom-SLM-1B",
280
+ scores: {
281
+ "AIME 2026": 0.12,
282
+ "Arc_easy": 0.74,
283
+ "Arc_challenge": 0.48,
284
+ "PIQA": 0.81,
285
+ "HellaSwag": 0.69
286
+ }
287
+ }</pre>
288
+ </div>
289
+
290
+ <div class="mt-6 flex justify-end">
291
+ <button onclick="toggleSubmitModal()" class="bg-brand-600 hover:bg-brand-500 text-white text-xs font-semibold px-4 py-2 rounded-lg">Got it!</button>
292
+ </div>
293
+ </div>
294
+ </div>
295
+
296
+ <!-- ========================================================================= -->
297
+ <!-- LEADERBOARD DATA & LOGIC ENGINE -->
298
+ <!-- ========================================================================= -->
299
+ <script>
300
+ // =========================================================================
301
+ // 1. CREATOR COLOR MAP (Configure your Username / Org Color here via PR)
302
+ // =========================================================================
303
+ const CREATOR_COLORS = {
304
+ "Martico2432": "#00FF00",
305
+ };
306
+
307
+ // =========================================================================
308
+ // 2. BENCHMARK CONFIGURATION (Eval weights based on lm_eval standard)
309
+ // =========================================================================
310
+ const BENCHMARK_CONFIG = {
311
+ "AIME 2026": { weight: 1.5, min: 0, max: 1 },
312
+ "Arc_easy": { weight: 1.0, min: 0, max: 1 },
313
+ "Arc_challenge": { weight: 0.5, min: 0, max: 1 },
314
+ "PIQA": { weight: 1.0, min: 0, max: 1 },
315
+ "HellaSwag": { weight: 1.0, min: 0, max: 1 }
316
+ };
317
+
318
+ // =========================================================================
319
+ // 3. MODELS JSON DATA (Add new models here via Hugging Face PR)
320
+ // =========================================================================
321
+ const MODELS_DATA = [
322
+ {
323
+ name: "SRLM-1M",
324
+ creator: "Martico2432",
325
+ params: 904000,
326
+ card_url: "https://huggingface.co/Martico2432/srlm-1m",
327
+ scores: { "AIME 2026": 0.0, "Arc_easy": 0.2866, "Arc_challenge": 0.2, "PIQA": 0.00, "HellaSwag": 0.2665 }
328
+ },
329
+ ];
330
+
331
+ // Global State Variables
332
+ let processedModels = [];
333
+ let currentSortColumn = 'overall';
334
+ let sortDirection = 'desc';
335
+ let activeSizeFilter = 'all';
336
+ let searchQuery = '';
337
+ let scatterChartObj = null;
338
+ let shareChartObj = null;
339
+ let radarChartObj = null;
340
+
341
+ // Calculate Weighted Score for a model
342
+ function calculateOverallScore(scores) {
343
+ let totalWeightedScore = 0;
344
+ let totalWeight = 0;
345
+
346
+ for (const [bench, cfg] of Object.entries(BENCHMARK_CONFIG)) {
347
+ const val = scores[bench] !== undefined ? scores[bench] : 0;
348
+ totalWeightedScore += val * cfg.weight;
349
+ totalWeight += cfg.weight;
350
+ }
351
+
352
+ // Return scaled percentage (0 to 100)
353
+ return (totalWeightedScore / totalWeight) * 100;
354
+ }
355
+
356
+ // Initialize and Process Model Data
357
+ function initData() {
358
+ processedModels = MODELS_DATA.map(m => {
359
+ const overall = calculateOverallScore(m.scores);
360
+ return {
361
+ ...m,
362
+ overall: overall
363
+ };
364
+ });
365
+ sortModels();
366
+ }
367
+
368
+ // Format Big Numbers (Params)
369
+ function formatParams(num) {
370
+ if (num >= 1e9) return (num / 1e9).toFixed(2) + 'B';
371
+ if (num >= 1e6) return (num / 1e6).toFixed(1) + 'M';
372
+ if (num >= 1e3) return (num / 1e3).toFixed(0) + 'K';
373
+ return num.toString();
374
+ }
375
+
376
+ // Get Creator Color Helper
377
+ function getCreatorColor(creator) {
378
+ return CREATOR_COLORS[creator] || CREATOR_COLORS["Community"];
379
+ }
380
+
381
+ // Sort Models Logic
382
+ function sortModels() {
383
+ processedModels.sort((a, b) => {
384
+ let valA = currentSortColumn === 'overall' ? a.overall : (a.scores[currentSortColumn] * 100 || 0);
385
+ let valB = currentSortColumn === 'overall' ? b.overall : (b.scores[currentSortColumn] * 100 || 0);
386
+
387
+ return sortDirection === 'desc' ? valB - valA : valA - valB;
388
+ });
389
+ }
390
+
391
+ function sortTable(column) {
392
+ if (currentSortColumn === column) {
393
+ sortDirection = sortDirection === 'desc' ? 'asc' : 'desc';
394
+ } else {
395
+ currentSortColumn = column;
396
+ sortDirection = 'desc';
397
+ }
398
+ sortModels();
399
+ renderTable();
400
+ }
401
+
402
+ // Render Leaderboard Table
403
+ function renderTable() {
404
+ const tbody = document.getElementById('leaderboard-body');
405
+ tbody.innerHTML = '';
406
+
407
+ const filtered = processedModels.filter(m => {
408
+ // Size filter
409
+ let passSize = true;
410
+ if (activeSizeFilter === '1M') passSize = m.params < 1e6;
411
+ else if (activeSizeFilter === '10M') passSize = m.params < 10e6;
412
+ else if (activeSizeFilter === '100M') passSize = m.params < 100e6;
413
+ else if (activeSizeFilter === '1B') passSize = m.params < 1e9;
414
+ else if (activeSizeFilter === '3B') passSize = m.params < 3e9;
415
+
416
+ // Search query
417
+ let passSearch = true;
418
+ if (searchQuery.trim() !== '') {
419
+ const q = searchQuery.toLowerCase();
420
+ passSearch = m.name.toLowerCase().includes(q) || m.creator.toLowerCase().includes(q);
421
+ }
422
+
423
+ return passSize && passSearch;
424
+ });
425
+
426
+ filtered.forEach((m, idx) => {
427
+ const tr = document.createElement('tr');
428
+ tr.className = "hover:bg-darkbg/80 transition border-b border-darkborder/50";
429
+
430
+ const color = getCreatorColor(m.creator);
431
+
432
+ tr.innerHTML = `
433
+ <td class="py-3 px-3 text-center text-slate-400 font-sans text-xs font-semibold">${idx + 1}</td>
434
+ <td class="py-3 px-3 font-semibold font-sans text-slate-100 flex items-center gap-2">
435
+ <span class="w-2 h-2 rounded-full inline-block" style="background-color: ${color}"></span>
436
+ ${m.name}
437
+ </td>
438
+ <td class="py-3 px-3 font-sans">
439
+ <span class="inline-flex items-center gap-1 px-2 py-0.5 rounded text-[11px] font-medium text-white/90 border border-white/10" style="background-color: ${color}20; color: ${color}; border-color: ${color}40">
440
+ ${m.creator}
441
+ </span>
442
+ </td>
443
+ <td class="py-3 px-3 text-right text-slate-400">${formatParams(m.params)}</td>
444
+ <td class="py-3 px-3 text-right font-bold text-brand-400 font-sans text-sm">${m.overall.toFixed(1)}%</td>
445
+ <td class="py-3 px-3 text-right text-slate-300">${(m.scores['AIME 2026'] * 100).toFixed(1)}%</td>
446
+ <td class="py-3 px-3 text-right text-slate-300">${(m.scores['Arc_easy'] * 100).toFixed(1)}%</td>
447
+ <td class="py-3 px-3 text-right text-slate-300">${(m.scores['Arc_challenge'] * 100).toFixed(1)}%</td>
448
+ <td class="py-3 px-3 text-right text-slate-300">${(m.scores['PIQA'] * 100).toFixed(1)}%</td>
449
+ <td class="py-3 px-3 text-right text-slate-300">${(m.scores['HellaSwag'] * 100).toFixed(1)}%</td>
450
+ <td class="py-3 px-3 text-center">
451
+ <a href="${m.card_url}" target="_blank" class="text-slate-400 hover:text-brand-400 text-xs transition">
452
+ <i class="fa-solid fa-arrow-up-right-from-square"></i>
453
+ </a>
454
+ </td>
455
+ `;
456
+
457
+ tbody.appendChild(tr);
458
+ });
459
+
460
+ // Update Statistics Banner
461
+ document.getElementById('stat-total-models').innerText = processedModels.length;
462
+ if (processedModels.length > 0) {
463
+ const top = [...processedModels].sort((a,b) => b.overall - a.overall)[0];
464
+ document.getElementById('stat-top-score').innerText = top.overall.toFixed(1) + '%';
465
+ document.getElementById('stat-top-model').innerText = `${top.name} (${top.creator})`;
466
+ }
467
+ }
468
+
469
+ // =========================================================================
470
+ // CHARTS LOGIC (Scatter Chart, Org Share, Radar Chart)
471
+ // =========================================================================
472
+
473
+ function initScatterChart() {
474
+ const ctx = document.getElementById('scatterChart').getContext('2d');
475
+
476
+ const scatterData = processedModels.map(m => ({
477
+ x: m.params,
478
+ y: m.overall,
479
+ modelName: m.name,
480
+ creator: m.creator,
481
+ color: getCreatorColor(m.creator)
482
+ }));
483
+
484
+ // Sort scatterData by params for trendline calculations
485
+ scatterData.sort((a, b) => a.x - b.x);
486
+
487
+ // Logarithmic regression fit for average line
488
+ const avgTrendPoints = generateTrendline(scatterData, 0.5);
489
+ const topTrendPoints = generateTrendline(scatterData, 0.95); // Top 10% efficiency line
490
+
491
+ if (scatterChartObj) scatterChartObj.destroy();
492
+
493
+ scatterChartObj = new Chart(ctx, {
494
+ type: 'scatter',
495
+ data: {
496
+ datasets: [
497
+ {
498
+ label: 'SLM Models',
499
+ data: scatterData,
500
+ backgroundColor: scatterData.map(d => d.color),
501
+ pointRadius: 6,
502
+ pointHoverRadius: 9,
503
+ pointBorderColor: '#ffffff',
504
+ pointBorderWidth: 1
505
+ },
506
+ {
507
+ label: 'Average Trend',
508
+ data: avgTrendPoints,
509
+ type: 'line',
510
+ borderColor: '#94a3b8',
511
+ borderWidth: 2,
512
+ borderDash: [5, 5],
513
+ pointRadius: 0,
514
+ fill: false
515
+ },
516
+ {
517
+ label: 'Efficient Frontier (Top 10%)',
518
+ data: topTrendPoints,
519
+ type: 'line',
520
+ borderColor: '#22c55e',
521
+ borderWidth: 2,
522
+ pointRadius: 0,
523
+ fill: false
524
+ }
525
+ ]
526
+ },
527
+ options: {
528
+ responsive: true,
529
+ maintainAspectRatio: false,
530
+ scales: {
531
+ x: {
532
+ type: 'logarithmic',
533
+ title: { display: true, text: 'Parameters Count (Log Scale)', color: '#94a3b8' },
534
+ grid: { color: '#1f2937' },
535
+ ticks: {
536
+ color: '#94a3b8',
537
+ callback: function(value) {
538
+ return formatParams(value);
539
+ }
540
+ }
541
+ },
542
+ y: {
543
+ title: { display: true, text: 'Intelligence Index (%)', color: '#94a3b8' },
544
+ grid: { color: '#1f2937' },
545
+ ticks: { color: '#94a3b8' },
546
+ min: 0,
547
+ max: 100
548
+ }
549
+ },
550
+ plugins: {
551
+ legend: {
552
+ labels: { color: '#cbd5e1', font: { size: 11 } }
553
+ },
554
+ tooltip: {
555
+ callbacks: {
556
+ label: function(context) {
557
+ const point = context.raw;
558
+ if (point.modelName) {
559
+ return `${point.modelName} (${point.creator}): ${point.y.toFixed(1)}% | ${formatParams(point.x)} params`;
560
+ }
561
+ return `${context.dataset.label}: ${context.parsed.y.toFixed(1)}%`;
562
+ }
563
+ }
564
+ }
565
+ }
566
+ }
567
+ });
568
+ }
569
+
570
+ // Helper to generate simple exponential/log trendline points
571
+ function generateTrendline(data, quantileOffset) {
572
+ if (data.length === 0) return [];
573
+
574
+ const minLog = Math.log10(data[0].x);
575
+ const maxLog = Math.log10(data[data.length - 1].x);
576
+ const points = [];
577
+ const steps = 20;
578
+
579
+ for (let i = 0; i <= steps; i++) {
580
+ const currentLog = minLog + (i / steps) * (maxLog - minLog);
581
+ const currentX = Math.pow(10, currentLog);
582
+
583
+ // Simple logarithmic fit estimation: Y = a * log10(X) + b
584
+ let estimatedY = 15 + 8 * (currentLog - 6);
585
+ if (quantileOffset > 0.8) estimatedY += 12; // Push top 10% higher
586
+
587
+ estimatedY = Math.min(98, Math.max(5, estimatedY));
588
+ points.push({ x: currentX, y: estimatedY });
589
+ }
590
+
591
+ return points;
592
+ }
593
+
594
+ function initShareChart() {
595
+ const ctx = document.getElementById('shareChart').getContext('2d');
596
+
597
+ const creatorCounts = {};
598
+ processedModels.forEach(m => {
599
+ creatorCounts[m.creator] = (creatorCounts[m.creator] || 0) + 1;
600
+ });
601
+
602
+ const labels = Object.keys(creatorCounts);
603
+ const counts = Object.values(creatorCounts);
604
+ const colors = labels.map(l => getCreatorColor(l));
605
+
606
+ if (shareChartObj) shareChartObj.destroy();
607
+
608
+ shareChartObj = new Chart(ctx, {
609
+ type: 'doughnut',
610
+ data: {
611
+ labels: labels,
612
+ datasets: [{
613
+ data: counts,
614
+ backgroundColor: colors,
615
+ borderColor: '#111827',
616
+ borderWidth: 2
617
+ }]
618
+ },
619
+ options: {
620
+ responsive: true,
621
+ maintainAspectRatio: false,
622
+ plugins: {
623
+ legend: {
624
+ position: 'bottom',
625
+ labels: { color: '#cbd5e1', font: { size: 10 }, boxWidth: 12 }
626
+ }
627
+ },
628
+ cutout: '65%'
629
+ }
630
+ });
631
+ }
632
+
633
+ // Radar & Insights Logic
634
+ function populateInsightSelector() {
635
+ const select = document.getElementById('insight-model-select');
636
+ select.innerHTML = '';
637
+
638
+ processedModels.forEach((m) => {
639
+ const opt = document.createElement('option');
640
+ opt.value = m.name;
641
+ opt.textContent = `${m.name} (${m.creator}) - ${m.overall.toFixed(1)}%`;
642
+ select.appendChild(opt);
643
+ });
644
+
645
+ select.addEventListener('change', (e) => {
646
+ updateInsights(e.target.value);
647
+ });
648
+
649
+ if (processedModels.length > 0) {
650
+ updateInsights(processedModels[0].name);
651
+ }
652
+ }
653
+
654
+ function calculateBenchmarkAverages() {
655
+ const averages = {};
656
+ for (const bench of Object.keys(BENCHMARK_CONFIG)) {
657
+ let sum = 0;
658
+ processedModels.forEach(m => {
659
+ sum += (m.scores[bench] || 0) * 100;
660
+ });
661
+ averages[bench] = sum / (processedModels.length || 1);
662
+ }
663
+ return averages;
664
+ }
665
+
666
+ function updateInsights(modelName) {
667
+ const model = processedModels.find(m => m.name === modelName);
668
+ if (!model) return;
669
+
670
+ const benchAverages = calculateBenchmarkAverages();
671
+ const benchKeys = Object.keys(BENCHMARK_CONFIG);
672
+
673
+ const modelScores = benchKeys.map(k => (model.scores[k] * 100) || 0);
674
+ const avgScores = benchKeys.map(k => benchAverages[k]);
675
+
676
+ // Render Radar Chart
677
+ const ctx = document.getElementById('radarChart').getContext('2d');
678
+ if (radarChartObj) radarChartObj.destroy();
679
+
680
+ const creatorColor = getCreatorColor(model.creator);
681
+
682
+ radarChartObj = new Chart(ctx, {
683
+ type: 'radar',
684
+ data: {
685
+ labels: benchKeys,
686
+ datasets: [
687
+ {
688
+ label: model.name,
689
+ data: modelScores,
690
+ backgroundColor: `${creatorColor}33`,
691
+ borderColor: creatorColor,
692
+ borderWidth: 2,
693
+ pointBackgroundColor: creatorColor
694
+ },
695
+ {
696
+ label: 'SLM Average',
697
+ data: avgScores,
698
+ backgroundColor: 'rgba(148, 163, 184, 0.1)',
699
+ borderColor: '#64748b',
700
+ borderWidth: 1.5,
701
+ borderDash: [4, 4],
702
+ pointBackgroundColor: '#64748b'
703
+ }
704
+ ]
705
+ },
706
+ options: {
707
+ responsive: true,
708
+ maintainAspectRatio: false,
709
+ scales: {
710
+ r: {
711
+ angleLines: { color: '#1f2937' },
712
+ grid: { color: '#1f2937' },
713
+ pointLabels: { color: '#cbd5e1', font: { size: 11 } },
714
+ ticks: { display: false },
715
+ suggestedMin: 0,
716
+ suggestedMax: 100
717
+ }
718
+ },
719
+ plugins: {
720
+ legend: { labels: { color: '#cbd5e1', font: { size: 11 } } }
721
+ }
722
+ }
723
+ });
724
+
725
+ // Update Header Card
726
+ const headerDiv = document.getElementById('insight-model-header');
727
+ headerDiv.innerHTML = `
728
+ <div>
729
+ <h3 class="text-base font-bold text-slate-100">${model.name}</h3>
730
+ <p class="text-xs text-slate-400">${model.creator} • ${formatParams(model.params)} parameters</p>
731
+ </div>
732
+ <div class="text-right">
733
+ <div class="text-2xl font-black text-brand-400">${model.overall.toFixed(1)}%</div>
734
+ <p class="text-[10px] text-slate-500 uppercase tracking-wider">Overall Score</p>
735
+ </div>
736
+ `;
737
+
738
+ // Strengths and Weaknesses Lists
739
+ const strengthsUl = document.getElementById('insight-strengths');
740
+ const weaknessesUl = document.getElementById('insight-weaknesses');
741
+
742
+ strengthsUl.innerHTML = '';
743
+ weaknessesUl.innerHTML = '';
744
+
745
+ benchKeys.forEach(bench => {
746
+ const score = (model.scores[bench] * 100) || 0;
747
+ const avg = benchAverages[bench];
748
+ const diff = score - avg;
749
+
750
+ const li = document.createElement('li');
751
+ li.className = "flex items-center justify-between";
752
+
753
+ if (diff >= 0) {
754
+ li.innerHTML = `
755
+ <span>${bench}: <strong class="text-white">${score.toFixed(1)}%</strong></span>
756
+ <span class="text-emerald-400 text-[11px] font-mono">+${diff.toFixed(1)}% vs avg</span>
757
+ `;
758
+ strengthsUl.appendChild(li);
759
+ } else {
760
+ li.innerHTML = `
761
+ <span>${bench}: <strong class="text-white">${score.toFixed(1)}%</strong></span>
762
+ <span class="text-rose-400 text-[11px] font-mono">${diff.toFixed(1)}% vs avg</span>
763
+ `;
764
+ weaknessesUl.appendChild(li);
765
+ }
766
+ });
767
+
768
+ if (!strengthsUl.hasChildNodes()) {
769
+ strengthsUl.innerHTML = '<li class="text-slate-500 italic">No metrics above current SLM average.</li>';
770
+ }
771
+ if (!weaknessesUl.hasChildNodes()) {
772
+ weaknessesUl.innerHTML = '<li class="text-slate-500 italic">Exceeds average across all benchmark benchmarks!</li>';
773
+ }
774
+ }
775
+
776
+ // =========================================================================
777
+ // EVENT LISTENERS & MODAL HANDLERS
778
+ // =========================================================================
779
+
780
+ function toggleSubmitModal() {
781
+ const modal = document.getElementById('submit-modal');
782
+ modal.classList.toggle('hidden');
783
+ }
784
+
785
+ document.addEventListener('DOMContentLoaded', () => {
786
+ initData();
787
+ renderTable();
788
+ initScatterChart();
789
+ initShareChart();
790
+ populateInsightSelector();
791
+
792
+ // Search input listener
793
+ document.getElementById('search-input').addEventListener('input', (e) => {
794
+ searchQuery = e.target.value;
795
+ renderTable();
796
+ });
797
+
798
+ // Filter button listeners
799
+ document.querySelectorAll('.size-filter-btn').forEach(btn => {
800
+ btn.addEventListener('click', (e) => {
801
+ document.querySelectorAll('.size-filter-btn').forEach(b => {
802
+ b.classList.remove('active', 'bg-brand-600', 'text-white');
803
+ b.classList.add('text-slate-400');
804
+ });
805
+
806
+ e.target.classList.add('active', 'bg-brand-600', 'text-white');
807
+ e.target.classList.remove('text-slate-400');
808
+
809
+ activeSizeFilter = e.target.getAttribute('data-size');
810
+ renderTable();
811
+ });
812
+ });
813
+ });
814
+ </script>
815
+ </body>
816
+ </html>