| import json |
| import html |
| import os |
| import re |
| import urllib.error |
| import urllib.parse |
| import urllib.request |
| from pathlib import Path |
| from typing import Any |
|
|
| DEFAULT_SPACE_ID = "nvidia/AlpasimE2EClosedLoopChallenge2026" |
|
|
| if os.environ.get("SPACE_HOST"): |
| os.environ.setdefault("SYSTEM", "spaces") |
| os.environ.setdefault("SPACE_ID", DEFAULT_SPACE_ID) |
|
|
| import gradio as gr |
| from fastapi import FastAPI |
| from fastapi.responses import HTMLResponse |
| from fastapi.staticfiles import StaticFiles |
|
|
|
|
| API_BASE_URL = os.environ.get( |
| "ALPASIM_API_BASE_URL", |
| "", |
| ).rstrip("/") |
| REGISTRATION_SECRET = os.environ.get("ALPASIM_REGISTRATION_SECRET", "") |
| ACTIVE_REGISTRATION_STATUSES = {"pending", "approved", "registered"} |
| REVIEW_STATUS_CHOICES = ["pending", "approved", "rejected", "all"] |
| LEADERBOARD_HEADERS = [ |
| "Rank", |
| "Team", |
| "Team ID", |
| "Policy Capability Score", |
| "Avg Distance Between At-Fault Incidents", |
| "Image Tag", |
| "Submission ID", |
| "Submitted At", |
| ] |
| LEADERBOARD_SORT_CHOICES = LEADERBOARD_HEADERS |
| MOCKED_HF_USER_IDS = {"11111111111111111111111"} |
| NVIDIA_GREEN = "#76B900" |
| NVIDIA_GREEN_DARK = "#5F9500" |
| BANNER_PATH = "assets/auto-alpasim-end-to-end-closed-loop-driving-1600x400.mp4" |
| BANNER_DIR = Path(__file__).resolve().parent / "assets" |
| BANNER_FILE = Path(__file__).resolve().parent / BANNER_PATH |
| gr.set_static_paths(paths=[BANNER_DIR]) |
| APP_THEME = gr.themes.Default(primary_hue="lime").set( |
| button_primary_background_fill=NVIDIA_GREEN, |
| button_primary_background_fill_hover=NVIDIA_GREEN_DARK, |
| button_primary_text_color="white", |
| loader_color=NVIDIA_GREEN, |
| slider_color=NVIDIA_GREEN, |
| ) |
| BANNER_HTML = f""" |
| <div class="topline"> |
| <div class="brand">AlpaSim<span>.</span> E2E Closed Loop Challenge</div> |
| <div class="navlinks"> |
| <a href="#overview">Overview</a> |
| <a href="#tracks">Tracks</a> |
| <a href="#timeline">Timeline</a> |
| <a href="#prizes">Prizes</a> |
| <a href="#docs">Docs</a> |
| <a href="#organizers">Organizers</a> |
| <a href="#registration">Leaderboard</a> |
| </div> |
| </div> |
| <header class="alpasim-hero"> |
| <video autoplay muted loop playsinline preload="auto" aria-label="AlpaSim E2E Closed Loop Challenge 2026 banner"> |
| <source src="/{BANNER_PATH}" type="video/mp4" /> |
| </video> |
| <div class="hero-overlay"> |
| <div class="hero-overlay-inner"> |
| <div class="hero-eyebrow">2026 · NVIDIA AV Research · KE:SAI</div> |
| <h1 class="hero-title">AlpaSim E2E Closed Loop Challenge</h1> |
| <p class="hero-lead"> |
| A closed-loop benchmark for evaluating autonomous driving policies. |
| </p> |
| </div> |
| </div> |
| </header> |
| """ |
| CHALLENGE_OVERVIEW_HTML = """ |
| <main class="challenge-info"> |
| <section id="overview"> |
| <h2><span>01</span> Overview</h2> |
| <p class="lead"> |
| Welcome to the AlpaSim End to End Closed Loop Challenge. This competition |
| invites teams to build autonomous driving policies and compare them |
| head-to-head in realistic closed-loop simulation, where each policy's |
| decisions shape the future scene it must handle. |
| </p> |
| <p class="lead"> |
| Autonomous driving research has made major progress, but it remains hard |
| to compare policies across labs and companies in a realistic, reproducible |
| way. Open-loop evaluation is useful, but it misses the compounding effects |
| that make driving hard: a small planning error can change future |
| observations, interactions, and risk. |
| </p> |
| <p class="lead"> |
| AlpaSim provides a shared simulator, public development data, starter |
| tools, baseline policies, and a common containerized submission interface. |
| Organizer-managed evaluation workers run submissions on private held-out |
| scenarios and publish leaderboard results with both a policy capability |
| score and a safety metric. |
| </p> |
| <p class="lead"> |
| Across both tracks, the goal is not just to crown a winner. We want to |
| learn which policy families are robust under distribution shift, where |
| they fail, and how the community can make AV evaluation more trustworthy. |
| </p> |
| </section> |
| |
| <section id="tracks"> |
| <h2><span>02</span> Challenge Tracks</h2> |
| <p class="lead"> |
| The competition has two complementary tracks, covering both large-scale |
| geographically diverse driving data and a lower-barrier entry point for |
| teams working with established nuPlan-style workflows. |
| </p> |
| <div class="track-grid"> |
| <div class="info-card"> |
| <div class="pill">Track 1 - PAI-AV</div> |
| <h3>Physical AI AV Track</h3> |
| <p> |
| The larger-scale setting for testing whether promising policies hold |
| up as scenario diversity and long-tail coverage increase. |
| </p> |
| </div> |
| <div class="info-card"> |
| <div class="pill">Track 2 - nuPlan</div> |
| <h3>nuPlan Track</h3> |
| <p> |
| A lower-barrier track for teams building on the widely used nuPlan |
| ecosystem or NAVSIM-style development workflows. |
| </p> |
| </div> |
| </div> |
| </section> |
| |
| <section id="timeline"> |
| <h2><span>03</span> Timeline</h2> |
| <ol class="timeline"> |
| <li> |
| <span class="date">2026-06-15</span> |
| <b>Competition goes live</b> |
| <span class="desc">Registration, public data, starter tools, and submission instructions open.</span> |
| </li> |
| <li> |
| <span class="date">2026-08-15</span> |
| <b>Mid-competition checkpoint</b> |
| <span class="desc">FAQ updates, leaderboard-health notes, and non-breaking clarifications.</span> |
| </li> |
| <li> |
| <span class="date">2026-09-15</span> |
| <b>Rules and submission format freeze</b> |
| <span class="desc">Final rules, metric implementation, Docker base image, and public submission format freeze except for critical fixes.</span> |
| </li> |
| <li> |
| <span class="date">2026-10-31</span> |
| <b>Public leaderboard closes</b> |
| <span class="desc">Teams select one final valid container per track. Technical reports are due.</span> |
| </li> |
| <li> |
| <span class="date">2026-11-15</span> |
| <b>Final results released</b> |
| <span class="desc">Final results and award decisions are released to participants.</span> |
| </li> |
| <li> |
| <span class="date">NeurIPS 2026</span> |
| <b>Competition track workshop</b> |
| <span class="desc">Winners and selected participants present results; organizers share final analysis and lessons learned.</span> |
| </li> |
| </ol> |
| </section> |
| |
| <section id="prizes"> |
| <h2><span>04</span> Prizes</h2> |
| <p class="lead"> |
| Each track will award two NVIDIA DGX Spark prizes: one for first place and one |
| for an innovative solution. |
| </p> |
| <div class="prize-grid"> |
| <div class="prize"> |
| <div class="icon">DGX</div> |
| <div> |
| <h3>PAI-AV Track</h3> |
| <p>Two NVIDIA DGX Spark prizes awarded.</p> |
| </div> |
| </div> |
| <div class="prize"> |
| <div class="icon">DGX</div> |
| <div> |
| <h3>nuPlan Track</h3> |
| <p>Two NVIDIA DGX Spark prizes awarded.</p> |
| </div> |
| </div> |
| </div> |
| </section> |
| |
| <section id="docs"> |
| <h2><span>05</span> Documentation Links</h2> |
| <div class="track-grid"> |
| <a class="info-card doc-card" href="https://github.com/NVlabs/alpasim/blob/e2e_challenge/e2e_challenge/README.md" target="_blank" rel="noopener noreferrer"> |
| <div class="pill">Guide</div> |
| <h3>Contestant Guide</h3> |
| <p>Challenge setup, tracks, scoring, and participant workflow.</p> |
| </a> |
| <a class="info-card doc-card" href="https://github.com/NVlabs/alpasim/blob/e2e_challenge/e2e_challenge/starter_kit/README.md" target="_blank" rel="noopener noreferrer"> |
| <div class="pill">Kit</div> |
| <h3>Starter Kit</h3> |
| <p>Baseline files and examples for building an initial submission.</p> |
| </a> |
| <a class="info-card doc-card" href="https://github.com/NVlabs/alpasim/tree/e2e_challenge/e2e_challenge/competitor_cli" target="_blank" rel="noopener noreferrer"> |
| <div class="pill">CLI</div> |
| <h3>Submission CLI</h3> |
| <p>Command-line tooling for packaging, validating, and submitting entries.</p> |
| </a> |
| <a class="info-card doc-card" href="https://github.com/NVlabs/alpasim/blob/e2e_challenge/e2e_challenge/README.md#submission-image-requirements-and-constraints" target="_blank" rel="noopener noreferrer"> |
| <div class="pill">Requirements</div> |
| <h3>Submission Image Requirements</h3> |
| <p>Container image constraints and requirements for valid submissions.</p> |
| </a> |
| </div> |
| </section> |
| |
| <section id="organizers"> |
| <h2><span>06</span> Organizers</h2> |
| <p class="lead"> |
| This competition is hosted by NVIDIA's Autonomous Vehicle Research Group and KE:SAI. |
| </p> |
| <div class="track-grid"> |
| <a class="info-card organizer-card" href="https://research.nvidia.com/labs/avg/" target="_blank" rel="noopener noreferrer"> |
| <div class="pill">Host</div> |
| <h3>NVIDIA Autonomous Vehicle Research Group</h3> |
| <p>Interdisciplinary NVIDIA Research team advancing vehicle autonomy across perception, prediction, planning, control, simulation, foundation models, and AI safety.</p> |
| </a> |
| <a class="info-card organizer-card" href="https://kesai.eu/" target="_blank" rel="noopener noreferrer"> |
| <div class="pill">Host</div> |
| <h3>KE:SAI</h3> |
| <p>Non-profit open-science research lab advancing robust, safe, and reproducible physical AI, with a focus on world models, autonomy, and open self-driving technology.</p> |
| </a> |
| </div> |
| </section> |
| </main> |
| """ |
| APP_EMBED_HTML = """ |
| <section id="registration" class="challenge-app"> |
| <h2><span>07</span> Leaderboard</h2> |
| <iframe |
| class="gradio-frame" |
| src="/gradio/" |
| title="AlpaSim leaderboard, registration, and review app" |
| ></iframe> |
| </section> |
| """ |
| BANNER_CSS = """ |
| html { |
| scroll-behavior: smooth; |
| } |
| |
| body { |
| margin: 0; |
| background: var(--bg); |
| color: var(--text); |
| font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; |
| } |
| |
| :root, |
| .gradio-container { |
| --bg: #ffffff; |
| --panel: #f8f9fb; |
| --panel-2: #f1f3f7; |
| --border: #e4e7ec; |
| --text: #1a1d23; |
| --muted: #6b7280; |
| --button-primary-background-fill: #76B900; |
| --button-primary-background-fill-hover: #5F9500; |
| --button-primary-border-color: #76B900; |
| --button-primary-text-color: white; |
| --color-accent: #76B900; |
| --link-text-color: #1f6feb; |
| --loader-color: #76B900; |
| --slider-color: #76B900; |
| color: var(--text); |
| } |
| |
| .gradio-container { |
| background: var(--bg); |
| max-width: none !important; |
| padding-top: 0 !important; |
| } |
| |
| .contain { |
| max-width: none !important; |
| } |
| |
| .topline { |
| position: sticky; |
| top: 0; |
| z-index: 50; |
| display: flex; |
| align-items: center; |
| justify-content: space-between; |
| gap: 20px; |
| padding: 12px 24px; |
| margin: 0; |
| background: rgba(255, 255, 255, 0.92); |
| backdrop-filter: blur(8px); |
| border-bottom: 1px solid var(--border); |
| } |
| |
| .brand { |
| font-weight: 700; |
| letter-spacing: 0.3px; |
| } |
| |
| .brand span { |
| color: #76B900; |
| } |
| |
| .navlinks { |
| display: flex; |
| gap: 18px; |
| flex-wrap: wrap; |
| } |
| |
| .navlinks a { |
| color: var(--muted); |
| text-decoration: none; |
| } |
| |
| .navlinks a:hover { |
| color: var(--text); |
| text-decoration: none; |
| } |
| |
| .alpasim-hero { |
| position: relative; |
| overflow: hidden; |
| margin: 0; |
| background: #000000; |
| border-bottom: 1px solid var(--border); |
| } |
| |
| .alpasim-hero video { |
| display: block; |
| width: 100%; |
| height: auto; |
| } |
| |
| .hero-overlay { |
| position: absolute; |
| inset: 0; |
| display: flex; |
| align-items: flex-end; |
| background: linear-gradient(180deg, rgba(0, 0, 0, 0.10) 0%, rgba(0, 0, 0, 0.55) 100%); |
| pointer-events: none; |
| } |
| |
| .hero-overlay-inner { |
| width: 100%; |
| max-width: 1100px; |
| margin: 0 auto; |
| padding: 40px 24px; |
| color: #ffffff; |
| } |
| |
| .hero-eyebrow { |
| color: #d6f3a3; |
| font-size: 0.85em; |
| font-weight: 600; |
| letter-spacing: 0.14em; |
| text-transform: uppercase; |
| } |
| |
| .hero-title { |
| margin: 8px 0 10px; |
| color: #ffffff; |
| font-size: clamp(28px, 4vw, 46px); |
| line-height: 1.1; |
| } |
| |
| .hero-lead { |
| max-width: 760px; |
| margin: 0; |
| color: #e7eaef; |
| font-size: 1.05em; |
| } |
| |
| .challenge-info { |
| max-width: 1100px; |
| margin: 0 auto; |
| padding: 0 24px; |
| } |
| |
| .challenge-info section { |
| padding: 48px 0; |
| border-bottom: 1px solid var(--border); |
| scroll-margin-top: 72px; |
| } |
| |
| .challenge-info section:last-child { |
| border-bottom: 0; |
| } |
| |
| .challenge-info h2 { |
| display: flex; |
| align-items: baseline; |
| gap: 12px; |
| margin: 0 0 10px; |
| font-size: 28px; |
| line-height: 1.2; |
| color: var(--text); |
| } |
| |
| .challenge-info h2 span { |
| color: #76B900; |
| font-family: ui-monospace, SFMono-Regular, Menlo, monospace; |
| font-size: 0.7em; |
| letter-spacing: 0.08em; |
| } |
| |
| .challenge-info .lead, |
| .info-card p, |
| .prize p { |
| color: #3c4250; |
| line-height: 1.6; |
| } |
| |
| .challenge-info .lead { |
| max-width: 860px; |
| margin: 0 0 14px; |
| } |
| |
| .track-grid, |
| .prize-grid { |
| display: grid; |
| grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); |
| gap: 18px; |
| margin-top: 18px; |
| } |
| |
| .info-card { |
| background: var(--panel); |
| border: 1px solid var(--border); |
| border-radius: 10px; |
| padding: 22px; |
| } |
| |
| .info-card h3, |
| .prize h3 { |
| margin: 0 0 8px; |
| font-size: 18px; |
| color: var(--text); |
| } |
| |
| .info-card p, |
| .prize p { |
| margin: 0; |
| } |
| |
| .organizer-card, |
| .doc-card { |
| display: block; |
| color: inherit; |
| text-decoration: none; |
| } |
| |
| .organizer-card:hover, |
| .doc-card:hover { |
| border-color: rgba(118, 185, 0, 0.45); |
| text-decoration: none; |
| } |
| |
| .pill { |
| display: inline-block; |
| margin-bottom: 10px; |
| padding: 3px 9px; |
| border-radius: 999px; |
| background: rgba(118, 185, 0, 0.15); |
| color: #5F9500; |
| border: 1px solid rgba(118, 185, 0, 0.3); |
| font-size: 0.78em; |
| letter-spacing: 0.04em; |
| } |
| |
| .timeline { |
| list-style: none; |
| padding: 0; |
| margin: 18px 0 0; |
| } |
| |
| .timeline li { |
| position: relative; |
| padding: 12px 14px 12px 38px; |
| border-left: 2px solid var(--border); |
| margin-left: 8px; |
| } |
| |
| .timeline li::before { |
| content: ""; |
| position: absolute; |
| left: -7px; |
| top: 18px; |
| width: 12px; |
| height: 12px; |
| border-radius: 50%; |
| background: #76B900; |
| } |
| |
| .timeline .date { |
| color: #5F9500; |
| font-family: ui-monospace, SFMono-Regular, Menlo, monospace; |
| font-size: 0.85em; |
| letter-spacing: 0.03em; |
| } |
| |
| .timeline b, |
| .timeline .desc { |
| display: block; |
| } |
| |
| .timeline .desc { |
| color: var(--muted); |
| font-size: 0.92em; |
| } |
| |
| .prize { |
| display: flex; |
| align-items: center; |
| gap: 18px; |
| padding: 24px; |
| background: linear-gradient(135deg, rgba(118, 185, 0, 0.10), rgba(118, 185, 0, 0.04)); |
| border: 1px solid rgba(118, 185, 0, 0.35); |
| border-radius: 12px; |
| } |
| |
| .prize .icon { |
| width: 64px; |
| height: 64px; |
| flex: 0 0 64px; |
| display: flex; |
| align-items: center; |
| justify-content: center; |
| border-radius: 14px; |
| background: #76B900; |
| color: #ffffff; |
| font-weight: 700; |
| } |
| |
| .identity-strip { |
| max-width: 1100px; |
| margin: 0 auto; |
| padding: 0 24px 18px; |
| } |
| |
| .identity-strip p { |
| margin: 0; |
| color: var(--muted); |
| } |
| |
| .tabs { |
| max-width: 1100px; |
| margin: 0 auto; |
| } |
| |
| .challenge-app { |
| max-width: 1100px; |
| margin: 0 auto; |
| padding: 48px 24px 72px; |
| scroll-margin-top: 72px; |
| } |
| |
| .challenge-app h2 { |
| display: flex; |
| align-items: baseline; |
| gap: 12px; |
| margin: 0 0 18px; |
| font-size: 28px; |
| } |
| |
| .challenge-app h2 span { |
| color: #76B900; |
| font-family: ui-monospace, SFMono-Regular, Menlo, monospace; |
| font-size: 0.7em; |
| letter-spacing: 0.08em; |
| } |
| |
| .gradio-frame { |
| display: block; |
| width: 100%; |
| min-height: 940px; |
| border: 1px solid var(--border); |
| border-radius: 8px; |
| background: #ffffff; |
| } |
| |
| @media (max-width: 720px) { |
| .topline { |
| align-items: flex-start; |
| flex-direction: column; |
| gap: 8px; |
| } |
| |
| .navlinks { |
| gap: 12px; |
| } |
| |
| .hero-overlay-inner { |
| padding: 12px 18px; |
| } |
| |
| .hero-eyebrow { |
| font-size: 0.62em; |
| letter-spacing: 0.08em; |
| } |
| |
| .hero-title { |
| margin: 4px 0 0; |
| font-size: clamp(16px, 5vw, 22px); |
| line-height: 1.05; |
| } |
| |
| .hero-lead { |
| display: none; |
| } |
| |
| .challenge-info { |
| padding: 0 18px; |
| } |
| |
| .challenge-info section, |
| .challenge-app { |
| scroll-margin-top: 112px; |
| } |
| |
| .challenge-app { |
| padding: 48px 18px 64px; |
| } |
| |
| .gradio-frame { |
| min-height: 1040px; |
| } |
| |
| .identity-strip { |
| padding: 0 18px 18px; |
| } |
| } |
| """ |
| GRADIO_CSS = """ |
| :root, |
| .gradio-container { |
| --bg: #ffffff; |
| --panel: #f8f9fb; |
| --panel-2: #f1f3f7; |
| --border: #e4e7ec; |
| --text: #1a1d23; |
| --muted: #6b7280; |
| --button-primary-background-fill: #76B900; |
| --button-primary-background-fill-hover: #5F9500; |
| --button-primary-border-color: #76B900; |
| --button-primary-text-color: white; |
| --color-accent: #76B900; |
| --link-text-color: #1f6feb; |
| --loader-color: #76B900; |
| --slider-color: #76B900; |
| color: var(--text); |
| } |
| |
| .gradio-container { |
| background: var(--bg); |
| max-width: none !important; |
| padding-top: 0 !important; |
| } |
| |
| .identity-strip { |
| max-width: 1100px; |
| margin: 0 auto; |
| padding: 0 24px 18px; |
| } |
| |
| .identity-strip p { |
| margin: 0; |
| color: var(--muted); |
| } |
| |
| .tabs { |
| max-width: 1100px; |
| margin: 0 auto; |
| } |
| |
| .leaderboard-controls { |
| margin: 0 0 14px; |
| max-width: 560px; |
| } |
| |
| .leaderboard-controls .form { |
| border: 1px solid var(--border); |
| border-radius: 8px; |
| background: #fbfcfd; |
| padding: 12px; |
| } |
| |
| .leaderboard-controls button { |
| width: 100%; |
| } |
| |
| .leaderboard-table-wrap { |
| width: 100%; |
| overflow-x: auto; |
| border: 1px solid var(--border); |
| border-radius: 8px; |
| background: #ffffff; |
| } |
| |
| .leaderboard-table { |
| width: 100%; |
| border-collapse: collapse; |
| table-layout: fixed; |
| font-size: 12px; |
| } |
| |
| .leaderboard-table th, |
| .leaderboard-table td { |
| padding: 10px 12px; |
| border-bottom: 1px solid #edf0f4; |
| vertical-align: top; |
| color: var(--text); |
| } |
| |
| .leaderboard-table th { |
| position: sticky; |
| top: 0; |
| z-index: 1; |
| background: #f7f9fb; |
| color: #3c4250; |
| font-size: 12px; |
| font-weight: 700; |
| text-align: left; |
| white-space: normal; |
| } |
| |
| .leaderboard-table td { |
| overflow-wrap: anywhere; |
| line-height: 1.35; |
| } |
| |
| .leaderboard-table tbody tr:nth-child(even) { |
| background: #fafbfc; |
| } |
| |
| .leaderboard-table tbody tr:hover { |
| background: #f3f8ea; |
| } |
| |
| .leaderboard-table .rank { |
| width: 6%; |
| } |
| |
| .leaderboard-table .team { |
| width: 18%; |
| } |
| |
| .leaderboard-table .score { |
| width: 14%; |
| } |
| |
| .leaderboard-table .incident-distance { |
| width: 21%; |
| } |
| |
| .leaderboard-table .image-tag { |
| width: 25%; |
| } |
| |
| .leaderboard-table .submitted-at { |
| width: 15%; |
| } |
| |
| .leaderboard-table .number { |
| text-align: right; |
| font-variant-numeric: tabular-nums; |
| } |
| |
| .leaderboard-main, |
| .leaderboard-sub { |
| display: block; |
| } |
| |
| .leaderboard-sub { |
| margin-top: 3px; |
| color: var(--muted); |
| font-size: 11px; |
| line-height: 1.25; |
| } |
| |
| .leaderboard-empty { |
| padding: 24px; |
| color: var(--muted); |
| } |
| |
| @media (max-width: 720px) { |
| .identity-strip { |
| padding: 0 18px 18px; |
| } |
| |
| .leaderboard-controls { |
| max-width: none; |
| } |
| } |
| """ |
| LANDING_HTML = f"""<!doctype html> |
| <html lang="en"> |
| <head> |
| <meta charset="utf-8" /> |
| <meta name="viewport" content="width=device-width, initial-scale=1" /> |
| <title>AlpaSim E2E Closed Loop Challenge 2026</title> |
| <style>{BANNER_CSS}</style> |
| </head> |
| <body> |
| {BANNER_HTML} |
| {CHALLENGE_OVERVIEW_HTML} |
| {APP_EMBED_HTML} |
| </body> |
| </html> |
| """ |
|
|
|
|
| def split_multivalue(value: str) -> list[str]: |
| items: list[str] = [] |
| seen: set[str] = set() |
| for item in re.split(r"[\n,]", value or ""): |
| cleaned = item.strip() |
| if not cleaned or cleaned in seen: |
| continue |
| items.append(cleaned) |
| seen.add(cleaned) |
| return items |
|
|
|
|
| def profile_value(profile: gr.OAuthProfile, *keys: str) -> str: |
| for key in keys: |
| value = profile.get(key) |
| if value: |
| text = str(value) |
| if key == "sub" and text in MOCKED_HF_USER_IDS: |
| return "" |
| return text |
| return "" |
|
|
|
|
| def current_identity(profile: gr.OAuthProfile | None) -> str: |
| if profile is None: |
| return ( |
| "To register a team, connect this Space to your Hugging Face account. " |
| "If you are already signed in on huggingface.co, this just authorizes " |
| "the Space to read your Hugging Face profile. " |
| "[Connect Hugging Face account](/login/huggingface?_target_url=/gradio/)" |
| ) |
|
|
| username = profile_value(profile, "preferred_username", "name") |
| user_id = profile_value(profile, "sub") |
| email = profile_value(profile, "email") |
| parts = [f"Connected to this Space as Hugging Face user `{username}`."] |
| if user_id: |
| parts.append(f"Stable HF user ID: `{user_id}`.") |
| if email: |
| parts.append(f"HF email: `{email}`.") |
| parts.append("[Disconnect](/logout?_target_url=/gradio/).") |
| return " ".join(parts) |
|
|
|
|
| def empty_review_state() -> tuple[list[list[str]], list[dict[str, Any]], object, str, str]: |
| return ( |
| [], |
| [], |
| gr.update(choices=[], value=None), |
| "No registration selected.", |
| "", |
| ) |
|
|
|
|
| def load_initial_review_state( |
| profile: gr.OAuthProfile | None, |
| ) -> tuple[object, list[list[str]], list[dict[str, Any]], object, str, str]: |
| if profile is None or not REGISTRATION_SECRET: |
| rows, registrations, selected, details, result = empty_review_state() |
| return gr.update(visible=False), rows, registrations, selected, details, result |
| try: |
| body = review_api_json( |
| "GET", |
| "/review/registrations", |
| profile, |
| query={"status": "pending"}, |
| ) |
| except (urllib.error.HTTPError, urllib.error.URLError, gr.Error): |
| rows, registrations, selected, details, result = empty_review_state() |
| return gr.update(visible=False), rows, registrations, selected, details, result |
|
|
| registrations = body.get("registrations") or [] |
| choices = registration_choices(registrations) |
| selected = choices[0] if choices else None |
| item = find_registration(registrations, selected_team_id(selected)) |
| result = f"Loaded {body.get('count', len(registrations))} pending registration(s)." |
| return ( |
| gr.update(visible=True), |
| registration_rows(registrations), |
| registrations, |
| gr.update(choices=choices, value=selected), |
| review_details(item), |
| result, |
| ) |
|
|
|
|
| def session_state( |
| profile: gr.OAuthProfile | None, |
| ) -> tuple[ |
| str, |
| object, |
| list[list[str]], |
| list[dict[str, Any]], |
| object, |
| str, |
| str, |
| ]: |
| review_state = load_initial_review_state(profile) |
| return (current_identity(profile), *review_state) |
|
|
|
|
| def api_json(method: str, path: str, payload: dict | None = None) -> dict: |
| if not API_BASE_URL: |
| raise gr.Error("Space is missing ALPASIM_API_BASE_URL.") |
| data = None if payload is None else json.dumps(payload).encode("utf-8") |
| request = urllib.request.Request( |
| f"{API_BASE_URL}{path}", |
| data=data, |
| method=method, |
| headers={ |
| "Content-Type": "application/json", |
| "Accept": "application/json", |
| "X-AlpaSim-Registration-Secret": REGISTRATION_SECRET, |
| }, |
| ) |
| with urllib.request.urlopen(request, timeout=15) as response: |
| return json.loads(response.read().decode("utf-8")) |
|
|
|
|
| def api_error_summary(action: str, exc: Exception) -> str: |
| if isinstance(exc, urllib.error.HTTPError): |
| details = exc.read().decode("utf-8", errors="replace") |
| return f"{action} failed with HTTP {exc.code}. {details}".strip() |
| if isinstance(exc, urllib.error.URLError): |
| return f"{action} failed: {exc.reason}" |
| return f"{action} failed: {exc}" |
|
|
|
|
| def has_active_registered_team(user: dict[str, Any] | None) -> bool: |
| if not user: |
| return False |
|
|
| team_id = str(user.get("team_id") or "") |
| status = str(user.get("registration_status") or "").strip().lower() |
| return bool(team_id) and status != "disabled" |
|
|
|
|
| def registered_team_status_detail( |
| profile: gr.OAuthProfile | None, |
| ) -> tuple[str, str, bool]: |
| if profile is None: |
| return "Sign in with Hugging Face to view team access.", "", False |
| if not REGISTRATION_SECRET: |
| return "Registration Space is missing ALPASIM_REGISTRATION_SECRET.", "", False |
|
|
| hf_user_id = profile_value(profile, "sub") |
| hf_username = profile_value(profile, "preferred_username", "name") |
| if not hf_user_id or not hf_username: |
| return "Could not read your Hugging Face identity.", "", False |
|
|
| query = urllib.parse.urlencode( |
| { |
| "hf_user_id": hf_user_id, |
| "hf_username": hf_username, |
| } |
| ) |
| try: |
| body = api_json("GET", f"/registrations/submitter-invitations?{query}") |
| except urllib.error.HTTPError as exc: |
| details = exc.read().decode("utf-8", errors="replace") |
| return f"Could not load team access status. HTTP {exc.code}.", details, False |
| except urllib.error.URLError as exc: |
| return f"Could not load team access status: {exc.reason}", "", False |
|
|
| registered_user = body.get("registered_user") |
| if not has_active_registered_team(registered_user): |
| return ( |
| "No approved team access found for your Hugging Face account.", |
| json.dumps(body, indent=2), |
| False, |
| ) |
|
|
| team_id = registered_user.get("team_id") |
| role = registered_user.get("role") or "member" |
| status = registered_user.get("registration_status") or "unknown" |
| return ( |
| f"You already have `{status}` access to team `{team_id}` as `{role}`.", |
| json.dumps(body, indent=2), |
| True, |
| ) |
|
|
|
|
| def registration_status_detail(profile: gr.OAuthProfile | None) -> tuple[str, str, bool]: |
| if profile is None: |
| return "Sign in with Hugging Face to view registration status.", "", False |
| if not REGISTRATION_SECRET: |
| return "Registration Space is missing ALPASIM_REGISTRATION_SECRET.", "", False |
|
|
| captain_hf_user_id = profile_value(profile, "sub") |
| if not captain_hf_user_id: |
| return "Could not read your stable Hugging Face user ID.", "", False |
|
|
| query = urllib.parse.urlencode({"captain_hf_user_id": captain_hf_user_id}) |
| try: |
| body = api_json("GET", f"/registrations/me?{query}") |
| except urllib.error.HTTPError as exc: |
| details = exc.read().decode("utf-8", errors="replace") |
| return f"Could not load registration status. HTTP {exc.code}.", details, False |
| except urllib.error.URLError as exc: |
| return f"Could not load registration status: {exc.reason}", "", False |
|
|
| registrations = body.get("registrations") or [] |
| if not registrations: |
| return ( |
| "No team registration found for your Hugging Face account.", |
| json.dumps(body, indent=2), |
| False, |
| ) |
|
|
| latest = registrations[0] |
| status = str(latest.get("registration_status") or "unknown").strip().lower() |
| team = latest.get("team_id") or "" |
| display_name = latest.get("team_display_name") or team |
| if status == "pending": |
| summary = f"Registration pending review: {display_name} ({team})." |
| elif status == "approved": |
| summary = f"Team approved: {display_name} ({team})." |
| elif status == "registered": |
| summary = f"Team registered: {display_name} ({team})." |
| elif status == "rejected": |
| reason = latest.get("rejection_reason") or "No reason provided." |
| summary = f"Registration rejected: {display_name} ({team}). Reason: {reason}" |
| else: |
| summary = f"Registration status for {display_name} ({team}): {status}." |
|
|
| return summary, json.dumps(body, indent=2), status in ACTIVE_REGISTRATION_STATUSES |
|
|
|
|
| def registration_panel_status(profile: gr.OAuthProfile | None): |
| summary, raw_json, has_active_registration = registration_status_detail(profile) |
| needs_connection = profile is None |
| if not needs_connection and not has_active_registration: |
| member_summary, member_raw_json, has_active_team = registered_team_status_detail( |
| profile |
| ) |
| if has_active_team: |
| summary = member_summary |
| raw_json = member_raw_json |
| has_active_registration = True |
|
|
| return ( |
| summary, |
| raw_json, |
| gr.update(visible=not needs_connection and not has_active_registration), |
| ) |
|
|
|
|
| def submitter_invitation_status( |
| profile: gr.OAuthProfile | None, |
| ) -> tuple[str, list[dict[str, Any]], object, object]: |
| if profile is None: |
| return ( |
| "Connect your Hugging Face account to check submitter invitations.", |
| [], |
| gr.update(choices=[], value=None), |
| gr.update(visible=False), |
| ) |
| if not REGISTRATION_SECRET: |
| return ( |
| "Registration Space is missing ALPASIM_REGISTRATION_SECRET.", |
| [], |
| gr.update(choices=[], value=None), |
| gr.update(visible=False), |
| ) |
|
|
| hf_user_id = profile_value(profile, "sub") |
| hf_username = profile_value(profile, "preferred_username", "name") |
| if not hf_user_id or not hf_username: |
| return ( |
| "Could not read your Hugging Face identity.", |
| [], |
| gr.update(choices=[], value=None), |
| gr.update(visible=False), |
| ) |
|
|
| query = urllib.parse.urlencode( |
| { |
| "hf_user_id": hf_user_id, |
| "hf_username": hf_username, |
| } |
| ) |
| try: |
| body = api_json("GET", f"/registrations/submitter-invitations?{query}") |
| except (urllib.error.HTTPError, urllib.error.URLError) as exc: |
| return api_error_summary("Loading submitter invitations", exc), [], gr.update(choices=[], value=None), gr.update(visible=False) |
|
|
| registered_user = body.get("registered_user") or {} |
| invitations = body.get("invitations") or [] |
| choices = registration_choices(invitations) |
|
|
| if invitations: |
| summary = ( |
| f"You are listed as an approved submitter for {len(invitations)} team(s). " |
| "Select a team and join it to enable challenge CLI, ECR login, and submissions." |
| ) |
| elif has_active_registered_team(registered_user): |
| summary = "" |
| else: |
| summary = "No approved submitter invitations found for your Hugging Face username." |
|
|
| return ( |
| summary, |
| invitations, |
| gr.update(choices=choices, value=choices[0] if choices else None), |
| gr.update(visible=bool(choices)), |
| ) |
|
|
|
|
| def claim_submitter_invitation( |
| choice: str, |
| profile: gr.OAuthProfile | None, |
| ) -> str: |
| if profile is None: |
| raise gr.Error("Connect your Hugging Face account first.") |
|
|
| team_id = selected_team_id(choice) |
| if not team_id: |
| raise gr.Error("Select a team invitation first.") |
|
|
| payload = { |
| "team_id": team_id, |
| "hf_user_id": profile_value(profile, "sub"), |
| "hf_username": profile_value(profile, "preferred_username", "name"), |
| "email": profile_value(profile, "email"), |
| } |
| try: |
| body = api_json("POST", "/registrations/claim-submitter", payload) |
| except (urllib.error.HTTPError, urllib.error.URLError) as exc: |
| raise gr.Error(api_error_summary(f"Joining {team_id}", exc)) from exc |
|
|
| return str(body.get("message") or f"Joined {team_id}.") |
|
|
|
|
| def leaderboard_html(rows: list[list[Any]]) -> str: |
| if not rows: |
| return '<div class="leaderboard-table-wrap"><div class="leaderboard-empty">No successful submissions yet.</div></div>' |
|
|
| visible_headers = [ |
| "Rank", |
| "Team", |
| "Policy Capability Score", |
| "Avg Distance Between At-Fault Incidents", |
| "Image Tag / Submission ID", |
| "Submitted At", |
| ] |
| column_classes = [ |
| "rank number", |
| "team", |
| "score number", |
| "incident-distance number", |
| "image-tag", |
| "submitted-at", |
| ] |
| header_cells = "".join( |
| f'<th class="{css_class}">{html.escape(header)}</th>' |
| for header, css_class in zip(visible_headers, column_classes) |
| ) |
| body_rows = [] |
| for row in rows: |
| rank, team, team_id, score, incident_distance, image_tag, submission_id, submitted_at = row |
|
|
| def escaped_text(value: Any) -> str: |
| return html.escape("" if value is None else str(value)) |
|
|
| team_title = html.escape( |
| " / ".join(str(value) for value in (team, team_id) if value not in ("", None)) |
| ) |
| image_title = html.escape( |
| " / ".join(str(value) for value in (image_tag, submission_id) if value not in ("", None)) |
| ) |
| cells = [ |
| f'<td class="rank number" title="{escaped_text(rank)}">{escaped_text(rank)}</td>', |
| ( |
| f'<td class="team" title="{team_title}">' |
| f'<span class="leaderboard-main">{escaped_text(team)}</span>' |
| f'<span class="leaderboard-sub">{escaped_text(team_id)}</span>' |
| "</td>" |
| ), |
| f'<td class="score number" title="{escaped_text(score)}">{escaped_text(score)}</td>', |
| ( |
| '<td class="incident-distance number" ' |
| f'title="{escaped_text(incident_distance)}">{escaped_text(incident_distance)}</td>' |
| ), |
| ( |
| f'<td class="image-tag" title="{image_title}">' |
| f'<span class="leaderboard-main">{escaped_text(image_tag)}</span>' |
| f'<span class="leaderboard-sub">{escaped_text(submission_id)}</span>' |
| "</td>" |
| ), |
| ( |
| f'<td class="submitted-at" title="{escaped_text(submitted_at)}">' |
| f"{escaped_text(submitted_at)}</td>" |
| ), |
| ] |
| body_rows.append(f"<tr>{''.join(cells)}</tr>") |
|
|
| return ( |
| '<div class="leaderboard-table-wrap">' |
| '<table class="leaderboard-table">' |
| f"<thead><tr>{header_cells}</tr></thead>" |
| f"<tbody>{''.join(body_rows)}</tbody>" |
| "</table>" |
| "</div>" |
| ) |
|
|
|
|
| def leaderboard( |
| show_all_successful: bool = False, |
| sort_by: str = "Rank", |
| sort_ascending: bool = True, |
| track: str = "pai", |
| ) -> tuple[str, str, str]: |
| try: |
| body = api_json("GET", f"/leaderboard?{urllib.parse.urlencode({'track': track})}") |
| except urllib.error.HTTPError as exc: |
| details = exc.read().decode("utf-8", errors="replace") |
| return f"Could not load leaderboard. HTTP {exc.code}.", leaderboard_html([]), details |
| except urllib.error.URLError as exc: |
| return f"Could not load leaderboard: {exc.reason}", leaderboard_html([]), "" |
|
|
| entries = body.get("leaderboard") or [] |
| if not show_all_successful: |
| score_order = str(body.get("score_order") or "desc").lower() |
| best_by_team: dict[str, dict[str, Any]] = {} |
| for index, entry in enumerate(entries): |
| team_id = str( |
| entry.get("team_id") |
| or entry.get("team_display_name") |
| or entry.get("submission_id") |
| or f"row-{index}" |
| ) |
| policy_score = entry.get("policy_capability_score") |
| if policy_score is None: |
| policy_score = entry.get("best_score") |
| try: |
| numeric_score = float(policy_score) |
| except (TypeError, ValueError): |
| numeric_score = None |
|
|
| current = best_by_team.get(team_id) |
| current_score = current.get("_numeric_policy_score") if current else None |
| if current is None: |
| best_entry = dict(entry) |
| best_entry["_numeric_policy_score"] = numeric_score |
| best_entry["_leaderboard_source_index"] = index |
| best_by_team[team_id] = best_entry |
| elif numeric_score is not None and ( |
| current_score is None |
| or (score_order == "asc" and numeric_score < current_score) |
| or (score_order != "asc" and numeric_score > current_score) |
| ): |
| best_entry = dict(entry) |
| best_entry["_numeric_policy_score"] = numeric_score |
| best_entry["_leaderboard_source_index"] = index |
| best_by_team[team_id] = best_entry |
| entries = sorted( |
| best_by_team.values(), |
| key=lambda entry: entry.get("_leaderboard_source_index", 0), |
| ) |
|
|
| def metric_value(value: Any) -> float | str: |
| if value is None: |
| return "" |
| try: |
| return round(float(value), 3) |
| except (TypeError, ValueError): |
| return str(value) |
|
|
| rows: list[list[Any]] = [] |
| for row_rank, entry in enumerate(entries, start=1): |
| displayed_rank = (entry.get("rank") or row_rank) if show_all_successful else row_rank |
| policy_score = entry.get("policy_capability_score") |
| if policy_score is None: |
| policy_score = entry.get("best_score") |
| incident_distance = entry.get("avg_dist_between_incidents_at_fault") |
| if incident_distance is None: |
| incident_distance = entry.get("legacy_score") |
| rows.append( |
| [ |
| displayed_rank, |
| entry.get("team_display_name") or entry.get("team_id") or "", |
| entry.get("team_id") or "", |
| metric_value(policy_score), |
| metric_value(incident_distance), |
| entry.get("image_tag") or "", |
| entry.get("submission_id") or "", |
| entry.get("submitted_at") or "", |
| ] |
| ) |
|
|
| if sort_by in LEADERBOARD_HEADERS: |
| sort_index = LEADERBOARD_HEADERS.index(sort_by) |
|
|
| def sort_key(row: list[Any]) -> Any: |
| value = row[sort_index] |
| if isinstance(value, (int, float)): |
| return value |
| return str(value).lower() |
|
|
| populated_rows = [row for row in rows if row[sort_index] not in ("", None)] |
| empty_rows = [row for row in rows if row[sort_index] in ("", None)] |
| rows = sorted(populated_rows, key=sort_key, reverse=not sort_ascending) + empty_rows |
|
|
| summary = ( |
| f"{track.upper()} leaderboard entries: {len(entries)} shown" |
| f" out of {body.get('count', 0)}. " |
| f"Score order: {body.get('score_order', 'desc')}." |
| ) |
| return summary, leaderboard_html(rows), json.dumps(body, indent=2) |
|
|
|
|
| def submit_registration( |
| team_display_name: str, |
| team_id: str, |
| captain_name: str, |
| contact_email: str, |
| additional_submitters: str, |
| credited_contributors: str, |
| organization: str, |
| country_region: str, |
| notes: str, |
| roster_ack: bool, |
| limit_ack: bool, |
| rules_ack: bool, |
| profile: gr.OAuthProfile | None, |
| ) -> tuple[str, str, str, object]: |
| if profile is None: |
| return "Connect your Hugging Face account first.", "", "", gr.update(visible=False) |
| if not REGISTRATION_SECRET: |
| return "Registration Space is missing ALPASIM_REGISTRATION_SECRET.", "", "", gr.update(visible=True) |
| if not roster_ack or not limit_ack or not rules_ack: |
| return "Please accept all required acknowledgments.", "", "", gr.update(visible=True) |
|
|
| status_summary, raw_json, form_update = registration_panel_status(profile) |
| if isinstance(form_update, dict) and form_update.get("visible") is False: |
| return ( |
| "You already have an active team registration or team access.", |
| raw_json, |
| status_summary, |
| form_update, |
| ) |
|
|
| captain_hf_user_id = profile_value(profile, "sub") |
| captain_hf_username = profile_value(profile, "preferred_username", "name") |
| captain_email = contact_email.strip() or profile_value(profile, "email") |
|
|
| payload = { |
| "team_display_name": team_display_name.strip(), |
| "team_id": team_id.strip(), |
| "captain_name": captain_name.strip(), |
| "captain_email": captain_email, |
| "captain_hf_user_id": captain_hf_user_id, |
| "captain_hf_username": captain_hf_username, |
| "submitter_hf_usernames": split_multivalue(additional_submitters), |
| "credited_contributors": split_multivalue(credited_contributors), |
| "organization": organization.strip(), |
| "country_region": country_region.strip(), |
| "notes": notes.strip(), |
| } |
|
|
| try: |
| body = api_json("POST", "/registrations", payload) |
| except urllib.error.HTTPError as exc: |
| body = exc.read().decode("utf-8", errors="replace") |
| status_summary, _, form_update = registration_panel_status(profile) |
| return f"Registration failed with HTTP {exc.code}.", body, status_summary, form_update |
| except urllib.error.URLError as exc: |
| status_summary, _, form_update = registration_panel_status(profile) |
| return f"Registration request failed: {exc.reason}", "", status_summary, form_update |
|
|
| status_summary, _, form_update = registration_panel_status(profile) |
| return "Registration submitted for admin review.", json.dumps(body, indent=2), status_summary, form_update |
|
|
|
|
| def reviewer_identity(profile: gr.OAuthProfile | None) -> dict[str, str]: |
| if profile is None: |
| raise gr.Error("Sign in with Hugging Face before reviewing registrations.") |
|
|
| reviewer_hf_user_id = profile_value(profile, "sub") |
| reviewer_hf_username = profile_value(profile, "preferred_username", "name") |
| if not reviewer_hf_user_id: |
| raise gr.Error("Could not read your stable Hugging Face user ID.") |
|
|
| return { |
| "reviewer_hf_user_id": reviewer_hf_user_id, |
| "reviewer_hf_username": reviewer_hf_username, |
| } |
|
|
|
|
| def review_api_json( |
| method: str, |
| path: str, |
| profile: gr.OAuthProfile | None, |
| payload: dict | None = None, |
| query: dict | None = None, |
| ) -> dict: |
| reviewer = reviewer_identity(profile) |
| query_with_reviewer = {**reviewer, **(query or {})} |
| encoded_query = urllib.parse.urlencode(query_with_reviewer) |
| path_with_query = f"{path}?{encoded_query}" if encoded_query else path |
| payload_with_reviewer = {**reviewer, **(payload or {})} if payload is not None else None |
| return api_json(method, path_with_query, payload_with_reviewer) |
|
|
|
|
| def registration_rows(registrations: list[dict[str, Any]]) -> list[list[str]]: |
| return [ |
| [ |
| str(item.get("team_id") or ""), |
| str(item.get("team_display_name") or ""), |
| str(item.get("registration_status") or ""), |
| str(item.get("captain_hf_username") or ""), |
| str(item.get("organization") or ""), |
| str(item.get("updated_at") or item.get("created_at") or ""), |
| ] |
| for item in registrations |
| ] |
|
|
|
|
| def registration_choices(registrations: list[dict[str, Any]]) -> list[str]: |
| choices = [] |
| for item in registrations: |
| team_id = str(item.get("team_id") or "") |
| display_name = str(item.get("team_display_name") or team_id) |
| if team_id: |
| choices.append(f"{team_id} | {display_name}") |
| return choices |
|
|
|
|
| def selected_team_id(choice: str | None) -> str: |
| return (choice or "").split("|", 1)[0].strip() |
|
|
|
|
| def find_registration( |
| registrations: list[dict[str, Any]], |
| team_id: str, |
| ) -> dict[str, Any] | None: |
| for item in registrations: |
| if str(item.get("team_id") or "") == team_id: |
| return item |
| return None |
|
|
|
|
| def format_list(value: Any) -> str: |
| if isinstance(value, list): |
| return ", ".join(str(part) for part in value if str(part)) or "-" |
| return str(value) if value not in (None, "") else "-" |
|
|
|
|
| def review_details(item: dict[str, Any] | None) -> str: |
| if not item: |
| return "No registration selected." |
|
|
| def value(key: str) -> str: |
| return format_list(item.get(key)) |
|
|
| lines = [ |
| f"### {value('team_display_name')} (`{value('team_id')}`)", |
| f"Status: `{value('registration_status')}`", |
| f"Source: `{value('registration_source')}`", |
| "", |
| f"Captain: {value('captain_name')} / `{value('captain_hf_username')}`", |
| f"Captain email: {value('captain_email')}", |
| f"Captain HF user ID: `{value('captain_hf_user_id')}`", |
| "", |
| f"Submitters: {value('submitter_hf_usernames')}", |
| f"Credited contributors: {value('credited_contributors')}", |
| f"Organization: {value('organization')}", |
| f"Country/region: {value('country_region')}", |
| "", |
| f"Notes: {value('notes')}", |
| "", |
| f"Created: {value('created_at')}", |
| f"Updated: {value('updated_at')}", |
| f"Approved: {value('approved_at')}", |
| ] |
| if item.get("rejection_reason"): |
| lines.append(f"Rejection reason: {value('rejection_reason')}") |
| if item.get("reviewed_by_hf_username") or item.get("reviewed_by_hf_user_id"): |
| lines.append( |
| "Reviewed by: " |
| f"{value('reviewed_by_hf_username')} (`{value('reviewed_by_hf_user_id')}`)" |
| ) |
| return "\n".join(lines) |
|
|
|
|
| def refresh_review_registrations( |
| status_filter: str, |
| profile: gr.OAuthProfile | None, |
| ) -> tuple[list[list[str]], list[dict[str, Any]], object, str, str]: |
| if not REGISTRATION_SECRET: |
| raise gr.Error("Registration Space is missing ALPASIM_REGISTRATION_SECRET.") |
|
|
| try: |
| body = review_api_json( |
| "GET", |
| "/review/registrations", |
| profile, |
| query={"status": status_filter or "pending"}, |
| ) |
| except (urllib.error.HTTPError, urllib.error.URLError) as exc: |
| raise gr.Error(api_error_summary("Loading review registrations", exc)) from exc |
|
|
| registrations = body.get("registrations") or [] |
| choices = registration_choices(registrations) |
| selected = choices[0] if choices else None |
| item = find_registration(registrations, selected_team_id(selected)) |
| result = f"Loaded {body.get('count', len(registrations))} registration(s)." |
| return ( |
| registration_rows(registrations), |
| registrations, |
| gr.update(choices=choices, value=selected), |
| review_details(item), |
| result, |
| ) |
|
|
|
|
| def refresh_review_registrations_without_result( |
| status_filter: str, |
| profile: gr.OAuthProfile | None, |
| ) -> tuple[list[list[str]], list[dict[str, Any]], object, str]: |
| rows, registrations, selected, details, _ = refresh_review_registrations( |
| status_filter, |
| profile, |
| ) |
| return rows, registrations, selected, details |
|
|
|
|
| def select_review_registration( |
| choice: str, |
| registrations: list[dict[str, Any]], |
| ) -> str: |
| item = find_registration(registrations or [], selected_team_id(choice)) |
| return review_details(item) |
|
|
|
|
| def approve_review_registration( |
| choice: str, |
| profile: gr.OAuthProfile | None, |
| ) -> str: |
| team_id = selected_team_id(choice) |
| if not team_id: |
| raise gr.Error("Select a registration first.") |
|
|
| try: |
| body = review_api_json( |
| "POST", |
| "/review/registrations/approve", |
| profile, |
| {"team_id": team_id}, |
| ) |
| except (urllib.error.HTTPError, urllib.error.URLError) as exc: |
| raise gr.Error(api_error_summary(f"Approving {team_id}", exc)) from exc |
|
|
| return str(body.get("message") or f"Approved {team_id}.") |
|
|
|
|
| def reject_review_registration( |
| choice: str, |
| reason: str, |
| profile: gr.OAuthProfile | None, |
| ) -> str: |
| team_id = selected_team_id(choice) |
| if not team_id: |
| raise gr.Error("Select a registration first.") |
| reason = reason.strip() |
| if not reason: |
| raise gr.Error("Enter a rejection reason.") |
|
|
| try: |
| body = review_api_json( |
| "POST", |
| "/review/registrations/reject", |
| profile, |
| {"team_id": team_id, "reason": reason}, |
| ) |
| except (urllib.error.HTTPError, urllib.error.URLError) as exc: |
| raise gr.Error(api_error_summary(f"Rejecting {team_id}", exc)) from exc |
|
|
| return str(body.get("message") or f"Rejected {team_id}.") |
|
|
|
|
| def add_oauth_route_marker() -> None: |
| if os.environ.get("SYSTEM") != "spaces" and not os.environ.get("OAUTH_CLIENT_ID"): |
| return |
|
|
| original_activate = gr.LoginButton.activate |
| gr.LoginButton.activate = lambda self: None |
| try: |
| gr.LoginButton(visible=False) |
| finally: |
| gr.LoginButton.activate = original_activate |
|
|
|
|
| with gr.Blocks( |
| title="AlpaSim E2E Closed Loop Challenge 2026", |
| theme=APP_THEME, |
| css=GRADIO_CSS, |
| ) as demo: |
| add_oauth_route_marker() |
| with gr.Group(elem_classes=["identity-strip"]): |
| identity = gr.Markdown() |
|
|
| with gr.Group(visible=False) as reviewer_app: |
| with gr.Tabs(selected="registration"): |
| with gr.Tab("Registration", id="registration"): |
| registration_summary = gr.Markdown() |
| submitter_invitation_summary = gr.Markdown() |
| submitter_invitation_state = gr.State([]) |
|
|
| with gr.Group(visible=False) as registration_form: |
| gr.Markdown( |
| "If the captain's Hugging Face account uses a personal email address, " |
| "enter an organization email below. Before accepting the application, " |
| "the AlpaSim team will email that organization address for confirmation." |
| ) |
|
|
| with gr.Row(): |
| team_display_name = gr.Textbox( |
| label="Team Display Name", |
| placeholder="Team Alpha", |
| max_lines=1, |
| ) |
| team_id = gr.Textbox( |
| label="Requested Team ID", |
| placeholder="team-alpha", |
| max_lines=1, |
| info="Lowercase letters, digits, hyphens. 3-40 characters.", |
| ) |
|
|
| with gr.Row(): |
| captain_name = gr.Textbox(label="Captain Full Name", max_lines=1) |
| contact_email = gr.Textbox( |
| label="Captain Contact / Organization Email", |
| max_lines=1, |
| info=( |
| "Use an organization email if your Hugging Face account " |
| "email is personal. Organizers may email this address " |
| "before accepting the application." |
| ), |
| ) |
|
|
| additional_submitters = gr.Textbox( |
| label="Additional Submitter Hugging Face Usernames", |
| lines=4, |
| placeholder="one username per line, or comma-separated", |
| ) |
| credited_contributors = gr.Textbox( |
| label="Credited Contributors", |
| lines=4, |
| placeholder="one name per line, or comma-separated", |
| ) |
|
|
| with gr.Row(): |
| organization = gr.Textbox(label="Organization / Affiliation", max_lines=1) |
| country_region = gr.Textbox(label="Country / Region", max_lines=1) |
|
|
| notes = gr.Textbox(label="Notes To Organizers", lines=3) |
|
|
| roster_ack = gr.Checkbox( |
| label="I understand that the submitter roster is frozen after approval except by administrator exception." |
| ) |
| limit_ack = gr.Checkbox( |
| label="I understand that submissions are limited at the team level and should only be used for images we want evaluated." |
| ) |
| rules_ack = gr.Checkbox( |
| label="I agree to follow the AlpaSim Challenge rules and organizer instructions." |
| ) |
|
|
| submit = gr.Button("Submit Registration", variant="primary") |
| status = gr.Textbox(label="Status", interactive=False) |
| response = gr.Code(label="Response", language="json", visible=False) |
|
|
| with gr.Group(visible=False) as submitter_invitation_panel: |
| submitter_invitation_choice = gr.Dropdown([], label="Submitter Invitation") |
| claim_submitter = gr.Button("Join Team", variant="primary") |
| claim_submitter_result = gr.Textbox(label="Result", interactive=False) |
|
|
| with gr.Tab("PAI Leaderboard", id="leaderboard"): |
| leaderboard_summary = gr.Markdown() |
| with gr.Group(elem_classes=["leaderboard-controls"]): |
| leaderboard_sort_by = gr.Dropdown( |
| LEADERBOARD_SORT_CHOICES, |
| value="Rank", |
| label="Sort by", |
| ) |
| with gr.Row(): |
| show_all_successful = gr.Checkbox( |
| label="All successful submissions", |
| value=False, |
| scale=1, |
| ) |
| leaderboard_sort_ascending = gr.Checkbox( |
| label="Ascending sort", |
| value=True, |
| scale=1, |
| ) |
| refresh_leaderboard = gr.Button("Refresh", variant="primary") |
| leaderboard_table = gr.HTML() |
| leaderboard_response = gr.Code( |
| label="Leaderboard JSON", |
| language="json", |
| visible=False, |
| ) |
|
|
| with gr.Tab("nuPlan Leaderboard", id="nuplan-leaderboard"): |
| nuplan_leaderboard_summary = gr.Markdown() |
| with gr.Group(elem_classes=["leaderboard-controls"]): |
| nuplan_leaderboard_sort_by = gr.Dropdown( |
| LEADERBOARD_SORT_CHOICES, |
| value="Rank", |
| label="Sort by", |
| ) |
| with gr.Row(): |
| nuplan_show_all_successful = gr.Checkbox( |
| label="All successful submissions", |
| value=False, |
| scale=1, |
| ) |
| nuplan_leaderboard_sort_ascending = gr.Checkbox( |
| label="Ascending sort", |
| value=True, |
| scale=1, |
| ) |
| refresh_nuplan_leaderboard = gr.Button("Refresh", variant="primary") |
| nuplan_leaderboard_table = gr.HTML() |
| nuplan_leaderboard_response = gr.Code( |
| label="Leaderboard JSON", |
| language="json", |
| visible=False, |
| ) |
|
|
| with gr.Tab("Review", id="review"): |
| gr.Markdown("Reviewer access is limited to active AlpaSim reviewers.") |
| review_state = gr.State([]) |
|
|
| with gr.Row(): |
| review_status_filter = gr.Dropdown( |
| REVIEW_STATUS_CHOICES, |
| value="pending", |
| label="Status", |
| scale=1, |
| ) |
| refresh_review = gr.Button("Refresh", variant="primary", scale=1) |
|
|
| review_table = gr.Dataframe( |
| headers=[ |
| "team_id", |
| "display_name", |
| "status", |
| "captain_hf_username", |
| "organization", |
| "updated", |
| ], |
| datatype=["str", "str", "str", "str", "str", "str"], |
| interactive=False, |
| wrap=True, |
| ) |
| selected_review_registration = gr.Dropdown([], label="Selected Registration") |
| review_registration_details = gr.Markdown("No registration selected.") |
|
|
| approve_review = gr.Button("Approve", variant="primary") |
|
|
| with gr.Accordion("Reject", open=False): |
| review_rejection_reason = gr.Textbox(label="Reason", lines=3) |
| reject_review = gr.Button("Reject", variant="stop") |
|
|
| review_result = gr.Textbox(label="Result", interactive=False) |
|
|
| demo.load( |
| session_state, |
| inputs=None, |
| outputs=[ |
| identity, |
| reviewer_app, |
| review_table, |
| review_state, |
| selected_review_registration, |
| review_registration_details, |
| review_result, |
| ], |
| ) |
| demo.load( |
| registration_panel_status, |
| inputs=None, |
| outputs=[ |
| registration_summary, |
| response, |
| registration_form, |
| ], |
| ) |
| demo.load( |
| submitter_invitation_status, |
| inputs=None, |
| outputs=[ |
| submitter_invitation_summary, |
| submitter_invitation_state, |
| submitter_invitation_choice, |
| submitter_invitation_panel, |
| ], |
| ) |
| demo.load( |
| lambda show_all, sort_by, ascending: leaderboard(show_all, sort_by, ascending, "pai"), |
| inputs=[show_all_successful, leaderboard_sort_by, leaderboard_sort_ascending], |
| outputs=[leaderboard_summary, leaderboard_table, leaderboard_response], |
| ) |
| refresh_leaderboard.click( |
| lambda show_all, sort_by, ascending: leaderboard(show_all, sort_by, ascending, "pai"), |
| inputs=[show_all_successful, leaderboard_sort_by, leaderboard_sort_ascending], |
| outputs=[leaderboard_summary, leaderboard_table, leaderboard_response], |
| ) |
| show_all_successful.change( |
| lambda show_all, sort_by, ascending: leaderboard(show_all, sort_by, ascending, "pai"), |
| inputs=[show_all_successful, leaderboard_sort_by, leaderboard_sort_ascending], |
| outputs=[leaderboard_summary, leaderboard_table, leaderboard_response], |
| ) |
| leaderboard_sort_by.change( |
| lambda show_all, sort_by, ascending: leaderboard(show_all, sort_by, ascending, "pai"), |
| inputs=[show_all_successful, leaderboard_sort_by, leaderboard_sort_ascending], |
| outputs=[leaderboard_summary, leaderboard_table, leaderboard_response], |
| ) |
| leaderboard_sort_ascending.change( |
| lambda show_all, sort_by, ascending: leaderboard(show_all, sort_by, ascending, "pai"), |
| inputs=[show_all_successful, leaderboard_sort_by, leaderboard_sort_ascending], |
| outputs=[leaderboard_summary, leaderboard_table, leaderboard_response], |
| ) |
| demo.load( |
| lambda show_all, sort_by, ascending: leaderboard(show_all, sort_by, ascending, "nuplan"), |
| inputs=[ |
| nuplan_show_all_successful, |
| nuplan_leaderboard_sort_by, |
| nuplan_leaderboard_sort_ascending, |
| ], |
| outputs=[ |
| nuplan_leaderboard_summary, |
| nuplan_leaderboard_table, |
| nuplan_leaderboard_response, |
| ], |
| ) |
| refresh_nuplan_leaderboard.click( |
| lambda show_all, sort_by, ascending: leaderboard(show_all, sort_by, ascending, "nuplan"), |
| inputs=[ |
| nuplan_show_all_successful, |
| nuplan_leaderboard_sort_by, |
| nuplan_leaderboard_sort_ascending, |
| ], |
| outputs=[ |
| nuplan_leaderboard_summary, |
| nuplan_leaderboard_table, |
| nuplan_leaderboard_response, |
| ], |
| ) |
| nuplan_show_all_successful.change( |
| lambda show_all, sort_by, ascending: leaderboard(show_all, sort_by, ascending, "nuplan"), |
| inputs=[ |
| nuplan_show_all_successful, |
| nuplan_leaderboard_sort_by, |
| nuplan_leaderboard_sort_ascending, |
| ], |
| outputs=[ |
| nuplan_leaderboard_summary, |
| nuplan_leaderboard_table, |
| nuplan_leaderboard_response, |
| ], |
| ) |
| nuplan_leaderboard_sort_by.change( |
| lambda show_all, sort_by, ascending: leaderboard(show_all, sort_by, ascending, "nuplan"), |
| inputs=[ |
| nuplan_show_all_successful, |
| nuplan_leaderboard_sort_by, |
| nuplan_leaderboard_sort_ascending, |
| ], |
| outputs=[ |
| nuplan_leaderboard_summary, |
| nuplan_leaderboard_table, |
| nuplan_leaderboard_response, |
| ], |
| ) |
| nuplan_leaderboard_sort_ascending.change( |
| lambda show_all, sort_by, ascending: leaderboard(show_all, sort_by, ascending, "nuplan"), |
| inputs=[ |
| nuplan_show_all_successful, |
| nuplan_leaderboard_sort_by, |
| nuplan_leaderboard_sort_ascending, |
| ], |
| outputs=[ |
| nuplan_leaderboard_summary, |
| nuplan_leaderboard_table, |
| nuplan_leaderboard_response, |
| ], |
| ) |
| submit.click( |
| submit_registration, |
| inputs=[ |
| team_display_name, |
| team_id, |
| captain_name, |
| contact_email, |
| additional_submitters, |
| credited_contributors, |
| organization, |
| country_region, |
| notes, |
| roster_ack, |
| limit_ack, |
| rules_ack, |
| ], |
| outputs=[ |
| status, |
| response, |
| registration_summary, |
| registration_form, |
| ], |
| ) |
| claim_submitter.click( |
| claim_submitter_invitation, |
| inputs=[submitter_invitation_choice], |
| outputs=[claim_submitter_result], |
| ).then( |
| submitter_invitation_status, |
| inputs=None, |
| outputs=[ |
| submitter_invitation_summary, |
| submitter_invitation_state, |
| submitter_invitation_choice, |
| submitter_invitation_panel, |
| ], |
| ).then( |
| registration_panel_status, |
| inputs=None, |
| outputs=[ |
| registration_summary, |
| response, |
| registration_form, |
| ], |
| ) |
| refresh_review.click( |
| refresh_review_registrations, |
| inputs=[review_status_filter], |
| outputs=[ |
| review_table, |
| review_state, |
| selected_review_registration, |
| review_registration_details, |
| review_result, |
| ], |
| ) |
| review_status_filter.change( |
| refresh_review_registrations, |
| inputs=[review_status_filter], |
| outputs=[ |
| review_table, |
| review_state, |
| selected_review_registration, |
| review_registration_details, |
| review_result, |
| ], |
| ) |
| selected_review_registration.change( |
| select_review_registration, |
| inputs=[selected_review_registration, review_state], |
| outputs=[review_registration_details], |
| ) |
| approve_review.click( |
| approve_review_registration, |
| inputs=[ |
| selected_review_registration, |
| ], |
| outputs=[review_result], |
| ).then( |
| refresh_review_registrations_without_result, |
| inputs=[review_status_filter], |
| outputs=[ |
| review_table, |
| review_state, |
| selected_review_registration, |
| review_registration_details, |
| ], |
| ) |
| reject_review.click( |
| reject_review_registration, |
| inputs=[selected_review_registration, review_rejection_reason], |
| outputs=[review_result], |
| ).then( |
| refresh_review_registrations_without_result, |
| inputs=[review_status_filter], |
| outputs=[ |
| review_table, |
| review_state, |
| selected_review_registration, |
| review_registration_details, |
| ], |
| ) |
|
|
| app = FastAPI(title="AlpaSim E2E Closed Loop Challenge 2026") |
| app.mount("/assets", StaticFiles(directory=str(BANNER_DIR)), name="assets") |
|
|
|
|
| @app.get("/", response_class=HTMLResponse, include_in_schema=False) |
| def landing_page() -> HTMLResponse: |
| return HTMLResponse(LANDING_HTML) |
|
|
|
|
| app = gr.mount_gradio_app( |
| app, |
| demo, |
| path="/gradio", |
| allowed_paths=[str(BANNER_FILE)], |
| ) |
|
|
| for route in app.routes: |
| if getattr(route, "path", None) == "/gradio" and hasattr(route, "app"): |
| |
| |
| |
| app.mount("/", route.app) |
| break |
| else: |
| raise RuntimeError("Unable to find mounted Gradio app for OAuth routes.") |
|
|
|
|
| if __name__ == "__main__": |
| import uvicorn |
|
|
| uvicorn.run( |
| app, |
| host="0.0.0.0", |
| port=int(os.environ.get("PORT", "7860")), |
| ) |
|
|