import logging from datetime import datetime, timezone import pathlib import tempfile import json from pathlib import Path import httpx import gradio import gradio as gr import pandas as pd from huggingface_hub import hf_hub_download, HfApi from huggingface_hub.errors import EntryNotFoundError from about import API, SUBMISSIONS_REPO, RESULTS_REPO, TOKEN, REGISTRATION_REPO from components.registration.config import TEAMS_FILE_NAME, TEAM_COLUMNS from evaluation import evaluate_problem logger = logging.getLogger(__name__) def make_user_clickable(name): link = f"https://huggingface.co/{name}" return f'{name}' def make_boundary_clickable(filename): link = f"https://huggingface.co/datasets/proxima-fusion/constellaration-bench-results/blob/main/{filename}" return f'link' def read_result_from_hub(filename): local_path = hf_hub_download( repo_id=RESULTS_REPO, repo_type="dataset", filename=filename, ) return local_path def read_submission_from_hub(filename): local_path = hf_hub_download( repo_id=SUBMISSIONS_REPO, repo_type="dataset", filename=filename, ) return local_path def write_results(record, result): record.update(result) record["result_filename"] = ( record["submission_filename"].rstrip(".json") + "_results.json" ) record["evaluated"] = True record["objectives"] = json.dumps(record.get("objectives", [])) record["feasibilities"] = json.dumps(record.get("feasibility", [])) if "objective" not in record.keys(): record["objective"] = 0.0 record["minimize_objective"] = True record["feasibility"] = sum(record["feasibility"]) / len(record["feasibility"]) with tempfile.NamedTemporaryFile(mode="w", suffix=".json", delete=False) as tmp: json.dump(record, tmp) tmp.flush() tmp_name = tmp.name API.upload_file( path_or_fileobj=tmp_name, path_in_repo=record["result_filename"], repo_id=RESULTS_REPO, repo_type="dataset", commit_message=f"Add result data for {record['result_filename']}", ) pathlib.Path(tmp_name).unlink() return def get_user(profile: gr.OAuthProfile | None) -> str: if profile is None: return "Please login to submit a boundary for evaluation." return profile.username def evaluate_boundary(filename): local_path = read_submission_from_hub(filename) with Path(local_path).open("r") as f: raw = f.read() data_dict = json.loads(raw) try: result = evaluate_problem(local_path) except Exception as e: raise gr.Error( f"Evaluation failed: {e}. No results written to results dataset." ) write_results(data_dict, result) return def show_output_box(message): return gr.update(value=message, visible=True) def push_data_to_dataset(df: pd.DataFrame, repo_id: str, filename: str) -> None: """Upload a DataFrame as a UTF-8 CSV file to the HF dataset repository.""" api = HfApi(token=TOKEN) csv_bytes = df.to_csv(index=False).encode("utf-8") api.upload_file( path_or_fileobj=csv_bytes, path_in_repo=filename, repo_id=repo_id, repo_type="dataset", commit_message=f"upsert {filename} – {datetime.now(timezone.utc).isoformat()}", ) def load_data_from_dataset( repo_id: str, filename: str, columns: list[str] ) -> pd.DataFrame: """ Download a CSV file from the HF dataset and return a DataFrame. :param repo_id: The HF dataset repository ID. :param filename: The name of the CSV file to load. :return: Returns the dataset if the file exists. Otherwise, an empty DataFrame with the correct columns. """ try: path = hf_hub_download( repo_id=repo_id, filename=filename, repo_type="dataset", token=TOKEN, ) df = pd.read_csv(path, dtype=str).fillna("") for col in columns: if col not in df.columns: df[col] = "" return df[columns] except EntryNotFoundError: return pd.DataFrame(columns=columns) except Exception as exc: logger.error("Failed to load %s from %s: %s", filename, repo_id, exc) raise def get_team(teams_df: pd.DataFrame, team_name: str) -> pd.Series | None: """Get the team record from teams_df corresponding to given team_name.""" rows = teams_df[teams_df["team_name"] == team_name] return rows.iloc[0] if not rows.empty else None def check_team_has_leader(team_name: str) -> bool: """Return True if the team exists and has a designated leader.""" try: teams_df = load_data_from_dataset( REGISTRATION_REPO, TEAMS_FILE_NAME, TEAM_COLUMNS ) except Exception: return False team = get_team(teams_df, team_name) if team is None: return False return bool((team.get("leader_username") or "").strip()) def prefill_user_info( oauth_profile: gradio.OAuthProfile | None, oauth_token: gradio.OAuthToken | None, ): empty = lambda: gr.update(value="", placeholder="Log in with HuggingFace first") if oauth_profile is None or oauth_token is None: return empty(), empty(), empty() try: resp = httpx.get( "https://huggingface.co/oauth/userinfo", headers={"Authorization": f"Bearer {oauth_token.token}"}, timeout=5, ) resp.raise_for_status() email = resp.json().get("email", "") except Exception: email = '' return ( gr.update(value=oauth_profile.username), gr.update(value=oauth_profile.name), gr.update(value=email), )