Spaces:
Runtime error
Runtime error
| import json | |
| from datetime import datetime, timezone | |
| from pathlib import Path | |
| import gradio as gr | |
| from huggingface_hub import snapshot_download | |
| from loguru import logger | |
| from pydantic import BaseModel, Field | |
| from envs import API, REPO_ID, USERS_PATH, USERS_REPO | |
| from formatting import styled_error, styled_message, styled_warning | |
| css = """ | |
| :root { | |
| color-scheme: light !important; | |
| --block-border-width: 0 !important; | |
| --section-header-text-weight: 600 !important; | |
| --section-header-text-size: 14px !important; | |
| --input-radius: var(--radius-xl) !important; | |
| --font-mono: "Space Mono", monospace !important; | |
| --text-sm: 12px !important; | |
| --text-md: 14px !important; | |
| --text-lg: 16px !important; | |
| --input-text-size: var(--text-sm) !important; | |
| --body-text-size: 14px !important; | |
| --input-background-fill-focus: var(--secondary-300) !important; | |
| // Button Colors | |
| --button-primary-background-fill: var(--primary-800) !important; | |
| --button-secondary-background-fill: var(--secondary-600) !important; | |
| --checkbox-label-text-color: var(--body-text-color) !important; | |
| --card-bg-color: #fcecd4; | |
| --card-btn-color: #D4E4FC; | |
| --card-btn-color-hover: #7DAEF6; | |
| --answer-bg-color: #f0f8ff; | |
| --hover-border-color: #121212; | |
| } | |
| :root .dark { | |
| color-scheme: dark !important; | |
| --block-border-width: 0 !important; | |
| --section-header-text-weight: 600 !important; | |
| --section-header-text-size: 14px !important; | |
| --input-radius: var(--radius-xl) !important; | |
| --font-mono: "Space Mono", monospace !important; | |
| --text-sm: 12px !important; | |
| --text-md: 14px !important; | |
| --text-lg: 16px !important; | |
| --input-text-size: var(--text-sm) !important; | |
| --body-text-size: 14px !important; | |
| --button-primary-background-fill: var(--neutral-100) !important; | |
| --button-secondary-background-fill: var(--secondary-300) !important; | |
| --button-primary-text-color: black !important; | |
| --button-secondary-text-color: black !important; | |
| --checkbox-label-text-color: var(--body-text-color) !important; | |
| --card-bg-color: #383127; | |
| --answer-bg-color: #1a2b3c; | |
| --hover-border-color: #ffffff; | |
| } | |
| .gradio-app { | |
| } | |
| .warning-header { | |
| color: red; | |
| } | |
| .neutral-header { | |
| color: blue; | |
| } | |
| .success-header { | |
| color: green; | |
| } | |
| .gradio-container { | |
| max-width: 1000px; | |
| margin: 0 auto; | |
| padding: 0 8px; | |
| } | |
| """ | |
| def restart_space(): | |
| API.restart_space(repo_id=REPO_ID) | |
| def download_dataset_snapshot(repo_id, local_dir): | |
| try: | |
| logger.info(f"Downloading dataset snapshot from {repo_id} to {local_dir}") | |
| snapshot_download( | |
| repo_id=repo_id, | |
| local_dir=local_dir, | |
| repo_type="dataset", | |
| tqdm_class=None, | |
| ) | |
| except Exception as e: | |
| logger.error(f"Error downloading dataset snapshot from {repo_id} to {local_dir}: {e}. Restarting space.") | |
| API.restart_space(repo_id=repo_id) | |
| download_dataset_snapshot(USERS_REPO, USERS_PATH) | |
| class User(BaseModel): | |
| """ | |
| Represents a user in the competition system, formatted for HuggingFace datasets. | |
| """ | |
| username: str = Field(description="HuggingFace username of the user") | |
| name: str = Field(description="Full name of the user") | |
| email: str = Field(description="Contact email of the user") | |
| affiliation: str = Field(description="Affiliation of the user") | |
| def create_user( | |
| username: str, | |
| name: str, | |
| email: str, | |
| affiliation: str, | |
| profile: gr.OAuthProfile | None, | |
| ) -> User: | |
| """ | |
| Create a user for a tossup model. | |
| Args: | |
| name: Display name of the submission | |
| description: Detailed description of what the submission does | |
| user_email: Email of the user who created the submission | |
| workflow: The workflow configuration for the tossup model | |
| Returns: | |
| Submission object if successful, None if validation fails | |
| """ | |
| # Create the submission | |
| dt = datetime.now(timezone.utc) | |
| submission = User( | |
| username=username, | |
| name=name, | |
| email=email, | |
| affiliation=affiliation, | |
| created_at=dt.isoformat(), | |
| ) | |
| return submission | |
| def get_user(username: str) -> User | None: | |
| """ | |
| Get a user from the registered users dataset. | |
| """ | |
| out_path = Path(f"{USERS_PATH}/{username}.json") | |
| if not out_path.exists(): | |
| return None | |
| with out_path.open("r") as f: | |
| user_dict = json.load(f) | |
| return User.model_validate(user_dict) | |
| def is_user_logged_in(profile: gr.OAuthProfile | None) -> bool: | |
| """ | |
| Check if a user is logged in. | |
| """ | |
| return profile is not None | |
| def user_signup( | |
| name: str, | |
| email: str, | |
| affiliation: str, | |
| profile: gr.OAuthProfile | None = None, | |
| ) -> User: | |
| """ | |
| Sign up for the competition. | |
| """ | |
| if profile is None: | |
| return styled_error("Please sign in using your HuggingFace account to register for the competition.") | |
| try: | |
| username = profile.username | |
| user = get_user(username) | |
| new_user = create_user( | |
| username=username, | |
| name=name, | |
| email=email, | |
| affiliation=affiliation, | |
| profile=profile, | |
| ) | |
| # Convert to dictionary format | |
| user_dict = new_user.model_dump() | |
| # Upload to HuggingFace dataset | |
| updated = bool(user) | |
| API.upload_file( | |
| path_or_fileobj=json.dumps(user_dict, indent=2).encode(), | |
| path_in_repo=f"{username}.json", | |
| repo_id=USERS_REPO, | |
| repo_type="dataset", | |
| commit_message=f"{'Update' if updated else 'Add'} user {username}", | |
| ) | |
| return styled_message( | |
| f"Successfully {'updated' if updated else 'registered'} user {username} for the competition!<br>" | |
| ) | |
| except Exception as e: | |
| logger.exception(e) | |
| return styled_error( | |
| "Error registering for the competition. Please try again later, or contact the organizers at <br><a href='mailto:qanta-challenge@googlegroups.com'>qanta-challenge@googlegroups.com</a>." | |
| ) | |
| def load_user_info(profile: gr.OAuthProfile | None): | |
| if profile is None: | |
| return ( | |
| gr.update(interactive=False), | |
| gr.update(interactive=False), | |
| gr.update(interactive=False), | |
| gr.update(interactive=False), | |
| gr.update( | |
| value="<h2 class='warning-header'>Please sign in using your HuggingFace account to register for the competition.</h2>", | |
| ), | |
| ) | |
| user = get_user(profile.username) | |
| if user is None: | |
| return ( | |
| gr.update(interactive=True), | |
| gr.update(interactive=True), | |
| gr.update(interactive=True), | |
| gr.update(interactive=True, value="Register"), | |
| gr.update( | |
| value="<h2 class='neutral-header'>Fill in your details below to register for the competition.</h2>", | |
| ), | |
| ) | |
| return ( | |
| gr.update(interactive=True, value=user.name), | |
| gr.update(interactive=True, value=user.email), | |
| gr.update(interactive=True, value=user.affiliation), | |
| gr.update(interactive=True, value="Update Information"), | |
| gr.update( | |
| value="<h2 class='success-header'>You are already registered! You can update your details below.</h2>", | |
| ), | |
| ) | |
| with gr.Blocks(title="Register - QANTA 2025 Quizbowl System Submission", css=css) as demo: | |
| gr.Markdown("# Register for QANTA 2025 Quizbowl System Submission") | |
| with gr.Row(): | |
| with gr.Column(): | |
| # HuggingFace Login Button | |
| hf_login_btn = gr.LoginButton(scale=1) | |
| header = gr.HTML("<h2>Fill in your details below</h2>") | |
| # Registration form | |
| name = gr.Textbox(label="Full Name", placeholder="Enter your full name") | |
| email = gr.Textbox(label="Contact Email", placeholder="Enter your email") | |
| affiliation = gr.Textbox( | |
| label="Affiliation", | |
| placeholder="Enter your organization or institution", | |
| ) | |
| submit_btn = gr.Button("Register") | |
| status = gr.Markdown() | |
| submit_btn.click( | |
| fn=user_signup, | |
| inputs=[name, email, affiliation], | |
| outputs=[status], | |
| ) | |
| demo.load( | |
| load_user_info, | |
| inputs=[], | |
| outputs=[name, email, affiliation, submit_btn, header], | |
| ) | |
| demo.queue(default_concurrency_limit=40).launch() | |