TheFey commited on
Commit
4902e39
·
verified ·
1 Parent(s): 281d5b3

Upload 5 files

Browse files
Dockerfile ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.10-slim
2
+
3
+ # Set up a new user named "user" with user ID 1000
4
+ RUN useradd -m -u 1000 user
5
+
6
+ # Switch to the "user" user
7
+ USER user
8
+
9
+ # Set home to the user's home directory
10
+ ENV HOME=/home/user \
11
+ PATH=/home/user/.local/bin:$PATH
12
+
13
+ # Set the working directory to the user's home directory
14
+ WORKDIR $HOME/app
15
+
16
+ # Install dependencies
17
+ COPY --chown=user requirements.txt .
18
+ RUN pip install --no-cache-dir -r requirements.txt
19
+
20
+ # Copy the current directory contents into the container
21
+ COPY --chown=user . .
22
+
23
+ # Command to run the application
24
+ CMD ["python", "app.py"]
app.py ADDED
@@ -0,0 +1,725 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import dash
2
+ from dash import html, dcc, Input, Output, State
3
+ import dash_ag_grid as dag
4
+ import pandas as pd
5
+ import numpy as np
6
+ from datetime import datetime, timedelta
7
+ import base64
8
+ import os
9
+
10
+ def load_leaderboard_data(csv_file_path):
11
+ try:
12
+ df = pd.read_csv(csv_file_path, na_values=['NA'])
13
+
14
+ # Add type sort value
15
+ def get_type_sort_value(row):
16
+ if row['Base']:
17
+ return 0 # B
18
+ return 4
19
+
20
+ df['model_type_sort'] = df.apply(get_type_sort_value, axis=1)
21
+
22
+ # Store model name and link separately
23
+ df['Model_Link'] = df['Model Link'].fillna('')
24
+ df['Model_Display'] = df['author/model_name']
25
+
26
+ # Add pinned and selected columns
27
+ df['pinned'] = False
28
+ df['selected'] = False
29
+
30
+ # Round numeric columns and handle NA values
31
+ numeric_columns = df.select_dtypes(include=[np.number]).columns
32
+ for col in numeric_columns:
33
+ df[col] = df[col].apply(lambda x: None if pd.isna(x) else round(x, 3))
34
+
35
+ # Sort with multiple keys in the required order
36
+ df = df.sort_values(
37
+ by=['Score', '8k 🪡', '16k 🪡'],
38
+ ascending=[False, False, False] # Score -> 8k -> 16k
39
+ )
40
+
41
+ return df
42
+ except Exception as e:
43
+ print(f"Error loading CSV file: {e}")
44
+ return pd.DataFrame()
45
+
46
+ # Initialize the Dash app
47
+ app = dash.Dash(__name__, external_stylesheets=[
48
+ "https://use.fontawesome.com/releases/v5.15.4/css/all.css"
49
+ ])
50
+ server = app.server
51
+
52
+ # Custom CSS
53
+ app.index_string = '''
54
+ <!DOCTYPE html>
55
+ <html>
56
+ <head>
57
+ {%metas%}
58
+ <title>Fey's Multi-Needle & Behavior Leaderboard</title>
59
+ {%favicon%}
60
+ {%css%}
61
+ <style>
62
+ :root {
63
+ --bg-color: #ffffff;
64
+ --text-color: #000000;
65
+ --grid-bg: #ffffff;
66
+ --grid-border: #ddd;
67
+ --link-color: #007bff;
68
+ --secondary-text: #666;
69
+ --pinned-bg: #f5f5f5;
70
+ --border-color: #ccc;
71
+ }
72
+ @media (prefers-color-scheme: dark) {
73
+ :root {
74
+ --bg-color: #0d1117;
75
+ --text-color: #e6e6e6;
76
+ --grid-bg: #161b22;
77
+ --grid-border: #30363d;
78
+ --link-color: #58a6ff;
79
+ --secondary-text: #8b949e;
80
+ --pinned-bg: #1c2128;
81
+ --border-color: #30363d;
82
+ color-scheme: dark;
83
+ }
84
+ .ag-theme-alpine .ag-menu {
85
+ background-color: #161b22 !important;
86
+ color: #e6e6e6 !important;
87
+ border-color: #30363d !important;
88
+ }
89
+ .ag-theme-alpine .ag-filter-condition {
90
+ background-color: #161b22 !important;
91
+ border-color: #30363d !important;
92
+ }
93
+ .ag-theme-alpine .ag-mini-filter input,
94
+ .ag-theme-alpine .ag-filter input {
95
+ background-color: #0d1117 !important;
96
+ color: #e6e6e6 !important;
97
+ border-color: #30363d !important;
98
+ }
99
+ .ag-theme-alpine .ag-select .ag-picker-field-wrapper {
100
+ background-color: #0d1117 !important;
101
+ color: #e6e6e6 !important;
102
+ border-color: #30363d !important;
103
+ }
104
+ .ag-theme-alpine .ag-picker-field-wrapper {
105
+ border-color: #30363d !important;
106
+ }
107
+ .ag-theme-alpine .ag-select-list {
108
+ background-color: #161b22 !important;
109
+ color: #e6e6e6 !important;
110
+ }
111
+ .ag-theme-alpine .ag-select-list-item:hover {
112
+ background-color: #1c2128 !important;
113
+ }
114
+ .ag-theme-alpine input[type="date"] {
115
+ color-scheme: dark;
116
+ background-color: #161b22;
117
+ color: #e6e6e6;
118
+ border-color: #30363d;
119
+ }
120
+
121
+ .ag-theme-alpine input[type="date"]::-webkit-calendar-picker-indicator {
122
+ background-color: #161b22;
123
+ cursor: pointer;
124
+ filter: invert(0.8);
125
+ }
126
+
127
+ }
128
+ body {
129
+ font-family: 'Segoe UI', Arial, sans-serif;
130
+ margin: 0;
131
+ padding: 20px;
132
+ background-color: var(--bg-color);
133
+ color: var(--text-color);
134
+ }
135
+ /* Header and Title Styles */
136
+ .page-title {
137
+ text-align: center;
138
+ margin: 0;
139
+ font-size: 38px;
140
+ color: var(--text-color) !important;
141
+ }
142
+ .page-subtitle {
143
+ text-align: center;
144
+ margin: 0;
145
+ font-size: 20px;
146
+ font-weight: 600;
147
+ color: var(--text-color) !important;
148
+ }
149
+ /* Filter Styles */
150
+ .model-type-filter {
151
+ color: var(--text-color) !important;
152
+ margin-right: 10px;
153
+ font-weight: bold;
154
+ },
155
+ #model-type-filter label,
156
+ #na-model-filter label {
157
+ color: var(--text-color) !important;
158
+ margin-right: 10px;
159
+ font-weight: bold;
160
+ }
161
+ /* Grid Styles */
162
+ .ag-theme-alpine {
163
+ --ag-font-family: 'Segoe UI', Arial, sans-serif;
164
+ --ag-font-size: 14px;
165
+ --ag-background-color: var(--grid-bg);
166
+ --ag-border-color: var(--grid-border);
167
+ --ag-header-background-color: var(--grid-bg);
168
+ --ag-odd-row-background-color: var(--grid-bg);
169
+ --ag-header-foreground-color: var(--text-color);
170
+ --ag-foreground-color: var(--text-color);
171
+ --ag-row-border-color: var(--grid-border);
172
+ }
173
+ .ag-theme-alpine .ag-pinned-left-header,
174
+ .ag-theme-alpine .ag-cell-last-left-pinned {
175
+ border-right: 2px solid var(--grid-border) !important;
176
+ margin-right: -1px !important;
177
+ }
178
+
179
+ /* Mobile specific fixes */
180
+ .ag-theme-alpine.ag-grid-mobile .ag-pinned-left-header,
181
+ .ag-theme-alpine.ag-grid-mobile .ag-cell-last-left-pinned {
182
+ border-right: 2px solid var(--grid-border) !important;
183
+ }
184
+
185
+ /* Ensure pinned columns maintain their position */
186
+ .ag-theme-alpine .ag-pinned-left-cols-container,
187
+ .ag-theme-alpine .ag-pinned-left-header {
188
+ position: sticky;
189
+ left: 0;
190
+ z-index: 1;
191
+ }
192
+ .ag-floating-top {
193
+ border-bottom: 3px solid var(--border-color) !important;
194
+ }
195
+ .ag-floating-top:empty {
196
+ border-bottom: none !important;
197
+ }
198
+ .pinned-row {
199
+ background-color: var(--pinned-bg) !important;
200
+ font-weight: 500;
201
+ }
202
+ /* Text Alignment Classes */
203
+ .ag-left-aligned-header {
204
+ text-align: left !important;
205
+ }
206
+ .ag-left-aligned-cell {
207
+ text-align: left !important;
208
+ }
209
+ .ag-header-cell-text {
210
+ white-space: normal !important;
211
+ line-height: 1.2em;
212
+ overflow: visible;
213
+ padding-bottom: 4px;
214
+ }
215
+
216
+ .ag-header-cell {
217
+ height: auto !important;
218
+ min-height: 48px;
219
+ }
220
+ .wrap-text {
221
+ white-space: normal !important;
222
+ line-height: 1.2em;
223
+ }
224
+ .no-break {
225
+ white-space: nowrap !important;
226
+ }
227
+ /* Border Classes */
228
+ .border-left {
229
+ border-left: 2px solid var(--grid-border) !important;
230
+ margin-left: -2px !important;
231
+ }
232
+ .border-right {
233
+ border-right: 2px solid var(--grid-border) !important;
234
+ }
235
+ /* Link Styles */
236
+ .model-link {
237
+ color: var(--link-color) !important;
238
+ text-decoration: none;
239
+ }
240
+ .model-link:visited {
241
+ color: var(--link-color) !important;
242
+ }
243
+ .model-link:active {
244
+ color: var(--link-color) !important;
245
+ }
246
+ .model-link:focus {
247
+ color: var(--link-color) !important;
248
+ }
249
+ .ag-theme-alpine a,
250
+ .ag-theme-alpine a:link,
251
+ .ag-theme-alpine a:visited,
252
+ .ag-theme-alpine a:hover,
253
+ .ag-theme-alpine a:active,
254
+ .ag-theme-alpine a:focus {
255
+ color: var(--link-color) !important;
256
+ text-decoration: none !important;
257
+ }
258
+
259
+ .ag-theme-alpine a:hover {
260
+ text-decoration: underline !important;
261
+ }
262
+ .source-link {
263
+ color: var(--link-color) !important;
264
+ text-decoration: none;
265
+ }
266
+ /* Details/Summary Styles */
267
+ .details-summary {
268
+ cursor: pointer;
269
+ font-weight: bold;
270
+ font-size: 1.2em;
271
+ margin-top: 20px;
272
+ color: var(--text-color) !important;
273
+ }
274
+ .ideology-note {
275
+ color: var(--secondary-text) !important;
276
+ font-size: 0.9em;
277
+ }
278
+ /* Markdown Content */
279
+ .markdown-content {
280
+ color: var(--text-color) !important;
281
+ }
282
+ .markdown-content a {
283
+ color: var(--link-color) !important;
284
+ }
285
+ /* Ko-fi Button Visibility */
286
+ .kofi-light {
287
+ display: none;
288
+ }
289
+ .kofi-dark {
290
+ display: none;
291
+ }
292
+ @media (prefers-color-scheme: light) {
293
+ .kofi-light {
294
+ display: block;
295
+ }
296
+ }
297
+ @media (prefers-color-scheme: dark) {
298
+ .kofi-dark {
299
+ display: block;
300
+ }
301
+ /* Dark Theme Specific Overrides */
302
+ .ag-theme-alpine {
303
+ --ag-background-color: #161b22 !important;
304
+ --ag-header-background-color: #161b22 !important;
305
+ --ag-odd-row-background-color: #161b22 !important;
306
+ --ag-row-background-color: #161b22 !important;
307
+ --ag-header-foreground-color: #e6e6e6 !important;
308
+ --ag-foreground-color: #e6e6e6 !important;
309
+ --ag-row-border-color: #30363d !important;
310
+ --ag-border-color: #30363d !important;
311
+ --ag-secondary-border-color: #30363d !important;
312
+ --ag-alpine-active-color: #58a6ff !important;
313
+ --ag-selected-row-background-color: #1c2128 !important;
314
+ --ag-row-hover-color: #1c2128 !important;
315
+ }
316
+ .ag-header-cell-filtered {
317
+ background-color: rgba(88, 166, 255, 0.1) !important;
318
+ }
319
+ input[type="checkbox"] {
320
+ accent-color: var(--link-color);
321
+ }
322
+ /* Ensure text colors in dark mode */
323
+ .page-title,
324
+ .page-subtitle,
325
+ .model-type-filter label,
326
+ #model-type-filter label,
327
+ #na-model-filter label {
328
+ color: #e6e6e6 !important;
329
+ }
330
+ .filter-description,
331
+ .ideology-note {
332
+ color: #8b949e !important;
333
+ }
334
+ }
335
+ a:visited {
336
+ color: var(--link-color) !important;
337
+ }
338
+
339
+ .markdown-content a:visited {
340
+ color: var(--link-color) !important;
341
+ }
342
+ .split-header-container {
343
+ display: flex;
344
+ flex-direction: column;
345
+ line-height: 1.2em;
346
+ }
347
+
348
+ .split-header-top, .split-header-bottom {
349
+ white-space: nowrap;
350
+ }
351
+ .ag-theme-alpine .new-emoji-cell.ag-cell {
352
+ font-size: 18px !important;
353
+ display: flex !important;
354
+ align-items: center !important;
355
+ justify-content: flex-start !important;
356
+ padding-left: 12px !important;
357
+ }
358
+ .ag-ltr .ag-cell {
359
+ border-right-width: 1px;
360
+ justify-content: center;
361
+ display: flex;
362
+ }
363
+ .ag-header-cell-label {
364
+ overflow: hidden;
365
+ text-overflow: ellipsis;
366
+ justify-content: center;
367
+ }
368
+ div.ag-cell.ag-cell-not-inline-editing.ag-cell-normal-height.ag-cell-last-left-pinned {
369
+ justify-content: right;
370
+ }
371
+ </style>
372
+ </head>
373
+ <body>
374
+ {%app_entry%}
375
+ <footer>
376
+ {%config%}
377
+ {%scripts%}
378
+ {%renderer%}
379
+ </footer>
380
+ </body>
381
+ </html>
382
+ '''
383
+
384
+ # Load data
385
+ df = load_leaderboard_data("fmnb-leaderboard-data.csv")
386
+
387
+ # Define helper functions
388
+ def create_numeric_column(field, width=125, sort=None, sortIndex=None, **kwargs):
389
+ column = {
390
+ "field": field,
391
+ "width": width,
392
+ "filter": "agNumberColumnFilter",
393
+ "filterParams": {
394
+ "defaultOption": "inRange",
395
+ "filterOptions": ['equals', 'notEqual', 'greaterThan', 'greaterThanOrEqual', 'lessThan', 'lessThanOrEqual', 'inRange']
396
+ },
397
+ "headerClass": "ag-left-aligned-header wrap-text",
398
+ "cellClass": "ag-left-aligned-cell",
399
+ "wrapHeaderText": True,
400
+ "autoHeaderHeight": True,
401
+ "suppressSizeToFit": True,
402
+ "sortingOrder": ['desc', 'asc'],
403
+ "comparator": {
404
+ "function": """
405
+ function(valueA, valueB, nodeA, nodeB, isInverted) {
406
+ const a = nodeA.data.__sortValue;
407
+ const b = nodeB.data.__sortValue;
408
+ return a - b;
409
+ }
410
+ """
411
+ }
412
+ }
413
+
414
+ # Update filterParams if provided in kwargs
415
+ if 'filterParams' in kwargs:
416
+ column['filterParams'].update(kwargs['filterParams'])
417
+
418
+ if sort:
419
+ column["sort"] = sort
420
+ if sortIndex is not None:
421
+ column["sortIndex"] = sortIndex
422
+ return column
423
+
424
+ def create_text_column(field, width=120):
425
+ return {
426
+ "field": field,
427
+ "width": width,
428
+ "filter": "agTextColumnFilter",
429
+ "filterParams": {
430
+ "defaultOption": "contains",
431
+ "filterOptions": ['contains', 'notContains', 'startsWith', 'endsWith']
432
+ },
433
+ "headerClass": "ag-left-aligned-header wrap-text",
434
+ "cellClass": "ag-left-aligned-cell",
435
+ "wrapHeaderText": True,
436
+ "autoHeaderHeight": True
437
+ }
438
+
439
+ # Define column configurations
440
+ columnDefs = [
441
+ {
442
+ "headerName": "📌",
443
+ "field": "pinned",
444
+ "width": 55,
445
+ "filter": False,
446
+ "suppressMenu": True,
447
+ "cellRenderer": "PinRenderer",
448
+ "sortable": False,
449
+ "pinned": "left"
450
+ },
451
+ {
452
+ "field": "Model_Display",
453
+ "headerName": "Model",
454
+ "cellRenderer": "ModelLink",
455
+ "filter": "agTextColumnFilter",
456
+ "filterParams": {
457
+ "defaultOption": "contains",
458
+ "filterOptions": ['contains', 'notContains', 'startsWith', 'endsWith']
459
+ },
460
+ "width": 420,
461
+ "suppressMenu": False,
462
+ "pinned": "left",
463
+ "headerClass": "ag-left-aligned-header wrap-text",
464
+ "wrapHeaderText": True,
465
+ "autoHeaderHeight": True
466
+ },
467
+ {
468
+ "field": "Score",
469
+ "FontWeight": 700,
470
+ "width": 110,
471
+ "filter": "agNumberColumnFilter",
472
+ "filterParams": {
473
+ "defaultOption": "greaterThanOrEqual"
474
+ },
475
+ "headerClass": "ag-left-aligned-header wrap-text",
476
+ "cellClass": ["ag-left-aligned-cell", "border-left"],
477
+ "wrapHeaderText": True,
478
+ "autoHeaderHeight": True,
479
+ "suppressSizeToFit": True,
480
+ "sortingOrder": ['desc', 'asc'],
481
+ "cellRenderer": "ScoreRenderer"
482
+ },
483
+ {
484
+ "headerName": "Behavior",
485
+ "headerClass": "ag-left-aligned-header wrap-text",
486
+ "cellClass": ["ag-left-aligned-cell", "border-left"],
487
+ "field": "Behavior",
488
+ "width": 120,
489
+ "filter": False,
490
+ "suppressMenu": True,
491
+ "cellRenderer": "BehaviorRenderer",
492
+ "sortable": True,
493
+ "sortingOrder": ['asc', 'desc']
494
+ },
495
+ {
496
+ "field": "8k 🪡",
497
+ "headerName": "8k 🪡",
498
+ "width": 100,
499
+ "filter": "agNumberColumnFilter",
500
+ "filterParams": {
501
+ "defaultOption": "greaterThanOrEqual",
502
+ "filterOptions": ['equals', 'notEqual', 'greaterThan', 'greaterThanOrEqual', 'lessThan', 'lessThanOrEqual', 'inRange']
503
+ },
504
+ "headerClass": "ag-left-aligned-header wrap-text",
505
+ "cellClass": ["ag-left-aligned-cell", "border-left"],
506
+ "wrapHeaderText": True,
507
+ "autoHeaderHeight": True,
508
+ "suppressSizeToFit": True,
509
+ "sortingOrder": ['desc', 'asc']
510
+ },
511
+ create_numeric_column("16k 🪡", width=100, filterParams={
512
+ "defaultOption": "greaterThanOrEqual"
513
+ }),
514
+ # Misc Columns
515
+ {
516
+ "field": "Size",
517
+ "width": 100,
518
+ "filter": "agNumberColumnFilter",
519
+ "filterParams": {
520
+ "defaultOption": "equals",
521
+ "filterOptions": ['equals', 'notEqual', 'greaterThan', 'greaterThanOrEqual', 'lessThan', 'lessThanOrEqual', 'inRange']
522
+ },
523
+ "headerClass": "ag-left-aligned-header wrap-text",
524
+ "cellClass": "ag-left-aligned-cell",
525
+ "wrapHeaderText": True,
526
+ "autoHeaderHeight": True,
527
+ "suppressSizeToFit": True,
528
+ "sortingOrder": ['desc', 'asc'],
529
+ },
530
+ {
531
+ "field": "model_type_sort",
532
+ "hide": True
533
+ },
534
+ {
535
+ "headerName": "Type",
536
+ "field": "model_type_sort", # sort field directly
537
+ "width": 90,
538
+ "filter": False,
539
+ "suppressMenu": True,
540
+ "cellRenderer": "TypeRenderer",
541
+ "sortable": True,
542
+ "sortingOrder": ['asc', 'desc']
543
+ },
544
+ {
545
+ "headerName": "Settings",
546
+ "field": "Settings",
547
+ "width": 120,
548
+ "filter": False,
549
+ "suppressMenu": True,
550
+ "cellClass": "ag-left-aligned-cell",
551
+ },
552
+ {
553
+ "headerName": "New",
554
+ "field": "New",
555
+ "width": 70,
556
+ "filter": False,
557
+ "suppressMenu": True,
558
+ "cellClass": "ag-left-aligned-cell",
559
+ }
560
+ ]
561
+
562
+
563
+ # Define the grid options with postSort
564
+ dashGridOptions = {
565
+ "animateRows": True,
566
+ "pagination": False,
567
+ "enableCellTextSelection": True,
568
+ "ensureDomOrder": True,
569
+ "suppressRowClickSelection": True,
570
+ "suppressCellFocus": True,
571
+ "getRowId": "params => params.data.Model_Display",
572
+ "pinnedTopRowData": [],
573
+ "suppressMaintainUnsortedOrder": True,
574
+ "suppressMultiSort": True,
575
+ "rowBuffer": 10,
576
+ "maxBlocksInCache": 2,
577
+ "icons": {
578
+ "menu": '<i class="fas fa-search" style="color: var(--text-color)"></i>'
579
+ },
580
+ "theme": "ag-theme-alpine-dark" if "prefers-color-scheme: dark" else "ag-theme-alpine",
581
+ "columnState": {
582
+ "function": """
583
+ function() {
584
+ return {
585
+ columnVisibility: {}
586
+ };
587
+ }
588
+ """
589
+ }
590
+ }
591
+
592
+ # Define the layout
593
+ app.layout = html.Div([
594
+ dcc.Store(id='pinned-models-store', data=[]),
595
+
596
+ # Title
597
+ html.Div([
598
+ html.H1("🪡 Fey's MNB Leaderboard 🪡",
599
+ className="page-title",
600
+ style={'fontSize': '38px'}),
601
+ html.H2("Multi-Needle & Behavior Evaluation",
602
+ className="page-subtitle"),
603
+ ], style={'marginBottom': '30px'}),
604
+
605
+ # Notice
606
+ # html.Div(
607
+ # html.P(
608
+ # "None",
609
+ # style={'textAlign': 'center', 'color': 'red', 'fontSize': '0.9em'}
610
+ # )
611
+ # ),
612
+
613
+ # Grid
614
+ html.Div([
615
+ dag.AgGrid(
616
+ id='leaderboard-grid',
617
+ columnDefs=columnDefs,
618
+ rowData=df.to_dict('records'),
619
+ defaultColDef={
620
+ "sortable": True,
621
+ "resizable": True,
622
+ "filter": "agNumberColumnFilter",
623
+ "floatingFilter": False,
624
+ "sortingOrder": ['desc', 'asc'],
625
+ "filterParams": {
626
+ "defaultOption": "between"
627
+ },
628
+ "comparator": {
629
+ "function": """
630
+ function(valueA, valueB, nodeA, nodeB, isInverted) {
631
+ const isEmptyA = valueA === null || valueA === undefined || valueA === '' || isNaN(valueA);
632
+ const isEmptyB = valueB === null || valueB === undefined || valueB === '' || isNaN(valueB);
633
+
634
+ // Force empty values to bottom
635
+ if (isEmptyA && !isEmptyB) return 1;
636
+ if (!isEmptyA && isEmptyB) return -1;
637
+ if (isEmptyA && isEmptyB) return 0;
638
+
639
+ // Normal comparison for non-empty values
640
+ if (typeof valueA === 'number' && typeof valueB === 'number') {
641
+ return valueA - valueB;
642
+ }
643
+ return String(valueA).localeCompare(String(valueB));
644
+ }
645
+ """
646
+ }
647
+ },
648
+ dashGridOptions=dashGridOptions,
649
+ dangerously_allow_code=True,
650
+ className="ag-theme-alpine",
651
+ style={"height": "600px", "width": "100%"},
652
+ enableEnterpriseModules=False,
653
+ getRowId="params.data.Model_Display"
654
+ )
655
+ ], style={'marginBottom': '10px'}),
656
+
657
+ # Description
658
+ html.Div([
659
+ html.H3("Info", style={'fontSize': '22px', 'marginBottom': '0px'}),
660
+
661
+ html.P([html.Strong(""), "This latest reiteration of the leaderboard has finally made it to Hugging Face with extended functionality based on the UGI leaderboard, enjoy!"],
662
+ style={'marginTop': '7px', 'marginBottom': '4px'}),
663
+
664
+ html.P([html.Strong("Score:"), " Primarily based on the scoring in the multi-needle test at 8k / 16k context, weighted towards 16k."],
665
+ style={'marginTop': '7px', 'marginBottom': '4px'}),
666
+
667
+ html.P([html.Strong("Behavior:"), " Qualitative assessment of the model's behavior during the evaluation. User discretion is advised, as it only has a minor impact on the final score."], style={'marginTop': '7px', 'marginBottom': '4px'}),
668
+
669
+ html.P([html.Strong("Difficulty:"), " The current difficulty is only set at a medium level. (Silver Tier 1)"], style={'marginTop': '7px', 'marginBottom': '4px'}),
670
+
671
+ html.P([html.Strong("Version:"), " 4.0"], style={'marginTop': '7px', 'marginBottom': '4px'}),
672
+
673
+ html.Br(),
674
+
675
+ html.Details([
676
+ html.Summary("Recommended Settings",
677
+ style={
678
+ 'fontWeight': 'bold',
679
+ 'fontSize': '1em',
680
+ 'marginLeft': '0px',
681
+ 'cursor': 'pointer'
682
+ }),
683
+ html.Ul([
684
+ html.Br(),
685
+ html.Li(["1: Recommended to manually set a RoPE Frequency of 2650000 with Nemo based models when using >8k context.",html.Br(),"LLama.cpp: --rope-freq-base 2650000 (RoPE Base in KoboldCpp)",html.Br(),"EXL2: rope_alpha 2.65"]),
686
+ html.Br(),
687
+ html.Li("2: Recommended to set </s> as an additional stopping token when using these models with ChatML."),
688
+ ], style={'marginTop': '0px', 'marginBottom': '16px', 'marginLeft': '40px'})
689
+ ], style={'marginBottom': '16px'}),
690
+
691
+ ], style={
692
+ 'maxWidth': '1200px',
693
+ 'margin': '0 auto',
694
+ 'padding': '0 20px',
695
+ 'color': 'var(--text-color)'
696
+ }),
697
+
698
+ ], style={'maxWidth': '100%', 'margin': '0 auto'})
699
+
700
+ if __name__ == '__main__':
701
+
702
+ app.run_server(host='0.0.0.0', port=8050)
703
+ app.clientside_callback(
704
+ """
705
+ function(n_clicks) {
706
+ if (!window.gridApi) return;
707
+
708
+ const pinnedRows = window.gridApi.getGridOption('pinnedTopRowData') || [];
709
+
710
+ if (pinnedRows.length > 0) {
711
+ const pinnedIds = new Set(pinnedRows.map(row => row.Model_Display));
712
+ const currentRows = [];
713
+ window.gridApi.forEachNode(node => {
714
+ if (!pinnedIds.has(node.data.Model_Display)) {
715
+ currentRows.push(node.data);
716
+ }
717
+ });
718
+ window.gridApi.setGridOption('rowData', currentRows);
719
+ }
720
+ return window.dash_clientside.no_update;
721
+ }
722
+ """,
723
+ Output('leaderboard-grid', 'rowData'),
724
+ Input('model-type-filter', 'value')
725
+ )
assets/dashAgGridComponentFunctions.js ADDED
@@ -0,0 +1,170 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ var dagcomponentfuncs = window.dashAgGridComponentFunctions = window.dashAgGridComponentFunctions || {};
2
+
3
+ dagcomponentfuncs.ModelLink = function(props) {
4
+ if (!props.data.Model_Link) {
5
+ return props.value; // Just return text if no link
6
+ }
7
+ return React.createElement(
8
+ 'a',
9
+ {
10
+ href: props.data.Model_Link,
11
+ target: '_blank',
12
+ style: {
13
+ color: '#007bff',
14
+ textDecoration: 'none'
15
+ }
16
+ },
17
+ props.value
18
+ );
19
+ };
20
+
21
+ dagcomponentfuncs.PinRenderer = function(props) {
22
+ return React.createElement(
23
+ 'div',
24
+ {
25
+ onClick: function() {
26
+ const api = props.api;
27
+ const modelId = props.data.Model_Display;
28
+ const isPinned = props.data.pinned || false;
29
+
30
+ if (isPinned) {
31
+ // Unpin
32
+ const currentPinned = api.getGridOption('pinnedTopRowData') || [];
33
+ const newPinnedRows = currentPinned.filter(row => row.Model_Display !== modelId);
34
+ api.setGridOption('pinnedTopRowData', newPinnedRows);
35
+ } else {
36
+ // Pin
37
+ const currentPinned = api.getGridOption('pinnedTopRowData') || [];
38
+ const pinnedRow = {...props.data, pinned: true};
39
+ api.setGridOption('pinnedTopRowData', [...currentPinned, pinnedRow]);
40
+ }
41
+ },
42
+ style: {
43
+ cursor: 'pointer',
44
+ textAlign: 'center',
45
+ fontSize: '16px'
46
+ }
47
+ },
48
+ props.data.pinned ? '📌' : '☐'
49
+ );
50
+ };
51
+
52
+ dagcomponentfuncs.TypeRenderer = function(props) {
53
+ const typeMap = {
54
+ 'Base': ['Base', '#ddd']
55
+ };
56
+
57
+ // Determine type from raw flags
58
+ let type = 'Unknown';
59
+ if (props.data['Base']) {
60
+ type = 'Base';
61
+ }
62
+
63
+ const [letter, color] = typeMap[type] || ['Other', '#999'];
64
+
65
+ return React.createElement('div', {
66
+ style: {
67
+ display: 'flex',
68
+ alignItems: 'center',
69
+ height: '100%'
70
+ }
71
+ },
72
+ React.createElement('div', {
73
+ style: {
74
+ color: color,
75
+ display: 'flex',
76
+ alignItems: 'center',
77
+ justifyContent: 'center',
78
+ fontWeight: 'bold',
79
+ fontSize: '14px',
80
+ lineHeight: '1',
81
+ textAlign: 'center'
82
+ }
83
+ }, letter)
84
+ );
85
+ };
86
+
87
+ dagcomponentfuncs.BehaviorRenderer = function(props) {
88
+ const typeMap = {
89
+ '10': ['10', '#6bde57'],
90
+ '9': ['9', '#88bd11'],
91
+ '8': ['8', '#b0d38d'],
92
+ '7': ['7', '#c3c669'],
93
+ '6': ['6', '#dabe78'],
94
+ '5': ['5', '#cb7951']
95
+ };
96
+
97
+ let type = props.data['Behavior'];
98
+
99
+ const [behavior, color] = typeMap[type] || ['?', '#999'];
100
+
101
+ return React.createElement('div', {
102
+ style: {
103
+ display: 'flex',
104
+ alignItems: 'center',
105
+ height: '100%'
106
+ }
107
+ },
108
+ React.createElement('div', {
109
+ style: {
110
+ color: color,
111
+ display: 'flex',
112
+ alignItems: 'center',
113
+ justifyContent: 'center',
114
+ fontWeight: 'bold',
115
+ fontSize: '14px',
116
+ lineHeight: '1',
117
+ textAlign: 'center'
118
+ }
119
+ }, behavior)
120
+ );
121
+ };
122
+
123
+ dagcomponentfuncs.ScoreRenderer = function(props) {
124
+ const typeMap = {
125
+ '10': ['#6bde57'],
126
+ '9': ['#88bd11'],
127
+ '8': ['#b0d38d'],
128
+ '7': ['#c3c669'],
129
+ '6': ['#dabe78'],
130
+ '5': ['#cb7951']
131
+ };
132
+
133
+ let type = 'Unknown';
134
+ if (props.data['Score'] >= 90) {
135
+ type = '10';
136
+ } else if (props.data['Score'] >= 80) {
137
+ type = '9';
138
+ } else if (props.data['Score'] >= 70) {
139
+ type = '8';
140
+ } else if (props.data['Score'] >= 60) {
141
+ type = '7';
142
+ } else if (props.data['Score'] >= 50) {
143
+ type = '6';
144
+ } else if (props.data['Score'] >= 40) {
145
+ type = '5';
146
+ }
147
+
148
+ const [score, color] = [props.data['Score'], typeMap[type]] || [props.data['Score'], '#999'];
149
+
150
+ return React.createElement('div', {
151
+ style: {
152
+ display: 'flex',
153
+ alignItems: 'center',
154
+ height: '100%'
155
+ }
156
+ },
157
+ React.createElement('div', {
158
+ style: {
159
+ color: color,
160
+ display: 'flex',
161
+ alignItems: 'center',
162
+ justifyContent: 'center',
163
+ fontWeight: 'bold',
164
+ fontSize: '14px',
165
+ lineHeight: '1',
166
+ textAlign: 'center'
167
+ }
168
+ }, score)
169
+ );
170
+ };
fmnb-leaderboard-data.csv ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ author/model_name,Score,Behavior,8k 🪡,16k 🪡,Size,New,Base,Model Link,Settings
2
+ TheDrummer/Cydonia-24B-v4.1,93,10,94,93,24B,,FALSE,https://huggingface.co/TheDrummer/Cydonia-24B-v4.1,
3
+ mistralai/Mistral-Small-3.2-24B-Instruct-2506,88,10,92,86,24B,,TRUE,https://huggingface.co/mistralai/Mistral-Small-3.2-24B-Instruct-2506,
4
+ ConicCat/Mistral-Small-3.2-AntiRep-24B,87,10,94,83,24B,,FALSE,https://huggingface.co/ConicCat/Mistral-Small-3.2-AntiRep-24B,
5
+ TheDrummer/Cydonia-R1-24B-v4,84,10,85,83,24B,,FALSE,https://huggingface.co/TheDrummer/Cydonia-R1-24B-v4,
6
+ TheDrummer/Cydonia-24B-v4,78,10,86,74,24B,,FALSE,https://huggingface.co/TheDrummer/Cydonia-24B-v4,
7
+ zerofata/MS3.2-PaintedFantasy-v2-24B,78,10,89,72,24B,,FALSE,https://huggingface.co/zerofata/MS3.2-PaintedFantasy-v2-24B,
8
+ kyx0r/Neona-12B,75,9,92,70,12B,,FALSE,https://huggingface.co/kyx0r/Neona-12B,1
9
+ DreadPoor/Irix-12B-Model_Stock,73,8,91,70,12B,,FALSE,https://huggingface.co/DreadPoor/Irix-12B-Model_Stock,1
10
+ Nitral-AI/CaptainErisNebula-12B-AE-v1,71,9,92,64,12B,,FALSE,https://huggingface.co/Nitral-AI/CaptainErisNebula-12B-AE-v1,1
11
+ Nitral-AI/Irixxed-Magcap-12B-Slerp,66,7,91,62,12B,,FALSE,https://huggingface.co/Nitral-AI/Irixxed-Magcap-12B-Slerp,1
12
+ Nitral-AI/CaptainErisNebula-12B-AE-v1r,67,8,91,61,12B,,FALSE,https://huggingface.co/Nitral-AI/CaptainErisNebula-12B-AE-v1r,1
13
+ Doctor-Shotgun/MS3.2-24B-Magnum-Diamond,68,9,69,71,24B,,FALSE,https://huggingface.co/Doctor-Shotgun/MS3.2-24B-Magnum-Diamond,
14
+ Entropicengine/Pinecone-Rune-12b,68,9,87,61,12B,,FALSE,https://huggingface.co/Entropicengine/Pinecone-Rune-12b,1 & 2
15
+ DreadPoor/Ward-12B-Model_Stock,67,9,86,61,12B,,FALSE,https://huggingface.co/DreadPoor/Ward-12B-Model_Stock,1
16
+ yamatazen/LorablatedStock-12B,67,9,88,60,12B,,FALSE,https://huggingface.co/yamatazen/LorablatedStock-12B,1
17
+ SicariusSicariiStuff/Impish_Longtail_12B_GGUF_HA,63,9,87,54,12B,,FALSE,https://huggingface.co/SicariusSicariiStuff/Impish_Longtail_12B_GGUF_HA,1
18
+ inflatebot/MN-12B-Mag-Mell-R1,53,7,79,49,12B,,FALSE,https://huggingface.co/inflatebot/MN-12B-Mag-Mell-R1,1 & 2
19
+ mistralai/Mistral-Nemo-Instruct-2407,55,9,76,48,12B,,TRUE,https://huggingface.co/mistralai/Mistral-Nemo-Instruct-2407,1
20
+ grimjim/MagnaMellRei-v1-12B,52,8,79,45,12B,,FALSE,https://huggingface.co/grimjim/MagnaMellRei-v1-12B,1
21
+ SicariusSicariiStuff/Impish_Nemo_12B,49,8,72,43,12B,,FALSE,https://huggingface.co/SicariusSicariiStuff/Impish_Nemo_12B,1
22
+ pot99rta/PatriSlush-DarkRPMax-12B,47,8,69,42,12B,,FALSE,https://huggingface.co/pot99rta/PatriSlush-DarkRPMax-12B,1
23
+ ReadyArt/The-Omega-Directive-M-12B-v1.0,42,7,67,39,12B,,FALSE,https://huggingface.co/ReadyArt/The-Omega-Directive-M-12B-v1.0,1
24
+ TheDrummer/Rocinante-12B-v1.1,66,8,83,63,12B,,FALSE,https://huggingface.co/TheDrummer/Rocinante-12B-v1.1,1
25
+ Nitral-AI/CaptainErisNebula-12B-Chimera-v1.1,64,8,85,59,12B,,FALSE,https://huggingface.co/Nitral-AI/CaptainErisNebula-12B-Chimera-v1.1,1
requirements.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ dash==2.14.2
2
+ dash-ag-grid==31.0.1
3
+ pandas
4
+ numpy
5
+ gunicorn