# app.py — максимально совместимый с Gradio 3.x / ранними 4.x import os import time import pandas as pd import gradio as gr from src.submission.check_validity import check_submission from src.submission.submit import evaluate_submission from src.envs import load_jsonl, CORPUS_PATH from huggingface_hub import hf_hub_download, HfApi HF_TOKEN = os.getenv("HF_TOKEN") LEADERBOARD_PATH = "leaderboard.csv" # Download from a dataset hf_hub_download(repo_id="datakomarov/RAG-LB", filename="leaderboard.csv", repo_type="space", token=HF_TOKEN, local_dir=".") LB_COLUMNS = [ "username", "team", "commit", "Answer not accepted", "Some truth", "Accepted answer", "valid_doc_ratio", "n", "timestamp", ] def ensure_leaderboard(): if not os.path.exists(LEADERBOARD_PATH): print("Something's wrong with reading a LB") def load_corpus_ids(): try: corpus = load_jsonl(CORPUS_PATH) return {str(x["doc_id"]) for x in corpus if "doc_id" in x} except Exception: return set() def parse_submission_doc_ids(file_path: str): sub = load_jsonl(file_path) out = {} for rec in sub: qid = str(rec.get("id")) doc_ids = rec.get("doc_ids", []) if not isinstance(doc_ids, list): doc_ids = [doc_ids] out[qid] = [str(x) for x in doc_ids[:10] if str(x).strip()] return out def compute_valid_doc_ratio(sub_docs, corpus_ids): if not sub_docs: return 0.0 flags = [] for _, ids in sub_docs.items(): if not ids: flags.append(False) else: flags.append(all(i in corpus_ids for i in ids)) return sum(flags) / len(flags) def sort_leaderboard(df): return df.sort_values( by=["Answer not accepted", "Accepted answer", "Some truth", "valid_doc_ratio", "n"], ascending=[True, False, False, False, False], ).reset_index(drop=True) def load_sorted_leaderboard(): ensure_leaderboard() df = pd.read_csv(LEADERBOARD_PATH) if df.empty: return df df = sort_leaderboard(df).reset_index(drop=False) df['Place'] = df['index'] + 1 df = df[['Place'] + LB_COLUMNS] return df def submit_file(file_obj, username, team, commit): ensure_leaderboard() username = (username or "").strip() team = (team or "").strip() commit = (commit or "").strip() if not username: return "❌ Please provide username", load_sorted_leaderboard() if file_obj is None: return "❌ Please upload JSONL file", load_sorted_leaderboard() file_path = file_obj.name ok, msg = check_submission(file_path) if not ok: return f"❌ Invalid submission: {msg}", load_sorted_leaderboard() try: result = evaluate_submission(file_path) except Exception as e: return f"❌ Eval failed: {e}", load_sorted_leaderboard() corpus_ids = load_corpus_ids() sub_docs = parse_submission_doc_ids(file_path) valid_ratio = compute_valid_doc_ratio(sub_docs, corpus_ids) row = { "timestamp": time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime()), "username": username, "team": team, "commit": commit, "Answer not accepted": result["zeros"], "Some truth": result["ones"], "Accepted answer": result["twos"], "valid_doc_ratio": valid_ratio, "n": result["n"], } df = pd.read_csv(LEADERBOARD_PATH) df.loc[len(df)] = row df.to_csv(LEADERBOARD_PATH, index=False) df = sort_leaderboard(df) api = HfApi() api.upload_file( path_or_fileobj=LEADERBOARD_PATH, path_in_repo=LEADERBOARD_PATH, repo_id="datakomarov/RAG-LB", repo_type="space", ) summary = ( f"✅ Submitted! " f"N={row['n']} | Answer not accepted:{row['Answer not accepted']} Some truth:{row['Some truth']} Accepted answer:{row['Accepted answer']} | " f"doc_ratio={valid_ratio:.1%}" ) return summary, df def build_ui(): ensure_leaderboard() with gr.Blocks(title="RAG Leaderboard") as demo: gr.Markdown("# 🏁 RAG Benchmark") # ===== 1) Лидерборд сверху ===== gr.Markdown("## 📊 Leaderboard") out_df = gr.Dataframe( value=load_sorted_leaderboard(), interactive=False, wrap=True, label="", ) # маленькая кнопка refresh, чтобы вручную обновлять таблицу refresh_btn = gr.Button("🔄 Refresh leaderboard", variant="secondary") refresh_btn.click( fn=lambda: load_sorted_leaderboard(), inputs=[], outputs=[out_df], ) gr.Markdown("---") # ===== 2) Форма сабмита снизу ===== gr.Markdown("## 📤 Submit your run") file_in = gr.File(label="Upload JSONL submission") username_in = gr.Text(label="Username (required)") team_in = gr.Text(label="Team (optional)") commit_in = gr.Text(label="Commit/tag (optional)") submit_btn = gr.Button("Submit", variant="primary") out_msg = gr.Markdown() submit_btn.click( submit_file, inputs=[file_in, username_in, team_in, commit_in], outputs=[out_msg, out_df], # обновляем и сообщение, и таблицу ) return demo if __name__ == "__main__": app = build_ui() app.launch() # server_name="0.0.0.0", server_port=7860)