flavourbench / app.py
josefchen's picture
Publish the arXiv-linked v1.3 leaderboard
f0c6805 verified
Raw
History Blame Contribute Delete
92.7 kB
from __future__ import annotations
import base64
import hashlib
import html
import json
import os
import shlex
import tempfile
from datetime import UTC, datetime
from pathlib import Path
from typing import Any
from urllib.parse import quote
import gradio as gr
import pandas as pd
try:
from lab_api import SpaceLabError, score_completion, score_payload
except ModuleNotFoundError: # repository-root imports used by CI
from hf.space.lab_api import SpaceLabError, score_completion, score_payload
HERE = Path(__file__).resolve().parent
BUNDLE_PATH = Path(
os.environ.get(
"FLAVOURBENCH_BUNDLE",
HERE / "data-complete-core" / "flavourbench-complete-core-space.json",
)
)
RUST = "#A83D34"
INK = "#161817"
PAPER_URL = "https://arxiv.org/abs/2608.20574"
DATASET_URL = "https://huggingface.co/datasets/josefchen/flavourbench"
SOURCE_URL = "https://github.com/josefchen/flavourbench"
DATASET_RESULTS_URL = (
"https://huggingface.co/datasets/josefchen/flavourbench/resolve/main/"
"data-complete-core/leaderboard.jsonl?download=true"
)
SUBMISSION_GUIDE_URL = (
"https://github.com/josefchen/flavourbench/blob/main/docs/submitting-results.md"
)
SUBMIT_RESULT_URL = (
"https://github.com/josefchen/flavourbench/issues/new?template=flavourbench-result.yml"
)
LAB_LOGO_FILES = {
"xAI": "xai.svg",
"Google": "google.svg",
"OpenAI": "openai.svg",
"Meta": "meta.svg",
"Anthropic": "anthropic.svg",
"Qwen": "qwen.svg",
"Kimi": "kimi.svg",
"DeepSeek": "deepseek.svg",
"Tencent": "tencent.svg",
"MiniMax": "minimax.svg",
}
def _asset_url(path: Path) -> str:
"""Serve one verified release asset through Gradio's allowlisted file route."""
if path.is_symlink() or not path.is_file():
raise FileNotFoundError(f"Space asset not found: {path}")
resolved = path.resolve()
if not resolved.is_relative_to((HERE / "assets").resolve()):
raise ValueError(f"Space asset is outside the public asset directory: {path}")
return f"/gradio_api/file={quote(str(resolved), safe='/')}"
def _font_data_url(path: Path) -> str:
"""Inline the small launch-font subsets before Gradio lays out the page."""
if path.is_symlink() or not path.is_file() or path.suffix.lower() != ".woff2":
raise FileNotFoundError(f"Space font not found: {path}")
resolved = path.resolve()
if not resolved.is_relative_to((HERE / "assets/fonts").resolve()):
raise ValueError(f"Space font is outside the public font directory: {path}")
return "data:font/woff2;base64," + base64.b64encode(path.read_bytes()).decode("ascii")
LAB_LOGO_URLS = {
lab: _asset_url(HERE / "assets" / "providers" / filename)
for lab, filename in LAB_LOGO_FILES.items()
}
ARCHITECTURE_URL = _asset_url(HERE / "assets" / "executable-judge.svg")
FONT_URLS = {
"lato_regular": _font_data_url(HERE / "assets/fonts/Lato-Regular.woff2"),
"lato_semibold": _font_data_url(HERE / "assets/fonts/Lato-Semibold.woff2"),
"lato_bold": _font_data_url(HERE / "assets/fonts/Lato-Bold.woff2"),
"lato_black": _font_data_url(HERE / "assets/fonts/Lato-Black.woff2"),
"mono_regular": _font_data_url(HERE / "assets/fonts/DejaVuSansMono-Regular.woff2"),
"mono_bold": _font_data_url(HERE / "assets/fonts/DejaVuSansMono-Bold.woff2"),
}
FONT_CSS = f"""
@font-face {{
font-family: "Lato";
font-style: normal;
font-weight: 400;
font-display: block;
src: url("{FONT_URLS["lato_regular"]}") format("woff2");
}}
@font-face {{
font-family: "Lato";
font-style: normal;
font-weight: 600;
font-display: block;
src: url("{FONT_URLS["lato_semibold"]}") format("woff2");
}}
@font-face {{
font-family: "Lato";
font-style: normal;
font-weight: 700;
font-display: block;
src: url("{FONT_URLS["lato_bold"]}") format("woff2");
}}
@font-face {{
font-family: "Lato";
font-style: normal;
font-weight: 900;
font-display: block;
src: url("{FONT_URLS["lato_black"]}") format("woff2");
}}
@font-face {{
font-family: "DejaVu Sans Mono";
font-style: normal;
font-weight: 400;
font-display: block;
src: url("{FONT_URLS["mono_regular"]}") format("woff2");
}}
@font-face {{
font-family: "DejaVu Sans Mono";
font-style: normal;
font-weight: 700;
font-display: block;
src: url("{FONT_URLS["mono_bold"]}") format("woff2");
}}
"""
CSS = """
:root {
--fb-accent: #A83D34;
--fb-accent-soft: #F1DFDC;
--fb-ink: #161817;
--fb-muted: #68706C;
--fb-line: #56605B;
--fb-paper: #F6F7F5;
--fb-paper-raised: #FBFCFA;
--fb-rule: #DDE1DE;
--fb-code: #ECEFEC;
--fb-z-nav: 20;
}
.dark {
--fb-accent: #EF796D;
--fb-accent-soft: #422723;
--fb-ink: #F0EFE9;
--fb-muted: #A9ACA3;
--fb-line: #B1B7B3;
--fb-paper: #171815;
--fb-paper-raised: #20211E;
--fb-rule: #41433D;
--fb-code: #2A2B27;
}
html { scroll-behavior: smooth; }
body, .gradio-container {
background: var(--fb-paper) !important;
color: var(--fb-ink) !important;
font-family: "Lato", "Avenir Next", system-ui, sans-serif !important;
}
#huggingface-space-header {
background: var(--fb-paper-raised) !important;
background-image: none !important;
border: 0 !important;
border-radius: 0 !important;
box-shadow: none !important;
display: none !important;
}
#huggingface-space-header a {
font-family: "Lato", "Avenir Next", system-ui, sans-serif !important;
}
.gradio-container {
max-width: none !important;
overflow: visible !important;
padding: 0 !important;
}
.gradio-container > main { padding: 0 !important; }
.fb-shell {
box-sizing: border-box;
margin: 0 auto;
max-width: 1440px;
padding-left: clamp(22px, 4vw, 62px);
padding-right: clamp(22px, 4vw, 62px);
}
.fb-masthead {
align-items: center;
display: flex;
justify-content: space-between;
padding-bottom: 7px;
padding-top: 18px;
}
.fb-masthead-brand {
align-items: baseline;
display: flex;
gap: 14px;
min-width: 0;
}
.fb-masthead-brand strong {
color: var(--fb-ink);
font-size: 15px;
font-weight: 900;
letter-spacing: -.03em;
}
.fb-masthead-brand span {
color: var(--fb-muted);
font-family: "DejaVu Sans Mono", ui-monospace, monospace;
font-size: 9px;
letter-spacing: .05em;
text-transform: uppercase;
}
.fb-masthead nav { display: flex; gap: 22px; }
.fb-masthead a {
color: var(--fb-muted) !important;
font-size: 12px;
font-weight: 700;
text-decoration: none;
}
.fb-masthead a:hover { color: var(--fb-accent) !important; }
.fb-hero {
display: grid;
gap: clamp(40px, 4vw, 64px);
grid-template-columns: minmax(560px, 1.05fr) minmax(500px, .95fr);
padding-bottom: clamp(28px, 3vw, 36px);
padding-top: clamp(24px, 3vw, 38px);
}
.fb-hero h1 {
color: var(--fb-ink);
font-size: clamp(56px, 5vw, 72px);
font-weight: 900;
letter-spacing: -.065em;
line-height: .91;
margin: 18px 0 23px;
max-width: 740px;
}
.fb-dek {
color: var(--fb-muted);
font-size: clamp(17px, 1.6vw, 21px);
line-height: 1.46;
margin: 0;
max-width: 570px;
}
.fb-stats {
display: grid;
gap: 20px;
grid-template-columns: repeat(4, minmax(88px, 1fr));
margin-top: 34px;
}
.fb-stat strong {
color: var(--fb-ink);
display: block;
font-size: 25px;
font-weight: 900;
letter-spacing: -.04em;
line-height: 1;
}
.fb-stat span {
color: var(--fb-muted);
display: block;
font-family: "DejaVu Sans Mono", ui-monospace, monospace;
font-size: 10px;
letter-spacing: .06em;
margin-top: 7px;
text-transform: uppercase;
}
.fb-frontier {
align-self: end;
min-width: 0;
}
.fb-frontier-head {
align-items: baseline;
display: flex;
gap: 16px;
justify-content: space-between;
margin-bottom: 15px;
}
.fb-frontier-head strong { font-size: 15px; font-weight: 620; }
.fb-mobile-label { display: none; }
.fb-frontier-head span {
color: var(--fb-muted);
font-family: "DejaVu Sans Mono", ui-monospace, monospace;
font-size: 10px;
text-align: right;
}
.fb-frontier-note {
align-items: baseline;
display: flex;
gap: 14px;
justify-content: space-between;
margin-top: 10px;
}
.fb-frontier-note span,
.fb-frontier-note strong {
font-family: "DejaVu Sans Mono", ui-monospace, monospace;
font-size: 9px;
line-height: 1.45;
}
.fb-frontier-note span { color: var(--fb-muted); }
.fb-frontier-note strong { color: var(--fb-ink); font-weight: 600; text-align: right; }
.fb-forest-row {
align-items: center;
display: grid;
gap: 12px;
grid-template-columns: 22px minmax(170px, 210px) 1fr 47px;
min-height: 36px;
}
.fb-place {
color: var(--fb-muted);
font-family: "DejaVu Sans Mono", ui-monospace, monospace;
font-size: 10px;
}
.fb-model {
align-items: center;
color: var(--fb-ink);
display: flex;
font-size: 12px;
font-weight: 700;
gap: 8px;
min-width: 0;
}
.fb-model-mark {
background: transparent;
box-sizing: border-box;
flex: 0 0 20px;
height: 20px;
object-fit: contain;
width: 20px;
}
.dark .fb-model-mark {
background: #F6F7F5;
border-radius: 50%;
padding: 2px;
}
.fb-model-text {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.fb-axis {
height: 10px;
position: relative;
}
.fb-axis::before {
background: var(--fb-rule);
content: "";
height: 2px;
left: 0;
position: absolute;
right: 0;
top: 4px;
}
.fb-bar {
background: var(--fb-line);
height: 4px;
left: 0;
position: absolute;
top: 3px;
}
.fb-point {
background: var(--fb-ink);
border-radius: 50%;
height: 10px;
position: absolute;
top: 0;
transform: translateX(-50%);
width: 10px;
}
.fb-forest-row:first-of-type .fb-bar,
.fb-forest-row:first-of-type .fb-point { background: var(--fb-accent); }
.fb-forest-row:first-of-type .fb-model,
.fb-forest-row:first-of-type .fb-number { color: var(--fb-accent); }
.fb-number {
color: var(--fb-ink);
font-family: "DejaVu Sans Mono", ui-monospace, monospace;
font-size: 12px;
font-weight: 600;
text-align: right;
}
.fb-chart-foot {
color: var(--fb-muted);
display: flex;
font-family: "DejaVu Sans Mono", ui-monospace, monospace;
font-size: 9px;
justify-content: space-between;
margin: 9px 59px 0 266px;
}
.tab-wrapper {
background: color-mix(in srgb, var(--fb-paper) 94%, transparent) !important;
backdrop-filter: blur(12px);
border: 0 !important;
padding-bottom: 0 !important;
position: sticky !important;
top: 0;
z-index: var(--fb-z-nav);
}
.tab-container[role="tablist"] {
margin: 0 auto !important;
max-width: 1316px !important;
padding-left: clamp(22px, 4vw, 62px) !important;
padding-right: clamp(22px, 4vw, 62px) !important;
}
.tab-container[role="tablist"]::after { display: none !important; }
.tab-container[role="tablist"] button {
border: 0 !important;
color: var(--fb-muted) !important;
font-size: 13px !important;
padding: 15px 0 13px !important;
margin-right: 30px !important;
}
.tab-container[role="tablist"] button.selected {
color: var(--fb-ink) !important;
}
.tab-container[role="tablist"] button.selected::after {
background: var(--fb-accent) !important;
height: 2px !important;
}
.overflow-menu { display: none !important; }
.tab-container.visually-hidden { display: none !important; }
.tabitem {
box-sizing: border-box;
margin: 0 auto !important;
max-width: 1440px !important;
padding: 0 clamp(22px, 4vw, 62px) !important;
}
.fb-section { margin: 36px 0 18px; }
.fb-section h2 {
color: var(--fb-ink);
font-size: clamp(30px, 3vw, 45px);
font-weight: 900;
letter-spacing: -.045em;
line-height: 1.02;
margin: 0 0 9px;
}
.fb-section p {
color: var(--fb-muted);
font-size: 15px;
line-height: 1.5;
margin: 0;
max-width: 72ch;
}
.fb-lab-path {
align-items: baseline;
display: grid;
gap: 14px clamp(28px, 5vw, 72px);
grid-template-columns: minmax(380px, 1.15fr) minmax(280px, .85fr);
margin: 10px 0 30px;
}
.fb-lab-path strong { color: var(--fb-ink); font-size: 18px; font-weight: 900; }
.fb-lab-path i { color: var(--fb-accent); font-style: normal; padding: 0 7px; }
.fb-lab-path span { color: var(--fb-muted); font-size: 13px; line-height: 1.5; }
.fb-choice-grid {
display: grid;
column-gap: 28px;
grid-template-columns: repeat(2, minmax(0, 1fr));
margin: 8px 0 20px;
}
.fb-data-heading {
color: var(--fb-muted);
font-family: "DejaVu Sans Mono", ui-monospace, monospace;
font-size: 10px;
font-weight: 600;
letter-spacing: .06em;
margin: 22px 0 8px;
text-transform: uppercase;
}
.fb-choice {
align-items: center;
border-bottom: 1px solid var(--fb-rule);
display: flex;
gap: 13px;
min-width: 0;
padding: 12px 20px 12px 0;
}
.fb-choice:nth-child(even) {
padding-left: 0;
}
.fb-choice:nth-last-child(-n+2) { border-bottom: 0; }
.fb-choice-label {
align-items: center;
background: var(--fb-ink);
border-radius: 50%;
color: var(--fb-paper);
display: inline-flex;
flex: 0 0 30px;
font-family: "DejaVu Sans Mono", ui-monospace, monospace;
font-size: 12px;
font-weight: 700;
height: 30px;
justify-content: center;
}
.fb-choice-name {
color: var(--fb-ink);
font-size: 14px;
font-weight: 700;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.fb-metric-grid {
display: grid;
gap: 20px clamp(22px, 4vw, 52px);
grid-template-columns: repeat(3, 1fr);
margin: 10px 0 22px;
}
.fb-metric { min-width: 0; padding: 12px 0 14px; }
.fb-metric:nth-child(3n+2), .fb-metric:nth-child(3n+3) {
padding-left: 0;
}
.fb-metric small {
color: var(--fb-muted);
display: block;
font-family: "DejaVu Sans Mono", ui-monospace, monospace;
font-size: 10px;
letter-spacing: .05em;
text-transform: uppercase;
}
.fb-metric strong {
color: var(--fb-ink);
display: block;
font-size: 24px;
font-weight: 900;
margin-top: 5px;
white-space: nowrap;
}
.fb-evidence {
color: var(--fb-ink);
line-height: 1.52;
padding: 12px 0;
}
.fb-evidence strong:first-child { color: var(--fb-accent); }
.fb-evidence code, .fb-hash {
background: var(--fb-code);
color: var(--fb-muted);
font-family: "DejaVu Sans Mono", ui-monospace, monospace;
font-size: 11px;
overflow-wrap: anywhere;
}
.fb-method {
display: grid;
gap: clamp(30px, 6vw, 86px);
grid-template-columns: 1.25fr .75fr;
}
.fb-method h3 { font-size: 19px; margin: 23px 0 6px; }
.fb-method p { color: var(--fb-muted); line-height: 1.55; }
.fb-method-visual {
align-items: start;
display: grid;
gap: clamp(34px, 5vw, 72px);
grid-template-columns: minmax(340px, .82fr) minmax(440px, 1.18fr);
}
.fb-architecture {
display: block;
height: auto;
width: 100%;
}
.fb-command-note {
color: var(--fb-muted);
font-family: "DejaVu Sans Mono", ui-monospace, monospace;
font-size: 10px;
line-height: 1.5;
}
.fb-table-wrap {
overflow-x: auto;
width: 100%;
}
.fb-leader-tools {
align-items: end;
display: grid;
gap: 18px;
grid-template-columns: minmax(220px, 1fr) auto auto;
padding: 4px 0 18px;
}
.fb-search-label {
color: var(--fb-muted);
display: block;
font-family: "DejaVu Sans Mono", ui-monospace, monospace;
font-size: 10px;
letter-spacing: .05em;
text-transform: uppercase;
}
.fb-search-label input {
background: transparent !important;
border: 0 !important;
border-bottom: 1px solid var(--fb-rule) !important;
color: var(--fb-ink) !important;
display: block;
font-family: "Lato", "Avenir Next", system-ui, sans-serif;
font-size: 15px;
margin-top: 5px;
min-height: 34px;
padding: 2px 0;
width: 100%;
}
.fb-filter-set { display: flex; }
.fb-filter-button {
background: transparent;
border: 1px solid var(--fb-rule);
border-radius: 0;
color: var(--fb-muted);
cursor: pointer;
font-family: "DejaVu Sans Mono", ui-monospace, monospace;
font-size: 10px;
min-height: 36px;
padding: 0 12px;
text-transform: uppercase;
}
.fb-filter-button + .fb-filter-button { border-left: 0; }
.fb-filter-button[aria-pressed="true"] {
background: var(--fb-ink);
border-color: var(--fb-ink);
color: var(--fb-paper);
}
.fb-leader-meta {
align-items: center;
display: flex;
gap: 16px;
justify-content: flex-end;
min-height: 36px;
}
.fb-metric-rail {
align-items: center;
display: grid;
gap: 10px 18px;
grid-template-columns: auto auto 1fr;
padding: 0 0 16px;
}
.fb-metric-rail-label,
.fb-metric-note {
color: var(--fb-muted);
font-family: "DejaVu Sans Mono", ui-monospace, monospace;
font-size: 9px;
}
.fb-metric-rail-label {
letter-spacing: .06em;
text-transform: uppercase;
}
.fb-metric-switch { display: flex; gap: 18px; }
.fb-metric-switch button {
background: transparent;
border: 0;
border-bottom: 2px solid transparent;
color: var(--fb-muted);
cursor: pointer;
font-family: "Lato", "Avenir Next", system-ui, sans-serif;
font-size: 12px;
font-weight: 700;
padding: 7px 0 5px;
white-space: nowrap;
}
.fb-metric-switch button[aria-pressed="true"] {
border-bottom-color: var(--fb-accent);
color: var(--fb-ink);
}
.fb-metric-switch button:hover { color: var(--fb-accent); }
.fb-metric-note { justify-self: end; text-align: right; }
.fb-result-count {
color: var(--fb-muted);
font-family: "DejaVu Sans Mono", ui-monospace, monospace;
font-size: 10px;
white-space: nowrap;
}
.fb-text-link,
.fb-action-link {
color: var(--fb-ink) !important;
font-size: 12px;
font-weight: 700;
text-decoration: underline;
text-decoration-color: var(--fb-rule);
text-underline-offset: 4px;
}
.fb-text-link:hover,
.fb-action-link:hover { color: var(--fb-accent) !important; text-decoration-color: currentColor; }
.fb-empty-row td {
color: var(--fb-muted);
padding: 28px 0 !important;
}
.fb-release-line {
align-items: center;
display: grid;
font-family: "DejaVu Sans Mono", ui-monospace, monospace;
font-size: 10px;
gap: 18px;
grid-template-columns: repeat(3, minmax(0, auto)) 1fr;
padding: 12px 0 0;
}
.fb-release-line span { color: var(--fb-muted); }
.fb-release-line strong { color: var(--fb-ink); font-weight: 700; }
.fb-release-line a { justify-self: end; }
.fb-insight-layout {
display: grid;
gap: clamp(34px, 5vw, 72px);
grid-template-columns: minmax(640px, 1.4fr) minmax(260px, .6fr);
}
.fb-panel-label {
color: var(--fb-muted);
font-family: "DejaVu Sans Mono", ui-monospace, monospace;
font-size: 10px;
font-weight: 600;
letter-spacing: .06em;
margin-bottom: 9px;
text-transform: uppercase;
}
.fb-ci-row {
align-items: center;
display: grid;
gap: 12px;
grid-template-columns: 24px minmax(180px, 240px) 1fr 48px;
min-height: 42px;
}
.fb-ci-track { height: 16px; position: relative; }
.fb-ci-track::before {
background: var(--fb-rule);
content: "";
height: 1px;
left: 0;
position: absolute;
right: 0;
top: 8px;
}
.fb-ci-band {
background: var(--fb-line);
height: 3px;
position: absolute;
top: 7px;
}
.fb-ci-band::before,
.fb-ci-band::after {
background: var(--fb-line);
content: "";
height: 9px;
position: absolute;
top: -3px;
width: 1px;
}
.fb-ci-band::before { left: 0; }
.fb-ci-band::after { right: 0; }
.fb-ci-point {
background: var(--fb-ink);
border-radius: 50%;
height: 9px;
position: absolute;
top: 4px;
transform: translateX(-50%);
width: 9px;
}
.fb-ci-row:first-child .fb-ci-band,
.fb-ci-row:first-child .fb-ci-band::before,
.fb-ci-row:first-child .fb-ci-band::after,
.fb-ci-row:first-child .fb-ci-point { background: var(--fb-accent); }
.fb-ci-axis-labels {
color: var(--fb-muted);
display: flex;
font-family: "DejaVu Sans Mono", ui-monospace, monospace;
font-size: 9px;
justify-content: space-between;
margin: 9px 60px 0 280px;
}
.fb-resolution-row {
padding: 0 0 25px;
}
.fb-resolution-row strong {
color: var(--fb-accent);
display: block;
font-size: clamp(30px, 3vw, 42px);
font-weight: 900;
letter-spacing: -.05em;
line-height: 1;
}
.fb-resolution-row span {
color: var(--fb-muted);
display: block;
font-size: 13px;
line-height: 1.4;
margin-top: 6px;
}
.fb-resolution-note { color: var(--fb-muted); font-size: 13px; line-height: 1.52; margin: 18px 0 0; }
.fb-family-insight { margin-top: 42px; }
.fb-family-insight h3 { color: var(--fb-ink); font-size: 22px; margin: 0 0 4px; }
.fb-family-insight > p { color: var(--fb-muted); font-size: 13px; margin: 0 0 14px; }
.fb-family-table { min-width: 760px; }
.fb-family-short { display: none; }
.fb-family-model {
align-items: center;
display: flex;
font-family: "Lato", "Avenir Next", system-ui, sans-serif;
font-weight: 700;
gap: 9px;
}
.fb-family-value {
align-items: center;
display: grid;
gap: 9px;
grid-template-columns: 44px 1fr;
}
.fb-family-mini-axis { height: 10px; position: relative; }
.fb-family-mini-axis::before {
background: var(--fb-rule);
content: "";
height: 1px;
left: 0;
position: absolute;
right: 0;
top: 5px;
}
.fb-family-dot {
background: var(--fb-ink);
border-radius: 50%;
height: 7px;
position: absolute;
top: 2px;
transform: translateX(-50%);
width: 7px;
}
.fb-family-best .fb-family-dot { background: var(--fb-accent); height: 9px; top: 1px; width: 9px; }
.fb-family-best > span { color: var(--fb-accent); font-weight: 700; }
.fb-publish-path {
align-items: center;
display: grid;
gap: 28px;
grid-template-columns: 1fr auto;
margin-top: 24px;
padding: 10px 0;
}
.fb-publish-path h3 { font-size: 19px; margin: 0 0 5px; }
.fb-publish-path p { color: var(--fb-muted); font-size: 13px; line-height: 1.5; margin: 0; max-width: 72ch; }
.fb-action-link {
border: 1px solid var(--fb-ink);
display: inline-flex;
padding: 11px 14px;
text-decoration: none;
white-space: nowrap;
}
.fb-action-link:hover { border-color: var(--fb-accent); }
.fb-table {
border: 0 !important;
border-collapse: separate !important;
border-spacing: 0 !important;
color: var(--fb-ink);
font-family: "DejaVu Sans Mono", ui-monospace, monospace;
font-size: 12px;
min-width: 860px;
width: 100%;
}
.fb-table tr { border: 0 !important; }
.fb-table--family { min-width: 100%; }
.fb-table--score { min-width: 760px; }
.fb-table--score td:nth-child(2) { white-space: nowrap; }
.fb-table caption {
height: 1px;
overflow: hidden;
position: absolute;
width: 1px;
}
.fb-table th {
border-left: 0 !important;
border-right: 0 !important;
border-top: 0 !important;
border-bottom: 1px solid var(--fb-rule) !important;
color: var(--fb-muted);
font-size: 10px;
font-weight: 600;
letter-spacing: .05em;
padding: 10px 12px 11px 0;
text-align: left;
text-transform: uppercase;
}
.fb-table td {
border-left: 0 !important;
border-right: 0 !important;
border-top: 0 !important;
border-bottom: 1px solid var(--fb-rule);
padding: 11px 12px 11px 0;
vertical-align: top;
}
.fb-table .fb-score-cell { font-weight: 600; }
.fb-table-model {
align-items: center;
display: flex;
font-family: "Lato", "Avenir Next", system-ui, sans-serif;
font-weight: 700;
gap: 9px;
min-width: 0;
}
.fb-table-model .fb-model-mark { flex-basis: 18px; height: 18px; width: 18px; }
.fb-table-model span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fb-score-head-short { display: none; }
.fb-table--leaderboard.fb-family-view .fb-overall-only { display: none; }
.fb-table tbody tr:first-child .fb-rank-cell,
.fb-table tbody tr:first-child .fb-score-cell { color: var(--fb-accent); }
.fb-table tbody tr:hover { background: color-mix(in srgb, var(--fb-ink) 3%, transparent); }
.fb-table .fb-selected-row td { color: var(--fb-accent); font-weight: 600; }
.fb-footer {
color: var(--fb-muted);
display: flex;
font-size: 12px;
justify-content: space-between;
margin-top: 54px;
padding-bottom: 30px;
padding-top: 18px;
}
.fb-footer-main,
.fb-footer-links {
align-items: center;
display: flex;
gap: 20px;
}
.fb-footer-main strong { color: var(--fb-ink); }
.fb-footer a { color: var(--fb-ink); text-decoration: none; }
.fb-footer a:hover { color: var(--fb-accent); text-decoration: underline; }
.gradio-container footer a, .gradio-container footer button { color: var(--fb-muted) !important; }
.gradio-container footer .built-with,
.gradio-container footer .divider,
.gradio-container footer button.settings { display: none !important; }
.gradio-container footer button.show-api img { display: none !important; }
.block, .form, .gradio-dataframe, .gradio-json, .gradio-textbox {
background: transparent !important;
border-radius: 0 !important;
box-shadow: none !important;
}
.block:not(.gradio-dataframe):not(.gradio-json):not(.gradio-textbox) {
border-color: transparent !important;
}
button.primary {
background: var(--fb-ink) !important;
border: 1px solid var(--fb-ink) !important;
border-radius: 0 !important;
color: var(--fb-paper) !important;
min-height: 44px !important;
white-space: nowrap !important;
}
button.primary:hover { background: var(--fb-accent) !important; border-color: var(--fb-accent) !important; }
button.primary:active,
.fb-filter-button:active,
.fb-metric-switch button:active,
.fb-action-link:active { transform: translateY(1px); }
.fb-download { max-width: 320px !important; }
.fb-download a,
.fb-download button {
background: transparent !important;
border: 1px solid var(--fb-ink) !important;
border-radius: 0 !important;
color: var(--fb-ink) !important;
}
input, textarea, select {
background: var(--fb-paper-raised) !important;
border-color: var(--fb-rule) !important;
border-radius: 0 !important;
box-shadow: none !important;
}
input:focus, textarea:focus, select:focus, button:focus-visible, a:focus-visible {
outline: 2px solid var(--fb-accent) !important;
outline-offset: 2px !important;
}
table { border-collapse: collapse !important; }
th { background: var(--fb-paper) !important; }
pre, code { border-radius: 0 !important; }
.prose pre,
.prose pre code,
.prose pre span {
background: var(--fb-code) !important;
color: var(--fb-ink) !important;
}
.gradio-dataframe table {
border-left: 0 !important;
border-right: 0 !important;
font-family: "DejaVu Sans Mono", ui-monospace, monospace !important;
}
.gradio-dataframe th,
.gradio-dataframe td {
border-left: 0 !important;
border-right: 0 !important;
}
@media (max-width: 1180px) {
.fb-hero { grid-template-columns: 1fr; }
.fb-frontier { max-width: 820px; }
.fb-method { grid-template-columns: 1fr; }
.fb-method-visual { grid-template-columns: minmax(300px, .85fr) minmax(390px, 1.15fr); }
.fb-insight-layout { grid-template-columns: 1fr; }
.fb-resolution { display: grid; grid-template-columns: repeat(3, 1fr); }
.fb-resolution-row { padding-right: 18px; }
.fb-resolution-row + .fb-resolution-row { padding-left: 18px; }
.fb-resolution-note { grid-column: 1 / -1; }
}
@media (max-width: 720px) {
.fb-hero { gap: 38px; padding-bottom: 32px; }
.fb-hero h1 { font-size: clamp(52px, 15vw, 72px); }
.fb-stats { gap: 16px 10px; grid-template-columns: repeat(2, 1fr); }
.fb-forest-row { gap: 8px; grid-template-columns: 19px minmax(122px, 164px) 1fr 42px; }
.fb-model { font-size: 11px; }
.fb-model-mark { flex-basis: 18px; height: 18px; width: 18px; }
.fb-chart-foot { margin-left: 163px; margin-right: 50px; }
.fb-chart-foot span:nth-child(2) { display: none; }
.fb-masthead-brand span { display: none; }
.fb-masthead nav { gap: 16px; }
.fb-masthead nav a:nth-child(2) { display: none; }
.fb-desktop-label { display: none; }
.fb-mobile-label { display: inline; }
.fb-frontier .fb-forest-row:nth-child(n+5) { display: none; }
.fb-frontier-note { justify-content: flex-end; }
.fb-frontier-note span { display: none; }
.fb-lab-path { grid-template-columns: 1fr; }
.fb-choice-grid { grid-template-columns: 1fr; }
.fb-choice,
.fb-choice:nth-child(even) { border-left: 0; padding-left: 0; }
.fb-choice:nth-last-child(-n+2) { border-bottom: 1px solid var(--fb-rule); }
.fb-choice:last-child { border-bottom: 0; }
.fb-table--score { min-width: 100%; }
.fb-table--score th:nth-child(2),
.fb-table--score td:nth-child(2) { display: none; }
.fb-table--leaderboard { min-width: 100%; table-layout: fixed; }
.fb-table--leaderboard th:nth-child(4),
.fb-table--leaderboard td:nth-child(4),
.fb-table--leaderboard th:nth-child(5),
.fb-table--leaderboard td:nth-child(5),
.fb-table--leaderboard th:nth-child(6),
.fb-table--leaderboard td:nth-child(6),
.fb-table--leaderboard th:nth-child(7),
.fb-table--leaderboard td:nth-child(7) { display: none; }
.fb-table--leaderboard th:nth-child(1),
.fb-table--leaderboard td:nth-child(1) { width: 12%; }
.fb-table--leaderboard th:nth-child(2),
.fb-table--leaderboard td:nth-child(2) { width: 64%; }
.fb-table--leaderboard th:nth-child(3),
.fb-table--leaderboard td:nth-child(3) { width: 24%; }
.fb-score-head-long { display: none; }
.fb-score-head-short { display: inline; }
.fb-table--leaderboard td:nth-child(2) {
overflow: hidden;
padding-left: 6px;
text-overflow: ellipsis;
white-space: nowrap;
}
.fb-table--leaderboard th:nth-child(2) { padding-left: 6px; }
.fb-family-table { min-width: 100%; table-layout: fixed; }
.fb-family-table th,
.fb-family-table td { font-size: 9px; padding-right: 4px; }
.fb-family-table th:first-child,
.fb-family-table td:first-child { width: 46%; }
.fb-family-model { gap: 5px; min-width: 0; }
.fb-family-model .fb-model-mark { flex-basis: 15px; height: 15px; width: 15px; }
.fb-family-model span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fb-family-value { display: block; }
.fb-family-mini-axis { display: none; }
.fb-family-long { display: none; }
.fb-family-short { display: inline; }
.fb-ci-axis-labels span:nth-child(2) { display: none; }
.fb-metric-grid { grid-template-columns: repeat(2, 1fr); }
.fb-metric:nth-child(3n+2), .fb-metric:nth-child(3n+3) { padding-left: 0; }
.fb-metric:nth-child(even) { padding-left: 0; }
.fb-metric strong { font-size: 21px; }
.fb-method-visual { grid-template-columns: 1fr; }
.fb-leader-tools { align-items: stretch; grid-template-columns: 1fr; gap: 11px; }
.fb-filter-set { width: 100%; }
.fb-filter-button { flex: 1; }
.fb-leader-meta { justify-content: space-between; }
.fb-metric-rail { display: block; }
.fb-metric-rail-label { display: block; margin-bottom: 4px; }
.fb-metric-switch {
gap: 19px;
overflow-x: auto;
padding-bottom: 4px;
scrollbar-width: none;
}
.fb-metric-switch::-webkit-scrollbar { display: none; }
.fb-metric-note { display: block; margin-top: 8px; text-align: left; }
.fb-release-line { grid-template-columns: repeat(2, 1fr); }
.fb-release-line a { justify-self: start; }
.fb-ci-row { gap: 8px; grid-template-columns: 20px minmax(128px, 168px) 1fr 43px; }
.fb-ci-axis-labels { margin-left: 196px; margin-right: 51px; }
.fb-resolution { grid-template-columns: 1fr; }
.fb-resolution-row + .fb-resolution-row { border-left: 0; padding-left: 0; }
.fb-publish-path { align-items: start; grid-template-columns: 1fr; }
.fb-action-link { justify-content: center; }
.tab-container[role="tablist"] { overflow-x: auto !important; }
.tab-container[role="tablist"] button { margin-right: 22px !important; white-space: nowrap !important; }
.fb-footer { display: block; }
.fb-footer-main,
.fb-footer-links { align-items: flex-start; flex-direction: column; gap: 6px; }
.fb-footer-links { margin-top: 14px; }
}
@media (prefers-reduced-transparency: reduce) {
.tab-wrapper { backdrop-filter: none; background: var(--fb-paper) !important; }
}
@media (max-width: 430px) {
.fb-forest-row { grid-template-columns: 18px minmax(112px, 140px) 1fr 39px; }
.fb-chart-foot { margin-left: 148px; margin-right: 47px; }
.fb-ci-row { grid-template-columns: 18px minmax(108px, 138px) 1fr 40px; }
.fb-ci-row .fb-model-mark { display: none; }
.fb-ci-axis-labels { margin-left: 164px; margin-right: 48px; }
}
@media (prefers-reduced-motion: reduce) {
html { scroll-behavior: auto; }
*, *::before, *::after { animation: none !important; transition: none !important; }
}
"""
HEAD = f"<style>{FONT_CSS}{CSS}</style>"
class SpaceDataError(RuntimeError):
"""The public explorer bundle is invalid."""
def _canonical(value: object) -> bytes:
return json.dumps(
value,
ensure_ascii=False,
separators=(",", ":"),
sort_keys=True,
allow_nan=False,
).encode()
def _load_bundle() -> dict[str, Any]:
if BUNDLE_PATH.is_symlink() or not BUNDLE_PATH.is_file():
raise FileNotFoundError(
f"Complete-core Space bundle not found at {BUNDLE_PATH}. Set FLAVOURBENCH_BUNDLE."
)
value = json.loads(BUNDLE_PATH.read_text(encoding="utf-8"))
payload = dict(value)
recorded = str(payload.pop("artifact_sha256", ""))
if (
recorded != hashlib.sha256(_canonical(payload)).hexdigest()
or value.get("schema_version") != "flavourbench-complete-core-space-bundle-v1"
or value.get("status") != "final_complete_common_core"
):
raise SpaceDataError("complete-core Space bundle failed verification")
return value
BUNDLE = _load_bundle()
MODELS = BUNDLE["models"]
TASKS = BUNDLE["tasks"]
LAB_TASKS = BUNDLE.get("lab_tasks", [])
PAIRWISE = BUNDLE["pairwise_comparisons"]
STABILITY = BUNDLE["stability_analysis"]
MODEL_COUNT = len(MODELS)
TASK_COUNT = len(TASKS)
PAIR_COUNT = len(PAIRWISE)
DESIGN = BUNDLE["design"]
PANEL_COUNT = int(DESIGN.get("panel_count", 1))
INDEPENDENT_CLUSTER_COUNT = int(DESIGN.get("unique_anchor_clusters", TASK_COUNT))
PRIMARY_COUNT = MODEL_COUNT * TASK_COUNT
MODEL_BY_NAME = {str(row["model_name"]): row for row in MODELS}
MODEL_BY_ID = {str(row["model_id"]): row for row in MODELS}
TASK_BY_ID = {str(row["task_id"]): row for row in TASKS}
LAB_TASK_BY_ID = {str(row["task_id"]): row for row in LAB_TASKS}
if set(TASK_BY_ID) & set(LAB_TASK_BY_ID):
raise SpaceDataError("official and training task IDs overlap")
OBSERVATIONS = {
(str(row["model_id"]), str(row["task_id"])): row for row in BUNDLE["primary_observations"]
}
PAIR_INDEX: dict[tuple[str, str], dict[str, Any]] = {}
for _row in PAIRWISE:
PAIR_INDEX[(str(_row["left_model_id"]), str(_row["right_model_id"]))] = _row
def _rank_key(row: dict[str, Any]) -> tuple[bool, int, str]:
rank = row.get("point_estimate_rank")
return rank is None, int(rank or 10_000), str(row["model_id"])
DISPLAY_MODELS = sorted(MODELS, key=_rank_key)
MODEL_NAMES = [str(row["model_name"]) for row in DISPLAY_MODELS]
TASK_LABEL_TO_ID = {
f"{row['task_id']} | {str(row['family']).replace('_', ' ')}": str(row["task_id"])
for row in TASKS
}
LAB_TASK_LABEL_TO_ID = {
f"{row['task_id']} | {str(row['family']).replace('_', ' ')} | {row['lab_split']}": str(
row["task_id"]
)
for row in LAB_TASKS
}
def _lab_name(row: dict[str, Any]) -> str:
model_name = str(row["model_name"])
prefixes = (
("SpaceXAI:", "xAI"),
("Anthropic:", "Anthropic"),
("Claude ", "Anthropic"),
("MoonshotAI:", "Kimi"),
("ByteDance Seed:", "ByteDance"),
("Thinking Machines:", "Thinking Machines"),
("MiniMax:", "MiniMax"),
("DeepSeek:", "DeepSeek"),
("OpenAI:", "OpenAI"),
("Google:", "Google"),
("Meta:", "Meta"),
("Qwen:", "Qwen"),
("Tencent:", "Tencent"),
("Z.ai:", "Z.ai"),
("NVIDIA:", "NVIDIA"),
("Cohere:", "Cohere"),
("Mistral:", "Mistral"),
)
for prefix, lab in prefixes:
if model_name.startswith(prefix):
return lab
return str(row.get("provider_name") or model_name.split(":", 1)[0])
def _model_label(model_name: str) -> str:
label = model_name.split(":", 1)[-1].strip()
return (
label.replace("GPT-5.6 ", "5.6 ")
.replace("Claude ", "")
.replace("DeepSeek ", "")
.replace("Command ", "")
)
_seen_labs: set[str] = set()
LAB_CHAMPIONS: list[dict[str, Any]] = []
for _model in DISPLAY_MODELS:
_lab = _lab_name(_model)
if _lab not in _seen_labs:
_seen_labs.add(_lab)
LAB_CHAMPIONS.append(_model)
LEADERBOARD_METRICS = (
("overall", "Overall", "FlavourBench Score", "Score"),
("substitution", "Substitution", "Substitution score", "Sub"),
("pairing", "Pairing", "Pairing score", "Pair"),
("constraint", "Constraints", "Constraint score", "Rules"),
)
def _leaderboard_metric_score(model: dict[str, Any], metric: str) -> float:
if metric == "overall":
return float(model["flavourbench_score"])
return float(model["family_scores"][metric])
LEADERBOARD_RANKS: dict[tuple[str, str], int] = {}
LEADERBOARD_CHAMPIONS: set[tuple[str, str]] = set()
for _metric, _, _, _ in LEADERBOARD_METRICS:
_ordered = sorted(
DISPLAY_MODELS,
key=lambda row, metric=_metric: (
-_leaderboard_metric_score(row, metric),
str(row["model_id"]),
),
)
_previous_score: float | None = None
_rank = 0
_metric_labs: set[str] = set()
for _position, _model in enumerate(_ordered, start=1):
_score = _leaderboard_metric_score(_model, _metric)
if _previous_score is None or _score != _previous_score:
_rank = _position
_previous_score = _score
_model_id = str(_model["model_id"])
LEADERBOARD_RANKS[(_metric, _model_id)] = _rank
_lab = _lab_name(_model)
if _lab not in _metric_labs:
_metric_labs.add(_lab)
LEADERBOARD_CHAMPIONS.add((_metric, _model_id))
LEADERBOARD_JS = """
if (element.dataset.fbReady !== "true") {
element.dataset.fbReady = "true";
const search = element.querySelector("[data-fb-search]");
const rows = Array.from(element.querySelectorAll("tbody tr[data-model]"));
const modeButtons = Array.from(element.querySelectorAll("[data-fb-mode]"));
const metricButtons = Array.from(element.querySelectorAll("[data-fb-metric]"));
const count = element.querySelector("[data-fb-count]");
const empty = element.querySelector("[data-fb-empty]");
const table = element.querySelector("[data-fb-leaderboard]");
const body = table?.querySelector("tbody");
const scoreHead = table?.querySelector("[data-fb-score-head]");
const scoreHeadLong = scoreHead?.querySelector("[data-fb-score-long]");
const scoreHeadShort = scoreHead?.querySelector("[data-fb-score-short]");
const metricNote = element.querySelector("[data-fb-metric-note]");
let mode = "all";
let metric = "overall";
const dataKey = (prefix) =>
prefix + metric.charAt(0).toUpperCase() + metric.slice(1);
const apply = () => {
const rankKey = dataKey("rank");
const scoreKey = dataKey("score");
const championKey = dataKey("champion");
rows.sort((left, right) => {
const rankGap = Number(left.dataset[rankKey]) - Number(right.dataset[rankKey]);
return rankGap || left.dataset.search.localeCompare(right.dataset.search);
});
for (const row of rows) body?.insertBefore(row, empty);
const query = (search?.value || "").trim().toLocaleLowerCase();
let visible = 0;
for (const row of rows) {
const matchesText = !query || row.dataset.search.includes(query);
const matchesMode = mode === "all" || row.dataset[championKey] === "true";
row.hidden = !(matchesText && matchesMode);
const rankCell = row.querySelector("[data-fb-rank]");
const scoreCell = row.querySelector("[data-fb-score]");
if (rankCell) rankCell.textContent = String(row.dataset[rankKey]).padStart(2, "0");
if (scoreCell) scoreCell.textContent = Number(row.dataset[scoreKey]).toFixed(2);
if (!row.hidden) visible += 1;
}
table?.classList.toggle("fb-family-view", metric !== "overall");
if (count) count.textContent = `${visible} model${visible === 1 ? "" : "s"}`;
if (empty) empty.hidden = visible !== 0;
};
search?.addEventListener("input", apply);
for (const button of modeButtons) {
button.addEventListener("click", () => {
mode = button.dataset.fbMode;
for (const peer of modeButtons) {
peer.setAttribute("aria-pressed", String(peer === button));
}
apply();
});
}
for (const button of metricButtons) {
button.addEventListener("click", () => {
metric = button.dataset.fbMetric;
for (const peer of metricButtons) {
peer.setAttribute("aria-pressed", String(peer === button));
}
if (scoreHeadLong) scoreHeadLong.textContent = button.dataset.fbScoreLabel;
if (scoreHeadShort) scoreHeadShort.textContent = button.dataset.fbScoreShort;
if (metricNote) metricNote.textContent = button.dataset.fbNote;
apply();
});
}
apply();
}
"""
def _completion_diagnostic(model_id: str) -> dict[str, Any]:
family_rows: dict[str, list[dict[str, Any]]] = {}
for task_id, task in TASK_BY_ID.items():
family = str(task["family"])
family_rows.setdefault(family, []).append(OBSERVATIONS[(model_id, task_id)])
conditional_family_scores: dict[str, float] = {}
completed_by_family: dict[str, int] = {}
scheduled_by_family: dict[str, int] = {}
for family, rows in family_rows.items():
completed = [
row
for row in rows
if row["status"] == "completed" and bool(row.get("scoring", {}).get("parseable", True))
]
scheduled_by_family[family] = len(rows)
completed_by_family[family] = len(completed)
conditional_family_scores[family] = (
sum(float(row["scoring"]["score"]) for row in completed) / len(completed)
if completed
else 0.0
)
completed = sum(completed_by_family.values())
return {
"scheduled": len(TASK_BY_ID),
"completed": completed,
"failed": len(TASK_BY_ID) - completed,
"completion_rate": completed / len(TASK_BY_ID),
"conditional_family_scores": conditional_family_scores,
"completed_by_family": completed_by_family,
"scheduled_by_family": scheduled_by_family,
"conditional_equal_family_score": sum(conditional_family_scores.values())
/ len(conditional_family_scores),
}
def _frontier_html() -> str:
axis_floor = 55.0
axis_ceiling = 66.0
rows = []
for place, model in enumerate(LAB_CHAMPIONS[:10], start=1):
score = float(model["flavourbench_score"])
position = max(0.0, min(100.0, (score - axis_floor) / (axis_ceiling - axis_floor) * 100))
full_name = str(model["model_name"])
lab = _lab_name(model)
label = _model_label(full_name)
logo_url = LAB_LOGO_URLS.get(lab)
logo = (
f"<img class='fb-model-mark' src='{logo_url}' alt='' loading='eager'>"
if logo_url
else ""
)
rows.append(
"<div class='fb-forest-row'>"
f"<div class='fb-place'>{place:02d}</div>"
f"<div class='fb-model' title='{html.escape(full_name)}'>"
f"{logo}<span class='fb-model-text'>{html.escape(lab)} · {html.escape(label)}</span>"
"</div>"
"<div class='fb-axis'>"
f"<span class='fb-bar' style='width:{position:.3f}%'></span>"
f"<span class='fb-point' style='left:{position:.3f}%'></span>"
"</div>"
f"<div class='fb-number'>{score:.1f}</div>"
"</div>"
)
return "".join(rows) + (
f"<div class='fb-chart-foot'><span>{axis_floor:.0f}</span>"
f"<span>FlavourBench Score</span><span>{axis_ceiling:.0f}</span></div>"
)
def _hero_html() -> str:
inference = BUNDLE["analysis"]["inference"]
leading_group_count = sum(int(model["statistical_rank_group"]) == 1 for model in DISPLAY_MODELS)
return f"""
<header class="fb-shell fb-masthead">
<div class="fb-masthead-brand">
<strong>FlavourBench</strong>
<span>Executable culinary benchmark</span>
</div>
<nav aria-label="Research resources">
<a href="{PAPER_URL}" target="_blank" rel="noreferrer">Paper</a>
<a href="{DATASET_URL}" target="_blank" rel="noreferrer">Dataset</a>
<a href="{SOURCE_URL}" target="_blank" rel="noreferrer">GitHub</a>
</nav>
</header>
<div class="fb-shell fb-hero">
<section>
<h1>Which AI knows food best?</h1>
<p class="fb-dek">Epicure scores every legal answer first. Then {MODEL_COUNT} frontier endpoints face the same {TASK_COUNT} food decisions.</p>
<div class="fb-stats">
<div class="fb-stat"><strong>{MODEL_COUNT}</strong><span>frontier endpoints</span></div>
<div class="fb-stat"><strong>{TASK_COUNT}</strong><span>shared tasks</span></div>
<div class="fb-stat"><strong>{PRIMARY_COUNT:,}</strong><span>scored answers</span></div>
<div class="fb-stat"><strong>{inference["pairwise_hypotheses"]}</strong><span>model pairs</span></div>
</div>
</section>
<section class="fb-frontier" aria-label="Best FlavourBench model from each leading lab">
<div class="fb-frontier-head"><strong><span class="fb-desktop-label">Best model from each lab</span><span class="fb-mobile-label">Top lab leaders</span></strong><span>Score / 100, focused 55 to 66 axis</span></div>
{_frontier_html()}
<div class="fb-frontier-note"><span>Overall point estimates</span><strong>{leading_group_count} models share the leading statistical group</strong></div>
</section>
</div>
"""
def _leaderboard_frame() -> pd.DataFrame:
rows = []
for model in DISPLAY_MODELS:
ci = model["score_simultaneous_95_ci"]
rank_ci = model["bootstrap_rank_95_interval"]
rows.append(
{
"Rank": model["point_estimate_rank"],
"Model": model["model_name"],
"Score ↑": round(float(model["flavourbench_score"]), 2),
"Simultaneous 95%": f"{ci[0]:.2f} to {ci[1]:.2f}",
"Group": model["statistical_rank_group"],
"Rank 95%": f"{rank_ci[0]} to {rank_ci[1]}",
"Cells": f"{model['coverage']['valid_scored']}/{TASK_COUNT}",
}
)
return pd.DataFrame(rows)
def _leaderboard_html() -> str:
family_task_counts = {
family: sum(str(task["family"]) == family for task in TASKS)
for family in ("substitution", "pairing", "constraint")
}
metric_controls = []
for metric, label, score_label, score_short in LEADERBOARD_METRICS:
note = (
"Equal-family mean. Open Insights for uncertainty and significance."
if metric == "overall"
else f"{family_task_counts[metric]} {label.lower()} tasks. Family views rank point scores only."
)
metric_controls.append(
f"<button type='button' data-fb-metric='{metric}' "
f"data-fb-score-label='{html.escape(score_label, quote=True)}' "
f"data-fb-score-short='{html.escape(score_short, quote=True)}' "
f"data-fb-note='{html.escape(note, quote=True)}' "
f"aria-pressed='{str(metric == 'overall').lower()}'>{html.escape(label)}</button>"
)
rows = []
for model in DISPLAY_MODELS:
ci = model["score_simultaneous_95_ci"]
rank_ci = model["bootstrap_rank_95_interval"]
model_name = str(model["model_name"])
lab = _lab_name(model)
label = _model_label(model_name)
model_id = str(model["model_id"])
search_value = html.escape(f"{model_name} {lab}".lower(), quote=True)
metric_attributes = " ".join(
(
f"data-score-{metric}='{_leaderboard_metric_score(model, metric):.8f}' "
f"data-rank-{metric}='{LEADERBOARD_RANKS[(metric, model_id)]}' "
f"data-champion-{metric}='{str((metric, model_id) in LEADERBOARD_CHAMPIONS).lower()}'"
)
for metric, _, _, _ in LEADERBOARD_METRICS
)
logo_url = LAB_LOGO_URLS.get(lab)
logo = (
f"<img class='fb-model-mark' src='{logo_url}' alt='' loading='lazy'>"
if logo_url
else ""
)
rows.append(
f"<tr data-model='{html.escape(model_id, quote=True)}' "
f"data-search='{search_value}' data-lab='{html.escape(lab, quote=True)}' "
f"{metric_attributes}>"
f"<td class='fb-rank-cell' data-fb-rank>{int(model['point_estimate_rank']):02d}</td>"
f"<td><div class='fb-table-model' title='{html.escape(model_name, quote=True)}'>"
f"{logo}<span>{html.escape(lab)} · {html.escape(label)}</span></div></td>"
f"<td class='fb-score-cell' data-fb-score>{float(model['flavourbench_score']):.2f}</td>"
f"<td class='fb-overall-only'>{float(ci[0]):.2f} to {float(ci[1]):.2f}</td>"
f"<td class='fb-overall-only'>G{model['statistical_rank_group']}</td>"
f"<td class='fb-overall-only'>{rank_ci[0]} to {rank_ci[1]}</td>"
f"<td>{model['coverage']['valid_scored']}/{TASK_COUNT}</td>"
"</tr>"
)
release_id = html.escape(str(BUNDLE["release_artifact_sha256"])[:12])
return (
f"""
<div class="fb-leader-tools" role="search" aria-label="Filter leaderboard">
<label class="fb-search-label">Find a model
<input type="search" placeholder="Model or lab" autocomplete="off" data-fb-search>
</label>
<div class="fb-filter-set" aria-label="Leaderboard scope">
<button type="button" class="fb-filter-button" data-fb-mode="all" aria-pressed="true">All {MODEL_COUNT}</button>
<button type="button" class="fb-filter-button" data-fb-mode="champions" aria-pressed="false">Lab leaders</button>
</div>
<div class="fb-leader-meta">
<span class="fb-result-count" data-fb-count aria-live="polite">{MODEL_COUNT} models</span>
<a class="fb-text-link" href="{DATASET_RESULTS_URL}" target="_blank" rel="noreferrer">Download JSONL</a>
</div>
</div>
<div class="fb-metric-rail">
<span class="fb-metric-rail-label">Rank by</span>
<div class="fb-metric-switch" role="group" aria-label="Leaderboard score view">
{"".join(metric_controls)}
</div>
<span class="fb-metric-note" data-fb-metric-note>Equal-family mean. Open Insights for uncertainty and significance.</span>
</div>
<div class="fb-table-wrap">
<table class="fb-table fb-table--leaderboard" data-fb-leaderboard>
<caption>Complete FlavourBench common-core leaderboard</caption>
<thead><tr>
<th scope="col">Rank</th><th scope="col">Model</th><th scope="col" data-fb-score-head><span class="fb-score-head-long" data-fb-score-long>FlavourBench Score</span><span class="fb-score-head-short" data-fb-score-short>Score</span></th>
<th scope="col" class="fb-overall-only">Simultaneous 95%</th><th scope="col" class="fb-overall-only">Group</th>
<th scope="col" class="fb-overall-only">Rank 95%</th><th scope="col">Cells</th>
</tr></thead>
<tbody>"""
+ "".join(rows)
+ f"""
<tr class="fb-empty-row" data-fb-empty hidden><td colspan="7">No model matches this search.</td></tr>
</tbody>
</table>
</div>
<div class="fb-release-line" aria-label="Release provenance">
<span><strong>Release</strong> {release_id}</span>
<span><strong>Matrix</strong> {MODEL_COUNT} × {TASK_COUNT}</span>
<span><strong>Coverage</strong> {PRIMARY_COUNT:,}/{PRIMARY_COUNT:,}</span>
<a class="fb-text-link" href="https://huggingface.co/datasets/josefchen/flavourbench" target="_blank" rel="noreferrer">Open dataset</a>
</div>
"""
)
def _axis_position(value: float, floor: float, ceiling: float) -> float:
return max(0.0, min(100.0, (value - floor) / (ceiling - floor) * 100.0))
def _insights_html() -> str:
axis_floor = 55.0
axis_ceiling = 70.0
score_rows = []
for model in DISPLAY_MODELS[:10]:
model_name = str(model["model_name"])
lab = _lab_name(model)
label = _model_label(model_name)
score = float(model["flavourbench_score"])
ci_low, ci_high = (float(value) for value in model["score_simultaneous_95_ci"])
low = _axis_position(ci_low, axis_floor, axis_ceiling)
high = _axis_position(ci_high, axis_floor, axis_ceiling)
point = _axis_position(score, axis_floor, axis_ceiling)
logo_url = LAB_LOGO_URLS.get(lab)
logo = (
f"<img class='fb-model-mark' src='{logo_url}' alt='' loading='lazy'>"
if logo_url
else ""
)
aria = html.escape(
f"{model_name}: score {score:.2f}, simultaneous 95 percent interval "
f"{ci_low:.2f} to {ci_high:.2f}",
quote=True,
)
score_rows.append(
"<div class='fb-ci-row'>"
f"<div class='fb-place'>{int(model['point_estimate_rank']):02d}</div>"
f"<div class='fb-model' title='{html.escape(model_name, quote=True)}'>"
f"{logo}<span class='fb-model-text'>{html.escape(lab)} · {html.escape(label)}</span>"
"</div>"
f"<div class='fb-ci-track' role='img' aria-label='{aria}'>"
f"<span class='fb-ci-band' style='left:{low:.3f}%;width:{high - low:.3f}%'></span>"
f"<span class='fb-ci-point' style='left:{point:.3f}%'></span>"
"</div>"
f"<div class='fb-number'>{score:.2f}</div>"
"</div>"
)
family_models = LAB_CHAMPIONS[:8]
families = (
("substitution", "Substitution"),
("pairing", "Pairing"),
("constraint", "Constraint"),
)
family_maxima = {
family: max(float(model["family_scores"][family]) for model in family_models)
for family, _ in families
}
family_rows = []
for model in family_models:
model_name = str(model["model_name"])
lab = _lab_name(model)
label = _model_label(model_name)
logo_url = LAB_LOGO_URLS.get(lab)
logo = (
f"<img class='fb-model-mark' src='{logo_url}' alt='' loading='lazy'>"
if logo_url
else ""
)
cells = []
for family, _ in families:
score = float(model["family_scores"][family])
position = _axis_position(score, 40.0, 75.0)
best_class = " fb-family-best" if score == family_maxima[family] else ""
cells.append(
f"<td class='{best_class.strip()}'>"
f"<div class='fb-family-value{best_class}'><span>{score:.1f}</span>"
"<span class='fb-family-mini-axis' aria-hidden='true'>"
f"<i class='fb-family-dot' style='left:{position:.3f}%'></i></span></div></td>"
)
family_rows.append(
"<tr>"
f"<td><div class='fb-family-model' title='{html.escape(model_name, quote=True)}'>"
f"{logo}<span>{html.escape(lab)} · {html.escape(label)}</span></div></td>"
+ "".join(cells)
+ "</tr>"
)
leading_group_count = sum(int(model["statistical_rank_group"]) == 1 for model in DISPLAY_MODELS)
resolved = int(BUNDLE["analysis"]["resolved_pair_count"])
chance = float(DISPLAY_MODELS[0]["chance_comparison"]["exact_chance_score"])
leader_gap = float(
DISPLAY_MODELS[0]["chance_comparison"].get(
"mean_difference", float(DISPLAY_MODELS[0]["flavourbench_score"]) - chance
)
)
stability_rows = []
for row in STABILITY["task_count_stability"]:
rank = row["metrics"]["rank_spearman"]
top_five = row["metrics"]["top_5_overlap"]
leader = row["metrics"]["top_1_preserved"]
stability_rows.append(
"<tr>"
f"<td>{int(row['tasks'])}</td>"
f"<td>{float(rank['median']):.3f}</td>"
f"<td>{float(rank['p2_5']):.3f}{float(rank['p97_5']):.3f}</td>"
f"<td>{float(top_five['median']) * 100:.0f}%</td>"
f"<td>{float(leader['mean']) * 100:.1f}%</td>"
"</tr>"
)
variance = STABILITY["variance_partition"]
generalizability = float(variance["relative_decision_generalizability_at_534_tasks"])
tasks_for_g_90 = int(variance["estimated_balanced_tasks_for_relative_g_0_90"])
return f"""
<div class="fb-insight-layout">
<section>
<div class="fb-panel-label">Top 10 / simultaneous 95% bands / focused 55 to 70 axis</div>
<div class="fb-ci-plot">{"".join(score_rows)}</div>
<div class="fb-ci-axis-labels"><span>{axis_floor:.0f}</span><span>FlavourBench Score</span><span>{axis_ceiling:.0f}</span></div>
</section>
<aside>
<div class="fb-panel-label">What the evidence resolves</div>
<div class="fb-resolution">
<div class="fb-resolution-row"><strong>{leading_group_count}</strong><span>models share the leading statistical group</span></div>
<div class="fb-resolution-row"><strong>{resolved}/{PAIR_COUNT}</strong><span>paired gaps remain significant after Holm control</span></div>
<div class="fb-resolution-row"><strong>+{leader_gap:.1f}</strong><span>points above the analytically computed random-choice baseline ({chance:.1f})</span></div>
<p class="fb-resolution-note">Point estimates give the order. The score bands and pairwise tests show which gaps this release can defend.</p>
</div>
</aside>
</div>
<section class="fb-family-insight">
<h3>Why 534 tasks?</h3>
<p>The crossed design's descriptive relative-decision generalizability is
<strong>{generalizability:.3f}</strong>; the same variance model estimates
<strong>{tasks_for_g_90}</strong> balanced tasks for 0.90. The table below repeatedly takes
score-blind, balanced subsets and compares them with the complete point order.</p>
<div class="fb-table-wrap">
<table class="fb-table">
<caption>5,000 family-by-panel stratified subsets at each non-complete task count</caption>
<thead><tr>
<th scope="col">Tasks</th>
<th scope="col">Median rank ρ</th>
<th scope="col">Empirical 95%</th>
<th scope="col">Top-five overlap</th>
<th scope="col">Point leader kept</th>
</tr></thead>
<tbody>{"".join(stability_rows)}</tbody>
</table>
</div>
<p class="fb-resolution-note">This is a precision diagnostic relative to the complete
release, not a post-hoc power claim. The point leader remains unstable in smaller subsets;
the simultaneous score bands and rank intervals remain the inferential result.</p>
</section>
<section class="fb-family-insight">
<h3>Where the leading labs differ</h3>
<p>Scores are out of 100. Red marks each column leader.</p>
<div class="fb-table-wrap">
<table class="fb-table fb-family-table">
<caption>Family scores for the eight leading lab champions</caption>
<thead><tr>
<th scope="col">Lab champion</th>
<th scope="col"><span class="fb-family-long">Substitution</span><span class="fb-family-short">Sub</span></th>
<th scope="col"><span class="fb-family-long">Pairing</span><span class="fb-family-short">Pair</span></th>
<th scope="col"><span class="fb-family-long">Constraint</span><span class="fb-family-short">Rules</span></th>
</tr></thead>
<tbody>{"".join(family_rows)}</tbody>
</table>
</div>
</section>
"""
def _model_detail(model_name: str) -> tuple[str, pd.DataFrame]:
model = MODEL_BY_NAME[model_name]
rank_interval = model["bootstrap_rank_95_interval"]
coverage = model["coverage"]
panel_replication = model["panel_replication"]
score_interval = model["score_simultaneous_95_ci"]
summary = f"""
<div class="fb-metric-grid">
<div class="fb-metric"><small>FlavourBench Score</small><strong>{model["flavourbench_score"]:.2f}</strong></div>
<div class="fb-metric"><small>Complete cells</small><strong>{coverage["valid_scored"]}/{coverage["scheduled"]}</strong></div>
<div class="fb-metric"><small>Point rank</small><strong>#{model["point_estimate_rank"]}</strong></div>
<div class="fb-metric"><small>Statistical group</small><strong>G{model["statistical_rank_group"]}</strong></div>
<div class="fb-metric"><small>Bootstrap rank</small><strong>{rank_interval[0]}-{rank_interval[1]}</strong></div>
<div class="fb-metric"><small>95% score band</small><strong>{float(score_interval[0]):.1f}-{float(score_interval[1]):.1f}</strong></div>
</div>
<div class="fb-evidence">
<strong>Identical evidence for every model.</strong> This score uses all {TASK_COUNT} common-core
cells: {coverage["valid_scored_per_family"]["substitution"]} substitution,
{coverage["valid_scored_per_family"]["pairing"]} pairing, and
{coverage["valid_scored_per_family"]["constraint"]} constraint tasks. Panel scores are
{float(panel_replication["panel_1"]):.2f} and
{float(panel_replication["panel_2"]):.2f}
({float(panel_replication["difference"]):+.2f}).
</div>
"""
family_rows = [
{
"Family": family.replace("_", " ").title(),
"Score": round(float(score), 3),
"Cells": coverage["valid_scored_per_family"][family],
}
for family, score in model["family_scores"].items()
]
chance = model["chance_comparison"]
chance_score = round(float(chance["exact_chance_score"]), 3)
family_rows.append(
{"Family": "Random legal choice (exact)", "Score": chance_score, "Cells": TASK_COUNT}
)
return summary, pd.DataFrame(family_rows)
def _family_table_html(frame: pd.DataFrame) -> str:
rows = []
for record in frame.to_dict(orient="records"):
rows.append(
"<tr>"
f"<td>{html.escape(str(record['Family']))}</td>"
f"<td class='fb-score-cell'>{float(record['Score']):.3f}</td>"
f"<td>{int(record['Cells'])}</td>"
"</tr>"
)
return (
"<div class='fb-data-heading'>Score by task family</div>"
"<div class='fb-table-wrap'><table class='fb-table fb-table--family'>"
"<caption>FlavourBench score by task family</caption>"
"<thead><tr><th scope='col'>Family</th><th scope='col'>Score</th>"
"<th scope='col'>Cells</th></tr></thead><tbody>" + "".join(rows) + "</tbody></table></div>"
)
def _model_detail_ui(model_name: str) -> tuple[str, str]:
summary, frame = _model_detail(model_name)
return summary, _family_table_html(frame)
def _choices_html(choices: dict[str, str]) -> str:
rows = []
for label, ingredient in choices.items():
rows.append(
"<div class='fb-choice'>"
f"<span class='fb-choice-label'>{html.escape(str(label))}</span>"
f"<span class='fb-choice-name'>{html.escape(str(ingredient))}</span>"
"</div>"
)
return (
"<div class='fb-data-heading'>Eight candidates</div>"
"<div class='fb-choice-grid'>" + "".join(rows) + "</div>"
)
def _score_table_html(frame: pd.DataFrame) -> str:
rows = []
for record in frame.to_dict(orient="records"):
selected = " fb-selected-row" if record["Role"] else ""
rows.append(
f"<tr class='{selected.strip()}'>"
f"<td>{html.escape(str(record['Selection']))}</td>"
f"<td>{html.escape(str(record['Ingredients']))}</td>"
f"<td class='fb-score-cell'>{float(record['Score']):.2f}</td>"
f"<td>{html.escape(str(record['Role']))}</td>"
"</tr>"
)
return (
"<div class='fb-data-heading'>Top 12 of 56 scored selections</div>"
"<div class='fb-table-wrap'><table class='fb-table fb-table--score'>"
"<caption>Highest-scoring legal ingredient selections</caption>"
"<thead><tr><th scope='col'>Selection</th><th scope='col'>Ingredients</th>"
"<th scope='col'>Score</th><th scope='col'>Role</th></tr></thead><tbody>"
+ "".join(rows)
+ "</tbody></table></div>"
)
def _task_detail(
model_name: str, task_label: str
) -> tuple[str, str, dict[str, str], pd.DataFrame, str, str]:
model = MODEL_BY_NAME[model_name]
task_id = TASK_LABEL_TO_ID[task_label]
task = TASK_BY_ID[task_id]
observation = OBSERVATIONS[(str(model["model_id"]), task_id)]
scoring = observation["scoring"]
observed = scoring.get("observed_selection")
optimum = str(task["optimal_selection"])
observed_ingredients = [task["choices"][label] for label in observed] if observed else []
optimum_ingredients = [task["choices"][label] for label in optimum]
if observation.get("status") != "completed" or not bool(scoring.get("parseable")):
raise SpaceDataError("common-core observation is not release-valid")
status = f"""
<div class="fb-evidence">
<strong>{html.escape(model_name)}</strong> selected
<code>{html.escape(str(observed))}</code> and scored
<strong>{float(scoring["score"]):.2f}</strong>. The optimum is
<code>{html.escape(optimum)}</code>.
<br>Observed: {html.escape(", ".join(observed_ingredients))}
<br>Optimum: {html.escape(", ".join(optimum_ingredients))}
</div>
"""
ranked = sorted(
task["selection_scores_bps"].items(),
key=lambda item: (-int(item[1]), str(item[0])),
)
score_rows = []
for selection, score in ranked[:12]:
roles = []
if selection == observed:
roles.append("model selection")
if selection == optimum:
roles.append("optimum")
score_rows.append(
{
"Selection": selection,
"Ingredients": ", ".join(task["choices"][label] for label in selection),
"Score": int(score) / 100,
"Role": ", ".join(roles),
}
)
provenance = (
f"Response SHA-256: `{observation['artifact_sha256']}` \n"
f"Actual model: `{observation.get('actual_model_id')}` \n"
f"Provider: `{observation.get('actual_provider')}` \n"
f"Prompt SHA-256: `{task['prompt_sha256']}`"
)
answer = str(observation.get("answer_excerpt") or "No answer was recorded.")
if observation.get("answer_truncated"):
answer += "\n\n[Excerpt truncated. The full response is in the dataset.]"
return (
status,
str(task["prompt"]),
dict(task["choices"]),
pd.DataFrame(score_rows),
answer,
provenance,
)
def _task_detail_ui(model_name: str, task_label: str) -> tuple[str, str, str, str, str, str]:
status, prompt, choices, score_map, answer, provenance = _task_detail(model_name, task_label)
return (
status,
prompt,
_choices_html(choices),
_score_table_html(score_map),
answer,
provenance,
)
def _pair_detail(left_name: str, right_name: str) -> str:
left = str(MODEL_BY_NAME[left_name]["model_id"])
right = str(MODEL_BY_NAME[right_name]["model_id"])
if left == right:
return "<div class='fb-evidence'>Choose two different models.</div>"
row = PAIR_INDEX.get((left, right))
sign = 1.0
if row is None:
row = PAIR_INDEX[(right, left)]
sign = -1.0
difference = sign * float(row["mean_difference"])
interval = [sign * float(value) for value in row["bootstrap_95_ci"]]
interval.sort()
verdict = "distinguishable after Holm correction" if row["holm_significant"] else "not resolved"
cohen_dz = row.get("cohen_dz")
cohen_text = f"{float(cohen_dz):+.3f}" if cohen_dz is not None else "not available"
return f"""
<div class="fb-evidence">
<strong>{html.escape(left_name)}</strong> minus <strong>{html.escape(right_name)}</strong>:
<strong>{difference:+.3f} points</strong> (bootstrap 95% {interval[0]:+.3f} to {interval[1]:+.3f}).
The comparison is <strong>{verdict}</strong> across all {PAIR_COUNT} tests
(shared valid tasks: <code>{row.get("shared_valid_tasks", TASK_COUNT)}</code>).
<br>Holm p = <code>{float(row["holm_p"]):.4g}</code>, paired Cohen dz =
<code>{cohen_text}</code>.
</div>
"""
def _score_completion_api(task_id: str, completion: str) -> dict[str, Any]:
"""Named Gradio endpoint for one released-map reward lookup."""
return score_completion(TASK_BY_ID, task_id, completion)
def _score_submission_api(payload: str) -> dict[str, Any]:
"""Named Gradio endpoint for a complete JSON/JSONL response artifact."""
report, _ = score_payload(TASKS, payload)
return report
def _training_reward_api(task_id: str, completion: str) -> dict[str, Any]:
"""Named endpoint for a development-map reward used during training."""
result = score_completion(LAB_TASK_BY_ID, task_id, completion)
task = LAB_TASK_BY_ID[task_id]
return {
**result,
"track": "development_training",
"split": task["lab_split"],
"family": task["family"],
"official_leaderboard_eligible": False,
}
def _command_preview(
runtime: str,
model: str,
base_url: str,
api_key_env: str,
scope: str,
) -> str:
"""Render a copyable lab command without receiving model credentials."""
model = " ".join(str(model or "").split()) or "your-exact-model-id"
base_url = " ".join(str(base_url or "").split()) or "https://your-endpoint.example/v1"
api_key_env = "".join(
character for character in str(api_key_env or "") if character.isalnum() or character == "_"
)
api_key_env = api_key_env or "LAB_MODEL_API_KEY"
smoke = " --limit 12" if scope.startswith("12-task") else ""
backend = "transformers" if runtime.startswith("Local") else "openai-compatible"
route = ""
if backend == "openai-compatible":
route = f" \\\n --base-url {shlex.quote(base_url)} \\\n --api-key-env {shlex.quote(api_key_env)}"
command = (
'python -m pip install "epicure-flavourbench @ '
'git+https://github.com/josefchen/flavourbench.git"\n\n'
f"flavourbench run \\\n --backend {backend} \\\n --model {shlex.quote(model)}"
f"{route} \\\n --responses responses.jsonl \\\n --report flavourbench-report.json \\\n --resume{smoke}"
)
note = (
f"Set `{api_key_env}` in your shell before running. The key stays on your machine."
if backend == "openai-compatible"
else "The checkpoint runs locally through Transformers. No endpoint credential is used."
)
return f"```bash\n{command}\n```\n\n{note}"
def _reward_preview(task_label: str, completion: str) -> str:
"""Score one development completion for the interactive reward demonstration."""
task_id = LAB_TASK_LABEL_TO_ID[task_label]
try:
result = _training_reward_api(task_id, completion)
except SpaceLabError as error:
return f"<div class='fb-evidence'><strong>Not parseable.</strong> {html.escape(str(error))}</div>"
selection = html.escape(str(result.get("selection") or result.get("observed_selection") or ""))
return f"""
<div class="fb-evidence">
<strong>Reward {float(result["reward"]):.4f}</strong> · score {float(result["score"]):.2f} · selection <code>{selection}</code><br>
This map belongs to the anchor-disjoint development track. It cannot alter the public leaderboard.
</div>
"""
def _score_upload(
artifact_path: str | None,
model_name: str,
disclosure: str,
) -> tuple[str, pd.DataFrame, str | None]:
"""Score one upload without publishing it or changing the leaderboard."""
if not artifact_path:
raise gr.Error("Choose a JSON or JSONL response artifact first.")
source = Path(artifact_path)
if source.is_symlink() or not source.is_file():
raise gr.Error("The upload is not a regular file.")
if source.stat().st_size > 16 * 1024 * 1024:
raise gr.Error("The upload exceeds 16 MiB.")
try:
report, per_task = score_payload(TASKS, source.read_text(encoding="utf-8"))
except (OSError, UnicodeError, SpaceLabError) as error:
raise gr.Error(str(error)) from error
label = " ".join(str(model_name or "").split())[:160] or "Unnamed model"
disclosure = " ".join(str(disclosure or "Not disclosed").split())[:240]
report["submission"] = {
"model_name": label,
"method_disclosure": disclosure,
"scored_at_utc": datetime.now(UTC).isoformat(),
"published_to_leaderboard": False,
}
report.pop("artifact_sha256", None)
report["artifact_sha256"] = hashlib.sha256(_canonical(report)).hexdigest()
coverage = report["coverage"]
if report["comparable"]:
score = float(report["flavourbench_score"])
summary = (
f"### {label}: {score:.2f}\n\n"
f"**Comparable lab score.** All {coverage['tasks']} tasks were present and parseable. "
"This result is not added to the public leaderboard automatically."
)
else:
diagnostic = report.get("diagnostic_valid_score")
diagnostic_text = f"{float(diagnostic):.2f}" if diagnostic is not None else "unavailable"
summary = (
f"### {label}: no FlavourBench Score issued\n\n"
f"Valid coverage is **{coverage['valid']}/{coverage['tasks']}** "
f"({coverage['fraction_valid']:.1%}); {coverage['missing']} missing and "
f"{coverage['invalid']} invalid. The valid-only diagnostic is {diagnostic_text}, "
"but it is not a comparable leaderboard score."
)
rows = pd.DataFrame(per_task)[
["task_id", "family", "status", "observed_selection", "score", "optimal"]
].rename(
columns={
"task_id": "Task",
"family": "Family",
"status": "Status",
"observed_selection": "Selection",
"score": "Score",
"optimal": "Optimal",
}
)
with tempfile.NamedTemporaryFile(
mode="w",
encoding="utf-8",
prefix="flavourbench-report-",
suffix=".json",
delete=False,
) as handle:
json.dump(report, handle, ensure_ascii=False, indent=2, sort_keys=True, allow_nan=False)
handle.write("\n")
report_path = handle.name
return summary, rows, report_path
def _score_upload_ui(
artifact_path: str | None,
model_name: str,
disclosure: str,
) -> tuple[Any, Any, Any]:
"""Reveal upload results only after the scorer has produced them."""
summary, rows, report_path = _score_upload(artifact_path, model_name, disclosure)
return (
gr.update(value=summary, visible=True),
gr.update(value=rows, visible=True),
gr.update(value=report_path, visible=True),
)
theme = gr.themes.Base(
primary_hue=gr.themes.Color(
c50="#F8ECE9",
c100="#F1DDD8",
c200="#E7BCB5",
c300="#D98F84",
c400="#C96357",
c500=RUST,
c600="#98352D",
c700="#7C2E28",
c800="#662A25",
c900="#562722",
c950="#2F120F",
),
neutral_hue="stone",
font=(
gr.themes.Font("Lato"),
gr.themes.Font("Avenir Next"),
gr.themes.Font("Arial"),
gr.themes.Font("sans-serif"),
),
font_mono=(
gr.themes.Font("DejaVu Sans Mono"),
gr.themes.Font("monospace"),
),
).set(
body_background_fill="#F6F7F5",
block_background_fill="#F6F7F5",
block_border_width="0px",
block_label_text_weight="600",
button_primary_background_fill=INK,
button_primary_background_fill_hover=RUST,
)
with gr.Blocks(title="FlavourBench | Which AI knows food best?") as demo:
gr.HTML(_hero_html(), elem_id="fb-hero-block")
with gr.Tabs():
with gr.Tab("Leaders"):
gr.HTML(
f"""
<div class="fb-section">
<h2>The complete leaderboard</h2>
<p>All {MODEL_COUNT} models face the same {TASK_COUNT} tasks. Change the score view, filter the field, then inspect the uncertainty behind the overall rank.</p>
</div>
"""
)
gr.HTML(_leaderboard_html(), js_on_load=LEADERBOARD_JS)
gr.Markdown(
"**Read the score first.** The focused chart above uses point estimates. "
"The table adds simultaneous 95% bands, bootstrap rank intervals, and multiplicity-controlled groups. "
"A score of 100 means selecting Epicure's optimum on every task."
)
with gr.Tab("Insights"):
gr.HTML(
"""
<div class="fb-section">
<h2>Ranks need error bars</h2>
<p>The point order is real, but not every adjacent gap is resolved. Simultaneous bands and paired tests show where the evidence separates models.</p>
</div>
"""
)
gr.HTML(_insights_html())
with gr.Tab("Profiles"):
gr.HTML(
"""
<div class="fb-section">
<h2>Where each model wins</h2>
<p>Break the headline score into substitution, pairing, and constraint performance, then compare the two collection panels.</p>
</div>
"""
)
model_selector = gr.Dropdown(
choices=MODEL_NAMES,
value=MODEL_NAMES[0],
label="Model",
filterable=True,
)
initial_model_summary, initial_family_table = _model_detail_ui(MODEL_NAMES[0])
model_summary = gr.HTML(initial_model_summary)
family_table = gr.HTML(initial_family_table)
model_selector.change(
_model_detail_ui,
inputs=model_selector,
outputs=[model_summary, family_table],
api_visibility="private",
)
with gr.Tab("Inspect"):
gr.HTML(
"""
<div class="fb-section">
<h2>Open one scored decision</h2>
<p>Every answer is traceable to the exact prompt, model response, and precomputed 56-choice reward surface.</p>
</div>
"""
)
with gr.Row():
task_model = gr.Dropdown(
choices=MODEL_NAMES,
value=MODEL_NAMES[0],
label="Model",
filterable=True,
scale=1,
)
task_selector = gr.Dropdown(
choices=list(TASK_LABEL_TO_ID),
value=next(iter(TASK_LABEL_TO_ID)),
label="Task",
filterable=True,
scale=2,
)
inspect_task = gr.Button("Inspect task", variant="primary", scale=0)
initial = _task_detail_ui(MODEL_NAMES[0], next(iter(TASK_LABEL_TO_ID)))
task_status = gr.HTML(initial[0])
prompt = gr.Textbox(value=initial[1], label="Exact prompt", lines=11, interactive=False)
choices = gr.HTML(initial[2])
score_map = gr.HTML(initial[3])
answer = gr.Markdown(value=initial[4], label="Model response")
provenance = gr.Markdown(value=initial[5], label="Content hashes and route")
inspect_task.click(
_task_detail_ui,
inputs=[task_model, task_selector],
outputs=[task_status, prompt, choices, score_map, answer, provenance],
api_visibility="private",
)
with gr.Tab("Run your model"):
gr.HTML(
f"""
<div class="fb-section">
<h2>Run FlavourBench on any model</h2>
<p>Your endpoint key or checkpoint stays in your environment. The open runner fetches the exact task set, resumes interrupted jobs, and writes a verifiable report.</p>
</div>
<div class="fb-lab-path">
<strong>Endpoint / checkpoint <i>→</i> {TASK_COUNT} shared tasks <i>→</i> verifiable report</strong>
<span>Keys stay local. Start with 12 tasks, resume without repeated calls, then publish the exact responses and route.</span>
</div>
"""
)
with gr.Row():
with gr.Column(scale=1):
runtime = gr.Radio(
choices=[
"Hosted OpenAI-compatible endpoint",
"Local Transformers checkpoint",
],
value="Hosted OpenAI-compatible endpoint",
label="Runtime",
)
run_model = gr.Textbox(
value="your-exact-model-id",
label="Model ID or checkpoint",
)
run_scope = gr.Radio(
choices=["12-task smoke test", f"Full {TASK_COUNT}-task benchmark"],
value="12-task smoke test",
label="Run size",
)
with gr.Column(scale=1):
run_base_url = gr.Textbox(
value="https://your-endpoint.example/v1",
label="Base URL for hosted endpoints",
)
run_key_env = gr.Textbox(
value="LAB_MODEL_API_KEY",
label="Local environment variable containing the key",
)
generate_command = gr.Button("Build command", variant="primary")
initial_command = _command_preview(
"Hosted OpenAI-compatible endpoint",
"your-exact-model-id",
"https://your-endpoint.example/v1",
"LAB_MODEL_API_KEY",
"12-task smoke test",
)
run_command = gr.Markdown(initial_command)
generate_command.click(
_command_preview,
inputs=[runtime, run_model, run_base_url, run_key_env, run_scope],
outputs=run_command,
api_visibility="private",
)
gr.HTML(
"""
<div class="fb-section">
<h2>Try the training reward</h2>
<p>Paste one completion and query an anchor-disjoint development map. This is the same deterministic reward used by the local GRPO recipe.</p>
</div>
"""
)
initial_lab_label = next(iter(LAB_TASK_LABEL_TO_ID))
with gr.Row():
reward_task = gr.Dropdown(
choices=list(LAB_TASK_LABEL_TO_ID),
value=initial_lab_label,
label="Development task",
filterable=True,
scale=2,
)
reward_completion = gr.Textbox(
value="FINAL_SELECTION: A,B,C",
label="Model completion",
scale=2,
)
score_reward = gr.Button("Score answer", variant="primary", scale=0)
reward_result = gr.HTML(_reward_preview(initial_lab_label, "FINAL_SELECTION: A,B,C"))
score_reward.click(
_reward_preview,
inputs=[reward_task, reward_completion],
outputs=reward_result,
api_visibility="private",
)
gr.HTML(
f"""
<div class="fb-section">
<h2>Score a completed run</h2>
<p>Upload one JSON or JSONL response per task. Complete runs receive a FlavourBench Score; partial runs receive diagnostics only.</p>
</div>
<div class="fb-evidence"><strong>Comparable means complete.</strong> All {TASK_COUNT} responses must be present and parseable. Uploads are scored in-session and never added to the public leaderboard automatically.</div>
"""
)
with gr.Row():
lab_name = gr.Textbox(
label="Model or experiment name",
placeholder="lab/model-name, checkpoint, decoding policy",
scale=2,
)
lab_disclosure = gr.Dropdown(
choices=[
"Base model; no FlavourBench training",
"Fine-tuned without FlavourBench training data",
"Fine-tuned with FlavourBench lab data or reward",
"Other; disclose in the artifact",
],
value="Base model; no FlavourBench training",
label="Method disclosure",
scale=2,
)
lab_upload = gr.File(
label="Responses (.jsonl or .json)",
file_types=[".jsonl", ".json"],
type="filepath",
height=150,
)
score_upload = gr.Button("Score complete artifact", variant="primary")
lab_summary = gr.Markdown(visible=False)
lab_rows = gr.Dataframe(
interactive=False,
wrap=True,
show_search="filter",
show_row_numbers=False,
label="Per-task results",
visible=False,
)
lab_report = gr.DownloadButton(
"Download content-addressed report",
visible=False,
size="md",
elem_classes="fb-download",
)
score_upload.click(
_score_upload_ui,
inputs=[lab_upload, lab_name, lab_disclosure],
outputs=[lab_summary, lab_rows, lab_report],
api_visibility="private",
)
gr.HTML(
f"""
<div class="fb-publish-path">
<div>
<h3>Publish a result</h3>
<p>Submit the complete report, raw responses, exact route, decoding settings, and training disclosure. Maintainers verify the {TASK_COUNT}-task matrix before any leaderboard update.</p>
</div>
<a class="fb-action-link" href="{SUBMIT_RESULT_URL}" target="_blank" rel="noreferrer">Open result submission</a>
</div>
"""
)
upload_api = gr.Button(visible=False)
upload_api.click(
_score_upload,
inputs=[lab_upload, lab_name, lab_disclosure],
outputs=[lab_summary, lab_rows, lab_report],
api_name="score_uploaded_submission",
)
gr.Markdown(
f"""
```json
{{"task_id":"...","status":"completed","response":"FINAL_SELECTION: A,B,C"}}
```
The named `score_completion`, `score_submission`, and `training_reward` endpoints appear under
**Use via API**. For high-throughput RL, use the local reward lookup and the runnable SFT, DPO,
and GRPO recipes in the source repository. The full publication contract is in the
[submission guide]({SUBMISSION_GUIDE_URL}).
"""
)
with gr.Tab("Compare"):
gr.HTML(
f"""
<div class="fb-section">
<h2>Does the gap hold up?</h2>
<p>Query any of the {PAIR_COUNT} paired model contrasts on the same tasks, with Holm control across the full comparison family.</p>
</div>
"""
)
with gr.Row():
left_model = gr.Dropdown(
choices=MODEL_NAMES,
value=MODEL_NAMES[0],
label="First model",
filterable=True,
)
right_model = gr.Dropdown(
choices=MODEL_NAMES,
value=MODEL_NAMES[1],
label="Second model",
filterable=True,
)
compare = gr.Button("Compare", variant="primary", scale=0)
pair_result = gr.HTML(_pair_detail(MODEL_NAMES[0], MODEL_NAMES[1]))
compare.click(
_pair_detail,
inputs=[left_model, right_model],
outputs=pair_result,
api_visibility="private",
)
with gr.Tab("Method"):
gr.HTML(
f"""
<div class="fb-section">
<h2>One lookup, repeated {TASK_COUNT} times</h2>
<p>The Space makes no provider calls. It reads released reward maps and returns deterministic scores.</p>
</div>
<div class="fb-method-visual">
<img class="fb-architecture" src="{ARCHITECTURE_URL}" alt="A culinary task branches to a model choosing three ingredients and Epicure scoring all 56 legal choices before the benchmark aggregates the result.">
<div>
<h3>Scoring contract</h3>
<p>A task score ranges from 0 to 100 on its released Epicure map. The complete
release is a {MODEL_COUNT} by {TASK_COUNT} matrix with one valid response in every cell.</p>
<h3>Inference</h3>
<p>Results use {INDEPENDENT_CLUSTER_COUNT:,} ingredient-anchor clusters,
50,000 shared cluster bootstraps, simultaneous score bands, 100,000 cluster
sign flips, Holm correction, exact tests against a random legal choice, bootstrap rank intervals,
and an independently compiled second panel.</p>
<h3>Training boundary</h3>
<p>The 342 optimizer-facing SFT, DPO, and GRPO maps use anchors that do not
occur in the 84-task transfer split or the {TASK_COUNT}-task leaderboard.
Training cannot query either evaluation map through the reward endpoint.</p>
<aside class="fb-evidence">
<strong>Content-addressed release</strong><br>
<span class="fb-hash">{BUNDLE["release_artifact_sha256"]}</span><br><br>
{MODEL_COUNT} endpoints<br>{TASK_COUNT} tasks<br>{INDEPENDENT_CLUSTER_COUNT:,} anchor clusters<br>{PRIMARY_COUNT:,} complete answers<br>{BUNDLE["analysis"]["resolved_pair_count"]}/{PAIR_COUNT} resolved pairs
</aside>
</div>
</div>
"""
)
gr.Markdown(
"""
```bash
git clone https://github.com/josefchen/flavourbench.git
cd flavourbench
python -m pip install -e '.[dev]'
pytest -q tests/lab_cli_test.py tests/hf_lab_space_api_test.py
```
"""
)
gr.api(
_score_completion_api,
api_name="score_completion",
api_description="Score one completion against one released FlavourBench task.",
queue=False,
)
gr.api(
_score_submission_api,
api_name="score_submission",
api_description="Score a complete response artifact supplied as JSON or JSON Lines text.",
queue=False,
)
gr.api(
_training_reward_api,
api_name="training_reward",
api_description="Return an Epicure-derived dense reward for a development task completion.",
queue=False,
)
gr.HTML(
"""
<div class="fb-shell fb-footer">
<div class="fb-footer-main">
<strong>FlavourBench</strong>
<span>Josef Chen, Independent Researcher</span>
<span>Erim Hayretci, Imperial College London</span>
</div>
<nav class="fb-footer-links" aria-label="Project resources">
<a href="https://arxiv.org/abs/2608.20574">Paper</a>
<a href="https://huggingface.co/datasets/josefchen/flavourbench">Dataset</a>
<a href="https://github.com/josefchen/flavourbench">Source</a>
</nav>
</div>
"""
)
if __name__ == "__main__":
demo.launch(
theme=theme,
css=CSS,
head=HEAD,
allowed_paths=[str(HERE / "assets")],
)