from __future__ import annotations import json import re from datetime import datetime, timezone from pathlib import Path import gradio as gr import pandas as pd from leaderboarder.config import Settings from leaderboarder.deploy import deploy_to_hf_space, generate_space_artifacts from leaderboarder.pipeline import LeaderboardPipeline WORKDIR = Path("/tmp/leaderboarder-builder-runs") WORKDIR.mkdir(parents=True, exist_ok=True) def slugify(text: str) -> str: value = re.sub(r"[^a-zA-Z0-9]+", "-", (text or "").strip().lower()).strip("-") return value or "benchmark" def resolve_owner(hf_token: str) -> str: from huggingface_hub import HfApi whoami = HfApi(token=hf_token).whoami() return whoami.get("name") or "" def run_build_and_deploy( benchmark_input: str, explicit_space_id: str, max_citations: int, read_citations: int, private_space: bool, ): benchmark_input = (benchmark_input or "").strip() if not benchmark_input: return "Missing benchmark input.", "", pd.DataFrame() settings = Settings.from_env() if not settings.openrouter_api_key: return ( "Missing OPENROUTER_API_KEY secret in this builder space.", "", pd.DataFrame(), ) if not settings.hf_token: return "Missing HF_TOKEN secret in this builder space.", "", pd.DataFrame() pipeline = LeaderboardPipeline(settings=settings) run_id = datetime.now(timezone.utc).strftime("%Y%m%d-%H%M%S") base_slug = slugify(benchmark_input) output_dir = WORKDIR / f"{base_slug}-{run_id}" try: summary = pipeline.run( input_value=benchmark_input, output_dir=str(output_dir), max_citations=int(max_citations), read_citations=int(read_citations), ) except Exception as exc: return f"Build failed: {exc}", "", pd.DataFrame() owner = resolve_owner(settings.hf_token) if not owner: return "Could not resolve HF account owner.", "", pd.DataFrame() if explicit_space_id.strip(): target_space = explicit_space_id.strip() else: target_space = f"{owner}/leaderboarder-{slugify(summary.benchmark_name)}" generate_space_artifacts(Path(summary.output_dir), summary.benchmark_name) try: deployed_url = deploy_to_hf_space( output_dir=Path(summary.output_dir), space_id=target_space, hf_token=settings.hf_token, private=bool(private_space), ) except Exception as exc: return f"Deployment failed: {exc}", json.dumps(summary.to_dict(), indent=2, ensure_ascii=False), pd.DataFrame() csv_path = Path(summary.output_dir) / "leaderboard.csv" preview = pd.read_csv(csv_path).head(25) if csv_path.exists() else pd.DataFrame() status = ( f"Built benchmark: {summary.benchmark_name}\n" f"Rows: {summary.final_rows}\n" f"Space: {target_space}\n" f"URL: {deployed_url}" ) return status, json.dumps(summary.to_dict(), indent=2, ensure_ascii=False), preview with gr.Blocks(title="Leaderboarder Builder") as demo: gr.Markdown("# Leaderboarder Builder") gr.Markdown( "Input a benchmark URL or benchmark name/query. " "The app extracts leaderboard rows, expands with related works, and deploys a new Hugging Face Space." ) gr.Markdown( "Required HF Space secrets: `OPENROUTER_API_KEY`, `HF_TOKEN`." ) benchmark_input = gr.Textbox( label="Benchmark input", placeholder="https://arxiv.org/abs/... or benchmark name", ) explicit_space_id = gr.Textbox( label="Target Space ID (optional)", placeholder="username/space-name", ) with gr.Row(): max_citations = gr.Slider( label="Max citation candidates", minimum=10, maximum=500, value=150, step=10, ) read_citations = gr.Slider( label="Citations to read deeply", minimum=5, maximum=100, value=30, step=1, ) private_space = gr.Checkbox(label="Create private Space", value=False) run_btn = gr.Button("Create and Deploy Leaderboard") status_out = gr.Textbox(label="Status", lines=6) summary_out = gr.Code(label="Pipeline summary", language="json") preview_out = gr.Dataframe(label="Leaderboard preview", wrap=False, row_count=(20, "fixed")) run_btn.click( fn=run_build_and_deploy, inputs=[ benchmark_input, explicit_space_id, max_citations, read_citations, private_space, ], outputs=[status_out, summary_out, preview_out], ) demo.queue(max_size=8).launch()