File size: 5,373 Bytes
1b9894c
 
 
c13f646
77fb5d6
358fc92
c13f646
97a7e44
77fb5d6
358fc92
 
 
97a7e44
 
 
 
c13f646
 
 
97a7e44
1b9894c
 
358fc92
 
 
 
 
 
97a7e44
f7ccc0d
 
 
97a7e44
f7ccc0d
1b9894c
 
97a7e44
 
 
 
 
 
 
 
 
 
 
ba339f9
 
 
 
 
 
 
 
 
 
 
 
 
 
97a7e44
1b9894c
c13f646
 
 
 
97a7e44
 
 
 
 
 
 
1b9894c
c13f646
97a7e44
c13f646
1b9894c
 
 
c13f646
1b9894c
97a7e44
1b9894c
97a7e44
 
 
c13f646
 
1b9894c
c13f646
1b9894c
 
 
c13f646
 
1b9894c
c13f646
 
1b9894c
97a7e44
1b9894c
c13f646
97a7e44
 
 
 
1b9894c
97a7e44
 
 
1b9894c
 
c13f646
1b9894c
 
c13f646
 
97a7e44
1b9894c
 
97a7e44
1b9894c
97a7e44
c13f646
 
 
97a7e44
c13f646
 
 
 
1b9894c
c13f646
1b9894c
 
 
97a7e44
1b9894c
97a7e44
c13f646
97a7e44
 
 
c13f646
1b9894c
 
 
97a7e44
c13f646
1b9894c
97a7e44
1b9894c
 
97a7e44
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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
import os
import requests
import pandas as pd
import gradio as gr

from smolagents import CodeAgent, DuckDuckGoSearchTool, TransformersModel

DEFAULT_API_URL = os.getenv("DEFAULT_API_URL", "https://agents-course-unit4-scoring.hf.space")

# You can override the model via the MODEL_ID Space variable.
# Use a small instruct/chat model so the agent can plan and call tools reliably.
DEFAULT_MODEL_ID = os.getenv("MODEL_ID", "HuggingFaceTB/SmolLM2-1.7B-Instruct")


# DuckDuckGo-based Wikipedia-style tool (just rename + description)
class WikipediaSearchTool(DuckDuckGoSearchTool):
    name = "wikipedia_search"
    description = "Search Wikipedia-style information using DuckDuckGo backend."


class BasicAgent:
    def __init__(self):
        # Use the official smolagents TransformersModel wrapper so the agent
        # can properly handle chat messages and tool calls, as in the course.
        model = TransformersModel(
            model_id=DEFAULT_MODEL_ID,
            max_new_tokens=512,
        )
        tools = [DuckDuckGoSearchTool(), WikipediaSearchTool()]
        self.agent = CodeAgent(
            tools=tools,
            model=model,
            additional_authorized_imports=["math", "datetime"],
        )

    def __call__(self, question: str) -> str:
        # smolagents versions differ:
        # - some expect agent.run("question")
        # - some accept messages list
        try:
            out = self.agent.run(question)
        except TypeError:
            out = self.agent.run([{"role": "user", "content": question}])
        return str(out).strip()


def _get_space_repo_id() -> str:
    # Preferred: full id
    space_id = (os.getenv("SPACE_ID") or "").strip()
    if space_id and "/" in space_id:
        return space_id

    # Fallback: author + repo name
    author = (os.getenv("SPACE_AUTHOR_NAME") or "").strip()
    repo = (os.getenv("SPACE_REPO_NAME") or "").strip()
    if author and repo:
        return f"{author}/{repo}"

    # Fallback: host sometimes exists like "monkminer-final-assignment-template.hf.space"
    # (Not always reversible reliably, so only last resort)
    return ""


def run_and_submit_all(profile: gr.OAuthProfile | None) -> tuple[str, pd.DataFrame]:
    if not profile:
        return "Please log in with your Hugging Face account.", pd.DataFrame()

    space_id = _get_space_repo_id()
    if not space_id or "/" not in space_id:
        return (
            "Error: Could not detect Space repo id. "
            "Make sure you're running inside a HF Space (and not locally).",
            pd.DataFrame(),
        )

    username = profile.username
    agent_code_url = f"https://huggingface.co/spaces/{space_id}/blob/main/app.py"

    try:
        agent = BasicAgent()
    except Exception as e:
        return f"Error initializing agent: {e}", pd.DataFrame()

    # Fetch questions
    try:
        resp = requests.get(f"{DEFAULT_API_URL}/questions", timeout=30)
        resp.raise_for_status()
        questions = resp.json()
        if not questions:
            return "No questions received from the API.", pd.DataFrame()
    except Exception as e:
        return f"Error fetching questions: {e}", pd.DataFrame()

    results_log = []
    answers_payload = []

    for item in questions:
        task_id = item.get("task_id")
        question = item.get("question")
        if not task_id or not question:
            continue

        try:
            submitted_answer = agent(question)
            answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
            results_log.append(
                {"Task ID": task_id, "Question": question, "Submitted Answer": submitted_answer}
            )
        except Exception as e:
            results_log.append(
                {"Task ID": task_id, "Question": question, "Submitted Answer": f"AGENT ERROR: {e}"}
            )

    if not answers_payload:
        return "Agent failed to generate any answers.", pd.DataFrame(results_log)

    submission_data = {
        "username": username,
        "agent_code": agent_code_url,
        "answers": answers_payload,
    }

    # Submit
    try:
        res = requests.post(f"{DEFAULT_API_URL}/submit", json=submission_data, timeout=120)
        res.raise_for_status()
        data = res.json()
        summary = (
            f" Submission Successful!\n"
            f"User: {data.get('username')}\n"
            f"Score: {data.get('score', 'N/A')}% "
            f"({data.get('correct_count', '?')}/{data.get('total_attempted', '?')})\n"
            f"Message: {data.get('message', 'No message received.')}"
        )
        return summary, pd.DataFrame(results_log)
    except Exception as e:
        return f"Submission Failed: {e}", pd.DataFrame(results_log)


with gr.Blocks() as demo:
    gr.Markdown("# Agent Evaluation Runner")
    gr.Markdown(
        "1) Clone this Space and edit `app.py`.\n"
        "2) Log in with your HF account.\n"
        "3) Click the button to evaluate and submit."
    )

    gr.LoginButton()
    run_button = gr.Button("Run Evaluation & Submit All Answers")
    status_output = gr.Textbox(label="Submission Status", lines=6, interactive=False)
    results_table = gr.DataFrame(label="Agent Responses")

    run_button.click(fn=run_and_submit_all, outputs=[status_output, results_table])

if __name__ == "__main__":
    demo.launch()