Shrutipanchal086's picture
Update app.py
b4e6d7c verified
Raw
History Blame
22.3 kB
import os
import gradio as gr
import requests
import pandas as pd
from smolagents import (
CodeAgent,
InferenceClientModel,
DuckDuckGoSearchTool,
VisitWebpageTool,
WikipediaSearchTool,
PythonInterpreterTool,
)
# ============================================================
# CONSTANTS
# ============================================================
# IMPORTANT:
# DO NOT CHANGE THIS URL.
DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
# ============================================================
# GENERAL PURPOSE GAIA AGENT
# ============================================================
class BasicAgent:
def __init__(self):
print("=" * 60)
print("Initializing General Purpose GAIA Agent...")
print("=" * 60)
# ----------------------------------------------------
# Hugging Face token
# ----------------------------------------------------
hf_token = os.getenv("HF_TOKEN")
if not hf_token:
raise RuntimeError(
"HF_TOKEN is missing.\n"
"Go to Space Settings -> Secrets and create:\n"
"Name: HF_TOKEN\n"
"Value: Your Hugging Face token"
)
# ----------------------------------------------------
# MODEL
# ----------------------------------------------------
self.model = InferenceClientModel(
model_id="Qwen/Qwen3-Next-80B-A3B-Thinking",
token=hf_token,
temperature=0.1,
max_tokens=3000,
)
# ----------------------------------------------------
# WEB SEARCH TOOL
# ----------------------------------------------------
self.search_tool = DuckDuckGoSearchTool(
max_results=8,
rate_limit=1.0
)
# ----------------------------------------------------
# WEBPAGE TOOL
# ----------------------------------------------------
self.webpage_tool = VisitWebpageTool(
max_output_length=40000
)
# ----------------------------------------------------
# WIKIPEDIA TOOL
# ----------------------------------------------------
self.wikipedia_tool = WikipediaSearchTool(
user_agent="StructuralGPT-GAIA-Agent/1.0",
language="en",
content_type="text",
extract_format="WIKI"
)
# ----------------------------------------------------
# PYTHON / CALCULATION TOOL
# ----------------------------------------------------
self.python_tool = PythonInterpreterTool(
authorized_imports=[
"math",
"statistics",
"datetime",
"json",
"re",
"decimal"
],
timeout_seconds=30
)
# ----------------------------------------------------
# SYSTEM INSTRUCTIONS
# ----------------------------------------------------
self.instructions = """
You are a highly capable general-purpose AI agent designed
to solve GAIA benchmark questions.
Your objective is to provide the CORRECT answer to the
user's question.
IMPORTANT RULES
===============
1. READ THE COMPLETE QUESTION CAREFULLY.
2. Determine exactly what the question is asking.
3. Use tools whenever they are useful.
4. Use web search for:
- current information
- factual information
- obscure information
- information that should be verified
- people, companies, events, dates, statistics, etc.
5. Use the webpage tool when the question provides a URL
or when you need the contents of a webpage.
6. Use Wikipedia search when the question specifically
refers to Wikipedia or historical/general information.
7. Use Python for:
- arithmetic
- percentages
- dates
- counting
- comparisons
- numerical reasoning
- data processing
8. NEVER guess a numerical answer when you can calculate it.
9. When a question contains several steps:
solve every required step before giving the answer.
10. Verify important facts whenever possible.
11. Do not invent information.
12. Pay close attention to:
- exact dates
- names
- numbers
- units
- percentages
- spelling
- requested formats
13. If the question asks:
"How many?"
return the number.
14. If it asks:
"Who?"
return the person's name.
15. If it asks:
"When?"
return the date/year.
16. If it asks for a calculation,
calculate it using Python.
17. If the question asks for a specific list,
provide exactly the requested list.
18. If the question contains a URL,
investigate the URL rather than guessing.
19. Do not include citations unless the question asks for them.
20. Do not say "FINAL ANSWER".
21. Do not write:
"Here is the answer:"
"The answer is:"
or unnecessary explanations.
22. The final response must contain ONLY the answer
required by the question.
23. The GAIA evaluator uses exact matching, so be precise
and concise.
24. Think through the problem carefully before producing
the final response.
25. NEVER intentionally return a generic response.
SPECIAL CASES
=============
For calculations:
- Use Python.
- Verify the result.
- Give the exact required number.
For web research:
- Search using precise keywords.
- Open useful results.
- Compare information when needed.
For Wikipedia questions:
- Use Wikipedia search.
- Pay attention to the requested Wikipedia version/date.
For questions involving a webpage:
- Visit the webpage.
- Extract the relevant information.
- Answer only what is requested.
For civil/structural engineering questions:
- You may use engineering knowledge.
- Use Indian Standards when appropriate.
- Keep the final answer focused on what was requested.
FINAL RESPONSE
==============
Return ONLY the concise answer.
"""
# ----------------------------------------------------
# CREATE AGENT
# ----------------------------------------------------
self.agent = CodeAgent(
model=self.model,
tools=[
self.search_tool,
self.webpage_tool,
self.wikipedia_tool,
self.python_tool,
],
max_steps=12,
instructions=self.instructions,
add_base_tools=True
)
print("GAIA Agent initialized successfully.")
print("=" * 60)
# ========================================================
# AGENT CALL
# ========================================================
def __call__(self, question: str) -> str:
print("\n")
print("=" * 70)
print("NEW GAIA QUESTION")
print("=" * 70)
print(question)
print("=" * 70)
try:
result = self.agent.run(question)
answer = str(result).strip()
# ------------------------------------------------
# Remove accidental answer labels
# ------------------------------------------------
unwanted_prefixes = [
"FINAL ANSWER:",
"FINAL ANSWER",
"Answer:",
"ANSWER:",
"The answer is:",
"The answer is"
]
for prefix in unwanted_prefixes:
if answer.lower().startswith(prefix.lower()):
answer = answer[len(prefix):].strip()
print("\nAGENT ANSWER:")
print(answer)
print("=" * 70)
return answer
except Exception as e:
print("\nAGENT ERROR:")
print(str(e))
print("=" * 70)
return f"Agent execution error: {e}"
# ============================================================
# RUN AND SUBMIT ALL QUESTIONS
# ============================================================
def run_and_submit_all(profile: gr.OAuthProfile | None):
"""
Fetches all GAIA questions,
runs the General Purpose Agent,
submits all answers,
and displays the results.
"""
# --------------------------------------------------------
# 1. CHECK HUGGING FACE LOGIN
# --------------------------------------------------------
if profile:
username = profile.username
print(
f"User logged in: {username}"
)
else:
print("User is not logged in.")
return (
"Please Login to Hugging Face with the button.",
None
)
# --------------------------------------------------------
# 2. SCORING API URLS
# --------------------------------------------------------
api_url = DEFAULT_API_URL
questions_url = f"{api_url}/questions"
submit_url = f"{api_url}/submit"
# --------------------------------------------------------
# 3. GET SPACE CODE URL
# --------------------------------------------------------
space_id = os.getenv("SPACE_ID")
if not space_id:
print(
"WARNING: SPACE_ID was not found."
)
agent_code = "SPACE_ID_NOT_FOUND"
else:
agent_code = (
f"https://huggingface.co/spaces/"
f"{space_id}/tree/main"
)
print(
f"Agent code URL: {agent_code}"
)
# --------------------------------------------------------
# 4. CREATE AGENT
# --------------------------------------------------------
try:
agent = BasicAgent()
except Exception as e:
print(
f"Error initializing agent: {e}"
)
return (
f"Error initializing agent: {e}",
None
)
# --------------------------------------------------------
# 5. FETCH QUESTIONS
# --------------------------------------------------------
print("\n")
print("=" * 70)
print("FETCHING GAIA QUESTIONS")
print("=" * 70)
try:
response = requests.get(
questions_url,
timeout=30
)
response.raise_for_status()
questions_data = response.json()
if not questions_data:
print("Questions list is empty.")
return (
"Fetched questions list is empty.",
None
)
print(
f"Fetched {len(questions_data)} questions."
)
except requests.exceptions.RequestException as e:
print(
f"Error fetching questions: {e}"
)
return (
f"Error fetching questions: {e}",
None
)
except ValueError as e:
print(
f"Invalid JSON response: {e}"
)
return (
f"Invalid JSON response: {e}",
None
)
except Exception as e:
print(
f"Unexpected error fetching questions: {e}"
)
return (
f"Unexpected error fetching questions: {e}",
None
)
# --------------------------------------------------------
# 6. RUN AGENT ON EVERY QUESTION
# --------------------------------------------------------
results_log = []
answers_payload = []
total_questions = len(questions_data)
print("\n")
print("=" * 70)
print("RUNNING GENERAL PURPOSE AGENT")
print("=" * 70)
for number, item in enumerate(
questions_data,
start=1
):
task_id = item.get(
"task_id"
)
question_text = item.get(
"question"
)
# ----------------------------------------------------
# Validate question
# ----------------------------------------------------
if not task_id:
print(
f"Skipping question {number}: "
"missing task_id."
)
continue
if question_text is None:
print(
f"Skipping question {number}: "
"missing question text."
)
continue
print("\n")
print(
f"QUESTION {number}/{total_questions}"
)
print(
f"TASK ID: {task_id}"
)
# ----------------------------------------------------
# Run agent
# ----------------------------------------------------
try:
submitted_answer = agent(
question_text
)
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:
error_message = (
f"AGENT ERROR: {e}"
)
print(error_message)
results_log.append(
{
"Task ID": task_id,
"Question": question_text,
"Submitted Answer":
error_message
}
)
# --------------------------------------------------------
# 7. CHECK ANSWERS
# --------------------------------------------------------
if not answers_payload:
print(
"Agent did not produce any answers."
)
return (
"Agent did not produce any answers.",
pd.DataFrame(results_log)
)
print("\n")
print("=" * 70)
print(
f"Agent produced {len(answers_payload)} "
f"answers."
)
print("=" * 70)
# --------------------------------------------------------
# 8. PREPARE SUBMISSION
# --------------------------------------------------------
submission_data = {
"username":
username.strip(),
"agent_code":
agent_code,
"answers":
answers_payload
}
status_update = (
f"Agent finished.\n"
f"Submitting {len(answers_payload)} answers "
f"for user '{username}'..."
)
print(status_update)
# --------------------------------------------------------
# 9. SUBMIT ANSWERS
# --------------------------------------------------------
print("\n")
print("=" * 70)
print("SUBMITTING TO GAIA SCORING SERVER")
print("=" * 70)
try:
response = requests.post(
submit_url,
json=submission_data,
timeout=120
)
response.raise_for_status()
result_data = response.json()
# ----------------------------------------------------
# SCORE
# ----------------------------------------------------
score = result_data.get(
"score",
"N/A"
)
correct_count = result_data.get(
"correct_count",
"?"
)
total_attempted = result_data.get(
"total_attempted",
"?"
)
message = result_data.get(
"message",
"No message received."
)
final_status = (
"Submission Successful!\n\n"
f"User: "
f"{result_data.get('username', username)}\n"
f"Overall Score: "
f"{score}%\n"
f"Correct: "
f"{correct_count}/"
f"{total_attempted}\n\n"
f"Message: "
f"{message}"
)
print(final_status)
results_df = pd.DataFrame(
results_log
)
return (
final_status,
results_df
)
# --------------------------------------------------------
# HTTP ERROR
# --------------------------------------------------------
except requests.exceptions.HTTPError as e:
error_detail = (
f"Server responded with "
f"status {e.response.status_code}."
)
try:
error_json = e.response.json()
error_detail += (
f" Detail: "
f"{error_json.get('detail', '')}"
)
except Exception:
error_detail += (
f" Response: "
f"{e.response.text[:500]}"
)
status_message = (
f"Submission Failed: "
f"{error_detail}"
)
print(status_message)
return (
status_message,
pd.DataFrame(results_log)
)
# --------------------------------------------------------
# TIMEOUT
# --------------------------------------------------------
except requests.exceptions.Timeout:
status_message = (
"Submission Failed: "
"The request timed out."
)
print(status_message)
return (
status_message,
pd.DataFrame(results_log)
)
# --------------------------------------------------------
# NETWORK ERROR
# --------------------------------------------------------
except requests.exceptions.RequestException as e:
status_message = (
f"Submission Failed: "
f"Network error - {e}"
)
print(status_message)
return (
status_message,
pd.DataFrame(results_log)
)
# --------------------------------------------------------
# OTHER ERROR
# --------------------------------------------------------
except Exception as e:
status_message = (
f"Unexpected error during submission: "
f"{e}"
)
print(status_message)
return (
status_message,
pd.DataFrame(results_log)
)
# ============================================================
# GRADIO INTERFACE
# ============================================================
with gr.Blocks() as demo:
gr.Markdown(
"""
# 🤖 General Purpose GAIA Agent
This agent uses:
- Qwen through Hugging Face
- Web Search
- Webpage retrieval
- Wikipedia
- Python calculations
- Multi-step reasoning
It is designed for the Hugging Face Agents Course
Unit 4 GAIA evaluation.
"""
)
gr.Markdown(
"""
### Instructions
1. Log in to your Hugging Face account.
2. Make sure `HF_TOKEN` is configured as a Space Secret.
3. Click **Run Evaluation & Submit All Answers**.
4. Wait while the agent processes all questions.
5. Your score will appear below.
**Important:** The evaluation can take several minutes
because the agent processes each question individually.
"""
)
# --------------------------------------------------------
# LOGIN
# --------------------------------------------------------
gr.LoginButton()
# --------------------------------------------------------
# RUN BUTTON
# --------------------------------------------------------
run_button = gr.Button(
"Run Evaluation & Submit All Answers",
variant="primary"
)
# --------------------------------------------------------
# STATUS
# --------------------------------------------------------
status_output = gr.Textbox(
label="Run Status / Submission Result",
lines=8,
interactive=False
)
# --------------------------------------------------------
# RESULTS
# --------------------------------------------------------
results_table = gr.DataFrame(
label="Questions and Agent Answers",
wrap=True
)
# --------------------------------------------------------
# BUTTON ACTION
# --------------------------------------------------------
run_button.click(
fn=run_and_submit_all,
outputs=[
status_output,
results_table
]
)
# ============================================================
# START APPLICATION
# ============================================================
if __name__ == "__main__":
print(
"\n" +
"-" * 30 +
" App Starting " +
"-" * 30
)
# --------------------------------------------------------
# SPACE INFORMATION
# --------------------------------------------------------
space_host_startup = os.getenv(
"SPACE_HOST"
)
space_id_startup = os.getenv(
"SPACE_ID"
)
# --------------------------------------------------------
# SPACE HOST
# --------------------------------------------------------
if space_host_startup:
print(
f"SPACE_HOST found: "
f"{space_host_startup}"
)
print(
"Runtime URL:"
)
print(
f"https://{space_host_startup}.hf.space"
)
else:
print(
"SPACE_HOST not found."
)
# --------------------------------------------------------
# SPACE ID
# --------------------------------------------------------
if space_id_startup:
print(
f"SPACE_ID found: "
f"{space_id_startup}"
)
print(
"Repository URL:"
)
print(
f"https://huggingface.co/spaces/"
f"{space_id_startup}"
)
print(
"Code URL:"
)
print(
f"https://huggingface.co/spaces/"
f"{space_id_startup}/tree/main"
)
else:
print(
"SPACE_ID not found."
)
print(
"\nLaunching General Purpose GAIA Agent..."
)
# --------------------------------------------------------
# LAUNCH
# --------------------------------------------------------
demo.launch(
debug=True,
share=False
)