hack-a-thon / app.py
KuuwangE's picture
feat<fancy>: leaderboard
18aba38 unverified
import os
import shutil
from datetime import datetime
from typing import List
import gradio as gr
import pandas as pd
from huggingface_hub import snapshot_download, upload_file
from gradio_leaderboard import Leaderboard
# ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ์— ๋งž์ถฐ import (src.*)
from src.envs import RESULTS_REPO, EVAL_RESULTS_PATH
from src.grader import grade # grade(submission_df, team_id) -> (score_df, report_dir)
# ---------------------------
# ํŒ€ ๋น„๋ฐ€๋ฒˆํ˜ธ ๋งคํ•‘ (์š”์ฒญ ๋ฐ˜์˜)
# ---------------------------
TEAM_PWD_MAP = {
"02Aug#29112#h": "JN_HACK13",
"02Aug!86113!g": "JN_HACK14",
"02Aug#33114#h": "JN_HACK15",
}
# ์ €์žฅ ํŒŒ์ผ๋ช… (๋ฆฌ๋”๋ณด๋“œ ์ง‘๊ณ„)
HISTORY_NAME = "graded_results.csv"
HISTORY_PATH = os.path.join(EVAL_RESULTS_PATH, HISTORY_NAME)
# ---------------------------
# ์ดˆ๊ธฐํ™”: Space ์žฌ์‹œ์ž‘ ๋Œ€๋น„
# ---------------------------
def init_cache() -> pd.DataFrame:
"""
- RESULTS_REPO ์Šค๋ƒ…์ƒท์„ EVAL_RESULTS_PATH๋กœ ๋‹ค์šด๋กœ๋“œ(๋™๊ธฐํ™”)
- graded_results.csv ๋กœ๋“œ (์—†์œผ๋ฉด ๋นˆ DF ์ƒ์„ฑ)
"""
os.makedirs(EVAL_RESULTS_PATH, exist_ok=True)
try:
snapshot_download(
repo_id=RESULTS_REPO,
repo_type="dataset",
local_dir=EVAL_RESULTS_PATH,
tqdm_class=None,
etag_timeout=30,
token=os.environ.get("HF_TOKEN"),
)
except Exception as e:
print(f"[WARN] snapshot_download failed: {e}")
if os.path.exists(HISTORY_PATH):
try:
df = pd.read_csv(HISTORY_PATH)
except Exception as e:
print(f"[WARN] failed to read {HISTORY_NAME}: {e}")
df = pd.DataFrame()
else:
df = pd.DataFrame()
# ์ตœ์†Œ ์Šคํ‚ค๋งˆ ๋ณด์ •
for col in ["TEAM", "TIMESTAMP"]:
if col not in df.columns:
df[col] = []
return df
# ์ „์—ญ ํžˆ์Šคํ† ๋ฆฌ ์ƒํƒœ (์•ฑ ๋ถ€ํŒ… ์‹œ ๋กœ๋“œ)
history_state = init_cache()
def save_and_upload_history(history_df: pd.DataFrame) -> None:
"""
- ๋กœ์ปฌ graded_results.csv ์ €์žฅ
- RESULTS_REPO์— ๋ฎ์–ด์“ฐ๊ธฐ ์—…๋กœ๋“œ
"""
history_df.to_csv(HISTORY_PATH, index=False)
upload_file(
path_or_fileobj=HISTORY_PATH,
path_in_repo=HISTORY_NAME,
repo_id=RESULTS_REPO,
repo_type="dataset",
token=os.environ.get("HF_TOKEN"),
)
# ---------------------------
# ์ฑ„์  ํ•ธ๋“ค๋Ÿฌ
# ---------------------------
def grade_csv(passwd: str, file):
global history_state
if file is None:
raise gr.Error("ํŒŒ์ผ ์—…๋กœ๋“œ๊ฐ€ ๋ˆ„๋ฝ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.")
team_id = TEAM_PWD_MAP.get((passwd or "").strip(), "UNKNOWN")
# if not team_id:
# raise gr.Error("๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ์˜ฌ๋ฐ”๋ฅด์ง€ ์•Š์Šต๋‹ˆ๋‹ค.")
# ์ œ์ถœ CSV ๋กœ๋“œ
submission_df = pd.read_csv(file.name)
# ์ฑ„์  ๋ฐ ๋ฆฌํฌํŠธ ์ƒ์„ฑ
score_df, report_dir = grade(submission_df, team_id=team_id)
# ๋ฉ”ํƒ€ ์†์„ฑ ๋ถ€์—ฌ
ts = datetime.utcnow().strftime("%Y-%m-%d %H:%M:%SZ")
score_df.insert(0, "TEAM", team_id)
score_df.insert(1, "TIMESTAMP", ts)
# ๊ธฐ์กด ํžˆ์Šคํ† ๋ฆฌ ๋กœ๋“œ(์—†์œผ๋ฉด ๋นˆ DF)
if os.path.exists(HISTORY_PATH):
try:
saved_df = pd.read_csv(HISTORY_PATH)
except Exception:
saved_df = pd.DataFrame()
else:
saved_df = pd.DataFrame()
# ์ตœ์†Œ ์Šคํ‚ค๋งˆ ํ†ต์ผ
for col in set(["TEAM", "TIMESTAMP"]) - set(saved_df.columns):
saved_df[col] = []
# ํžˆ์Šคํ† ๋ฆฌ append
merged_score = pd.concat([saved_df, score_df], ignore_index=True)
history_state = merged_score.copy() # ์ „์—ญ ์ƒํƒœ ๊ฐฑ์‹ 
# ๋กœ์ปฌ ์ €์žฅ + Hub ์—…๋กœ๋“œ
save_and_upload_history(history_state)
# ๋ฆฌํฌํŠธ ZIP ์ƒ์„ฑ
report_zip = f"report_{team_id}.zip"
shutil.make_archive(f"report_{team_id}", "zip", report_dir)
# ๊ฐค๋Ÿฌ๋ฆฌ ์ด๋ฏธ์ง€ ํŒŒ์ผ ๋ชฉ๋ก
image_files: List[str] = [
os.path.join(report_dir, f)
for f in os.listdir(report_dir)
if f.lower().endswith(".png")
]
# UI ๋ฐ˜ํ™˜: ์ ์ˆ˜ํ‘œ, ZIP, ๊ฐค๋Ÿฌ๋ฆฌ, ๋ฆฌ๋”๋ณด๋“œ ๊ฐฑ์‹ ๋ณธ
return score_df, report_zip, image_files, history_state
def refresh_leaderboard():
"""์‚ฌ์šฉ์ž ์š”์ฒญ ์‹œ Hub ์žฌ๋™๊ธฐํ™” ํ›„ ๋ฆฌ๋”๋ณด๋“œ ๊ฐฑ์‹ ."""
global history_state
history_state = init_cache()
return history_state
# ---------------------------
# UI
# ---------------------------
with gr.Blocks() as demo:
gr.Markdown("## Hackathon with <Caramella Inc.,>")
with gr.Tabs():
with gr.Tab("ํ‰๊ฐ€ ์š”์ฒญ"):
with gr.Row():
with gr.Column():
csv_input = gr.File(label="CSV ์—…๋กœ๋“œ", file_types=[".csv"])
password = gr.Textbox(label="ํŒ€ ๋น„๋ฐ€๋ฒˆํ˜ธ", type="password", placeholder="ํŒ€๋ณ„๋กœ ๊ณต์ง€๋œ ๋น„๋ฐ€๋ฒˆํ˜ธ")
submit_button = gr.Button("ํ‰๊ฐ€ ์š”์ฒญ", variant="primary")
df_output = gr.Dataframe(label="ํ‰๊ฐ€ ์ง€ํ‘œ ๊ฒฐ๊ณผ")
with gr.Column():
report_output = gr.File(label="๋ฆฌํฌํŠธ ZIP ๋‹ค์šด๋กœ๋“œ", height="100px")
image_gallery = gr.Gallery(
label="Plant๋ณ„ ๋น„๊ต ๊ทธ๋ž˜ํ”„",
show_label=True,
height="auto"
)
with gr.Tab("๋ฆฌ๋”๋ณด๋“œ"):
leaderboard_table = Leaderboard(
value=history_state.rename(columns={"TOTAL": "TOTAL โฌ†๏ธ"}),
search_columns=["TEAM", "RMSE_AC", "RMSE_AC_SCALED", "NMAE_RANGE", "NMAE_MEAN", "TOTAL โฌ†๏ธ"],
hide_columns=[], # ์ˆจ๊ธธ ๊ฒŒ ์žˆ์œผ๋ฉด ์—ฌ๊ธฐ์— ์ถ”๊ฐ€
filter_columns=["TEAM"],
label="Leaderboard",
)
with gr.Row():
refresh_btn = gr.Button("๋ฆฌ๋”๋ณด๋“œ ์ƒˆ๋กœ๊ณ ์นจ (Hub ๋™๊ธฐํ™”)")
# ์ƒˆ๋กœ๊ณ ์นจ: Hub โ†’ ๋กœ์ปฌ ์žฌ๋™๊ธฐํ™” ํ›„ ํ…Œ์ด๋ธ” ๊ฐฑ์‹ 
refresh_btn.click(
fn=refresh_leaderboard,
inputs=None,
outputs=leaderboard_table
)
# ์—…๋กœ๋“œ โ†’ ์ฑ„์  ์‹คํ–‰
submit_button.click(
fn=grade_csv,
inputs=[password, csv_input],
outputs=[df_output, report_output, image_gallery, leaderboard_table], # ๋งˆ์ง€๋ง‰์€ ๋ฆฌ๋”๋ณด๋“œ ํƒญ์˜ ํ…Œ์ด๋ธ”์— ์—ฐ๊ฒฐ
queue=True
)
if __name__ == "__main__":
demo.launch()
# demo.launch(debug=True, show_error=True, enable_monitoring=True)