Nicolas Wagner
adjust size
b5a5f3d
import os
import gradio as gr
import pandas as pd
from apscheduler.schedulers.background import BackgroundScheduler
from gradio_leaderboard import Leaderboard, SelectColumns
from huggingface_hub import snapshot_download
from src.about import (
INTRODUCTION_TEXT,
LLM_BENCHMARKS_TEXT,
TITLE,
)
from src.display.css_html_js import custom_css
from src.display.formatting import styled_error, styled_message
from src.display.utils import (
COLS,
SUBMISSION_COLS,
SUBMISSION_TYPES,
TeamColumn,
fields,
)
from src.envs import (
API,
REPO_ID,
SUBMISSIONS_PATH,
SUBMISSIONS_REPO,
TEAMS_PATH,
TEAMS_REPO,
TOKEN,
)
from src.evaluation.load_labels import load_true_labels
from src.populate import get_leaderboard_df, get_submission_queue_df
from src.submission.submit_csv import submit_csv
from src.teams.register import create_team
def restart_space():
API.restart_space(repo_id=REPO_ID)
try:
snapshot_download(
repo_id=TEAMS_REPO,
local_dir=TEAMS_PATH,
repo_type="dataset",
tqdm_class=None,
etag_timeout=30,
token=TOKEN,
)
except Exception as e:
print(f"Warning: Could not download teams dataset from {TEAMS_REPO}: {e}")
try:
snapshot_download(
repo_id=SUBMISSIONS_REPO,
local_dir=SUBMISSIONS_PATH,
repo_type="dataset",
tqdm_class=None,
etag_timeout=30,
token=TOKEN,
)
except Exception as e:
print(f"Warning: Could not download submissions dataset from {SUBMISSIONS_REPO}: {e}")
try:
load_true_labels()
except Exception as e:
print(f"Warning: Could not load true labels: {e}")
LEADERBOARD_DF = get_leaderboard_df(SUBMISSIONS_PATH, COLS)
(
accepted_submissions_df,
rejected_submissions_df,
all_submissions_df,
) = get_submission_queue_df(SUBMISSIONS_PATH, SUBMISSION_COLS)
def init_leaderboard(dataframe):
team_columns = [c for c in fields(TeamColumn) if isinstance(c, type(TeamColumn.team_name))]
valid_cols = [col for col in COLS if col is not None and isinstance(col, str) and col.strip() != ""]
if not valid_cols:
valid_cols = [
"Team Name",
"Best F1 Score ⬆️",
"Best Accuracy ⬆️",
"Best Precision ⬆️",
"Best Recall ⬆️",
"Best TP ⬆️",
"Best FP ⬇️",
"Best FN ⬇️",
"Best TN ⬆️",
"Submission Date",
]
if dataframe is None or dataframe.empty:
empty_df = pd.DataFrame(columns=valid_cols)
column_to_type = {c.name: c.type for c in team_columns}
datatypes = []
for col in valid_cols:
dtype = column_to_type.get(col, "str")
if not dtype or dtype == "":
dtype = "str"
datatypes.append(dtype)
print(empty_df)
print(datatypes)
search_col = TeamColumn.team_name.name if TeamColumn.team_name.name in valid_cols else valid_cols[0]
return Leaderboard(
value=empty_df,
datatype=datatypes,
search_columns=[search_col],
select_columns=SelectColumns(
default_selection=valid_cols,
cant_deselect=[search_col],
label="Select Columns to Display:",
),
filter_columns=[],
hide_columns=[],
interactive=False,
height=800,
)
dataframe = dataframe[
[col for col in dataframe.columns if col is not None and isinstance(col, str) and col.strip() != ""]
]
if dataframe.empty or len(dataframe.columns) == 0:
dataframe = pd.DataFrame(columns=valid_cols)
missing_cols = [col for col in valid_cols if col not in dataframe.columns]
for col in missing_cols:
dataframe[col] = None
dataframe = dataframe[valid_cols]
column_to_type = {c.name: c.type for c in team_columns}
datatypes = []
for col in dataframe.columns:
dtype = column_to_type.get(col, "str")
if not dtype or dtype == "":
dtype = "str"
datatypes.append(dtype)
default_selection = [
c.name for c in team_columns if getattr(c, "displayed_by_default", False) and c.name in dataframe.columns
]
cant_deselect = [c.name for c in team_columns if getattr(c, "never_hidden", False) and c.name in dataframe.columns]
hide_cols = [c.name for c in team_columns if getattr(c, "hidden", False) and c.name in dataframe.columns]
search_cols = []
if hasattr(TeamColumn, "team_name") and hasattr(TeamColumn.team_name, "name"):
search_col_name = TeamColumn.team_name.name
if search_col_name and search_col_name in dataframe.columns:
search_cols = [search_col_name]
return Leaderboard(
value=dataframe,
datatype=datatypes,
select_columns=SelectColumns(
default_selection=default_selection if default_selection else [],
cant_deselect=cant_deselect if cant_deselect else [],
label="Select Columns to Display:",
),
search_columns=search_cols if search_cols else [],
hide_columns=hide_cols if hide_cols else [],
filter_columns=[],
interactive=False,
height=800,
)
def register_team_ui(team_name: str, num_teammates: int):
try:
num_teammates_int = int(num_teammates)
except (ValueError, TypeError):
return styled_error("Number of teammates must be a valid integer.")
try:
token, team_data = create_team(team_name, num_teammates_int)
return styled_message(
f"Team '{team_name}' registered successfully!\n\n"
f"**IMPORTANT: Save your token now - you won't be able to see it again!**\n\n"
f"Your team token: `{token}`\n\n"
f"Use this token to submit your predictions."
)
except ValueError as e:
return styled_error(str(e))
except Exception as e:
return styled_error(f"Registration failed: {str(e)}")
def submit_csv_ui(token: str, csv_file):
updated_leaderboard_df = get_leaderboard_df(SUBMISSIONS_PATH, COLS)
if not token or not token.strip():
accepted, rejected, all_subs = get_submission_queue_df(SUBMISSIONS_PATH, SUBMISSION_COLS)
return styled_error("Please provide your team token."), updated_leaderboard_df, accepted, rejected, all_subs
if csv_file is None:
accepted, rejected, all_subs = get_submission_queue_df(SUBMISSIONS_PATH, SUBMISSION_COLS)
return styled_error("Please upload a CSV file."), updated_leaderboard_df, accepted, rejected, all_subs
try:
with open(csv_file.name, "r") as f:
csv_content = f.read()
except Exception as e:
accepted, rejected, all_subs = get_submission_queue_df(SUBMISSIONS_PATH, SUBMISSION_COLS)
return styled_error(f"Could not read CSV file: {str(e)}"), updated_leaderboard_df, accepted, rejected, all_subs
success, message = submit_csv(token, csv_content)
updated_leaderboard_df = get_leaderboard_df(SUBMISSIONS_PATH, COLS)
accepted, rejected, all_subs = get_submission_queue_df(SUBMISSIONS_PATH, SUBMISSION_COLS)
if success:
return styled_message(message), updated_leaderboard_df, accepted, rejected, all_subs
else:
return styled_error(message), updated_leaderboard_df, accepted, rejected, all_subs
def refresh_leaderboard():
fresh_df = get_leaderboard_df(SUBMISSIONS_PATH, COLS)
return fresh_df
def refresh_submission_history():
accepted, rejected, all_subs = get_submission_queue_df(SUBMISSIONS_PATH, SUBMISSION_COLS)
return accepted, rejected, all_subs
logo_image_path = os.path.abspath("assets/logo.png")
demo = gr.Blocks(css=custom_css, theme=gr.themes.Soft())
with demo:
with gr.Row(elem_id="title-row"):
with gr.Column(scale=0, min_width=120):
gr.Image(
value=logo_image_path,
show_label=False,
container=False,
height=120,
width=120,
show_download_button=False,
show_fullscreen_button=False,
show_share_button=False,
interactive=False,
)
with gr.Column(scale=1):
gr.HTML(TITLE)
gr.Markdown(INTRODUCTION_TEXT, elem_classes="markdown-text")
with gr.Tabs(elem_classes="tab-buttons") as tabs:
with gr.TabItem("πŸ… Leaderboard", elem_id="leaderboard-tab", id=0):
leaderboard = init_leaderboard(LEADERBOARD_DF)
with gr.TabItem("πŸ“ About", elem_id="about-tab", id=1):
gr.Markdown(LLM_BENCHMARKS_TEXT, elem_classes="markdown-text")
with gr.TabItem("πŸ‘₯ Register Team", elem_id="register-tab", id=2):
with gr.Column():
gr.Markdown("## Create Your Team", elem_classes="markdown-text")
gr.Markdown(
"Register your team to participate in the hackathon. "
"You will receive a token that you'll need to submit predictions.",
elem_classes="markdown-text",
)
with gr.Row():
with gr.Column():
team_name_input = gr.Textbox(
label="Team Name",
placeholder="Enter your team name",
interactive=True,
)
num_teammates_input = gr.Number(
label="Number of Teammates",
value=1,
minimum=1,
maximum=100,
step=1,
interactive=True,
)
register_button = gr.Button("Register Team", variant="primary")
registration_result = gr.Markdown()
register_button.click(
register_team_ui,
[team_name_input, num_teammates_input],
registration_result,
)
with gr.TabItem("πŸš€ Submit Predictions", elem_id="submit-tab", id=3):
with gr.Column():
gr.Markdown("## Submit Your Predictions", elem_classes="markdown-text")
gr.Markdown(
"Upload a CSV file with your predictions. The CSV must have two columns: "
"`id` (UUID) and `label` (must be exactly `0.0` or `1.0`). All IDs from the test set must be included.",
elem_classes="markdown-text",
)
with gr.Row():
with gr.Column():
token_input = gr.Textbox(
label="Team Token",
placeholder="Enter your team token",
type="password",
interactive=True,
)
csv_file_input = gr.File(
label="CSV File",
file_types=[".csv"],
interactive=True,
)
submit_button = gr.Button("Submit CSV", variant="primary")
submission_result = gr.Markdown()
with gr.Accordion("πŸ“Š Submission History", open=False):
with gr.Tabs():
with gr.TabItem("βœ… Accepted Submissions"):
accepted_table = gr.components.Dataframe(
value=accepted_submissions_df,
datatype=SUBMISSION_TYPES,
row_count=10,
)
with gr.TabItem("❌ Rejected Submissions"):
rejected_table = gr.components.Dataframe(
value=rejected_submissions_df,
datatype=SUBMISSION_TYPES,
row_count=10,
)
with gr.TabItem("πŸ“‹ All Submissions"):
all_table = gr.components.Dataframe(
value=all_submissions_df,
datatype=SUBMISSION_TYPES,
row_count=10,
)
submit_button.click(
submit_csv_ui,
[token_input, csv_file_input],
[submission_result, leaderboard, accepted_table, rejected_table, all_table],
)
demo.load(
lambda: (refresh_leaderboard(), *refresh_submission_history()),
outputs=[leaderboard, accepted_table, rejected_table, all_table],
)
if __name__ == "__main__":
scheduler = BackgroundScheduler()
scheduler.add_job(restart_space, "interval", seconds=1800)
scheduler.start()
demo.queue(default_concurrency_limit=40).launch(
allowed_paths=[logo_image_path],
)