minette-kaunismaki begumcig commited on
Commit
1dd19c2
·
1 Parent(s): e680130

log scale (#3)

Browse files

- style fixes (d5590ebceb9361133bf317e15d76897c1091d28e)
- cleaning css (baa43b90710449175cd743f22621f241258c111f)
- light and dark mode (1bf1b48daa446fc0f2498117fc66bf9d5844635a)
- updating about page (517e6683cfecc16172b4a95611d77b4277d12254)
- refactor: update about tab with experimentation details (3473c50e525da355506889d610dda53eaca89e34)
- fixing mobile rendering (754a2279b6b26d1708a4d33fd8dfbfce08c54825)
- changing inferbench to p-bench (0fa188200802697b6c27337446101c5d73142efe)
- new ui (4b9f11d4ff35dd618331fb51b31778ed7a75bcf8)
- feat: add AA and Arenaai results, fix some ui features (4527ab9a70703593fd674dca571ccbe2c9900633)
- ui updates (3f9b0a536cd48fdd6062945abb5e008f6101b144)
- fixing samples (335823ace0a429bbb7942bb7870a32c80c4bd959)
- cleaning and updating about (a9c18ffb9ca574375a1e1431b8a3c9a911c0aff2)
- adding log scale and fixing safari rendering (a8fa348f1d1ddd3931e22df2891fc56d0b375074)
- Merge style/ui-update into pr/3 (6d8f26e0e086e31a95553f9076f5ecfccbafdd8b)
- removed raw win rate and swaped log to main plot view (f9d57b3e5e77667c498f5bc4ed86aab1cea875f0)


Co-authored-by: Begüm Çığ <begumcig@users.noreply.huggingface.co>

Files changed (5) hide show
  1. .DS_Store +0 -0
  2. README.md +0 -2
  3. app.py +297 -24
  4. data/.DS_Store +0 -0
  5. ui.py +296 -15
.DS_Store ADDED
Binary file (8.2 kB). View file
 
README.md CHANGED
@@ -30,8 +30,6 @@ pip install "gradio==5.19.0" pandas -r requirements.txt
30
  python app.py
31
  ```
32
 
33
- The app is served at `http://127.0.0.1:7860`.
34
-
35
  `requirements.txt` lists Plotly. Gradio and pandas are required locally;
36
  Hugging Face Spaces installs Gradio from the YAML `sdk_version` above.
37
 
 
30
  python app.py
31
  ```
32
 
 
 
33
  `requirements.txt` lists Plotly. Gradio and pandas are required locally;
34
  Hugging Face Spaces installs Gradio from the YAML `sdk_version` above.
35
 
app.py CHANGED
@@ -62,6 +62,9 @@ custom_css = """
62
  --pruna-accordion-bg: rgba(255, 255, 255, 0.02);
63
  --pruna-accordion-border: rgba(216, 180, 254, 0.15);
64
  --pruna-dropdown-hover: #2a1844;
 
 
 
65
  color-scheme: dark;
66
  }
67
 
@@ -105,13 +108,27 @@ custom_css = """
105
  --pruna-accordion-bg: var(--pruna-bg-card);
106
  --pruna-accordion-border: var(--pruna-border);
107
  --pruna-dropdown-hover: #f3e8ff;
 
 
 
108
  color-scheme: light;
109
  }
110
 
111
- html, body {
112
  width: 100% !important;
113
  max-width: 100% !important;
114
- overflow-x: clip;
 
 
 
 
 
 
 
 
 
 
 
115
  -webkit-tap-highlight-color: transparent;
116
  }
117
  html, body, .gradio-container, .main {
@@ -134,18 +151,25 @@ button, a, label, input, select, textarea,
134
  /* Subtle depth — not a marketing-site hero glow */
135
  body, .gradio-container {
136
  background-image: var(--pruna-glow) !important;
137
- background-attachment: fixed !important;
 
 
 
 
 
 
138
  }
139
 
140
  .gradio-container {
141
  width: 100% !important;
142
  max-width: 1200px !important;
 
143
  margin: 0 auto !important;
144
  padding-top: 0 !important;
145
  padding-left: 20px !important;
146
  padding-right: 20px !important;
147
  box-sizing: border-box !important;
148
- overflow-x: clip;
149
  }
150
  .gradio-container .main,
151
  .gradio-container .wrap,
@@ -166,6 +190,7 @@ body, .gradio-container {
166
  .workspace-filters,
167
  .view-filters {
168
  max-width: 100% !important;
 
169
  }
170
 
171
  /* —— App header (P-Bench only) —— */
@@ -300,6 +325,9 @@ button.theme-toggle[data-mode="light"] .theme-icon-moon { display: block !import
300
  background: transparent !important;
301
  box-shadow: none !important;
302
  }
 
 
 
303
  .workspace-shell > .tabs,
304
  .workspace-shell > .main-tabs,
305
  .workspace-shell > .block:not(.workspace-filters),
@@ -323,12 +351,49 @@ button.theme-toggle[data-mode="light"] .theme-icon-moon { display: block !import
323
  margin: 0 0 16px !important;
324
  justify-content: center !important;
325
  width: 100% !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
326
  }
327
  .main-tabs .tab-container {
328
  height: auto !important;
 
329
  justify-content: center !important;
330
  flex-wrap: wrap !important;
331
- overflow: hidden !important;
332
  max-width: 100% !important;
333
  gap: 2px;
334
  }
@@ -445,6 +510,8 @@ button.theme-toggle[data-mode="light"] .theme-icon-moon { display: block !import
445
  .app-header-brand h1,
446
  .gradio-container .app-header-brand h1 {
447
  font-size: 1.55rem !important;
 
 
448
  }
449
  .app-header-tagline {
450
  font-size: 0.88rem !important;
@@ -521,17 +588,29 @@ button.theme-toggle[data-mode="light"] .theme-icon-moon { display: block !import
521
  left: 0 !important;
522
  width: 2.4rem;
523
  min-width: 2.4rem;
 
524
  }
525
  .ranking-table .model-cell,
526
- .prose .ranking-table .model-cell,
527
- .ranking-table th.model-cell {
 
 
 
 
 
 
 
 
528
  position: sticky !important;
529
- left: 2.4rem !important;
530
- min-width: 108px;
531
- max-width: 36vw;
 
 
 
532
  }
533
- .ranking-table .model-cell strong {
534
- white-space: nowrap;
535
  }
536
  .compare-controls,
537
  .compare-controls.row,
@@ -604,7 +683,7 @@ button.theme-toggle[data-mode="light"] .theme-icon-moon { display: block !import
604
  .view-filters {
605
  display: flex !important;
606
  flex-wrap: wrap !important;
607
- align-items: end !important;
608
  gap: 12px !important;
609
  margin: 0;
610
  overflow: visible !important;
@@ -612,7 +691,7 @@ button.theme-toggle[data-mode="light"] .theme-icon-moon { display: block !import
612
  .view-filters > div,
613
  .view-filters > .block,
614
  .view-filters > .form {
615
- flex: 1 1 0 !important;
616
  min-width: 0 !important;
617
  }
618
  .view-filters > .block,
@@ -764,6 +843,10 @@ button.theme-toggle[data-mode="light"] .theme-icon-moon { display: block !import
764
  line-height: 1.45 !important;
765
  font-weight: 400 !important;
766
  }
 
 
 
 
767
  .view-filters span[data-testid="block-info"],
768
  .view-filters .info,
769
  .view-filters .block-info {
@@ -901,7 +984,7 @@ button.theme-toggle[data-mode="light"] .theme-icon-moon { display: block !import
901
  .leaderboard-controls {
902
  display: flex !important;
903
  flex-wrap: wrap !important;
904
- align-items: end !important;
905
  gap: 10px !important;
906
  margin-bottom: 12px;
907
  overflow: visible !important;
@@ -1317,7 +1400,9 @@ button.theme-toggle[data-mode="light"] .theme-icon-moon { display: block !import
1317
  box-shadow: none !important;
1318
  }
1319
  .compare-controls .compare-prompt-count .head {
1320
- display: contents;
 
 
1321
  margin: 0 !important;
1322
  }
1323
  .compare-controls .compare-prompt-count .head label {
@@ -1491,7 +1576,182 @@ button.theme-toggle[data-mode="light"] .theme-icon-moon { display: block !import
1491
  margin: 0 !important;
1492
  }
1493
  .compare-row { display: grid; gap: 12px; min-width: 0; width: 100%; }
1494
- .compare-prompt-text { overflow-wrap: anywhere; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1495
  .pareto-layout,
1496
  .pareto-layout.row,
1497
  .pareto-layout .form {
@@ -1549,7 +1809,7 @@ button.theme-toggle[data-mode="light"] .theme-icon-moon { display: block !import
1549
  .app-header .app-header-brand h1 {
1550
  display: block !important;
1551
  width: max-content !important;
1552
- max-width: none !important;
1553
  flex: 0 0 auto !important;
1554
  margin: 0 !important;
1555
  padding: 0 !important;
@@ -2026,7 +2286,7 @@ def load_qwen_combined_dataframe(path):
2026
  df = df[~df["Model"].astype(str).str.startswith("#")].copy()
2027
  df["Model"] = df["Model"].astype(str).str.strip()
2028
 
2029
- return _as_numeric(
2030
  df,
2031
  [
2032
  "Price / Image (USD)",
@@ -2036,7 +2296,9 @@ def load_qwen_combined_dataframe(path):
2036
  "Rapidata Elo",
2037
  "Datapoint Elo",
2038
  ],
2039
- ).reset_index(drop=True)
 
 
2040
 
2041
 
2042
  df = load_oneig_dataframe(oneig_path)
@@ -2109,7 +2371,6 @@ qwen_display_columns = [
2109
  "Datapoint Elo",
2110
  "Rapidata Elo",
2111
  "P-Judge Overall",
2112
- "Raw Win Rate",
2113
  "Median Generation Time (s)",
2114
  "Min Generation Time (s)",
2115
  "Price / Image (USD)",
@@ -2317,11 +2578,23 @@ custom_head = """
2317
  return found;
2318
  };
2319
 
2320
- const restylePlots = (mode) => {
2321
  const layout = PLOT_LAYOUT[mode];
2322
- if (!layout || typeof Plotly === "undefined") return;
 
 
 
 
 
 
 
 
 
 
 
2323
  queryAll(".js-plotly-plot").forEach((gd) => {
2324
- try { Plotly.relayout(gd, layout); } catch (e) {}
 
2325
  });
2326
  };
2327
 
 
62
  --pruna-accordion-bg: rgba(255, 255, 255, 0.02);
63
  --pruna-accordion-border: rgba(216, 180, 254, 0.15);
64
  --pruna-dropdown-hover: #2a1844;
65
+ --pruna-toggle-track: var(--pruna-bg-header);
66
+ --pruna-toggle-thumb: var(--pruna-bg-elevated);
67
+ --pruna-toggle-thumb-shadow: 0 1px 2px rgba(0, 0, 0, 0.45), inset 0 1px rgba(255, 255, 255, 0.06);
68
  color-scheme: dark;
69
  }
70
 
 
108
  --pruna-accordion-bg: var(--pruna-bg-card);
109
  --pruna-accordion-border: var(--pruna-border);
110
  --pruna-dropdown-hover: #f3e8ff;
111
+ --pruna-toggle-track: var(--pruna-bg-header);
112
+ --pruna-toggle-thumb: var(--pruna-bg-card);
113
+ --pruna-toggle-thumb-shadow: 0 1px 2px rgba(88, 28, 135, 0.12);
114
  color-scheme: light;
115
  }
116
 
117
+ html {
118
  width: 100% !important;
119
  max-width: 100% !important;
120
+ min-width: 0 !important;
121
+ overflow-x: hidden;
122
+ overflow-y: auto;
123
+ -webkit-text-size-adjust: 100%;
124
+ text-size-adjust: 100%;
125
+ -webkit-tap-highlight-color: transparent;
126
+ }
127
+ body, gradio-app {
128
+ width: 100% !important;
129
+ max-width: 100% !important;
130
+ min-width: 0 !important;
131
+ overflow: visible;
132
  -webkit-tap-highlight-color: transparent;
133
  }
134
  html, body, .gradio-container, .main {
 
151
  /* Subtle depth — not a marketing-site hero glow */
152
  body, .gradio-container {
153
  background-image: var(--pruna-glow) !important;
154
+ background-repeat: no-repeat !important;
155
+ background-attachment: scroll !important;
156
+ }
157
+ @media (min-width: 701px) and (hover: hover) and (pointer: fine) {
158
+ body, .gradio-container {
159
+ background-attachment: fixed !important;
160
+ }
161
  }
162
 
163
  .gradio-container {
164
  width: 100% !important;
165
  max-width: 1200px !important;
166
+ min-width: 0 !important;
167
  margin: 0 auto !important;
168
  padding-top: 0 !important;
169
  padding-left: 20px !important;
170
  padding-right: 20px !important;
171
  box-sizing: border-box !important;
172
+ overflow-x: hidden;
173
  }
174
  .gradio-container .main,
175
  .gradio-container .wrap,
 
190
  .workspace-filters,
191
  .view-filters {
192
  max-width: 100% !important;
193
+ min-width: 0 !important;
194
  }
195
 
196
  /* —— App header (P-Bench only) —— */
 
325
  background: transparent !important;
326
  box-shadow: none !important;
327
  }
328
+ /* Flatten tabs so the bar sits above shared filters. display:contents is
329
+ the fallback; Safari can drop or mis-order those children, so browsers
330
+ with subgrid use the grid layout below instead. */
331
  .workspace-shell > .tabs,
332
  .workspace-shell > .main-tabs,
333
  .workspace-shell > .block:not(.workspace-filters),
 
351
  margin: 0 0 16px !important;
352
  justify-content: center !important;
353
  width: 100% !important;
354
+ overflow: visible !important;
355
+ }
356
+ @supports (grid-template-rows: subgrid) {
357
+ .workspace-shell,
358
+ .workspace-shell.block,
359
+ .workspace-shell.column,
360
+ .workspace-shell.gap {
361
+ display: grid !important;
362
+ grid-template-columns: minmax(0, 1fr) !important;
363
+ grid-template-rows: auto auto auto !important;
364
+ align-content: start !important;
365
+ }
366
+ .workspace-shell > .tabs,
367
+ .workspace-shell > .main-tabs,
368
+ .workspace-shell .tabs.main-tabs {
369
+ display: grid !important;
370
+ grid-template-columns: minmax(0, 1fr) !important;
371
+ grid-template-rows: subgrid !important;
372
+ grid-column: 1 !important;
373
+ grid-row: 1 / 4 !important;
374
+ position: static !important;
375
+ }
376
+ .main-tabs > .tab-wrapper {
377
+ grid-row: 1 !important;
378
+ order: 0 !important;
379
+ }
380
+ .workspace-filters {
381
+ grid-column: 1 !important;
382
+ grid-row: 2 !important;
383
+ order: 0 !important;
384
+ }
385
+ .main-tabs .tabitem {
386
+ grid-row: 3 !important;
387
+ order: 0 !important;
388
+ min-width: 0 !important;
389
+ }
390
  }
391
  .main-tabs .tab-container {
392
  height: auto !important;
393
+ min-height: 0 !important;
394
  justify-content: center !important;
395
  flex-wrap: wrap !important;
396
+ overflow: visible !important;
397
  max-width: 100% !important;
398
  gap: 2px;
399
  }
 
510
  .app-header-brand h1,
511
  .gradio-container .app-header-brand h1 {
512
  font-size: 1.55rem !important;
513
+ width: auto !important;
514
+ max-width: 100% !important;
515
  }
516
  .app-header-tagline {
517
  font-size: 0.88rem !important;
 
588
  left: 0 !important;
589
  width: 2.4rem;
590
  min-width: 2.4rem;
591
+ box-shadow: 6px 0 8px -6px rgba(0, 0, 0, 0.45);
592
  }
593
  .ranking-table .model-cell,
594
+ .prose .ranking-table .model-cell {
595
+ position: static !important;
596
+ left: auto !important;
597
+ z-index: auto;
598
+ min-width: 140px;
599
+ max-width: none;
600
+ background: transparent !important;
601
+ }
602
+ .ranking-table th.model-cell,
603
+ .prose .ranking-table th.model-cell {
604
  position: sticky !important;
605
+ top: 0 !important;
606
+ left: auto !important;
607
+ z-index: 3;
608
+ min-width: 140px;
609
+ max-width: none;
610
+ background: var(--pruna-bg-header) !important;
611
  }
612
+ .ranking-table tbody tr:hover .model-cell {
613
+ background: var(--pruna-table-hover) !important;
614
  }
615
  .compare-controls,
616
  .compare-controls.row,
 
683
  .view-filters {
684
  display: flex !important;
685
  flex-wrap: wrap !important;
686
+ align-items: flex-end !important;
687
  gap: 12px !important;
688
  margin: 0;
689
  overflow: visible !important;
 
691
  .view-filters > div,
692
  .view-filters > .block,
693
  .view-filters > .form {
694
+ flex: 1 1 0% !important;
695
  min-width: 0 !important;
696
  }
697
  .view-filters > .block,
 
843
  line-height: 1.45 !important;
844
  font-weight: 400 !important;
845
  }
846
+ .view-help + .view-help,
847
+ .prose .view-help + .view-help {
848
+ margin-top: 0.45rem !important;
849
+ }
850
  .view-filters span[data-testid="block-info"],
851
  .view-filters .info,
852
  .view-filters .block-info {
 
984
  .leaderboard-controls {
985
  display: flex !important;
986
  flex-wrap: wrap !important;
987
+ align-items: flex-end !important;
988
  gap: 10px !important;
989
  margin-bottom: 12px;
990
  overflow: visible !important;
 
1400
  box-shadow: none !important;
1401
  }
1402
  .compare-controls .compare-prompt-count .head {
1403
+ display: block !important;
1404
+ grid-column: 1 / -1;
1405
+ grid-row: 1;
1406
  margin: 0 !important;
1407
  }
1408
  .compare-controls .compare-prompt-count .head label {
 
1576
  margin: 0 !important;
1577
  }
1578
  .compare-row { display: grid; gap: 12px; min-width: 0; width: 100%; }
1579
+ .compare-prompt-text { overflow-wrap: anywhere; word-break: break-word; }
1580
+ .pareto-heading-row,
1581
+ .pareto-heading-row.row,
1582
+ .pareto-heading-row .form {
1583
+ display: flex !important;
1584
+ flex-wrap: wrap !important;
1585
+ align-items: center !important;
1586
+ gap: 8px 12px !important;
1587
+ width: 100% !important;
1588
+ margin-bottom: 0.4rem !important;
1589
+ }
1590
+ .pareto-heading-row .pareto-subhead,
1591
+ .pareto-heading-row > div:first-child,
1592
+ .pareto-heading-row .form > div:first-child {
1593
+ flex: 1 1 240px !important;
1594
+ min-width: 0 !important;
1595
+ margin: 0 !important;
1596
+ }
1597
+ .pareto-heading-row .pareto-scale-control {
1598
+ display: flex !important;
1599
+ flex-direction: row !important;
1600
+ align-items: center !important;
1601
+ justify-content: flex-end !important;
1602
+ flex: 0 0 auto !important;
1603
+ gap: 0 !important;
1604
+ margin-left: auto !important;
1605
+ max-width: 168px !important;
1606
+ padding: 0 !important;
1607
+ }
1608
+ .pareto-scale-all-row,
1609
+ .pareto-scale-all-row.row,
1610
+ .pareto-scale-all-row .form {
1611
+ display: flex !important;
1612
+ flex-direction: row !important;
1613
+ flex-wrap: wrap !important;
1614
+ align-items: center !important;
1615
+ justify-content: flex-start !important;
1616
+ gap: 8px 12px !important;
1617
+ width: 100% !important;
1618
+ margin: 2px 0 14px !important;
1619
+ }
1620
+ .pareto-scale-all-row .html-container,
1621
+ .pareto-scale-all-row .block {
1622
+ border: none !important;
1623
+ background: transparent !important;
1624
+ box-shadow: none !important;
1625
+ padding: 0 !important;
1626
+ margin: 0 !important;
1627
+ width: auto !important;
1628
+ flex: 0 0 auto !important;
1629
+ }
1630
+ .pareto-scale-all-row .html-container {
1631
+ flex: 1 1 auto !important;
1632
+ min-width: 0 !important;
1633
+ }
1634
+ .pareto-scale-all-label {
1635
+ color: var(--pruna-text-muted);
1636
+ font-size: 0.8rem;
1637
+ font-weight: 500;
1638
+ white-space: nowrap;
1639
+ }
1640
+ .pareto-scale-all-row .pareto-scale-toggle {
1641
+ margin-left: auto !important;
1642
+ }
1643
+ .pareto-scale-toggle,
1644
+ .pareto-scale-toggle.block {
1645
+ min-width: 0 !important;
1646
+ width: auto !important;
1647
+ border: none !important;
1648
+ background: transparent !important;
1649
+ box-shadow: none !important;
1650
+ padding: 0 !important;
1651
+ margin: 0 !important;
1652
+ }
1653
+ .pareto-scale-toggle .wrap,
1654
+ .pareto-scale-toggle .form {
1655
+ display: block !important;
1656
+ width: auto !important;
1657
+ margin: 0 !important;
1658
+ padding: 0 !important;
1659
+ border: none !important;
1660
+ background: transparent !important;
1661
+ box-shadow: none !important;
1662
+ }
1663
+ .pareto-scale-toggle legend {
1664
+ display: none !important;
1665
+ }
1666
+ .pareto-scale-toggle fieldset,
1667
+ .pareto-scale-toggle .wrap:has(> label),
1668
+ .pareto-scale-toggle .form:has(> label) {
1669
+ position: relative !important;
1670
+ display: grid !important;
1671
+ grid-template-columns: 1fr 1fr !important;
1672
+ align-items: stretch !important;
1673
+ isolation: isolate;
1674
+ box-sizing: border-box !important;
1675
+ width: max-content !important;
1676
+ min-width: 0 !important;
1677
+ padding: 4px !important;
1678
+ gap: 4px !important;
1679
+ border: 1px solid var(--pruna-input-border) !important;
1680
+ border-radius: 10px !important;
1681
+ background: var(--pruna-toggle-track) !important;
1682
+ box-shadow: none !important;
1683
+ }
1684
+ .pareto-scale-toggle fieldset::before,
1685
+ .pareto-scale-toggle .wrap:has(> label)::before,
1686
+ .pareto-scale-toggle .form:has(> label)::before {
1687
+ content: none !important;
1688
+ }
1689
+ .pareto-scale-toggle label {
1690
+ position: relative !important;
1691
+ z-index: 1 !important;
1692
+ display: flex !important;
1693
+ flex: 1 1 auto !important;
1694
+ align-items: center !important;
1695
+ justify-content: center !important;
1696
+ gap: 0 !important;
1697
+ box-sizing: border-box !important;
1698
+ min-width: 58px !important;
1699
+ min-height: 26px !important;
1700
+ margin: 0 !important;
1701
+ padding: 5px 12px !important;
1702
+ border: none !important;
1703
+ border-radius: 6px !important;
1704
+ background: transparent !important;
1705
+ box-shadow: none !important;
1706
+ color: var(--pruna-text-body) !important;
1707
+ font-size: 0.72rem !important;
1708
+ font-weight: 600 !important;
1709
+ line-height: 1.2 !important;
1710
+ letter-spacing: 0.01em;
1711
+ white-space: nowrap;
1712
+ cursor: pointer !important;
1713
+ }
1714
+ .pareto-scale-toggle-all label {
1715
+ min-width: 68px !important;
1716
+ min-height: 30px !important;
1717
+ padding: 6px 14px !important;
1718
+ font-size: 0.85rem !important;
1719
+ }
1720
+ .pareto-scale-toggle label span {
1721
+ margin: 0 !important;
1722
+ padding: 0 !important;
1723
+ color: inherit !important;
1724
+ opacity: 1 !important;
1725
+ }
1726
+ .pareto-scale-toggle label > * + * {
1727
+ margin-left: 0 !important;
1728
+ }
1729
+ .pareto-scale-toggle label + label::before,
1730
+ .pareto-scale-toggle label + label {
1731
+ content: none !important;
1732
+ border-left: none !important;
1733
+ }
1734
+ .pareto-scale-toggle input[type="radio"] {
1735
+ position: absolute !important;
1736
+ appearance: none !important;
1737
+ opacity: 0 !important;
1738
+ width: 0 !important;
1739
+ height: 0 !important;
1740
+ margin: 0 !important;
1741
+ pointer-events: none !important;
1742
+ }
1743
+ .pareto-scale-toggle label:hover {
1744
+ background: transparent !important;
1745
+ color: var(--pruna-text-primary) !important;
1746
+ }
1747
+ .pareto-scale-toggle label.selected,
1748
+ .pareto-scale-toggle label:has(input:checked) {
1749
+ background: var(--pruna-toggle-thumb) !important;
1750
+ color: var(--pruna-lavender) !important;
1751
+ font-weight: 700 !important;
1752
+ border-color: transparent !important;
1753
+ box-shadow: var(--pruna-toggle-thumb-shadow) !important;
1754
+ }
1755
  .pareto-layout,
1756
  .pareto-layout.row,
1757
  .pareto-layout .form {
 
1809
  .app-header .app-header-brand h1 {
1810
  display: block !important;
1811
  width: max-content !important;
1812
+ max-width: 100% !important;
1813
  flex: 0 0 auto !important;
1814
  margin: 0 !important;
1815
  padding: 0 !important;
 
2286
  df = df[~df["Model"].astype(str).str.startswith("#")].copy()
2287
  df["Model"] = df["Model"].astype(str).str.strip()
2288
 
2289
+ df = _as_numeric(
2290
  df,
2291
  [
2292
  "Price / Image (USD)",
 
2296
  "Rapidata Elo",
2297
  "Datapoint Elo",
2298
  ],
2299
+ )
2300
+ df = df.drop(columns=["Raw Win Rate"], errors="ignore")
2301
+ return df.reset_index(drop=True)
2302
 
2303
 
2304
  df = load_oneig_dataframe(oneig_path)
 
2371
  "Datapoint Elo",
2372
  "Rapidata Elo",
2373
  "P-Judge Overall",
 
2374
  "Median Generation Time (s)",
2375
  "Min Generation Time (s)",
2376
  "Price / Image (USD)",
 
2578
  return found;
2579
  };
2580
 
2581
+ const applyPlotTheme = (gd, mode) => {
2582
  const layout = PLOT_LAYOUT[mode];
2583
+ if (!layout || typeof Plotly === "undefined" || !gd) return;
2584
+ if (gd.layout && gd.layout.paper_bgcolor === layout.paper_bgcolor) return;
2585
+ try { Plotly.relayout(gd, layout); } catch (e) {}
2586
+ };
2587
+
2588
+ const watchPlotTheme = (gd) => {
2589
+ if (!gd || gd.__inferbenchThemeBound) return;
2590
+ gd.__inferbenchThemeBound = true;
2591
+ gd.addEventListener("plotly_afterplot", () => applyPlotTheme(gd, currentMode()));
2592
+ };
2593
+
2594
+ const restylePlots = (mode) => {
2595
  queryAll(".js-plotly-plot").forEach((gd) => {
2596
+ watchPlotTheme(gd);
2597
+ applyPlotTheme(gd, mode);
2598
  });
2599
  };
2600
 
data/.DS_Store ADDED
Binary file (6.15 kB). View file
 
ui.py CHANGED
@@ -1,4 +1,5 @@
1
  from html import escape
 
2
  from pathlib import Path
3
  import base64
4
  import random
@@ -25,6 +26,12 @@ MAX_PARETO_METRICS = 8
25
  _PARETO_SLOT_COUNT = 1 + MAX_PARETO_METRICS * 8
26
  _PARETO_PRICE_COLUMN = "Price / Image (USD)"
27
  _PARETO_TIME_COLUMN = "Min Generation Time (s)"
 
 
 
 
 
 
28
 
29
  TAB_LEADERBOARDS = "leaderboards"
30
  TAB_PARETO = "pareto"
@@ -585,7 +592,6 @@ def _display_label(column):
585
  "Arena Art Elo": "Art",
586
  "Arena Portraits Elo": "Portraits",
587
  "Arena Text Rendering Elo": "Text Rendering",
588
- "Raw Win Rate": "Raw win rate",
589
  "Median Generation Time (s)": "Median generation time",
590
  "Min Generation Time (s)": "Min generation time",
591
  "Price / Image (USD)": "Price per image",
@@ -670,6 +676,7 @@ def _build_pareto_figure(
670
  x_title,
671
  x_hover_prefix="",
672
  x_hover_suffix="",
 
673
  ):
674
  scatter = (
675
  data[["Model", score_column, x_column]]
@@ -755,7 +762,29 @@ def _build_pareto_figure(
755
  )
756
  axis_font = {"color": "#fafafa", "size": 13}
757
  tick_font = {"color": "#a3a3a3", "size": 12}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
758
  fig.update_xaxes(
 
 
759
  showgrid=True,
760
  gridcolor="rgba(74, 57, 98, 0.55)",
761
  zeroline=False,
@@ -774,6 +803,55 @@ def _build_pareto_figure(
774
  return fig
775
 
776
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
777
  def _pareto_axis(data, score_column, x_column, x_title, missing_message, empty_message, **hover):
778
  if x_column not in data.columns:
779
  return None, missing_message
@@ -789,7 +867,12 @@ def _pareto_axis(data, score_column, x_column, x_title, missing_message, empty_m
789
  return fig, None
790
 
791
 
792
- def _pareto_pair(data, score_column):
 
 
 
 
 
793
  score_missing = "No score data is available for this metric."
794
  if data is None or not score_column or score_column not in data.columns:
795
  return None, score_missing, None, score_missing
@@ -802,6 +885,7 @@ def _pareto_pair(data, score_column):
802
  "Price per image isn't available for this dataset.",
803
  "No models have both a score and a price for this metric.",
804
  x_hover_prefix="$",
 
805
  )
806
  time_fig, time_message = _pareto_axis(
807
  data,
@@ -811,6 +895,7 @@ def _pareto_pair(data, score_column):
811
  "Min generation time isn't available for this dataset.",
812
  "No models have both a score and a min generation time for this metric.",
813
  x_hover_suffix="s",
 
814
  )
815
  return price_fig, price_message, time_fig, time_message
816
 
@@ -849,9 +934,16 @@ def _pareto_slot_note(price_fig, price_message, time_fig, time_message, data):
849
  return " ".join(notes)
850
 
851
 
852
- def _pareto_slot_updates(data, score_columns):
 
 
 
 
 
853
  """Updates for a fixed bank of Gradio Plot slots (visible/hidden)."""
854
  score_columns = [column for column in (score_columns or []) if column]
 
 
855
  has_price = data is not None and _PARETO_PRICE_COLUMN in data.columns
856
  has_time = data is not None and _PARETO_TIME_COLUMN in data.columns
857
  dataset_note = _pareto_dataset_message(data)
@@ -873,7 +965,10 @@ def _pareto_slot_updates(data, score_columns):
873
  continue
874
  score_column = score_columns[index]
875
  price_fig, price_message, time_fig, time_message = _pareto_pair(
876
- data, score_column
 
 
 
877
  )
878
  show_price = price_fig is not None
879
  show_time = time_fig is not None
@@ -900,6 +995,30 @@ def _pareto_slot_updates(data, score_columns):
900
  return updates
901
 
902
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
903
  def _samples_html(samples, selected_models, num_prompts, seed=0):
904
  if not samples:
905
  return _pareto_unavailable_html(
@@ -1117,12 +1236,27 @@ def render_image_workspace(datasets, metrics, default_dataset_id, default_metric
1117
  ) as pp_tab:
1118
  gr.Markdown(
1119
  "<p class='view-help'>"
1120
- "Score against price and generation time. Green points are on the "
1121
- "frontier; lavender points sit below it. Hover a point to see "
1122
- "which model it is."
 
 
 
 
1123
  "</p>",
1124
  elem_classes="view-help-host",
1125
  )
 
 
 
 
 
 
 
 
 
 
 
1126
  pareto_dataset_note = gr.HTML(
1127
  "",
1128
  padding=False,
@@ -1148,9 +1282,8 @@ def render_image_workspace(datasets, metrics, default_dataset_id, default_metric
1148
  min_width=320,
1149
  elem_classes="pareto-col",
1150
  ) as slot_price_col:
1151
- gr.Markdown(
1152
- "#### Price vs score",
1153
- elem_classes="pareto-subhead",
1154
  )
1155
  slot_price = gr.Plot(
1156
  value=None,
@@ -1162,9 +1295,8 @@ def render_image_workspace(datasets, metrics, default_dataset_id, default_metric
1162
  min_width=320,
1163
  elem_classes="pareto-col",
1164
  ) as slot_time_col:
1165
- gr.Markdown(
1166
- "#### Min generation time vs score",
1167
- elem_classes="pareto-subhead",
1168
  )
1169
  slot_time = gr.Plot(
1170
  value=None,
@@ -1185,8 +1317,10 @@ def render_image_workspace(datasets, metrics, default_dataset_id, default_metric
1185
  slot_layout,
1186
  slot_price_col,
1187
  slot_price,
 
1188
  slot_time_col,
1189
  slot_time,
 
1190
  )
1191
  )
1192
 
@@ -1324,6 +1458,8 @@ def render_image_workspace(datasets, metrics, default_dataset_id, default_metric
1324
  "optimized": list(
1325
  extras.get("optimized", prev.get("optimized") or [])
1326
  ),
 
 
1327
  "stale": {
1328
  TAB_LEADERBOARDS: not flags["include_leaderboard"],
1329
  TAB_PARETO: not flags["include_pareto"],
@@ -1383,6 +1519,8 @@ def render_image_workspace(datasets, metrics, default_dataset_id, default_metric
1383
  include_leaderboard=True,
1384
  include_pareto=False,
1385
  include_samples=False,
 
 
1386
  ):
1387
  view = resolve_view(datasets, metrics, dataset_id, metric_id)
1388
  data = view["data"]
@@ -1403,7 +1541,12 @@ def render_image_workspace(datasets, metrics, default_dataset_id, default_metric
1403
  ranking_html = gr.skip()
1404
  if include_pareto:
1405
  pareto_data = _filter_leaderboard(data, [], [], [], models=models)
1406
- pareto_updates = _pareto_slot_updates(pareto_data, view["score_columns"])
 
 
 
 
 
1407
  else:
1408
  pareto_updates = _pareto_skip_updates()
1409
  if include_samples:
@@ -1537,6 +1680,8 @@ def render_image_workspace(datasets, metrics, default_dataset_id, default_metric
1537
  extras[2],
1538
  num_prompts,
1539
  seed,
 
 
1540
  **flags,
1541
  ),
1542
  "state": _commit_state(
@@ -1739,6 +1884,8 @@ def render_image_workspace(datasets, metrics, default_dataset_id, default_metric
1739
  optimized_value,
1740
  num_prompts,
1741
  seed,
 
 
1742
  **flags,
1743
  )
1744
  stale[tab] = False
@@ -1795,6 +1942,70 @@ def render_image_workspace(datasets, metrics, default_dataset_id, default_metric
1795
  next_seed,
1796
  )
1797
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1798
  def _on_tab(tab):
1799
  def handler(
1800
  dataset_id,
@@ -1832,6 +2043,8 @@ def render_image_workspace(datasets, metrics, default_dataset_id, default_metric
1832
  "platform": [],
1833
  "owner": [],
1834
  "optimized": [],
 
 
1835
  "stale": {
1836
  TAB_LEADERBOARDS: False,
1837
  TAB_PARETO: True,
@@ -1843,7 +2056,7 @@ def render_image_workspace(datasets, metrics, default_dataset_id, default_metric
1843
  pareto_dataset_note,
1844
  *[
1845
  component
1846
- for slot_group, slot_title, slot_note, slot_layout, slot_price_col, slot_price, slot_time_col, slot_time in pareto_slots
1847
  for component in (
1848
  slot_group,
1849
  slot_title,
@@ -1856,6 +2069,24 @@ def render_image_workspace(datasets, metrics, default_dataset_id, default_metric
1856
  )
1857
  ],
1858
  ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1859
  view_inputs = [
1860
  platform,
1861
  owner,
@@ -1960,6 +2191,56 @@ def render_image_workspace(datasets, metrics, default_dataset_id, default_metric
1960
  show_progress="hidden",
1961
  )
1962
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1963
  prompt_count.change(
1964
  on_samples_controls,
1965
  inputs=[dataset_dd, models_dd, prompt_count, seed_state],
 
1
  from html import escape
2
+ from math import ceil, floor, log10
3
  from pathlib import Path
4
  import base64
5
  import random
 
26
  _PARETO_SLOT_COUNT = 1 + MAX_PARETO_METRICS * 8
27
  _PARETO_PRICE_COLUMN = "Price / Image (USD)"
28
  _PARETO_TIME_COLUMN = "Min Generation Time (s)"
29
+ _PARETO_SCALE_CHOICES = [
30
+ ("Log", "Logarithmic"),
31
+ ("Linear", "Linear"),
32
+ ]
33
+ _PARETO_SCALE_VALUES = {value for _, value in _PARETO_SCALE_CHOICES}
34
+ _PARETO_SCALE_DEFAULT = "Logarithmic"
35
 
36
  TAB_LEADERBOARDS = "leaderboards"
37
  TAB_PARETO = "pareto"
 
592
  "Arena Art Elo": "Art",
593
  "Arena Portraits Elo": "Portraits",
594
  "Arena Text Rendering Elo": "Text Rendering",
 
595
  "Median Generation Time (s)": "Median generation time",
596
  "Min Generation Time (s)": "Min generation time",
597
  "Price / Image (USD)": "Price per image",
 
676
  x_title,
677
  x_hover_prefix="",
678
  x_hover_suffix="",
679
+ x_axis_type="linear",
680
  ):
681
  scatter = (
682
  data[["Model", score_column, x_column]]
 
762
  )
763
  axis_font = {"color": "#fafafa", "size": 13}
764
  tick_font = {"color": "#a3a3a3", "size": 12}
765
+ x_axis_ticks = {}
766
+ if x_axis_type == "log":
767
+ positive_x = scatter.loc[scatter[x_column] > 0, x_column].astype(float)
768
+ if not positive_x.empty:
769
+ minimum = positive_x.min()
770
+ maximum = positive_x.max()
771
+ tick_values = [
772
+ factor * (10**exponent)
773
+ for exponent in range(
774
+ floor(log10(minimum)),
775
+ ceil(log10(maximum)) + 1,
776
+ )
777
+ for factor in (1, 2, 5)
778
+ if minimum * 0.8 <= factor * (10**exponent) <= maximum * 1.2
779
+ ]
780
+ x_axis_ticks = {
781
+ "tickmode": "array",
782
+ "tickvals": tick_values,
783
+ "ticktext": [f"{value:g}" for value in tick_values],
784
+ }
785
  fig.update_xaxes(
786
+ type=x_axis_type,
787
+ **x_axis_ticks,
788
  showgrid=True,
789
  gridcolor="rgba(74, 57, 98, 0.55)",
790
  zeroline=False,
 
803
  return fig
804
 
805
 
806
+ def _is_log_scale(scale):
807
+ return scale == "Logarithmic"
808
+
809
+
810
+ def _pareto_axis_type(scale):
811
+ return "log" if _is_log_scale(scale) else "linear"
812
+
813
+
814
+ def _pareto_scale_radio(*extra_classes):
815
+ return gr.Radio(
816
+ choices=_PARETO_SCALE_CHOICES,
817
+ value=_PARETO_SCALE_DEFAULT,
818
+ show_label=False,
819
+ container=False,
820
+ elem_classes=["pareto-scale-toggle", *extra_classes],
821
+ )
822
+
823
+
824
+ def _pareto_plot_heading(title):
825
+ with gr.Row(equal_height=False, elem_classes="pareto-heading-row"):
826
+ gr.Markdown(f"#### {title}", elem_classes="pareto-subhead")
827
+ with gr.Column(min_width=140, elem_classes="pareto-scale-control"):
828
+ return _pareto_scale_radio()
829
+
830
+
831
+ def _default_pareto_scales():
832
+ return [_PARETO_SCALE_DEFAULT] * MAX_PARETO_METRICS
833
+
834
+
835
+ def _normalize_pareto_scales(scales):
836
+ values = list(scales or [])
837
+ if len(values) < MAX_PARETO_METRICS:
838
+ values.extend(
839
+ [_PARETO_SCALE_DEFAULT] * (MAX_PARETO_METRICS - len(values))
840
+ )
841
+ return values[:MAX_PARETO_METRICS]
842
+
843
+
844
+ def _uniform_pareto_scales(scale):
845
+ return [scale] * MAX_PARETO_METRICS
846
+
847
+
848
+ def _pareto_master_scale_update(price_scales, time_scales):
849
+ values = list(price_scales) + list(time_scales)
850
+ if values and all(value == values[0] for value in values):
851
+ return gr.update(value=values[0])
852
+ return gr.update(value=None)
853
+
854
+
855
  def _pareto_axis(data, score_column, x_column, x_title, missing_message, empty_message, **hover):
856
  if x_column not in data.columns:
857
  return None, missing_message
 
867
  return fig, None
868
 
869
 
870
+ def _pareto_pair(
871
+ data,
872
+ score_column,
873
+ latency_scale=_PARETO_SCALE_DEFAULT,
874
+ price_scale=_PARETO_SCALE_DEFAULT,
875
+ ):
876
  score_missing = "No score data is available for this metric."
877
  if data is None or not score_column or score_column not in data.columns:
878
  return None, score_missing, None, score_missing
 
885
  "Price per image isn't available for this dataset.",
886
  "No models have both a score and a price for this metric.",
887
  x_hover_prefix="$",
888
+ x_axis_type=_pareto_axis_type(price_scale),
889
  )
890
  time_fig, time_message = _pareto_axis(
891
  data,
 
895
  "Min generation time isn't available for this dataset.",
896
  "No models have both a score and a min generation time for this metric.",
897
  x_hover_suffix="s",
898
+ x_axis_type=_pareto_axis_type(latency_scale),
899
  )
900
  return price_fig, price_message, time_fig, time_message
901
 
 
934
  return " ".join(notes)
935
 
936
 
937
+ def _pareto_slot_updates(
938
+ data,
939
+ score_columns,
940
+ price_scales=None,
941
+ time_scales=None,
942
+ ):
943
  """Updates for a fixed bank of Gradio Plot slots (visible/hidden)."""
944
  score_columns = [column for column in (score_columns or []) if column]
945
+ price_scales = _normalize_pareto_scales(price_scales)
946
+ time_scales = _normalize_pareto_scales(time_scales)
947
  has_price = data is not None and _PARETO_PRICE_COLUMN in data.columns
948
  has_time = data is not None and _PARETO_TIME_COLUMN in data.columns
949
  dataset_note = _pareto_dataset_message(data)
 
965
  continue
966
  score_column = score_columns[index]
967
  price_fig, price_message, time_fig, time_message = _pareto_pair(
968
+ data,
969
+ score_column,
970
+ latency_scale=time_scales[index],
971
+ price_scale=price_scales[index],
972
  )
973
  show_price = price_fig is not None
974
  show_time = time_fig is not None
 
995
  return updates
996
 
997
 
998
+ def _pareto_all_scale_updates(data, score_columns, scale):
999
+ """Apply one scale to every Pareto plot and radio."""
1000
+ score_columns = [column for column in (score_columns or []) if column]
1001
+ price_updates = []
1002
+ time_updates = []
1003
+ for index in range(MAX_PARETO_METRICS):
1004
+ if index >= len(score_columns):
1005
+ price_updates.append(gr.skip())
1006
+ time_updates.append(gr.skip())
1007
+ continue
1008
+ price_fig, _, time_fig, _ = _pareto_pair(
1009
+ data,
1010
+ score_columns[index],
1011
+ latency_scale=scale,
1012
+ price_scale=scale,
1013
+ )
1014
+ price_updates.append(_pareto_plot_update(price_fig))
1015
+ time_updates.append(_pareto_plot_update(time_fig))
1016
+ radio_updates = [
1017
+ gr.update(value=scale) for _ in range(MAX_PARETO_METRICS * 2)
1018
+ ]
1019
+ return price_updates + time_updates + radio_updates
1020
+
1021
+
1022
  def _samples_html(samples, selected_models, num_prompts, seed=0):
1023
  if not samples:
1024
  return _pareto_unavailable_html(
 
1236
  ) as pp_tab:
1237
  gr.Markdown(
1238
  "<p class='view-help'>"
1239
+ "Score against price and generation time. Green points are on "
1240
+ "the frontier; lavender points sit below it. Hover a point to "
1241
+ "see which model it is."
1242
+ "</p>"
1243
+ "<p class='view-help'>"
1244
+ "Plots use a logarithmic scale by default. You can switch "
1245
+ "to linear for all plots, or individually for each plot."
1246
  "</p>",
1247
  elem_classes="view-help-host",
1248
  )
1249
+ with gr.Row(
1250
+ equal_height=False,
1251
+ elem_classes="pareto-scale-all-row",
1252
+ ):
1253
+ gr.HTML(
1254
+ "<span class='pareto-scale-all-label'>All plots</span>",
1255
+ padding=False,
1256
+ )
1257
+ pareto_all_scale = _pareto_scale_radio(
1258
+ "pareto-scale-toggle-all",
1259
+ )
1260
  pareto_dataset_note = gr.HTML(
1261
  "",
1262
  padding=False,
 
1282
  min_width=320,
1283
  elem_classes="pareto-col",
1284
  ) as slot_price_col:
1285
+ slot_price_scale = _pareto_plot_heading(
1286
+ "Price vs score"
 
1287
  )
1288
  slot_price = gr.Plot(
1289
  value=None,
 
1295
  min_width=320,
1296
  elem_classes="pareto-col",
1297
  ) as slot_time_col:
1298
+ slot_time_scale = _pareto_plot_heading(
1299
+ "Min generation time vs score"
 
1300
  )
1301
  slot_time = gr.Plot(
1302
  value=None,
 
1317
  slot_layout,
1318
  slot_price_col,
1319
  slot_price,
1320
+ slot_price_scale,
1321
  slot_time_col,
1322
  slot_time,
1323
+ slot_time_scale,
1324
  )
1325
  )
1326
 
 
1458
  "optimized": list(
1459
  extras.get("optimized", prev.get("optimized") or [])
1460
  ),
1461
+ "price_scales": _normalize_pareto_scales(prev.get("price_scales")),
1462
+ "time_scales": _normalize_pareto_scales(prev.get("time_scales")),
1463
  "stale": {
1464
  TAB_LEADERBOARDS: not flags["include_leaderboard"],
1465
  TAB_PARETO: not flags["include_pareto"],
 
1519
  include_leaderboard=True,
1520
  include_pareto=False,
1521
  include_samples=False,
1522
+ price_scales=None,
1523
+ time_scales=None,
1524
  ):
1525
  view = resolve_view(datasets, metrics, dataset_id, metric_id)
1526
  data = view["data"]
 
1541
  ranking_html = gr.skip()
1542
  if include_pareto:
1543
  pareto_data = _filter_leaderboard(data, [], [], [], models=models)
1544
+ pareto_updates = _pareto_slot_updates(
1545
+ pareto_data,
1546
+ view["score_columns"],
1547
+ price_scales=price_scales,
1548
+ time_scales=time_scales,
1549
+ )
1550
  else:
1551
  pareto_updates = _pareto_skip_updates()
1552
  if include_samples:
 
1680
  extras[2],
1681
  num_prompts,
1682
  seed,
1683
+ price_scales=view_state.get("price_scales"),
1684
+ time_scales=view_state.get("time_scales"),
1685
  **flags,
1686
  ),
1687
  "state": _commit_state(
 
1884
  optimized_value,
1885
  num_prompts,
1886
  seed,
1887
+ price_scales=view_state.get("price_scales"),
1888
+ time_scales=view_state.get("time_scales"),
1889
  **flags,
1890
  )
1891
  stale[tab] = False
 
1942
  next_seed,
1943
  )
1944
 
1945
+ def _on_pareto_plot_scale(slot_index, axis):
1946
+ def handler(dataset_id, metric_id, models, scale, view_state):
1947
+ view_state = dict(view_state or {})
1948
+ price_scales = _normalize_pareto_scales(
1949
+ view_state.get("price_scales")
1950
+ )
1951
+ time_scales = _normalize_pareto_scales(
1952
+ view_state.get("time_scales")
1953
+ )
1954
+ if axis == "price":
1955
+ if price_scales[slot_index] == scale:
1956
+ return gr.skip(), gr.skip(), gr.skip()
1957
+ price_scales[slot_index] = scale
1958
+ else:
1959
+ if time_scales[slot_index] == scale:
1960
+ return gr.skip(), gr.skip(), gr.skip()
1961
+ time_scales[slot_index] = scale
1962
+ view_state["price_scales"] = price_scales
1963
+ view_state["time_scales"] = time_scales
1964
+ master_scale = _pareto_master_scale_update(
1965
+ price_scales, time_scales
1966
+ )
1967
+ view = resolve_view(datasets, metrics, dataset_id, metric_id)
1968
+ score_columns = [
1969
+ column for column in (view["score_columns"] or []) if column
1970
+ ]
1971
+ if slot_index >= len(score_columns):
1972
+ return gr.skip(), master_scale, view_state
1973
+ data = _filter_leaderboard(
1974
+ view["data"], [], [], [], models=list(models or [])
1975
+ )
1976
+ price_fig, _, time_fig, _ = _pareto_pair(
1977
+ data,
1978
+ score_columns[slot_index],
1979
+ latency_scale=time_scales[slot_index],
1980
+ price_scale=price_scales[slot_index],
1981
+ )
1982
+ fig = price_fig if axis == "price" else time_fig
1983
+ return _pareto_plot_update(fig), master_scale, view_state
1984
+
1985
+ handler.__name__ = f"on_pareto_{axis}_scale_{slot_index}"
1986
+ return handler
1987
+
1988
+ def on_pareto_all_scale(dataset_id, metric_id, models, scale, view_state):
1989
+ if scale not in _PARETO_SCALE_VALUES:
1990
+ return (*_skip_all(MAX_PARETO_METRICS * 4), gr.skip())
1991
+ view_state = dict(view_state or {})
1992
+ scales = _uniform_pareto_scales(scale)
1993
+ if (
1994
+ _normalize_pareto_scales(view_state.get("price_scales")) == scales
1995
+ and _normalize_pareto_scales(view_state.get("time_scales")) == scales
1996
+ ):
1997
+ return (*_skip_all(MAX_PARETO_METRICS * 4), gr.skip())
1998
+ view_state["price_scales"] = scales
1999
+ view_state["time_scales"] = scales
2000
+ view = resolve_view(datasets, metrics, dataset_id, metric_id)
2001
+ data = _filter_leaderboard(
2002
+ view["data"], [], [], [], models=list(models or [])
2003
+ )
2004
+ return (
2005
+ *_pareto_all_scale_updates(data, view["score_columns"], scale),
2006
+ view_state,
2007
+ )
2008
+
2009
  def _on_tab(tab):
2010
  def handler(
2011
  dataset_id,
 
2043
  "platform": [],
2044
  "owner": [],
2045
  "optimized": [],
2046
+ "price_scales": _default_pareto_scales(),
2047
+ "time_scales": _default_pareto_scales(),
2048
  "stale": {
2049
  TAB_LEADERBOARDS: False,
2050
  TAB_PARETO: True,
 
2056
  pareto_dataset_note,
2057
  *[
2058
  component
2059
+ for slot_group, slot_title, slot_note, slot_layout, slot_price_col, slot_price, slot_price_scale, slot_time_col, slot_time, slot_time_scale in pareto_slots
2060
  for component in (
2061
  slot_group,
2062
  slot_title,
 
2069
  )
2070
  ],
2071
  ]
2072
+ pareto_all_scale_outputs = [
2073
+ *[
2074
+ slot_price
2075
+ for _, _, _, _, _, slot_price, _, _, _, _ in pareto_slots
2076
+ ],
2077
+ *[
2078
+ slot_time
2079
+ for _, _, _, _, _, _, _, _, slot_time, _ in pareto_slots
2080
+ ],
2081
+ *[
2082
+ slot_price_scale
2083
+ for _, _, _, _, _, _, slot_price_scale, _, _, _ in pareto_slots
2084
+ ],
2085
+ *[
2086
+ slot_time_scale
2087
+ for _, _, _, _, _, _, _, _, _, slot_time_scale in pareto_slots
2088
+ ],
2089
+ ]
2090
  view_inputs = [
2091
  platform,
2092
  owner,
 
2191
  show_progress="hidden",
2192
  )
2193
 
2194
+ pareto_all_scale.change(
2195
+ on_pareto_all_scale,
2196
+ inputs=[
2197
+ dataset_dd,
2198
+ metric_dd,
2199
+ models_dd,
2200
+ pareto_all_scale,
2201
+ view_state,
2202
+ ],
2203
+ outputs=[*pareto_all_scale_outputs, view_state],
2204
+ **_VIEW_EVENTS,
2205
+ )
2206
+
2207
+ for slot_index, (
2208
+ _,
2209
+ _,
2210
+ _,
2211
+ _,
2212
+ _,
2213
+ slot_price,
2214
+ slot_price_scale,
2215
+ _,
2216
+ slot_time,
2217
+ slot_time_scale,
2218
+ ) in enumerate(pareto_slots):
2219
+ slot_price_scale.change(
2220
+ _on_pareto_plot_scale(slot_index, "price"),
2221
+ inputs=[
2222
+ dataset_dd,
2223
+ metric_dd,
2224
+ models_dd,
2225
+ slot_price_scale,
2226
+ view_state,
2227
+ ],
2228
+ outputs=[slot_price, pareto_all_scale, view_state],
2229
+ **_VIEW_EVENTS,
2230
+ )
2231
+ slot_time_scale.change(
2232
+ _on_pareto_plot_scale(slot_index, "time"),
2233
+ inputs=[
2234
+ dataset_dd,
2235
+ metric_dd,
2236
+ models_dd,
2237
+ slot_time_scale,
2238
+ view_state,
2239
+ ],
2240
+ outputs=[slot_time, pareto_all_scale, view_state],
2241
+ **_VIEW_EVENTS,
2242
+ )
2243
+
2244
  prompt_count.change(
2245
  on_samples_controls,
2246
  inputs=[dataset_dd, models_dd, prompt_count, seed_state],