# app.py import gradio as gr import pandas as pd from apscheduler.schedulers.background import BackgroundScheduler from gradio.themes import Base, colors, sizes from gradio_leaderboard import Leaderboard, SelectColumns from huggingface_hub import whoami # Updated import to get the new HTML variable from src.about import CITATION_BUTTON_LABEL, CITATION_BUTTON_TEXT, EVALUATION_QUEUE_TEXT, WHAT_IS_F1_HTML from src.datamodel.data import F1Data from src.display.css_html_js import custom_css from src.display.formatting import styled_error from src.display.utils import AutoEvalColumn, ModelType, fields from src.envs import API, CODE_PROBLEMS_REPO, REPO_ID, RESULTS_REPO, SUBMISSIONS_REPO from src.logger import get_logger from src.populate import get_leaderboard_df from src.submission.submit import add_new_solutions, fetch_user_info from src.validation.validate import MAX_INPUT_LENGTH, MIN_INPUT_LENGTH, is_submission_file_valid, is_valid logger = get_logger(__name__) ENSURE_ALL_PRESENT = False SPLIT = "warmup" lbdb = F1Data( cp_ds_name=CODE_PROBLEMS_REPO, sub_ds_name=SUBMISSIONS_REPO, res_ds_name=RESULTS_REPO, split=SPLIT, ) leaderboard_df = None logger.info("Initialized LBDB") def restart_space(): logger.info("Restarting space") API.restart_space(repo_id=REPO_ID) def refresh_leaderboard_data(): global leaderboard_df try: logger.info("Loading leaderboard data...") new_leaderboard_df = get_leaderboard_df(RESULTS_REPO) if new_leaderboard_df is not None: logger.info("Leaderboard data refreshed successfully") leaderboard_df = new_leaderboard_df else: logger.warning("No new leaderboard data found") except Exception as e: logger.error(f"Error refreshing leaderboard data: {e}") def init_leaderboard(dataframe: pd.DataFrame): if dataframe is None: raise ValueError("Leaderboard DataFrame is None.") return Leaderboard( value=dataframe, datatype=[c.type for c in fields(AutoEvalColumn)], select_columns=SelectColumns( default_selection=[c.name for c in fields(AutoEvalColumn) if c.displayed_by_default], cant_deselect=[c.name for c in fields(AutoEvalColumn) if c.never_hidden], label="Select Columns to Display:", ), search_columns=[AutoEvalColumn.system.name, AutoEvalColumn.system_type.name], hide_columns=[c.name for c in fields(AutoEvalColumn) if c.hidden], bool_checkboxgroup_label="Hide models", interactive=False, ) def add_solution_cbk( system_name: str, org: str, sys_type: str, submission_path: str, profile: gr.OAuthProfile | None, oauth_token: gr.OAuthToken | None, ): if profile is None or oauth_token is None: return styled_error("Please sign in with Hugging Face before submitting.") user_info = fetch_user_info(oauth_token) stable_id = user_info.get("id") if user_info else None if not stable_id: return styled_error("Could not retrieve your stable user ID. Please try signing in again.") if not profile.username: return styled_error("Could not retrieve username. Please try signing in again.") try: if not submission_path: return styled_error("Please upload JSONL submission file.") if not is_submission_file_valid(submission_path, is_warmup_dataset=(SPLIT == "warmup")): return styled_error("Failed to read JSONL submission file. Please try again later.") for val, val_name in [(system_name, "System name"), (org, "Organisation name"), (sys_type, "System type")]: if len(val) == 0: return styled_error(f"Please fill in the '{val_name}' field.") if not is_valid(val): return styled_error( f"{val_name} is invalid! Must only contain characters [a-zA-Z0-9], spaces, or the special characters '-' and '.', and be of length between {MIN_INPUT_LENGTH} and {MAX_INPUT_LENGTH}." ) except Exception: logger.warning("Failed to process user submission", exc_info=True) return styled_error("An error occurred. Please try again later.") return add_new_solutions( lbdb, profile.username, stable_id, system_name, org, sys_type, submission_path, is_warmup_dataset=(SPLIT == "warmup"), ensure_all_present=ENSURE_ALL_PRESENT, ) def gate_submission(oauth_token: gr.OAuthToken | None): if oauth_token is None: return gr.update(visible=True), gr.update(visible=False) try: whoami(oauth_token.token) return gr.update(visible=False), gr.update(visible=True) except Exception: return gr.update(visible=True), gr.update(visible=False) def get_theme(): return Base( primary_hue=colors.cyan, secondary_hue=colors.pink, neutral_hue=colors.gray, text_size=sizes.text_md, spacing_size=sizes.spacing_md, radius_size=sizes.radius_md, ).set( body_background_fill="#0b0f14", background_fill_primary="#0b0f14", background_fill_secondary="#0e141a", ) blocks = gr.Blocks(css=custom_css, theme=get_theme()) with blocks: gr.Image( "assets/banner.png", interactive=False, show_label=False, show_download_button=False, container=False, elem_classes=["banner_image"], ) # The main layout is now controlled by these three tabs with gr.Tabs(elem_classes="tab-buttons") as tabs: with gr.TabItem("What is FormulaOne", id=0): gr.HTML(WHAT_IS_F1_HTML) with gr.TabItem("🏅 FormulaOne Leaderboard", id=1): refresh_leaderboard_data() assert leaderboard_df is not None, "Leaderboard data failed to load." leaderboard_component = init_leaderboard(leaderboard_df) with gr.TabItem("🚀 Submit Solutions", id=2): with gr.Column(): gr.Markdown(EVALUATION_QUEUE_TEXT, elem_classes="markdown-text") gr.Markdown("# ✉️✨ Submit your solutions", elem_classes="markdown-text") login_box = gr.Group(visible=True) with login_box: gr.Markdown("Please sign in with Hugging Face to submit") gr.LoginButton() submit_panel = gr.Group(visible=False) with submit_panel: with gr.Row(): with gr.Column(): system_name_textbox = gr.Textbox(label=AutoEvalColumn.system.name) org_textbox = gr.Textbox(label=AutoEvalColumn.organization.name) sys_type_dropdown = gr.Dropdown( choices=[t.to_str() for t in ModelType], label=AutoEvalColumn.system_type.name, multiselect=False, value=ModelType.LLM.to_str(), interactive=True, ) submission_file = gr.File(label="JSONL solutions file", file_types=[".jsonl"]) submit_button = gr.Button("Submit", variant="primary") submission_result = gr.Markdown() submit_button.click( add_solution_cbk, [system_name_textbox, org_textbox, sys_type_dropdown, submission_file], submission_result, ) with gr.Row(): with gr.Accordion(CITATION_BUTTON_LABEL, open=False): gr.Code(value=CITATION_BUTTON_TEXT.strip(), elem_id="citation-block") blocks.load(lambda: leaderboard_df, inputs=[], outputs=[leaderboard_component]) blocks.load(gate_submission, inputs=None, outputs=[login_box, submit_panel]) scheduler = BackgroundScheduler() scheduler.add_job(restart_space, "interval", seconds=1800) scheduler.add_job(refresh_leaderboard_data, "interval", seconds=120) scheduler.start() blocks.queue(default_concurrency_limit=40).launch()