agent-course / app.py
bsenst's picture
Upload folder using huggingface_hub
9b55593 verified
Raw
History Blame Contribute Delete
7.11 kB
"""
app.py
======
Gradio app for the Hugging Face Agents Course - Unit 4 (GAIA leaderboard).
This app exposes the agent (whichever framework solution is shipped in this
Space: smolagents / LangGraph / LlamaIndex) through a simple UI:
* fetch the 20 evaluation questions from the scoring API,
* run the agent on a single question, or on all questions,
* locally self-score (optional, needs HF_TOKEN + GAIA dataset access),
* submit the answers to the leaderboard.
Environment variables (set as Space secrets):
LLM_API_KEY required - key for an OpenAI-compatible endpoint
LLM_BASE_URL optional - default https://api.openai.com/v1
LLM_MODEL optional - default gpt-4o-mini
HF_TOKEN optional - GAIA-dataset file fallback + local self-scoring
VISION_MODEL optional - vision model for image questions
WHISPER_MODEL optional - default 'small' (use 'base'/'tiny' on CPU)
"""
from __future__ import annotations
import os
import gradio as gr
import pandas as pd
import requests
import gaia_common as gc
# --- pick whichever framework solution is bundled in this Space -------------
SOLUTION_MODULES = ["solution_smolagents", "solution_langgraph", "solution_llamaindex"]
for _mod in SOLUTION_MODULES:
try:
solution = __import__(_mod)
FRAMEWORK = _mod
break
except ImportError:
continue
else:
raise RuntimeError("No framework solution module found in this Space.")
def make_agent():
if FRAMEWORK == "solution_smolagents":
return solution.GAIAAgent()
if FRAMEWORK == "solution_langgraph":
return solution.GAIALangGraphAgent()
return solution.GAIALlamaIndexAgent()
# --- core functions ---------------------------------------------------------
def build_question_options() -> list[str]:
try:
qs = gc.fetch_questions()
if qs:
return [f"{q['task_id']} :: {q['question'][:80]}" for q in qs]
except Exception as e:
print(f"Could not fetch questions at startup: {e}")
return ["Questions unavailable at startup - reload after the API is reachable"]
def _run_single(task_id: str, question: str, agent) -> str:
answer = agent(task_id, question)
return gc.normalize_final_answer(answer)
def run_single(selection: str, profile: gr.OAuthProfile | None):
if not profile:
return "Please login with the Login button (required for submission).", None
if not selection:
return "Please choose a question from the dropdown.", None
task_id = selection.split(" :: ")[0]
questions = {q["task_id"]: q["question"] for q in gc.fetch_questions()}
question = questions.get(task_id, "")
try:
agent = make_agent()
answer = _run_single(task_id, question, agent)
return f"QUESTION:\n{question}\n\nANSWER:\n{answer}", pd.DataFrame(
[{"task_id": task_id, "submitted_answer": answer}]
)
except Exception as e:
return f"Agent error: {e}", None
def run_all(submit: bool, profile: gr.OAuthProfile | None) -> tuple[str, pd.DataFrame]:
if not profile:
return "Please login with the Login button.", None
if not os.environ.get("LLM_API_KEY") and not os.environ.get("HF_TOKEN"):
return (
"No LLM credentials found. Set the Space secrets LLM_API_KEY "
"(OpenAI-compatible endpoint) to run the agent.",
None,
)
agent_code = f"https://huggingface.co/spaces/{os.getenv('SPACE_ID', '?')}/tree/main"
username = profile.username
questions = gc.fetch_questions()
rows = []
answers_payload = []
agent = make_agent()
for item in questions:
task_id = item["task_id"]
question = item["question"]
try:
answer = agent(task_id, question)
except Exception as e:
answer = f"AGENT ERROR: {e}"
rows.append({"Task ID": task_id, "Question": question, "Submitted Answer": answer})
answers_payload.append({"task_id": task_id, "submitted_answer": answer})
status = f"Agent finished {len(answers_payload)} questions.\n"
if submit:
try:
res = gc.submit_answers(username, agent_code, answers_payload)
status += (
f"SUBMITTED for {res.get('username')} -> "
f"score {res.get('score')}% ({res.get('correct_count')} correct)."
)
except Exception as e:
status += f"Submission failed: {e}"
else:
local = gc.self_score(answers_payload)
if local.get("total"):
status += f"LOCAL self-score: {local['score']}% ({local['correct']}/{local['total']})."
else:
status += "Local self-scoring skipped (set HF_TOKEN + accept GAIA dataset gating)."
return status, pd.DataFrame(rows)
def run_all_and_submit(profile: gr.OAuthProfile | None):
return run_all(True, profile)
def run_all_selfscore(profile: gr.OAuthProfile | None):
return run_all(False, profile)
# --- UI ---------------------------------------------------------------------
with gr.Blocks(title="GAIA Agent - Unit 4") as demo:
gr.Markdown(
f"# GAIA Level-1 Agent · framework: `{FRAMEWORK}`\n\n"
"Course **Unit 4 hands-on** — answers 20 GAIA level-1 questions and submits "
"them to the leaderboard. The agent uses the canonical GAIA system prompt "
"and a toolbelt: web search, page fetch, file download (with GAIA-dataset "
"fallback), whisper transcription, vision analysis and python execution."
)
with gr.Row():
gr.LoginButton()
questions_dd = gr.Dropdown(
label="Pick a question",
choices=build_question_options(),
allow_custom_value=False,
)
run_single_btn = gr.Button("Run single question")
single_out = gr.Textbox(label="Single-question result", lines=6, interactive=False)
with gr.Row():
run_all_btn = gr.Button("Run all 20 questions (self-score if possible)")
submit_btn = gr.Button("Run all 20 questions AND submit to leaderboard")
status_out = gr.Textbox(label="Status / submission result", lines=8, interactive=False)
results_table = gr.DataFrame(label="Questions and agent answers", wrap=True)
run_single_btn.click(run_single, inputs=[questions_dd], outputs=[single_out])
run_all_btn.click(run_all_selfscore, inputs=[], outputs=[status_out, results_table])
submit_btn.click(run_all_and_submit, inputs=[], outputs=[status_out, results_table])
gr.Markdown(
"### Instructions\n"
"1. This Space runs a real agent — it calls an LLM API and may take several minutes "
"for all 20 questions (audio transcription and YouTube downloads are the slowest).\n"
"2. Set Space secrets: `LLM_API_KEY` (required), optionally `LLM_BASE_URL`, "
"`LLM_MODEL`, `HF_TOKEN`, `VISION_MODEL`, `WHISPER_MODEL`.\n"
"3. Log in, then click **Run all & submit**.\n\n"
"> Keep this Space public so your code link on the leaderboard verifies your submission."
)
if __name__ == "__main__":
demo.launch()