Clemson-Computing-User's picture
Add Cosmos3 eval
aae61f5
Raw
History Blame Contribute Delete
42.2 kB
"""VANTAGE-Bench Leaderboard β€” Hugging Face Space entry point.
Data and ranks are computed once at startup. Filters narrow the displayed
subset only; they never recompute official scores or ranks.
"""
from __future__ import annotations
import re
from datetime import datetime
from pathlib import Path
import gradio as gr
from util.config import (
LEADERBOARD_TABS,
PARAM_BUCKETS,
PILLARS,
)
from util.data import ModelRecord, load_results_json
from util.ranking import GLOBAL_RANKS, compute_global_ranks
from util.render import (
build_all_tables,
build_overall_html_table,
datatypes_for_tab,
headers_for_tab,
make_radar_svg,
)
from css import CSS
# ---------------------------------------------------------------------------
# Startup β€” one-shot, immutable after this point
# ---------------------------------------------------------------------------
REPO_ROOT = Path(__file__).resolve().parent
DATA_PATH = REPO_ROOT / "data" / "results.json"
ABOUT_PATH = REPO_ROOT / "assets" / "about.md"
DATA = load_results_json(DATA_PATH)
compute_global_ranks(DATA.models, LEADERBOARD_TABS) # populates GLOBAL_RANKS
# "2026-05-29" β†’ "May 29, 2026" β€” no zero-padded day, cross-platform.
_dt = datetime.strptime(DATA.updated, "%Y-%m-%d")
_UPDATED_DISPLAY = f"{_dt.strftime('%B')} {_dt.day}, {_dt.year}"
ABOUT_MD = ABOUT_PATH.read_text(encoding="utf-8")
# Initial tables β€” no filters, sorted by overall rank
_INIT_TABLES = build_all_tables(DATA.models, GLOBAL_RANKS)
_INIT_OVERALL_HTML = build_overall_html_table(DATA.models, GLOBAL_RANKS["overall"])
_INIT_STATUS = f'<p class="lb-status">Showing all {len(DATA.models)} models</p>'
# ---------------------------------------------------------------------------
# Static markup
# ---------------------------------------------------------------------------
HEADER_HTML = """
<div class="lb-header">
<div class="lb-hero">
<h1 class="lb-wordmark">
<span class="lb-vantage">VANTAGE</span><span class="lb-dash">-</span><span class="lb-bench-label">Bench</span>
</h1>
<p class="lb-acronym"><b>V</b>ideo <b>AN</b>alysis <b>T</b>asks <b>A</b>cross <b>G</b>eneralized <b>E</b>nvironments</p>
<p class="lb-summary">A multi-task benchmark for evaluating Vision-Language Models on real-world fixed-camera footage across Warehouse, Transportation, and Smart Spaces, spanning Spatial, Spatio-Temporal, Temporal, and Semantic understanding.</p>
<nav class="lb-nav lb-nav-hero">
<a href="https://vantage-bench.org/" target="_blank" rel="noopener">Website</a>
<span class="lb-sep">|</span>
<a href="https://github.com/Clemson-Capstone/VANTAGE-Bench" target="_blank" rel="noopener">GitHub</a>
<span class="lb-sep">|</span>
<a href="https://huggingface.co/datasets/nvidia/PhysicalAI-VANTAGE-Bench" target="_blank" rel="noopener">Dataset</a>
</nav>
<div class="lb-stats">
<span class="lb-stat"><b>3</b> Domains</span>
<span class="lb-stat-sep">Β·</span>
<span class="lb-stat"><b>8</b> Tasks</span>
<span class="lb-stat-sep">Β·</span>
<span class="lb-stat"><b>35,027</b> Annotations</span>
<span class="lb-stat-sep">Β·</span>
<span class="lb-stat"><b>3,346</b> Media</span>
</div>
</div>
</div>
"""
# ---------------------------------------------------------------------------
# Filter helpers
# ---------------------------------------------------------------------------
# Ordered pillar keys matching the tab order
_PILLAR_ORDER: list[str] = ["overall", "spatial", "st", "temporal", "semantic"]
def _param_matches(m: ModelRecord, bucket: str) -> bool:
"""True if model belongs to the selected param bucket.
Buckets (keys mirror util.config.PARAM_BUCKETS):
"all" – every model.
"lt10" – strictly < 10B.
"10to40" – inclusive 10B ≀ v ≀ 40B.
"gt40" – strictly > 40B.
Models with an undisclosed param count (param_value is None) β€” e.g.
closed/API models like Gemini β€” are visible ONLY under "All sizes"
(Option A): they are excluded from every numeric bucket so a user
selecting a specific size range does not get noisy "unknown" rows.
"""
if bucket == "all":
return True
v = m.param_value
if v is None:
return False # null β†’ only visible under "all"
if bucket == "lt10":
return v < 10.0
if bucket == "10to40":
return 10.0 <= v <= 40.0
if bucket == "gt40":
return v > 40.0
return True
def _filter_models(
search: str,
model_type: str,
access: str,
params_bucket: str,
verified_only: bool = False,
) -> list[ModelRecord]:
models: list[ModelRecord] = list(DATA.models)
# Free-text search (name or org, case-insensitive)
if search and search.strip():
q = search.strip().lower()
models = [m for m in models
if q in m.name.lower() or q in m.organization.lower()]
# Submission Type β€” UI label "System / Pipeline" maps to the internal
# "ensemble" enum value (kept for schema/data backwards compatibility).
if model_type and model_type != "All":
rt = {"Single": "single", "System / Pipeline": "ensemble"}.get(model_type)
if rt:
models = [m for m in models if m.result_type == rt]
# Access (Open-weight / Proprietary)
if access and access != "All":
ac = {"Open-weight": "open", "Proprietary": "closed"}.get(access)
if ac:
models = [m for m in models if m.type == ac]
# Param size bucket
models = [m for m in models if _param_matches(m, params_bucket)]
# Verified only
if verified_only:
models = [m for m in models if m.verified]
return models
# ---------------------------------------------------------------------------
# Reactive callback
# ---------------------------------------------------------------------------
def on_filter_change(
search: str,
model_type: str,
access: str,
params_bucket: str,
verified_only: bool,
) -> tuple:
"""Rebuild the Overall HTML table and four pillar DataFrames from filters."""
filtered = _filter_models(search, model_type, access, params_bucket, verified_only)
tables = build_all_tables(filtered, GLOBAL_RANKS)
overall_html = build_overall_html_table(filtered, GLOBAL_RANKS["overall"])
n = len(filtered)
total = len(DATA.models)
if n == 0:
status = '<p class="lb-status">No models match β€” adjust the filters.</p>'
elif n == total:
status = f'<p class="lb-status">Showing all {total} models</p>'
else:
status = f'<p class="lb-status">Showing {n} of {total} models</p>'
# _PILLAR_ORDER is ["overall", "spatial", "st", "temporal", "semantic"];
# Overall outputs HTML, the four pillars output DataFrames.
table_outputs: tuple = (overall_html,) + tuple(tables[p] for p in _PILLAR_ORDER[1:])
return table_outputs + (status,) + ("",) * 5 + (gr.update(visible=False),) * 5
# ---------------------------------------------------------------------------
# Side-panel helpers
# ---------------------------------------------------------------------------
_PANEL_TASK_ROWS: list[tuple[str, str]] = [
("2D Object Localization", "2d_localization"),
("2D Referring Expressions", "2d_referring_expressions"),
("Pointing", "2d_spatial_pointing"),
("SOT", "single_object_tracking"),
("Temporal Loc.", "temporal_localization"),
("DVC", "dense_video_captioning"),
("Event Verification", "event_verification"),
("VQA", "video_qa"),
]
def _make_panel_html(m: ModelRecord) -> str:
"""Build the HTML string for the model detail side panel."""
# Model card link (shown in header)
card_link = (
f' <a href="{m.model_url}" target="_blank" class="sp-card-link">Model card β†—</a>'
if m.model_url else ""
)
# Model info section
type_label = "System / Pipeline" if m.result_type == "ensemble" else "Single"
access_label = "Open-weight" if m.type == "open" else "Proprietary"
info_cells = (
f'<span class="sp-k">Parameters</span><span class="sp-v">{m.params}</span>'
f'<span class="sp-k">Type</span><span class="sp-v">{type_label}</span>'
f'<span class="sp-k">Access</span><span class="sp-v">{access_label}</span>'
f'<span class="sp-k">Evaluated</span><span class="sp-v">{m.date_evaluated}</span>'
)
# Header badges (verified / new only)
top_badges: list[str] = []
if m.verified:
top_badges.append('<span class="b b-verified">βœ“ verified</span>')
if m.is_new:
top_badges.append('<span class="b b-new">new</span>')
top_badges_html = (
f'<div class="sp-panel-badges">{" ".join(top_badges)}</div>'
if top_badges else ""
)
# Task scores grid (all 8 tasks)
task_cells = "".join(
f'<span class="sp-k">{label}</span>'
f'<span class="sp-v">{f"{m.scores[f]:.1f}" if (f := field) in m.scores else "β€”"}</span>'
for label, field in _PANEL_TASK_ROWS
)
radar_svg = make_radar_svg(m)
return (
f'<div class="sp-wrap">'
f'<div class="sp-hdr">'
f'<div class="sp-name">{m.name}{card_link}</div>'
f'<div class="sp-org">{m.organization}</div>'
f'{top_badges_html}'
f'</div>'
f'<div class="sp-body">'
f'<div class="sp-section"><div class="sp-section-label">Model info</div>'
f'<div class="sp-info-grid">{info_cells}</div></div>'
f'<div class="sp-section"><div class="sp-section-label">Pillar scores</div>'
f'<div class="sp-radar">{radar_svg}</div></div>'
f'<div class="sp-section"><div class="sp-section-label">All task scores</div>'
f'<div class="sp-grid">{task_cells}</div></div>'
f'</div></div>'
)
def _on_row_select(evt: gr.SelectData, df_val) -> tuple:
"""Handle a dataframe row-click; returns (panel_html, column_visible_update)."""
try:
row_idx = evt.index[0]
model_cell = str(df_val.iloc[row_idx, 1])
# Strip bold markdown, extract name before " Β· "
match = re.search(r'data-n="([^"]+)"', model_cell)
name = match.group(1) if match else model_cell.split(' Β· ')[0].strip('*').strip()
m = next((x for x in DATA.models if x.name == name), None)
if m is None:
return "", gr.update(visible=False)
return _make_panel_html(m), gr.update(visible=True)
except Exception:
return "", gr.update(visible=False)
def _on_overall_row_click_id(raw: str) -> tuple:
"""Handle a row click from the Overall HTML table.
The JS bridge in _RESIZE_JS writes "{model_id}|{timestamp}" into the
hidden gr.Textbox (#lb-overall-selected-id). The timestamp suffix forces
a value change even when the same row is clicked twice (e.g. close
panel β†’ click same row again), so gr.Textbox.change always fires.
"""
if not raw:
return "", gr.update(visible=False)
model_id = raw.split("|", 1)[0]
m = DATA.model_by_id.get(model_id)
if m is None:
return "", gr.update(visible=False)
return _make_panel_html(m), gr.update(visible=True)
# ---------------------------------------------------------------------------
# UI layout
# ---------------------------------------------------------------------------
# Gradio tuple-choice lists so the component returns keys, not display labels
_PARAMS_CHOICES: list[tuple[str, str]] = [
(label, key) for key, label in PARAM_BUCKETS.items()
]
# Tab spec: (pillar_key, tab_label, css_class_suffix)
_TAB_SPECS: list[tuple[str, str, str]] = [
("overall", "Overall", "overall"),
("spatial", "Spatial", "spatial"),
("st", "Spatio-Temporal", "st"),
("temporal", "Temporal", "temporal"),
("semantic", "Semantic", "semantic"),
]
# Per-tab contextual description HTML (shown above the table)
_TAB_DESCRIPTIONS: dict[str, str] = {
"overall": (
"Ranks models by their mean score across four reasoning pillars β€” "
"Semantic, Spatial, Spatio-Temporal, and Temporal. "
"Click any row to view the per-task breakdown."
),
"spatial": (
"Evaluates precise geometric grounding in dense, fixed-camera scenes β€” "
"distinguishing between dozens of identical objects from an elevated, oblique viewpoint."
),
"st": (
"Evaluates continuous visual persistence β€” can a model maintain "
"awareness of a specific object across an entire video sequence?"
),
"temporal": (
"Evaluates perception of event timing and duration in long, "
"untrimmed infrastructure video with extended periods of inactivity."
),
"semantic": (
"Evaluates high-level causal and operational reasoning β€” does the "
"model understand what happened and why, not just what is visible?"
),
}
_TAB_DETAIL_DESC: dict[str, str] = {
"overall": (
'<div class="lb-detail-desc">'
'Each pillar score is the mean of its constituent tasks. '
'<b>Spatial</b>: Referring Expressions Β· Pointing Β· Object Localization. '
'<b>Spatio-Temporal</b>: Single Object Tracking. '
'<b>Temporal</b>: Temporal Localization Β· Dense Video Captioning. '
'<b>Semantic</b>: Event Verification Β· Video QA.'
'</div>'
),
"spatial": (
'<div class="lb-detail-desc">'
'<b>Referring Expressions (mIoU):</b> Localize a target described in natural language β€” mean IoU between predicted and ground-truth bounding box.<br>'
'<b>Pointing (Acc):</b> Select the correct 2D coordinate from multiple-choice options β€” Top-1 accuracy.<br>'
'<b>Object Localization (F1@0.5):</b> Detect all instances of a given class in the scene β€” F1 score at IoU threshold 0.5.'
'</div>'
),
"st": (
'<div class="lb-detail-desc">'
'<b>SOT (Success AUC):</b> Given a bounding box on frame 1, predict the target\u2019s trajectory across all subsequent frames in a single forward pass. '
'No rolling memory β€” pure vision-language inference. '
'Success AUC = area under the success plot, varying IoU threshold from 0 to 1. '
'This is the first quantitative VLM tracking benchmark in existence.'
'</div>'
),
"temporal": (
'<div class="lb-detail-desc">'
'<b>Temporal Localization (mIoU):</b> Predict the start and end timestamp for a natural language event query β€” mean IoU between predicted and ground-truth temporal segment.<br>'
'<b>DVC (SODAc):</b> Autonomously localize and caption all events in chronological order without any query. '
'SODAc jointly evaluates temporal localization accuracy and semantic caption quality via BERTScore.'
'</div>'
),
"semantic": (
'<div class="lb-detail-desc">'
'<b>Event Verification (Macro F1):</b> Verify a hypothesis about a video event as true or false against visual evidence. '
'Macro F1 penalizes models that exploit majority-class bias.<br>'
'<b>VQA (Accuracy):</b> Multi-step logical reasoning over untrimmed infrastructure video. Top-1 accuracy on 4-choice MCQ.'
'</div>'
),
}
_BADGE_LEGEND_HTML = (
'<div class="lb-badge-legend">'
'<div class="legend-title">Legend</div>'
'<div class="legend-grid">'
'<span class="legend-item"><span class="b b-verified">βœ“ verified</span>'
'<span class="legend-desc">independently verified by VANTAGE-Bench team</span></span>'
'<span class="legend-item"><span class="b b-open">open</span>'
'<span class="legend-desc">open-weight model</span></span>'
'<span class="legend-item"><span class="b b-prop">prop.</span>'
'<span class="legend-desc">proprietary / closed model</span></span>'
'<span class="legend-item"><span class="b b-ensemble">system / pipeline</span>'
'<span class="legend-desc">system, pipeline, or orchestration of multiple models</span></span>'
'<span class="legend-item"><span class="b b-single">single</span>'
'<span class="legend-desc">single model result</span></span>'
'<span class="legend-item"><span class="b b-new">new</span>'
'<span class="legend-desc">added in the last 30 days</span></span>'
'</div>'
'</div>'
)
# ── Pillar tab intros (rendered above the filter row on pillar tabs only) ─
_PILLAR_INTRO_HTML: dict[str, str] = {
"spatial": (
'<div class="lb-pillar-desc">'
'Evaluates precise geometric grounding in dense, fixed-camera scenes, '
'measuring how well models localize, distinguish, and reason about '
'objects from elevated and oblique viewpoints.'
'</div>'
),
"st": (
'<div class="lb-pillar-desc">'
'Evaluates continuous object understanding over time, measuring '
'whether models can maintain identity and spatial awareness across '
'motion, occlusion, and scene changes.'
'</div>'
),
"temporal": (
'<div class="lb-pillar-desc">'
'Evaluates temporal reasoning in camera footage, measuring how well '
'models localize events and understand activity progression over time.'
'</div>'
),
"semantic": (
'<div class="lb-pillar-desc">'
'Evaluates high-level semantic understanding and operational reasoning, '
'measuring how well models interpret events, intent, and activity in '
'fixed-camera environments.'
'</div>'
),
}
# ── Below-table descriptions (rendered between table and legend) ──────────
# Overall gets a single explanatory paragraph; pillar tabs get a compact
# task-definition list.
_BELOW_TABLE_HTML: dict[str, str] = {
"overall": (
'<div class="lb-desc lb-desc-overall">'
'<p>Ranks all models by their mean score across four operational '
'pillars: Spatial, Spatio-Temporal, Temporal, and Semantic. Each '
'pillar score is computed as the average of its constituent tasks, '
'measuring overall Infrastructure AI capability. '
'Click any model row to view detailed model information and '
'per-task scores.</p>'
'</div>'
),
"spatial": (
'<div class="lb-desc lb-desc-tasks">'
'<dl>'
'<dt>2D Object Localization</dt>'
'<dd>Detect and localize instances of a given class.</dd>'
'<dt>2D Referring Expressions</dt>'
'<dd>Localize a target described in natural language.</dd>'
'<dt>2D Pointing</dt>'
'<dd>Select the correct 2D coordinate from multiple choices.</dd>'
'</dl>'
'</div>'
),
"st": (
'<div class="lb-desc lb-desc-tasks">'
'<dl>'
'<dt>Single Object Tracking</dt>'
'<dd>Track a target object consistently across multiple frames.</dd>'
'</dl>'
'</div>'
),
"temporal": (
'<div class="lb-desc lb-desc-tasks">'
'<dl>'
'<dt>Temporal Localization</dt>'
'<dd>Predict precise start and end timestamps of events.</dd>'
'<dt>Dense Video Captioning</dt>'
'<dd>Generate temporally grounded descriptions of chronological events.</dd>'
'</dl>'
'</div>'
),
"semantic": (
'<div class="lb-desc lb-desc-tasks">'
'<dl>'
'<dt>Event Verification</dt>'
'<dd>Verify whether operational or safety-critical events occurred.</dd>'
'<dt>Video QA</dt>'
'<dd>Answer multi-choice questions based on video evidence.</dd>'
'</dl>'
'</div>'
),
}
_TABLE_FOOTER_HTML = (
'<div class="lb-table-footer">'
'<span class="lb-footer-left">'
'<span class="lb-footer-nav">'
'<a href="https://vantage-bench.org/" target="_blank" rel="noopener">Website <span class="lb-nav-arrow">β†—</span></a>'
'<span class="lb-sep">|</span>'
'<a href="https://github.com/Clemson-Capstone/VANTAGE-Bench" target="_blank" rel="noopener">GitHub <span class="lb-nav-arrow">β†—</span></a>'
'<span class="lb-sep">|</span>'
'<a href="https://huggingface.co/datasets/nvidia/PhysicalAI-VANTAGE-Bench" target="_blank" rel="noopener">Dataset <span class="lb-nav-arrow">β†—</span></a>'
'</span>'
'<span class="lb-sep">|</span>'
'<span class="lb-version">v1.0</span>'
'</span>'
f'<span class="lb-updated">Last updated: {_UPDATED_DISPLAY}</span>'
'</div>'
)
_ABOUT_TASK_TABLE = """
<div style="margin-top:16px">
<p style="font-size:13px;font-weight:600;color:#111827;margin-bottom:8px">Task Taxonomy</p>
<table style="width:100%;font-size:12px;border-collapse:collapse;line-height:1.6;color:#6b7280">
<thead><tr>
<th style="text-align:left;padding:6px 10px;border-bottom:2px solid #e5e7eb;color:#374151;font-weight:600">Task</th>
<th style="text-align:left;padding:6px 10px;border-bottom:2px solid #e5e7eb;color:#374151;font-weight:600">Pillar</th>
<th style="text-align:left;padding:6px 10px;border-bottom:2px solid #e5e7eb;color:#374151;font-weight:600">Metric</th>
<th style="text-align:left;padding:6px 10px;border-bottom:2px solid #e5e7eb;color:#374151;font-weight:600">Description</th>
</tr></thead>
<tbody>
<tr>
<td style="padding:6px 10px;border-bottom:1px solid #f3f4f6;font-weight:500;color:#374151">Grounding</td>
<td style="padding:6px 10px;border-bottom:1px solid #f3f4f6">Spatial</td>
<td style="padding:6px 10px;border-bottom:1px solid #f3f4f6">mIoU</td>
<td style="padding:6px 10px;border-bottom:1px solid #f3f4f6">Referring expression comprehension β€” localize a target object by natural language</td>
</tr>
<tr>
<td style="padding:6px 10px;border-bottom:1px solid #f3f4f6;font-weight:500;color:#374151">Pointing</td>
<td style="padding:6px 10px;border-bottom:1px solid #f3f4f6">Spatial</td>
<td style="padding:6px 10px;border-bottom:1px solid #f3f4f6">Accuracy</td>
<td style="padding:6px 10px;border-bottom:1px solid #f3f4f6">2D spatial pointing from multiple-choice coordinate options</td>
</tr>
<tr>
<td style="padding:6px 10px;border-bottom:1px solid #f3f4f6;font-weight:500;color:#374151">Obj. Localization</td>
<td style="padding:6px 10px;border-bottom:1px solid #f3f4f6">Spatial</td>
<td style="padding:6px 10px;border-bottom:1px solid #f3f4f6">F1@0.5</td>
<td style="padding:6px 10px;border-bottom:1px solid #f3f4f6">Detect all instances of a class in a scene</td>
</tr>
<tr>
<td style="padding:6px 10px;border-bottom:1px solid #f3f4f6;font-weight:500;color:#374151">SOT</td>
<td style="padding:6px 10px;border-bottom:1px solid #f3f4f6">Spatio-Temporal</td>
<td style="padding:6px 10px;border-bottom:1px solid #f3f4f6">AUC</td>
<td style="padding:6px 10px;border-bottom:1px solid #f3f4f6">Single object tracking across frames via pure VLM inference</td>
</tr>
<tr>
<td style="padding:6px 10px;border-bottom:1px solid #f3f4f6;font-weight:500;color:#374151">Temp. Localization</td>
<td style="padding:6px 10px;border-bottom:1px solid #f3f4f6">Temporal</td>
<td style="padding:6px 10px;border-bottom:1px solid #f3f4f6">mIoU</td>
<td style="padding:6px 10px;border-bottom:1px solid #f3f4f6">Predict start/end timestamps for a natural language event query</td>
</tr>
<tr>
<td style="padding:6px 10px;border-bottom:1px solid #f3f4f6;font-weight:500;color:#374151">DVC</td>
<td style="padding:6px 10px;border-bottom:1px solid #f3f4f6">Temporal</td>
<td style="padding:6px 10px;border-bottom:1px solid #f3f4f6">SODAc</td>
<td style="padding:6px 10px;border-bottom:1px solid #f3f4f6">Autonomously localize and caption all events in a video</td>
</tr>
<tr>
<td style="padding:6px 10px;border-bottom:1px solid #f3f4f6;font-weight:500;color:#374151">Event Verification</td>
<td style="padding:6px 10px;border-bottom:1px solid #f3f4f6">Semantic</td>
<td style="padding:6px 10px;border-bottom:1px solid #f3f4f6">Macro F1</td>
<td style="padding:6px 10px;border-bottom:1px solid #f3f4f6">Verify a hypothesis about a video event as true or false</td>
</tr>
<tr>
<td style="padding:6px 10px;font-weight:500;color:#374151">VQA</td>
<td style="padding:6px 10px">Semantic</td>
<td style="padding:6px 10px">Accuracy</td>
<td style="padding:6px 10px">Multi-step logical reasoning over untrimmed infrastructure video</td>
</tr>
</tbody>
</table>
</div>
"""
# ---------------------------------------------------------------------------
# Resize JS β€” custom drag handle for each leaderboard table.
#
# Why JS: Gradio's Svelte `Dataframe` ships scoped CSS that constrains the
# real scroll viewport (`.table-wrap`). Browser-native `resize: vertical`
# on .table-wrap either gets clobbered by Gradio's own height/flex logic or
# resizes a decorative wrapper without growing the row area. So we attach a
# visible handle ourselves and write `.table-wrap.style.height` directly on
# pointer drag β€” the actual element that controls how many rows are visible.
#
# Scoped to `.lb-table` so About / side-panel tables are untouched. Survives
# Gradio re-renders (filter changes / tab switches) via a debounced
# MutationObserver that re-attaches the handle and re-applies the current
# height when the table is replaced or re-styled.
# ---------------------------------------------------------------------------
_RESIZE_JS = r"""
() => {
const MIN_H = 280;
const MAX_H = 1100;
const DEFAULT_H = 480;
function applyHeight(lbTable, h) {
// .table-wrap is the actual scroll viewport that controls row visibility.
lbTable.querySelectorAll('.table-wrap').forEach(function (wrap) {
wrap.style.height = h + 'px';
wrap.style.maxHeight = 'none';
wrap.style.minHeight = '0';
wrap.style.overflowY = 'auto';
wrap.style.overflowX = 'auto';
wrap.style.display = 'block';
wrap.style.boxSizing = 'border-box';
});
}
function getOrCreateHandle(lbTable) {
// Place the handle as a SIBLING right after .lb-table so Gradio's
// Svelte tree doesn't manage (and potentially reap) it.
var next = lbTable.nextElementSibling;
if (next && next.classList && next.classList.contains('lb-resize-handle')) {
return next;
}
var handle = document.createElement('div');
handle.className = 'lb-resize-handle';
handle.setAttribute('role', 'separator');
handle.setAttribute('aria-orientation', 'horizontal');
handle.setAttribute('aria-label', 'Resize leaderboard table');
handle.setAttribute('title', 'Drag to resize table');
lbTable.parentNode.insertBefore(handle, lbTable.nextSibling);
return handle;
}
function attach(lbTable) {
if (window.matchMedia('(max-width: 768px)').matches) return;
// Skip the Overall tab: it is a raw HTML table sized by content,
// not a Gradio Dataframe; it has no .table-wrap and needs no resize handle.
if (lbTable.classList.contains('lb-table-overall')) return;
var handle = getOrCreateHandle(lbTable);
var currentH = handle._lbHeight || DEFAULT_H;
handle._lbHeight = currentH;
applyHeight(lbTable, currentH);
if (handle._lbAttached) return;
handle._lbAttached = true;
var startY = 0;
var startH = 0;
var dragging = false;
function onMove(e) {
if (!dragging) return;
var clientY = (e.touches && e.touches[0]) ? e.touches[0].clientY : e.clientY;
var dy = clientY - startY;
var h = Math.max(MIN_H, Math.min(MAX_H, startH + dy));
handle._lbHeight = h;
applyHeight(lbTable, h);
}
function onUp() {
if (!dragging) return;
dragging = false;
document.body.style.cursor = '';
document.body.style.userSelect = '';
document.removeEventListener('mousemove', onMove);
document.removeEventListener('mouseup', onUp);
document.removeEventListener('touchmove', onMove);
document.removeEventListener('touchend', onUp);
}
function onDown(e) {
e.preventDefault();
dragging = true;
var clientY = (e.touches && e.touches[0]) ? e.touches[0].clientY : e.clientY;
startY = clientY;
startH = handle._lbHeight;
document.body.style.cursor = 'ns-resize';
document.body.style.userSelect = 'none';
document.addEventListener('mousemove', onMove);
document.addEventListener('mouseup', onUp);
document.addEventListener('touchmove', onMove, { passive: false });
document.addEventListener('touchend', onUp);
}
handle.addEventListener('mousedown', onDown);
handle.addEventListener('touchstart', onDown, { passive: false });
// Keyboard accessibility: ArrowUp/Down on focused handle.
handle.setAttribute('tabindex', '0');
handle.addEventListener('keydown', function (e) {
var step = e.shiftKey ? 40 : 16;
if (e.key === 'ArrowDown') {
handle._lbHeight = Math.min(MAX_H, handle._lbHeight + step);
applyHeight(lbTable, handle._lbHeight);
e.preventDefault();
} else if (e.key === 'ArrowUp') {
handle._lbHeight = Math.max(MIN_H, handle._lbHeight - step);
applyHeight(lbTable, handle._lbHeight);
e.preventDefault();
}
});
}
// Row-click bridge for the Overall HTML table.
// gr.HTML has no .select event, so we delegate <tr data-id> clicks to a
// hidden gr.Textbox (#lb-overall-selected-id) whose .change handler in
// Python opens the side panel. A timestamp suffix is appended so that
// repeat clicks on the same row still register as a value change.
function attachOverallClick() {
document.querySelectorAll('.lb-table-overall tbody').forEach(function (tbody) {
if (tbody._lbOverallClickAttached) return;
tbody._lbOverallClickAttached = true;
tbody.style.cursor = 'pointer';
tbody.addEventListener('click', function (ev) {
var tr = ev.target.closest('tr[data-id]');
if (!tr) return;
var modelId = tr.getAttribute('data-id');
if (!modelId) return;
var host = document.getElementById('lb-overall-selected-id');
if (!host) return;
var input = host.querySelector('input, textarea');
if (!input) return;
var proto = (input.tagName === 'TEXTAREA')
? window.HTMLTextAreaElement.prototype
: window.HTMLInputElement.prototype;
var nativeSetter = Object.getOwnPropertyDescriptor(proto, 'value').set;
nativeSetter.call(input, modelId + '|' + Date.now());
input.dispatchEvent(new Event('input', { bubbles: true }));
input.dispatchEvent(new Event('change', { bubbles: true }));
});
});
}
function scan() {
document.querySelectorAll('.lb-table').forEach(attach);
attachOverallClick();
}
scan();
// Settle pass after the initial Gradio render finishes.
setTimeout(scan, 300);
// Debounced re-scan: filter callbacks and tab switches mutate the DOM and
// may strip the inline height from .table-wrap; reapply on each frame.
var scheduled = false;
var obs = new MutationObserver(function () {
if (scheduled) return;
scheduled = true;
requestAnimationFrame(function () {
scheduled = false;
scan();
});
});
obs.observe(document.body, { childList: true, subtree: true });
}
"""
def _col_widths(headers: list[str]) -> list[str]:
out = []
for h in headers:
if h == "#":
out.append("48px")
elif h == "Name":
out.append("360px")
else:
out.append("90px")
return out
def build_demo() -> gr.Blocks:
with gr.Blocks(
title="VANTAGE-Bench Leaderboard",
analytics_enabled=False,
fill_width=True,
) as demo:
# ── Header ───────────────────────────────────────────────────────
gr.HTML(HEADER_HTML)
# ── Leaderboard tabs + static tabs ────────────────────────────────
# df_widgets[0] is a gr.HTML for the Overall tab (grouped header is
# rendered as raw HTML because gr.Dataframe does not support multi-
# level column headers). Indices 1-4 are gr.Dataframe for pillar tabs.
df_widgets: list = []
panel_html_widgets: list[gr.HTML] = []
panel_col_widgets: list[gr.Column] = []
close_btns: list[gr.Button] = []
# Hidden textbox that the JS row-click bridge writes the clicked
# model id into; its .change event opens the Overall-tab side panel.
overall_select_id: gr.Textbox | None = None
tab_filter_groups: list[list] = []
# ── Leaderboard tabs + static tabs ─────────────────────────────────
with gr.Tabs(elem_classes=["lb-top-tabs"]):
for pillar_key, tab_label, cls_suffix in _TAB_SPECS:
with gr.Tab(tab_label):
hdrs = headers_for_tab(pillar_key)
if pillar_key in _PILLAR_INTRO_HTML:
gr.HTML(
_PILLAR_INTRO_HTML[pillar_key],
elem_classes=["lb-pillar-desc-wrap"],
)
with gr.Row(elem_classes=["lb-filters"]):
with gr.Column(scale=2, min_width=200, elem_classes=["lb-filter-col"]):
gr.HTML('<span class="filter-lbl">Search</span>')
tab_search = gr.Textbox(
placeholder="Search by model name or organization…",
show_label=False, container=False,
elem_classes=["lb-search-box"],
)
with gr.Column(scale=1, min_width=120, elem_classes=["lb-filter-col"]):
gr.HTML('<span class="filter-lbl">Submission Type</span>')
tab_type_dd = gr.Dropdown(
choices=["All", "Single", "System / Pipeline"], value="All",
show_label=False, filterable=False,
interactive=True, container=False,
)
with gr.Column(scale=1, min_width=120, elem_classes=["lb-filter-col"]):
gr.HTML('<span class="filter-lbl">Access</span>')
tab_access_dd = gr.Dropdown(
choices=["All", "Open-weight", "Proprietary"], value="All",
show_label=False, filterable=False,
interactive=True, container=False,
)
with gr.Column(scale=1, min_width=120, elem_classes=["lb-filter-col"]):
gr.HTML('<span class="filter-lbl">Parameters</span>')
tab_params_dd = gr.Dropdown(
choices=_PARAMS_CHOICES, value="all",
show_label=False, filterable=False,
interactive=True, container=False,
)
with gr.Column(scale=0, min_width=110, elem_classes=["lb-filter-col", "lb-filter-verified"]):
tab_verified_cb = gr.Checkbox(
value=False, label="Verified only",
container=False,
elem_classes=["lb-verified-cb"],
)
tab_filter_groups.append([tab_search, tab_type_dd, tab_access_dd, tab_params_dd, tab_verified_cb])
with gr.Row(elem_classes=["lb-table-row"]):
with gr.Column():
if pillar_key == "overall":
# Hidden bridge: JS writes "{model_id}|{ts}"
# here on row click; .change fires the side-panel
# callback. See attachOverallClick() in _RESIZE_JS.
# NOTE: must be visible=True so Gradio renders the
# <input> into the DOM (visible=False is omitted
# entirely in Gradio 6.0); CSS in css.py hides
# the wrapper visually.
overall_select_id = gr.Textbox(
value="",
show_label=False,
container=False,
elem_id="lb-overall-selected-id",
elem_classes=["lb-overall-hidden-input"],
)
df = gr.HTML(
value=_INIT_OVERALL_HTML,
elem_classes=["lb-table", f"lb-table-{cls_suffix}"],
)
else:
df = gr.Dataframe(
value=_INIT_TABLES[pillar_key],
headers=hdrs,
datatype=datatypes_for_tab(pillar_key),
interactive=False,
wrap=False,
show_label=False,
elem_classes=["lb-table", f"lb-table-{cls_suffix}"],
)
df_widgets.append(df)
if pillar_key in _BELOW_TABLE_HTML:
gr.HTML(
_BELOW_TABLE_HTML[pillar_key],
elem_classes=["lb-desc-wrap"],
)
gr.HTML(_BADGE_LEGEND_HTML, elem_classes=["lb-legend-wrap"])
gr.HTML(_TABLE_FOOTER_HTML, elem_classes=["lb-footer-wrap"])
with gr.Column(
scale=0, min_width=280, visible=False,
elem_classes=["lb-side-panel"],
) as panel_col:
close_btn = gr.Button("βœ•", elem_classes=["sp-close-btn"])
panel_html = gr.HTML(
"", elem_classes=["lb-panel-content"],
)
panel_html_widgets.append(panel_html)
panel_col_widgets.append(panel_col)
close_btns.append(close_btn)
with gr.Tab("About"):
gr.Markdown(ABOUT_MD, elem_classes=["lb-about"])
# ── Status line ───────────────────────────────────────────────────
status_html = gr.HTML(_INIT_STATUS, elem_classes=["lb-status-wrap"])
# ── Wiring: filter controls β†’ tables + status + panels ────────────
outputs = (
df_widgets # 5 DataFrames
+ [status_html] # 1 status HTML
+ panel_html_widgets # 5 panel HTML strings
+ panel_col_widgets # 5 panel Column visibility
)
for group in tab_filter_groups:
for ctrl in group:
ctrl.change(
fn=on_filter_change,
inputs=group,
outputs=outputs,
)
# ── Row-click: open side panel ─────────────────────────────────────
# Pillar tabs (gr.Dataframe) use Gradio's built-in .select event.
# The Overall tab (gr.HTML) has no .select event, so it uses a JS-to-
# Gradio bridge: a hidden gr.Textbox receives the clicked row's
# data-id and its .change fires the same kind of side-panel update.
for df, ph, pc in zip(df_widgets, panel_html_widgets, panel_col_widgets):
if isinstance(df, gr.Dataframe):
df.select(
fn=_on_row_select,
inputs=[df],
outputs=[ph, pc],
)
if overall_select_id is not None:
overall_select_id.change(
fn=_on_overall_row_click_id,
inputs=[overall_select_id],
outputs=[panel_html_widgets[0], panel_col_widgets[0]],
)
# ── Close buttons: one per tab ──────────────────────────────────────
for close_btn, ph, pc in zip(close_btns, panel_html_widgets, panel_col_widgets):
close_btn.click(
fn=lambda: ("", gr.update(visible=False)),
outputs=[ph, pc],
)
return demo
demo = build_demo()
if __name__ == "__main__":
# NOTE: in Gradio 6.0 the `js` and `css` arguments live on launch(),
# not on Blocks(); passing them to Blocks silently no-ops.
# `js=` proved unreliable in 6.0, so the same code is also injected as
# a real <script> tag via `head=` for redundancy. The script self-
# invokes after DOMContentLoaded.
_head_script = (
"<script>"
"function __lb_boot(){ ("
+ _RESIZE_JS.strip()
+ ")(); }"
"if (document.readyState === 'loading') {"
" document.addEventListener('DOMContentLoaded', __lb_boot);"
"} else { __lb_boot(); }"
"</script>"
)
demo.launch(css=CSS, js=_RESIZE_JS, head=_head_script,
theme=gr.themes.Default())