CP Legendre commited on
Commit ·
e4bbf8f
1
Parent(s): 344a63b
Address chart styling feedback
Browse files- app.py +63 -120
- src/charts.py +98 -50
app.py
CHANGED
|
@@ -65,114 +65,18 @@ API = HfApi(token=TOKEN)
|
|
| 65 |
COLOR_BY_CHOICES = ["Model", "Harness"]
|
| 66 |
COLOR_PALETTE_CHOICES = ["Citrus", "Okabe-Ito", "High contrast", "Rainbow"]
|
| 67 |
DEFAULT_COLOR_PALETTE = "Citrus"
|
| 68 |
-
|
| 69 |
-
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
}
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
.main,
|
| 81 |
-
.wrap,
|
| 82 |
-
.contain,
|
| 83 |
-
#component-0 {
|
| 84 |
-
background: #15110F !important;
|
| 85 |
-
}
|
| 86 |
-
|
| 87 |
-
.markdown-text,
|
| 88 |
-
.markdown-text p,
|
| 89 |
-
.markdown-text li,
|
| 90 |
-
.markdown-text td,
|
| 91 |
-
.markdown-text th,
|
| 92 |
-
.gradio-container label,
|
| 93 |
-
.gradio-container .prose,
|
| 94 |
-
.gradio-container .prose * {
|
| 95 |
-
color: #E5E7EB !important;
|
| 96 |
-
}
|
| 97 |
-
|
| 98 |
-
.gradio-container h1,
|
| 99 |
-
.gradio-container h2,
|
| 100 |
-
.gradio-container h3,
|
| 101 |
-
.gradio-container h4 {
|
| 102 |
-
color: #F8FAFC !important;
|
| 103 |
-
}
|
| 104 |
-
|
| 105 |
-
.gradio-container .block,
|
| 106 |
-
.gradio-container .form,
|
| 107 |
-
.gradio-container .panel,
|
| 108 |
-
.gradio-container .tabitem,
|
| 109 |
-
.gradio-container .tabs,
|
| 110 |
-
.gradio-container .plot-container,
|
| 111 |
-
.gradio-container .js-plotly-plot {
|
| 112 |
-
background: #27211E !important;
|
| 113 |
-
color: #F8FAFC !important;
|
| 114 |
-
border-color: rgba(248, 250, 252, 0.14) !important;
|
| 115 |
-
}
|
| 116 |
-
|
| 117 |
-
.gradio-container input,
|
| 118 |
-
.gradio-container textarea,
|
| 119 |
-
.gradio-container select,
|
| 120 |
-
.gradio-container button,
|
| 121 |
-
.gradio-container .wrap-inner {
|
| 122 |
-
color: #F8FAFC !important;
|
| 123 |
-
}
|
| 124 |
-
|
| 125 |
-
/* Radio/dropdown color controls need explicit contrast. Gradio's citrus theme can
|
| 126 |
-
otherwise produce light text on light inactive radio buttons. */
|
| 127 |
-
.gradio-container .color-control label,
|
| 128 |
-
.gradio-container .color-control label span,
|
| 129 |
-
.gradio-container .color-control button,
|
| 130 |
-
.gradio-container .color-control .wrap label span {
|
| 131 |
-
color: #F8FAFC !important;
|
| 132 |
-
}
|
| 133 |
-
|
| 134 |
-
.gradio-container .color-control label:not(:has(input:checked)),
|
| 135 |
-
.gradio-container .color-control button:not([aria-pressed="true"]) {
|
| 136 |
-
background: #3B332F !important;
|
| 137 |
-
color: #F8FAFC !important;
|
| 138 |
-
border-color: rgba(248, 250, 252, 0.18) !important;
|
| 139 |
-
}
|
| 140 |
-
|
| 141 |
-
.gradio-container .color-control label:has(input:checked),
|
| 142 |
-
.gradio-container .color-control label.selected,
|
| 143 |
-
.gradio-container .color-control button.selected,
|
| 144 |
-
.gradio-container .color-control button[aria-pressed="true"] {
|
| 145 |
-
background: #F59E0B !important;
|
| 146 |
-
color: #111827 !important;
|
| 147 |
-
border-color: #FBBF24 !important;
|
| 148 |
-
}
|
| 149 |
-
|
| 150 |
-
.gradio-container .color-control label:has(input:checked) span,
|
| 151 |
-
.gradio-container .color-control label.selected span,
|
| 152 |
-
.gradio-container .color-control button.selected,
|
| 153 |
-
.gradio-container .color-control button[aria-pressed="true"] {
|
| 154 |
-
color: #111827 !important;
|
| 155 |
-
}
|
| 156 |
-
|
| 157 |
-
.gradio-container .color-control input[type="radio"] {
|
| 158 |
-
accent-color: #F59E0B;
|
| 159 |
-
}
|
| 160 |
-
|
| 161 |
-
/* Let Plotly consume the available card width instead of keeping a fixed SVG size. */
|
| 162 |
-
.gradio-container .plot-container,
|
| 163 |
-
.gradio-container .js-plotly-plot,
|
| 164 |
-
.gradio-container .plotly,
|
| 165 |
-
.gradio-container .svg-container,
|
| 166 |
-
.gradio-container .main-svg {
|
| 167 |
-
width: 100% !important;
|
| 168 |
-
max-width: 100% !important;
|
| 169 |
-
}
|
| 170 |
-
|
| 171 |
-
.gradio-container .js-plotly-plot,
|
| 172 |
-
.gradio-container .svg-container {
|
| 173 |
-
min-height: 520px !important;
|
| 174 |
-
height: clamp(520px, 58vh, 760px) !important;
|
| 175 |
-
}
|
| 176 |
"""
|
| 177 |
|
| 178 |
|
|
@@ -186,21 +90,33 @@ BENCHMARK_RUN_DF = get_benchmark_run_df()
|
|
| 186 |
SCORE_VS_COST_DF = get_score_vs_cost_df()
|
| 187 |
|
| 188 |
|
| 189 |
-
def render_leaderboard_benchmark_plot(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 190 |
return create_leaderboard_benchmark_plot(
|
| 191 |
BENCHMARK_RUN_DF,
|
| 192 |
benchmark_name=benchmark_name,
|
| 193 |
color_by=color_by,
|
| 194 |
palette_name=color_palette,
|
|
|
|
| 195 |
)
|
| 196 |
|
| 197 |
|
| 198 |
-
def render_score_vs_cost_plot(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 199 |
return create_score_vs_cost_plot(
|
| 200 |
SCORE_VS_COST_DF,
|
| 201 |
benchmark_name=benchmark_name,
|
| 202 |
color_by=color_by,
|
| 203 |
palette_name=color_palette,
|
|
|
|
| 204 |
)
|
| 205 |
|
| 206 |
|
|
@@ -273,7 +189,7 @@ def init_benchmark_runs(dataframe):
|
|
| 273 |
)
|
| 274 |
|
| 275 |
|
| 276 |
-
demo = gr.Blocks(theme="citrus",
|
| 277 |
with demo:
|
| 278 |
gr.HTML(build_header_html(BENCHMARK_RUN_DF))
|
| 279 |
gr.Markdown(INTRODUCTION_TEXT, elem_classes="markdown-text")
|
|
@@ -294,24 +210,35 @@ with demo:
|
|
| 294 |
label="Color palette",
|
| 295 |
elem_classes="color-control",
|
| 296 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 297 |
|
| 298 |
leaderboard_plots = []
|
| 299 |
for benchmark_name in BENCHMARK_NAMES:
|
| 300 |
gr.Markdown(f"#### {benchmark_name}")
|
| 301 |
plot = gr.Plot(
|
| 302 |
-
value=render_leaderboard_benchmark_plot(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 303 |
show_label=False,
|
| 304 |
elem_classes="responsive-plot",
|
| 305 |
)
|
| 306 |
leaderboard_plots.append((benchmark_name, plot))
|
| 307 |
|
| 308 |
for benchmark_name, plot in leaderboard_plots:
|
| 309 |
-
for control in (leaderboard_color_by, leaderboard_palette):
|
| 310 |
control.change(
|
| 311 |
-
fn=lambda color_by, palette, name=benchmark_name: render_leaderboard_benchmark_plot(
|
| 312 |
-
name, color_by, palette
|
| 313 |
),
|
| 314 |
-
inputs=[leaderboard_color_by, leaderboard_palette],
|
| 315 |
outputs=plot,
|
| 316 |
)
|
| 317 |
|
|
@@ -334,24 +261,40 @@ with demo:
|
|
| 334 |
label="Color palette",
|
| 335 |
elem_classes="color-control",
|
| 336 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 337 |
score_vs_cost_plot = gr.Plot(
|
| 338 |
-
value=render_score_vs_cost_plot(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 339 |
show_label=False,
|
| 340 |
elem_classes="responsive-plot",
|
| 341 |
)
|
| 342 |
cost_benchmark.change(
|
| 343 |
fn=render_score_vs_cost_plot,
|
| 344 |
-
inputs=[cost_benchmark, cost_color_by, cost_palette],
|
| 345 |
outputs=score_vs_cost_plot,
|
| 346 |
)
|
| 347 |
cost_color_by.change(
|
| 348 |
fn=render_score_vs_cost_plot,
|
| 349 |
-
inputs=[cost_benchmark, cost_color_by, cost_palette],
|
| 350 |
outputs=score_vs_cost_plot,
|
| 351 |
)
|
| 352 |
cost_palette.change(
|
| 353 |
fn=render_score_vs_cost_plot,
|
| 354 |
-
inputs=[cost_benchmark, cost_color_by, cost_palette],
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 355 |
outputs=score_vs_cost_plot,
|
| 356 |
)
|
| 357 |
|
|
|
|
| 65 |
COLOR_BY_CHOICES = ["Model", "Harness"]
|
| 66 |
COLOR_PALETTE_CHOICES = ["Citrus", "Okabe-Ito", "High contrast", "Rainbow"]
|
| 67 |
DEFAULT_COLOR_PALETTE = "Citrus"
|
| 68 |
+
PLOT_BACKGROUND_CHOICES = ["Dark", "White"]
|
| 69 |
+
DEFAULT_PLOT_BACKGROUND = "Dark"
|
| 70 |
+
FORCE_DARK_MODE_HEAD = """
|
| 71 |
+
<script>
|
| 72 |
+
(() => {
|
| 73 |
+
const url = new URL(window.location.href);
|
| 74 |
+
if (!url.searchParams.has("__theme")) {
|
| 75 |
+
url.searchParams.set("__theme", "dark");
|
| 76 |
+
window.location.replace(url.toString());
|
| 77 |
+
}
|
| 78 |
+
})();
|
| 79 |
+
</script>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 80 |
"""
|
| 81 |
|
| 82 |
|
|
|
|
| 90 |
SCORE_VS_COST_DF = get_score_vs_cost_df()
|
| 91 |
|
| 92 |
|
| 93 |
+
def render_leaderboard_benchmark_plot(
|
| 94 |
+
benchmark_name,
|
| 95 |
+
color_by,
|
| 96 |
+
color_palette=DEFAULT_COLOR_PALETTE,
|
| 97 |
+
plot_background=DEFAULT_PLOT_BACKGROUND,
|
| 98 |
+
):
|
| 99 |
return create_leaderboard_benchmark_plot(
|
| 100 |
BENCHMARK_RUN_DF,
|
| 101 |
benchmark_name=benchmark_name,
|
| 102 |
color_by=color_by,
|
| 103 |
palette_name=color_palette,
|
| 104 |
+
background_name=plot_background,
|
| 105 |
)
|
| 106 |
|
| 107 |
|
| 108 |
+
def render_score_vs_cost_plot(
|
| 109 |
+
benchmark_name,
|
| 110 |
+
color_by,
|
| 111 |
+
color_palette=DEFAULT_COLOR_PALETTE,
|
| 112 |
+
plot_background=DEFAULT_PLOT_BACKGROUND,
|
| 113 |
+
):
|
| 114 |
return create_score_vs_cost_plot(
|
| 115 |
SCORE_VS_COST_DF,
|
| 116 |
benchmark_name=benchmark_name,
|
| 117 |
color_by=color_by,
|
| 118 |
palette_name=color_palette,
|
| 119 |
+
background_name=plot_background,
|
| 120 |
)
|
| 121 |
|
| 122 |
|
|
|
|
| 189 |
)
|
| 190 |
|
| 191 |
|
| 192 |
+
demo = gr.Blocks(theme="citrus", head=FORCE_DARK_MODE_HEAD)
|
| 193 |
with demo:
|
| 194 |
gr.HTML(build_header_html(BENCHMARK_RUN_DF))
|
| 195 |
gr.Markdown(INTRODUCTION_TEXT, elem_classes="markdown-text")
|
|
|
|
| 210 |
label="Color palette",
|
| 211 |
elem_classes="color-control",
|
| 212 |
)
|
| 213 |
+
leaderboard_background = gr.Dropdown(
|
| 214 |
+
choices=PLOT_BACKGROUND_CHOICES,
|
| 215 |
+
value=DEFAULT_PLOT_BACKGROUND,
|
| 216 |
+
label="Image background",
|
| 217 |
+
elem_classes="color-control",
|
| 218 |
+
)
|
| 219 |
|
| 220 |
leaderboard_plots = []
|
| 221 |
for benchmark_name in BENCHMARK_NAMES:
|
| 222 |
gr.Markdown(f"#### {benchmark_name}")
|
| 223 |
plot = gr.Plot(
|
| 224 |
+
value=render_leaderboard_benchmark_plot(
|
| 225 |
+
benchmark_name,
|
| 226 |
+
"Model",
|
| 227 |
+
DEFAULT_COLOR_PALETTE,
|
| 228 |
+
DEFAULT_PLOT_BACKGROUND,
|
| 229 |
+
),
|
| 230 |
show_label=False,
|
| 231 |
elem_classes="responsive-plot",
|
| 232 |
)
|
| 233 |
leaderboard_plots.append((benchmark_name, plot))
|
| 234 |
|
| 235 |
for benchmark_name, plot in leaderboard_plots:
|
| 236 |
+
for control in (leaderboard_color_by, leaderboard_palette, leaderboard_background):
|
| 237 |
control.change(
|
| 238 |
+
fn=lambda color_by, palette, background, name=benchmark_name: render_leaderboard_benchmark_plot(
|
| 239 |
+
name, color_by, palette, background
|
| 240 |
),
|
| 241 |
+
inputs=[leaderboard_color_by, leaderboard_palette, leaderboard_background],
|
| 242 |
outputs=plot,
|
| 243 |
)
|
| 244 |
|
|
|
|
| 261 |
label="Color palette",
|
| 262 |
elem_classes="color-control",
|
| 263 |
)
|
| 264 |
+
cost_background = gr.Dropdown(
|
| 265 |
+
choices=PLOT_BACKGROUND_CHOICES,
|
| 266 |
+
value=DEFAULT_PLOT_BACKGROUND,
|
| 267 |
+
label="Image background",
|
| 268 |
+
elem_classes="color-control",
|
| 269 |
+
)
|
| 270 |
score_vs_cost_plot = gr.Plot(
|
| 271 |
+
value=render_score_vs_cost_plot(
|
| 272 |
+
DEFAULT_BENCHMARK,
|
| 273 |
+
"Model",
|
| 274 |
+
DEFAULT_COLOR_PALETTE,
|
| 275 |
+
DEFAULT_PLOT_BACKGROUND,
|
| 276 |
+
),
|
| 277 |
show_label=False,
|
| 278 |
elem_classes="responsive-plot",
|
| 279 |
)
|
| 280 |
cost_benchmark.change(
|
| 281 |
fn=render_score_vs_cost_plot,
|
| 282 |
+
inputs=[cost_benchmark, cost_color_by, cost_palette, cost_background],
|
| 283 |
outputs=score_vs_cost_plot,
|
| 284 |
)
|
| 285 |
cost_color_by.change(
|
| 286 |
fn=render_score_vs_cost_plot,
|
| 287 |
+
inputs=[cost_benchmark, cost_color_by, cost_palette, cost_background],
|
| 288 |
outputs=score_vs_cost_plot,
|
| 289 |
)
|
| 290 |
cost_palette.change(
|
| 291 |
fn=render_score_vs_cost_plot,
|
| 292 |
+
inputs=[cost_benchmark, cost_color_by, cost_palette, cost_background],
|
| 293 |
+
outputs=score_vs_cost_plot,
|
| 294 |
+
)
|
| 295 |
+
cost_background.change(
|
| 296 |
+
fn=render_score_vs_cost_plot,
|
| 297 |
+
inputs=[cost_benchmark, cost_color_by, cost_palette, cost_background],
|
| 298 |
outputs=score_vs_cost_plot,
|
| 299 |
)
|
| 300 |
|
src/charts.py
CHANGED
|
@@ -10,16 +10,18 @@ from plotly.graph_objs._figure import Figure
|
|
| 10 |
|
| 11 |
ColorBy = Literal["Model", "Harness"]
|
| 12 |
PaletteName = Literal["Citrus", "Okabe-Ito", "High contrast", "Rainbow"]
|
|
|
|
| 13 |
DEFAULT_PALETTE: PaletteName = "Citrus"
|
|
|
|
| 14 |
|
| 15 |
# Separate categorical palettes for each grouping dimension.
|
| 16 |
# Model and harness colors intentionally start from different hue families so
|
| 17 |
# switching "Color by" remains visually obvious.
|
| 18 |
MODEL_COLORS: dict[str, str] = {
|
| 19 |
-
"GPT 5.5 - high": "#
|
| 20 |
-
"Opus 4.8": "#
|
| 21 |
"RedHatAI/Qwen3.6-35B-A3B-NVFP4": "#F97316", # orange
|
| 22 |
-
"Sonnet 4.6": "#
|
| 23 |
}
|
| 24 |
|
| 25 |
HARNESS_COLORS: dict[str, str] = {
|
|
@@ -33,16 +35,16 @@ HARNESS_COLORS: dict[str, str] = {
|
|
| 33 |
}
|
| 34 |
|
| 35 |
MODEL_FALLBACK_PALETTE = [
|
| 36 |
-
"#
|
| 37 |
-
"#
|
| 38 |
-
"#
|
| 39 |
-
"#
|
| 40 |
-
"#
|
| 41 |
-
"#
|
| 42 |
-
"#
|
| 43 |
-
"#
|
| 44 |
-
"#F472B6", # pink
|
| 45 |
-
"#
|
| 46 |
]
|
| 47 |
|
| 48 |
HARNESS_FALLBACK_PALETTE = [
|
|
@@ -66,6 +68,30 @@ TEXT_MUTED = "#CBD5E1"
|
|
| 66 |
GRID_COLOR = "rgba(248,250,252,0.14)"
|
| 67 |
ZERO_LINE_COLOR = "rgba(248,250,252,0.24)"
|
| 68 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 69 |
def clean_markdown_link(value: object) -> str:
|
| 70 |
"""Return human-readable text from Markdown links used in leaderboard tables."""
|
| 71 |
text = str(value).replace("<sup>*</sup>", "")
|
|
@@ -102,6 +128,18 @@ def normalize_palette_name(palette_name: str | None) -> PaletteName:
|
|
| 102 |
return DEFAULT_PALETTE
|
| 103 |
|
| 104 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 105 |
def stable_color(name: str, color_by: ColorBy, palette_name: str | None = DEFAULT_PALETTE) -> str:
|
| 106 |
palette_key = normalize_palette_name(palette_name)
|
| 107 |
palettes = MODEL_PALETTES if color_by == "Model" else HARNESS_PALETTES
|
|
@@ -158,7 +196,8 @@ def color_map_for(
|
|
| 158 |
}
|
| 159 |
|
| 160 |
|
| 161 |
-
def empty_figure(message: str) -> Figure:
|
|
|
|
| 162 |
fig = go.Figure()
|
| 163 |
fig.add_annotation(
|
| 164 |
text=message,
|
|
@@ -167,50 +206,52 @@ def empty_figure(message: str) -> Figure:
|
|
| 167 |
y=0.5,
|
| 168 |
xref="paper",
|
| 169 |
yref="paper",
|
| 170 |
-
font={"size": 14, "color":
|
| 171 |
)
|
| 172 |
-
return apply_plot_theme(fig)
|
| 173 |
|
| 174 |
|
| 175 |
-
def apply_plot_theme(fig: Figure) -> Figure:
|
|
|
|
| 176 |
fig.update_layout(
|
| 177 |
-
template="
|
| 178 |
autosize=True,
|
| 179 |
-
paper_bgcolor="
|
| 180 |
-
plot_bgcolor=
|
| 181 |
-
font={"color":
|
| 182 |
-
title={"font": {"color":
|
| 183 |
-
margin={"t":
|
| 184 |
legend={
|
| 185 |
"orientation": "h",
|
| 186 |
-
"yanchor": "
|
| 187 |
-
"y": 1
|
| 188 |
"xanchor": "center",
|
| 189 |
"x": 0.5,
|
| 190 |
-
"font": {"color":
|
| 191 |
},
|
| 192 |
)
|
| 193 |
# Remove fixed dimensions so Gradio/Plotly can size to the browser/container.
|
| 194 |
fig.update_layout(width=None, height=None)
|
| 195 |
fig.update_xaxes(
|
| 196 |
-
|
| 197 |
-
|
| 198 |
-
|
| 199 |
-
|
| 200 |
-
|
| 201 |
-
|
|
|
|
| 202 |
)
|
| 203 |
fig.update_yaxes(
|
| 204 |
-
|
| 205 |
-
|
| 206 |
-
|
| 207 |
-
|
| 208 |
-
|
| 209 |
-
|
|
|
|
| 210 |
)
|
| 211 |
return fig
|
| 212 |
|
| 213 |
-
|
| 214 |
def prepare_benchmark_run_plot_df(dataframe: pd.DataFrame) -> pd.DataFrame:
|
| 215 |
plot_df = dataframe.copy()
|
| 216 |
plot_df["Model Label"] = plot_df["Model"].map(clean_markdown_link)
|
|
@@ -226,19 +267,21 @@ def create_leaderboard_benchmark_plot(
|
|
| 226 |
benchmark_name: str,
|
| 227 |
color_by: ColorBy = "Model",
|
| 228 |
palette_name: str | None = DEFAULT_PALETTE,
|
|
|
|
| 229 |
) -> Figure:
|
| 230 |
if dataframe is None or dataframe.empty:
|
| 231 |
-
return empty_figure("No benchmark data available.")
|
| 232 |
|
| 233 |
plot_df = prepare_benchmark_run_plot_df(dataframe)
|
| 234 |
plot_df = plot_df[plot_df["Benchmark Label"] == benchmark_name].dropna(subset=["Score"])
|
| 235 |
plot_df = plot_df.sort_values("Score", ascending=False)
|
| 236 |
|
| 237 |
if plot_df.empty:
|
| 238 |
-
return empty_figure(f"No results available for {benchmark_name}.")
|
| 239 |
|
| 240 |
color_source = "Model Label" if color_by == "Model" else "Harness Label"
|
| 241 |
colors = color_map_for(plot_df[color_source], color_by, palette_name)
|
|
|
|
| 242 |
fig = go.Figure()
|
| 243 |
|
| 244 |
for group, group_df in plot_df.groupby(color_source, sort=True):
|
|
@@ -247,7 +290,10 @@ def create_leaderboard_benchmark_plot(
|
|
| 247 |
x=group_df["Run Label"],
|
| 248 |
y=group_df["Score"],
|
| 249 |
name=str(group),
|
| 250 |
-
marker={
|
|
|
|
|
|
|
|
|
|
| 251 |
text=group_df["Score"].map(lambda score: f"{score:.1f}"),
|
| 252 |
textposition="outside",
|
| 253 |
customdata=group_df[["Model Label", "Harness Label", "Score"]],
|
|
@@ -261,14 +307,14 @@ def create_leaderboard_benchmark_plot(
|
|
| 261 |
)
|
| 262 |
|
| 263 |
fig.update_layout(
|
| 264 |
-
title=
|
| 265 |
xaxis={"title": "Model / Harness", "categoryorder": "array", "categoryarray": plot_df["Run Label"].tolist()},
|
| 266 |
yaxis={"title": "Score (%)", "range": [0, 105]},
|
| 267 |
legend_title_text=color_by,
|
| 268 |
bargap=0.28,
|
| 269 |
)
|
| 270 |
fig.update_xaxes(tickangle=-28)
|
| 271 |
-
return apply_plot_theme(fig)
|
| 272 |
|
| 273 |
|
| 274 |
def create_score_vs_cost_plot(
|
|
@@ -276,12 +322,13 @@ def create_score_vs_cost_plot(
|
|
| 276 |
benchmark_name: str | None,
|
| 277 |
color_by: ColorBy = "Model",
|
| 278 |
palette_name: str | None = DEFAULT_PALETTE,
|
|
|
|
| 279 |
) -> Figure:
|
| 280 |
if dataframe is None or dataframe.empty:
|
| 281 |
-
return empty_figure("No cost data available.")
|
| 282 |
|
| 283 |
if not benchmark_name:
|
| 284 |
-
return empty_figure("Select a benchmark to view cost data.")
|
| 285 |
|
| 286 |
plot_df = dataframe.copy()
|
| 287 |
plot_df = plot_df[plot_df["Benchmark"] == benchmark_name]
|
|
@@ -290,9 +337,10 @@ def create_score_vs_cost_plot(
|
|
| 290 |
plot_df = plot_df.dropna(subset=["Score", "Cost Per Task (USD)"])
|
| 291 |
|
| 292 |
if plot_df.empty:
|
| 293 |
-
return empty_figure(f"No cost data available for {benchmark_name}.")
|
| 294 |
|
| 295 |
colors = color_map_for(plot_df[color_by], color_by, palette_name)
|
|
|
|
| 296 |
fig = go.Figure()
|
| 297 |
|
| 298 |
for group, group_df in plot_df.groupby(color_by, sort=True):
|
|
@@ -307,7 +355,7 @@ def create_score_vs_cost_plot(
|
|
| 307 |
marker={
|
| 308 |
"size": 15,
|
| 309 |
"color": colors[str(group)],
|
| 310 |
-
"line": {"width": 1, "color":
|
| 311 |
},
|
| 312 |
customdata=group_df[["Model", "Harness", "Benchmark", "Score", "Cost Per Task (USD)"]],
|
| 313 |
hovertemplate=(
|
|
@@ -322,9 +370,9 @@ def create_score_vs_cost_plot(
|
|
| 322 |
)
|
| 323 |
|
| 324 |
fig.update_layout(
|
| 325 |
-
title=
|
| 326 |
xaxis={"title": "Cost per task (USD)", "tickprefix": "$", "tickformat": ".2f"},
|
| 327 |
yaxis={"title": "Score (%)", "range": [0, 105]},
|
| 328 |
legend_title_text=color_by,
|
| 329 |
)
|
| 330 |
-
return apply_plot_theme(fig)
|
|
|
|
| 10 |
|
| 11 |
ColorBy = Literal["Model", "Harness"]
|
| 12 |
PaletteName = Literal["Citrus", "Okabe-Ito", "High contrast", "Rainbow"]
|
| 13 |
+
PlotBackground = Literal["Dark", "White"]
|
| 14 |
DEFAULT_PALETTE: PaletteName = "Citrus"
|
| 15 |
+
DEFAULT_BACKGROUND: PlotBackground = "Dark"
|
| 16 |
|
| 17 |
# Separate categorical palettes for each grouping dimension.
|
| 18 |
# Model and harness colors intentionally start from different hue families so
|
| 19 |
# switching "Color by" remains visually obvious.
|
| 20 |
MODEL_COLORS: dict[str, str] = {
|
| 21 |
+
"GPT 5.5 - high": "#F8FAFC", # white
|
| 22 |
+
"Opus 4.8": "#FEF3C7", # cream
|
| 23 |
"RedHatAI/Qwen3.6-35B-A3B-NVFP4": "#F97316", # orange
|
| 24 |
+
"Sonnet 4.6": "#DC2626", # red
|
| 25 |
}
|
| 26 |
|
| 27 |
HARNESS_COLORS: dict[str, str] = {
|
|
|
|
| 35 |
}
|
| 36 |
|
| 37 |
MODEL_FALLBACK_PALETTE = [
|
| 38 |
+
"#F8FAFC", # white
|
| 39 |
+
"#FEF3C7", # cream
|
| 40 |
+
"#FACC15", # yellow
|
| 41 |
+
"#FB923C", # orange
|
| 42 |
+
"#DC2626", # red
|
| 43 |
+
"#93C5FD", # blue fallback
|
| 44 |
+
"#22C55E", # green fallback
|
| 45 |
+
"#C084FC", # violet fallback
|
| 46 |
+
"#F472B6", # pink fallback
|
| 47 |
+
"#14B8A6", # teal fallback
|
| 48 |
]
|
| 49 |
|
| 50 |
HARNESS_FALLBACK_PALETTE = [
|
|
|
|
| 68 |
GRID_COLOR = "rgba(248,250,252,0.14)"
|
| 69 |
ZERO_LINE_COLOR = "rgba(248,250,252,0.24)"
|
| 70 |
|
| 71 |
+
PLOT_BACKGROUNDS: dict[PlotBackground, dict[str, str]] = {
|
| 72 |
+
"Dark": {
|
| 73 |
+
"template": "plotly_dark",
|
| 74 |
+
"paper_bgcolor": DARK_CARD,
|
| 75 |
+
"plot_bgcolor": DARK_PLOT,
|
| 76 |
+
"text_primary": TEXT_PRIMARY,
|
| 77 |
+
"text_muted": TEXT_MUTED,
|
| 78 |
+
"grid_color": GRID_COLOR,
|
| 79 |
+
"zero_line_color": ZERO_LINE_COLOR,
|
| 80 |
+
"marker_line_color": DARK_PAPER,
|
| 81 |
+
},
|
| 82 |
+
"White": {
|
| 83 |
+
"template": "plotly_white",
|
| 84 |
+
"paper_bgcolor": "#FFFFFF",
|
| 85 |
+
"plot_bgcolor": "#FFFFFF",
|
| 86 |
+
"text_primary": "#0F172A",
|
| 87 |
+
"text_muted": "#475569",
|
| 88 |
+
"grid_color": "rgba(15,23,42,0.12)",
|
| 89 |
+
"zero_line_color": "rgba(15,23,42,0.25)",
|
| 90 |
+
"marker_line_color": "#334155",
|
| 91 |
+
},
|
| 92 |
+
}
|
| 93 |
+
|
| 94 |
+
|
| 95 |
def clean_markdown_link(value: object) -> str:
|
| 96 |
"""Return human-readable text from Markdown links used in leaderboard tables."""
|
| 97 |
text = str(value).replace("<sup>*</sup>", "")
|
|
|
|
| 128 |
return DEFAULT_PALETTE
|
| 129 |
|
| 130 |
|
| 131 |
+
def normalize_background_name(background_name: str | None) -> PlotBackground:
|
| 132 |
+
if background_name == "Current":
|
| 133 |
+
return "Dark"
|
| 134 |
+
if background_name in PLOT_BACKGROUNDS:
|
| 135 |
+
return background_name # type: ignore[return-value]
|
| 136 |
+
return DEFAULT_BACKGROUND
|
| 137 |
+
|
| 138 |
+
|
| 139 |
+
def get_plot_background(background_name: str | None = DEFAULT_BACKGROUND) -> dict[str, str]:
|
| 140 |
+
return PLOT_BACKGROUNDS[normalize_background_name(background_name)]
|
| 141 |
+
|
| 142 |
+
|
| 143 |
def stable_color(name: str, color_by: ColorBy, palette_name: str | None = DEFAULT_PALETTE) -> str:
|
| 144 |
palette_key = normalize_palette_name(palette_name)
|
| 145 |
palettes = MODEL_PALETTES if color_by == "Model" else HARNESS_PALETTES
|
|
|
|
| 196 |
}
|
| 197 |
|
| 198 |
|
| 199 |
+
def empty_figure(message: str, background_name: str | None = DEFAULT_BACKGROUND) -> Figure:
|
| 200 |
+
theme = get_plot_background(background_name)
|
| 201 |
fig = go.Figure()
|
| 202 |
fig.add_annotation(
|
| 203 |
text=message,
|
|
|
|
| 206 |
y=0.5,
|
| 207 |
xref="paper",
|
| 208 |
yref="paper",
|
| 209 |
+
font={"size": 14, "color": theme["text_muted"]},
|
| 210 |
)
|
| 211 |
+
return apply_plot_theme(fig, background_name)
|
| 212 |
|
| 213 |
|
| 214 |
+
def apply_plot_theme(fig: Figure, background_name: str | None = DEFAULT_BACKGROUND) -> Figure:
|
| 215 |
+
theme = get_plot_background(background_name)
|
| 216 |
fig.update_layout(
|
| 217 |
+
template=theme["template"],
|
| 218 |
autosize=True,
|
| 219 |
+
paper_bgcolor=theme["paper_bgcolor"],
|
| 220 |
+
plot_bgcolor=theme["plot_bgcolor"],
|
| 221 |
+
font={"color": theme["text_primary"]},
|
| 222 |
+
title={"font": {"color": theme["text_primary"]}},
|
| 223 |
+
margin={"t": 0, "b": 0, "l": 0, "r": 0},
|
| 224 |
legend={
|
| 225 |
"orientation": "h",
|
| 226 |
+
"yanchor": "top",
|
| 227 |
+
"y": 1,
|
| 228 |
"xanchor": "center",
|
| 229 |
"x": 0.5,
|
| 230 |
+
"font": {"color": theme["text_muted"]},
|
| 231 |
},
|
| 232 |
)
|
| 233 |
# Remove fixed dimensions so Gradio/Plotly can size to the browser/container.
|
| 234 |
fig.update_layout(width=None, height=None)
|
| 235 |
fig.update_xaxes(
|
| 236 |
+
automargin=True,
|
| 237 |
+
color=theme["text_muted"],
|
| 238 |
+
gridcolor=theme["grid_color"],
|
| 239 |
+
zerolinecolor=theme["zero_line_color"],
|
| 240 |
+
linecolor=theme["grid_color"],
|
| 241 |
+
title_font={"color": theme["text_muted"]},
|
| 242 |
+
tickfont={"color": theme["text_muted"]},
|
| 243 |
)
|
| 244 |
fig.update_yaxes(
|
| 245 |
+
automargin=True,
|
| 246 |
+
color=theme["text_muted"],
|
| 247 |
+
gridcolor=theme["grid_color"],
|
| 248 |
+
zerolinecolor=theme["zero_line_color"],
|
| 249 |
+
linecolor=theme["grid_color"],
|
| 250 |
+
title_font={"color": theme["text_muted"]},
|
| 251 |
+
tickfont={"color": theme["text_muted"]},
|
| 252 |
)
|
| 253 |
return fig
|
| 254 |
|
|
|
|
| 255 |
def prepare_benchmark_run_plot_df(dataframe: pd.DataFrame) -> pd.DataFrame:
|
| 256 |
plot_df = dataframe.copy()
|
| 257 |
plot_df["Model Label"] = plot_df["Model"].map(clean_markdown_link)
|
|
|
|
| 267 |
benchmark_name: str,
|
| 268 |
color_by: ColorBy = "Model",
|
| 269 |
palette_name: str | None = DEFAULT_PALETTE,
|
| 270 |
+
background_name: str | None = DEFAULT_BACKGROUND,
|
| 271 |
) -> Figure:
|
| 272 |
if dataframe is None or dataframe.empty:
|
| 273 |
+
return empty_figure("No benchmark data available.", background_name)
|
| 274 |
|
| 275 |
plot_df = prepare_benchmark_run_plot_df(dataframe)
|
| 276 |
plot_df = plot_df[plot_df["Benchmark Label"] == benchmark_name].dropna(subset=["Score"])
|
| 277 |
plot_df = plot_df.sort_values("Score", ascending=False)
|
| 278 |
|
| 279 |
if plot_df.empty:
|
| 280 |
+
return empty_figure(f"No results available for {benchmark_name}.", background_name)
|
| 281 |
|
| 282 |
color_source = "Model Label" if color_by == "Model" else "Harness Label"
|
| 283 |
colors = color_map_for(plot_df[color_source], color_by, palette_name)
|
| 284 |
+
theme = get_plot_background(background_name)
|
| 285 |
fig = go.Figure()
|
| 286 |
|
| 287 |
for group, group_df in plot_df.groupby(color_source, sort=True):
|
|
|
|
| 290 |
x=group_df["Run Label"],
|
| 291 |
y=group_df["Score"],
|
| 292 |
name=str(group),
|
| 293 |
+
marker={
|
| 294 |
+
"color": colors[str(group)],
|
| 295 |
+
"line": {"width": 1, "color": theme["marker_line_color"]},
|
| 296 |
+
},
|
| 297 |
text=group_df["Score"].map(lambda score: f"{score:.1f}"),
|
| 298 |
textposition="outside",
|
| 299 |
customdata=group_df[["Model Label", "Harness Label", "Score"]],
|
|
|
|
| 307 |
)
|
| 308 |
|
| 309 |
fig.update_layout(
|
| 310 |
+
title=None,
|
| 311 |
xaxis={"title": "Model / Harness", "categoryorder": "array", "categoryarray": plot_df["Run Label"].tolist()},
|
| 312 |
yaxis={"title": "Score (%)", "range": [0, 105]},
|
| 313 |
legend_title_text=color_by,
|
| 314 |
bargap=0.28,
|
| 315 |
)
|
| 316 |
fig.update_xaxes(tickangle=-28)
|
| 317 |
+
return apply_plot_theme(fig, background_name)
|
| 318 |
|
| 319 |
|
| 320 |
def create_score_vs_cost_plot(
|
|
|
|
| 322 |
benchmark_name: str | None,
|
| 323 |
color_by: ColorBy = "Model",
|
| 324 |
palette_name: str | None = DEFAULT_PALETTE,
|
| 325 |
+
background_name: str | None = DEFAULT_BACKGROUND,
|
| 326 |
) -> Figure:
|
| 327 |
if dataframe is None or dataframe.empty:
|
| 328 |
+
return empty_figure("No cost data available.", background_name)
|
| 329 |
|
| 330 |
if not benchmark_name:
|
| 331 |
+
return empty_figure("Select a benchmark to view cost data.", background_name)
|
| 332 |
|
| 333 |
plot_df = dataframe.copy()
|
| 334 |
plot_df = plot_df[plot_df["Benchmark"] == benchmark_name]
|
|
|
|
| 337 |
plot_df = plot_df.dropna(subset=["Score", "Cost Per Task (USD)"])
|
| 338 |
|
| 339 |
if plot_df.empty:
|
| 340 |
+
return empty_figure(f"No cost data available for {benchmark_name}.", background_name)
|
| 341 |
|
| 342 |
colors = color_map_for(plot_df[color_by], color_by, palette_name)
|
| 343 |
+
theme = get_plot_background(background_name)
|
| 344 |
fig = go.Figure()
|
| 345 |
|
| 346 |
for group, group_df in plot_df.groupby(color_by, sort=True):
|
|
|
|
| 355 |
marker={
|
| 356 |
"size": 15,
|
| 357 |
"color": colors[str(group)],
|
| 358 |
+
"line": {"width": 1, "color": theme["marker_line_color"]},
|
| 359 |
},
|
| 360 |
customdata=group_df[["Model", "Harness", "Benchmark", "Score", "Cost Per Task (USD)"]],
|
| 361 |
hovertemplate=(
|
|
|
|
| 370 |
)
|
| 371 |
|
| 372 |
fig.update_layout(
|
| 373 |
+
title=None,
|
| 374 |
xaxis={"title": "Cost per task (USD)", "tickprefix": "$", "tickformat": ".2f"},
|
| 375 |
yaxis={"title": "Score (%)", "range": [0, 105]},
|
| 376 |
legend_title_text=color_by,
|
| 377 |
)
|
| 378 |
+
return apply_plot_theme(fig, background_name)
|