Spaces:
Sleeping
Sleeping
| import os | |
| import gradio as gr | |
| import requests | |
| import pandas as pd | |
| from agents import LangAgent | |
| # (Keep Constants as is) | |
| # --- Constants --- | |
| DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space" | |
| def resolve_user(profile: gr.OAuthProfile | None): | |
| if not profile: | |
| print("User not logged in.") | |
| return None, "Please Login to Hugging Face with the button." | |
| username = f"{profile.username}" | |
| print(f"User logged in: {username}") | |
| return username, None | |
| def build_agent(): | |
| try: | |
| return LangAgent(), None | |
| except Exception as e: | |
| print(f"Error instantiating agent: {e}") | |
| return None, f"Error initializing agent: {e}" | |
| def build_agent_code(space_id: str | None): | |
| return f"https://huggingface.co/spaces/{space_id}/tree/main" | |
| def fetch_questions(questions_url: str): | |
| print(f"Fetching questions from: {questions_url}") | |
| try: | |
| response = requests.get(questions_url, timeout=15) | |
| response.raise_for_status() | |
| questions_data = response.json() | |
| if not questions_data: | |
| print("Fetched questions list is empty.") | |
| return None, "Fetched questions list is empty or invalid format." | |
| print(f"Fetched {len(questions_data)} questions.") | |
| return questions_data, None | |
| except requests.exceptions.RequestException as e: | |
| print(f"Error fetching questions: {e}") | |
| return None, f"Error fetching questions: {e}" | |
| except requests.exceptions.JSONDecodeError as e: | |
| print(f"Error decoding JSON response from questions endpoint: {e}") | |
| return None, f"Error decoding server response for questions: {e}" | |
| except Exception as e: | |
| print(f"An unexpected error occurred fetching questions: {e}") | |
| return None, f"An unexpected error occurred fetching questions: {e}" | |
| def log_backend_file_status(with_file, total_count: int, api_url: str): | |
| without_file = total_count - len(with_file) | |
| print(f"Questions with file_name set: {len(with_file)}; without: {without_file}") | |
| for q in with_file: | |
| print(f"Task {q.get('task_id')} expects file: {q.get('file_name')}") | |
| for q in with_file: | |
| task_id = q.get("task_id") | |
| file_url = f"{api_url}/files/{task_id}" | |
| try: | |
| probe = requests.get(file_url, timeout=15) | |
| print( | |
| f"Attempted access to resource at {file_url} -> " | |
| f"status {probe.status_code}, " | |
| f"content-type {probe.headers.get('content-type')}, " | |
| f"bytes {len(probe.content)}" | |
| ) | |
| except Exception as e: | |
| print(f"Attempted access to resource at {file_url} -> error: {e}") | |
| def get_hf_token(profile: gr.OAuthProfile | None): | |
| token = None | |
| if profile: | |
| try: | |
| print("Profile attributes:", list(profile.__dict__.keys())) | |
| except Exception as e: | |
| print(f"Could not inspect profile attributes: {e}") | |
| for attr in ("access_token", "token"): | |
| token = getattr(profile, attr, None) | |
| if token: | |
| print(f"Using token from profile.{attr}") | |
| break | |
| if not token: | |
| for attr in ("tokens", "auth"): | |
| container = getattr(profile, attr, None) | |
| if isinstance(container, dict): | |
| token = container.get("access_token") or container.get("token") | |
| if token: | |
| print(f"Using token from profile.{attr}") | |
| break | |
| if not token: | |
| token = ( | |
| os.getenv("HF_TOKEN") | |
| or os.getenv("HUGGINGFACEHUB_API_TOKEN") | |
| or os.getenv("HUGGINGFACE_HUB_TOKEN") | |
| ) | |
| if token: | |
| print("Using token from environment.") | |
| if not token: | |
| try: | |
| try: | |
| from huggingface_hub import HfFolder # older versions | |
| except Exception: | |
| from huggingface_hub.hf_api import HfFolder # fallback for space runtime | |
| token = HfFolder.get_token() | |
| if token: | |
| print("Using token from local HF cache (huggingface-cli login).") | |
| except Exception as e: | |
| print(f"Could not load token from local HF cache: {e}") | |
| if token: | |
| # Avoid printing full token; show a short preview for debugging. | |
| print(f"HF token obtained (length {len(token)}).") | |
| else: | |
| print("No HF token available from profile or environment.") | |
| return token | |
| def download_gaia_file(file_name: str, token: str | None): | |
| """Download a GAIA validation file by name from the pinned revision.""" | |
| try: | |
| from huggingface_hub import hf_hub_download | |
| except Exception as e: | |
| print(f"Cannot download {file_name}: huggingface_hub unavailable ({e}).") | |
| return None | |
| repo_id = "gaia-benchmark/GAIA" | |
| revision = "86620fe7a265fdd074ea8d8c8b7a556a1058b0af" | |
| path_in_repo = f"2023/validation/{file_name}" | |
| try: | |
| local_path = hf_hub_download( | |
| repo_id=repo_id, | |
| filename=path_in_repo, | |
| repo_type="dataset", | |
| token=token, # can be None if huggingface-cli cache is available | |
| revision=revision, | |
| ) | |
| print(f"Downloaded GAIA file {file_name} to {local_path}") | |
| return local_path | |
| except Exception as e: | |
| print(f"Failed to download GAIA file {file_name}: {e}") | |
| return None | |
| def resolve_file(file_name: str | None, token: str | None): | |
| if not file_name: | |
| return None | |
| # Prefer local cache if present. | |
| candidate = os.path.join("validation", file_name) | |
| if os.path.exists(candidate): | |
| print(f"Local file found: {candidate}") | |
| return candidate | |
| print(f"No local file found (expected {candidate}), trying GAIA download.") | |
| return download_gaia_file(file_name, token) | |
| def run_agent_on_questions(agent, questions_data, token: str | None): | |
| results_log = [] | |
| answers_payload = [] | |
| print(f"Running agent on {len(questions_data)} questions...") | |
| for item in questions_data: | |
| task_id = item.get("task_id") | |
| question_text = item.get("question") | |
| file_name = item.get("file_name") | |
| file_path = resolve_file(file_name, token) | |
| if not task_id or question_text is None: | |
| print(f"Skipping item with missing task_id or question: {item}") | |
| continue | |
| try: | |
| submitted_answer = agent(question_text, file_path=file_path) | |
| answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer}) | |
| results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": submitted_answer}) | |
| except Exception as e: | |
| print(f"Error running agent on task {task_id}: {e}") | |
| results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": f"AGENT ERROR: {e}"}) | |
| return answers_payload, results_log | |
| def submit_answers(submit_url: str, username: str, agent_code: str, answers_payload, results_log): | |
| submission_data = {"username": username.strip(), "agent_code": agent_code, "answers": answers_payload} | |
| status_update = f"Agent finished. Submitting {len(answers_payload)} answers for user '{username}'..." | |
| print(status_update) | |
| print(f"Submitting {len(answers_payload)} answers to: {submit_url}") | |
| try: | |
| response = requests.post(submit_url, json=submission_data, timeout=60) | |
| response.raise_for_status() | |
| result_data = response.json() | |
| final_status = ( | |
| f"Submission Successful!\n" | |
| f"User: {result_data.get('username')}\n" | |
| f"Overall Score: {result_data.get('score', 'N/A')}% " | |
| f"({result_data.get('correct_count', '?')}/{result_data.get('total_attempted', '?')} correct)\n" | |
| f"Message: {result_data.get('message', 'No message received.')}" | |
| ) | |
| print("Submission successful.") | |
| results_df = pd.DataFrame(results_log) | |
| return final_status, results_df | |
| except requests.exceptions.HTTPError as e: | |
| error_detail = f"Server responded with status {e.response.status_code}." | |
| try: | |
| error_json = e.response.json() | |
| error_detail += f" Detail: {error_json.get('detail', e.response.text)}" | |
| except requests.exceptions.JSONDecodeError: | |
| error_detail += f" Response: {e.response.text[:500]}" | |
| status_message = f"Submission Failed: {error_detail}" | |
| print(status_message) | |
| results_df = pd.DataFrame(results_log) | |
| return status_message, results_df | |
| except requests.exceptions.Timeout: | |
| status_message = "Submission Failed: The request timed out." | |
| print(status_message) | |
| results_df = pd.DataFrame(results_log) | |
| return status_message, results_df | |
| except requests.exceptions.RequestException as e: | |
| status_message = f"Submission Failed: Network error - {e}" | |
| print(status_message) | |
| results_df = pd.DataFrame(results_log) | |
| return status_message, results_df | |
| except Exception as e: | |
| status_message = f"An unexpected error occurred during submission: {e}" | |
| print(status_message) | |
| results_df = pd.DataFrame(results_log) | |
| return status_message, results_df | |
| def run_and_submit_all(profile: gr.OAuthProfile | None): | |
| """ | |
| Fetch questions, run the agent, and submit answers. | |
| """ | |
| space_id = os.getenv("SPACE_ID") | |
| api_url = DEFAULT_API_URL | |
| questions_url = f"{api_url}/questions" | |
| submit_url = f"{api_url}/submit" | |
| username, user_error = resolve_user(profile) | |
| if user_error: | |
| return user_error, None | |
| agent, agent_error = build_agent() | |
| if agent_error: | |
| return agent_error, None | |
| agent_code = build_agent_code(space_id) | |
| print(agent_code) | |
| questions_data, fetch_error = fetch_questions(questions_url) | |
| if fetch_error: | |
| return fetch_error, None | |
| with_file = [q for q in questions_data if q.get("file_name")] | |
| log_backend_file_status(with_file, len(questions_data), api_url) | |
| token = get_hf_token(profile) | |
| answers_payload, results_log = run_agent_on_questions(agent, questions_data, token) | |
| if not answers_payload: | |
| print("Agent did not produce any answers to submit.") | |
| return "Agent did not produce any answers to submit.", pd.DataFrame(results_log) | |
| return submit_answers(submit_url, username, agent_code, answers_payload, results_log) | |
| # --- Build Gradio Interface using Blocks --- | |
| with gr.Blocks() as demo: | |
| gr.Markdown("# Basic Agent Evaluation Runner") | |
| gr.Markdown( | |
| """ | |
| **Instructions:** | |
| 1. Please clone this space, then modify the code to define your agent's logic, the tools, the necessary packages, etc ... | |
| 2. Log in to your Hugging Face account using the button below. This uses your HF username for submission. | |
| 3. Click 'Run Evaluation & Submit All Answers' to fetch questions, run your agent, submit answers, and see the score. | |
| --- | |
| **Disclaimers:** | |
| Once clicking on the "submit button, it can take quite some time ( this is the time for the agent to go through all the questions). | |
| This space provides a basic setup and is intentionally sub-optimal to encourage you to develop your own, more robust solution. For instance for the delay process of the submit button, a solution could be to cache the answers and submit in a seperate action or even to answer the questions in async. | |
| """ | |
| ) | |
| gr.LoginButton() | |
| run_button = gr.Button("Run Evaluation & Submit All Answers") | |
| status_output = gr.Textbox(label="Run Status / Submission Result", lines=5, interactive=False) | |
| # Removed max_rows=10 from DataFrame constructor | |
| results_table = gr.DataFrame(label="Questions and Agent Answers", wrap=True) | |
| run_button.click( | |
| fn=run_and_submit_all, | |
| outputs=[status_output, results_table] | |
| ) | |
| if __name__ == "__main__": | |
| print("\n" + "-"*30 + " App Starting " + "-"*30) | |
| # Check for SPACE_HOST and SPACE_ID at startup for information | |
| space_host_startup = os.getenv("SPACE_HOST") | |
| space_id_startup = os.getenv("SPACE_ID") # Get SPACE_ID at startup | |
| if space_host_startup: | |
| print(f"✅ SPACE_HOST found: {space_host_startup}") | |
| print(f" Runtime URL should be: https://{space_host_startup}.hf.space") | |
| else: | |
| print("ℹ️ SPACE_HOST environment variable not found (running locally?).") | |
| if space_id_startup: # Print repo URLs if SPACE_ID is found | |
| print(f"✅ SPACE_ID found: {space_id_startup}") | |
| print(f" Repo URL: https://huggingface.co/spaces/{space_id_startup}") | |
| print(f" Repo Tree URL: https://huggingface.co/spaces/{space_id_startup}/tree/main") | |
| else: | |
| print("ℹ️ SPACE_ID environment variable not found (running locally?). Repo URL cannot be determined.") | |
| print("-"*(60 + len(" App Starting ")) + "\n") | |
| print("Launching Gradio Interface for Basic Agent Evaluation...") | |
| demo.launch(debug=True, share=False) | |