| """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 |
|
|
| |
| |
| |
|
|
| 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) |
|
|
| |
| _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") |
|
|
| |
| _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>' |
|
|
|
|
|
|
| |
| |
| |
|
|
| 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> |
| """ |
|
|
| |
| |
| |
|
|
| |
| _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 |
| 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) |
|
|
| |
| 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()] |
|
|
| |
| |
| 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] |
|
|
| |
| 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] |
|
|
| |
| models = [m for m in models if _param_matches(m, params_bucket)] |
|
|
| |
| if verified_only: |
| models = [m for m in models if m.verified] |
|
|
| return models |
|
|
|
|
| |
| |
| |
|
|
| 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>' |
|
|
| |
| |
| table_outputs: tuple = (overall_html,) + tuple(tables[p] for p in _PILLAR_ORDER[1:]) |
| return table_outputs + (status,) + ("",) * 5 + (gr.update(visible=False),) * 5 |
|
|
|
|
| |
| |
| |
|
|
| _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.""" |
| |
| card_link = ( |
| f' <a href="{m.model_url}" target="_blank" class="sp-card-link">Model card β</a>' |
| if m.model_url else "" |
| ) |
|
|
| |
| 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>' |
| ) |
|
|
| |
| 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_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]) |
| |
| 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) |
|
|
|
|
| |
| |
| |
|
|
| |
| _PARAMS_CHOICES: list[tuple[str, str]] = [ |
| (label, key) for key, label in PARAM_BUCKETS.items() |
| ] |
| |
| _TAB_SPECS: list[tuple[str, str, str]] = [ |
| ("overall", "Overall", "overall"), |
| ("spatial", "Spatial", "spatial"), |
| ("st", "Spatio-Temporal", "st"), |
| ("temporal", "Temporal", "temporal"), |
| ("semantic", "Semantic", "semantic"), |
| ] |
|
|
| |
| _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_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_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 = 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: |
|
|
| |
| gr.HTML(HEADER_HTML) |
|
|
| |
| |
| |
| |
| df_widgets: list = [] |
| panel_html_widgets: list[gr.HTML] = [] |
| panel_col_widgets: list[gr.Column] = [] |
| close_btns: list[gr.Button] = [] |
| |
| |
| overall_select_id: gr.Textbox | None = None |
|
|
| tab_filter_groups: list[list] = [] |
|
|
| |
| 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": |
| |
| |
| |
| |
| |
| |
| |
| 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_html = gr.HTML(_INIT_STATUS, elem_classes=["lb-status-wrap"]) |
|
|
| |
| outputs = ( |
| df_widgets |
| + [status_html] |
| + panel_html_widgets |
| + panel_col_widgets |
| ) |
|
|
| for group in tab_filter_groups: |
| for ctrl in group: |
| ctrl.change( |
| fn=on_filter_change, |
| inputs=group, |
| outputs=outputs, |
| ) |
|
|
| |
| |
| |
| |
| |
| 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]], |
| ) |
|
|
| |
| 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__": |
| |
| |
| |
| |
| |
| _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()) |
|
|