File size: 4,362 Bytes
44a479a
 
5420db5
 
 
 
 
 
9b5b26a
5420db5
44a479a
8c01ffb
5420db5
8c01ffb
5420db5
 
 
44a479a
5420db5
 
 
44a479a
 
 
 
 
 
 
5420db5
 
 
 
44a479a
5420db5
 
44a479a
 
5420db5
 
44a479a
5420db5
 
 
44a479a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5420db5
 
44a479a
 
 
5420db5
44a479a
 
 
 
 
5420db5
44a479a
 
 
 
5420db5
44a479a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5420db5
 
44a479a
5420db5
 
44a479a
 
 
5420db5
44a479a
 
 
 
5420db5
 
 
 
 
8fe992b
9b5b26a
5420db5
44a479a
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
from __future__ import annotations

import os
from collections.abc import Callable
from typing import Any

import gradio as gr
import pandas as pd
import requests

from agent import answer_question

DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"


def space_code_url(space_id: str | None) -> tuple[str, str]:
    if not space_id:
        return "", "SPACE_ID is not configured; agent_code will be empty."
    return f"https://huggingface.co/spaces/{space_id}/tree/main", ""


def _fetch_questions(api_url: str) -> list[dict[str, Any]]:
    response = requests.get(f"{api_url}/questions", timeout=30)
    response.raise_for_status()
    payload = response.json()
    if not isinstance(payload, list) or not payload:
        raise ValueError("The questions endpoint returned an empty or invalid payload.")
    return [item for item in payload if isinstance(item, dict)]


def run_and_submit_all(profile: gr.OAuthProfile | None):
    if not profile:
        return "Please log in to Hugging Face first.", None

    username = str(profile.username).strip()
    api_url = os.getenv("GAIA_API_URL", DEFAULT_API_URL).rstrip("/")
    agent_code, warning = space_code_url(os.getenv("SPACE_ID"))

    try:
        questions = _fetch_questions(api_url)
    except Exception as exc:
        return f"Error fetching questions: {exc}", None

    rows: list[dict[str, Any]] = []
    answers: list[dict[str, str]] = []

    for index, item in enumerate(questions, start=1):
        task_id = str(item.get("task_id") or "").strip()
        question = str(item.get("question") or "")
        file_name = str(item.get("file_name") or "").strip()
        if not task_id or not question:
            continue

        try:
            answer = answer_question(question, file_name=file_name)
            if answer is None:
                status = "skipped_attachment"
                displayed_answer = ""
            else:
                status = "answered"
                displayed_answer = answer
                answers.append({"task_id": task_id, "submitted_answer": answer})
        except Exception as exc:
            status = f"error: {type(exc).__name__}: {exc}"
            displayed_answer = ""

        rows.append(
            {
                "#": index,
                "task_id": task_id,
                "file_name": file_name,
                "status": status,
                "submitted_answer": displayed_answer,
                "question": question,
            }
        )

    frame = pd.DataFrame(rows)
    if not answers:
        return "No answers were produced; nothing was submitted.", frame

    payload = {
        "username": username,
        "agent_code": agent_code,
        "answers": answers,
    }

    try:
        response = requests.post(f"{api_url}/submit", json=payload, timeout=90)
        response.raise_for_status()
        result = response.json()
    except Exception as exc:
        status = f"Submission failed: {exc}"
        if warning:
            status = f"{warning}\n{status}"
        return status, frame

    status = (
        "Submission successful!\n"
        f"User: {result.get('username', username)}\n"
        f"Submitted answers: {len(answers)}/{len(rows)}\n"
        f"Overall score: {result.get('score', 'N/A')}% "
        f"({result.get('correct_count', '?')}/{result.get('total_attempted', '?')} correct)\n"
        f"Message: {result.get('message', 'No message received.')}"
    )
    if warning:
        status = f"{warning}\n{status}"
    return status, frame


def build_demo(login_button_factory: Callable[[], Any] | None = None) -> gr.Blocks:
    with gr.Blocks() as demo:
        gr.Markdown("# GAIA Agent Evaluation Runner")
        gr.Markdown(
            "File-attachment questions are skipped. YouTube questions use Gemini; "
            "all other questions use one LangChain/OpenAI agent."
        )
        (login_button_factory or gr.LoginButton)()
        run_button = gr.Button("Run Evaluation & Submit")
        status_output = gr.Textbox(label="Status", lines=7, interactive=False)
        results_table = gr.DataFrame(label="Question results", wrap=True)
        run_button.click(
            fn=run_and_submit_all,
            outputs=[status_output, results_table],
        )
    return demo


if __name__ == "__main__":
    build_demo().launch(debug=True, share=False)