| """ |
| agent.py - GAIA Agent (Phase 2) |
| Core agent for solving GAIA Level 1 benchmark questions using smolagents + Qwen2.5-72B. |
| """ |
| import os |
| from dotenv import load_dotenv |
|
|
| load_dotenv() |
|
|
| from smolagents import CodeAgent, OpenAIModel, DuckDuckGoSearchTool |
|
|
| |
| |
| |
| SYSTEM_PROMPT = """You are an expert assistant solving questions from the GAIA benchmark. |
| |
| STRICT RULES: |
| 1. Reply ONLY with the final answer value - nothing else. |
| 2. No introduction, no explanation, no trailing punctuation unless it is part of the answer. |
| 3. No surrounding quotes unless the question explicitly asks for a quoted string. |
| 4. If the answer is a number, return only the number (e.g. 42). |
| 5. If the answer is a list, separate items with commas (e.g. apple, banana, cherry). |
| 6. If the answer is a proper noun, use the exact correct spelling. |
| 7. If the question is reversed, encoded, or obfuscated, write Python code to decode it first, and then follow the decoded instruction to find the final answer. |
| |
| Format examples: |
| - Question: "What is the capital of France?" -> Paris |
| - Question: "How much is 15 + 27?" -> 42 |
| - Question: "List these fruits alphabetically: banana, apricot, cherry" -> apricot, banana, cherry |
| - Question: "What is the chemical symbol for gold?" -> Au |
| """ |
|
|
|
|
|
|
|
|
| class GAIAAgent: |
| """Agent for solving GAIA Level 1 benchmark questions. |
| |
| Uses smolagents CodeAgent backed by Qwen/Qwen2.5-72B-Instruct:novita via the |
| Hugging Face OpenAI-compatible Router API. |
| """ |
|
|
| def __init__(self): |
| token = os.environ.get("HF_TOKEN") or os.environ.get("HUGGINGFACEHUB_API_TOKEN") |
| if not token: |
| raise ValueError( |
| "Hugging Face token not found (checked HF_TOKEN and HUGGINGFACEHUB_API_TOKEN). " |
| "Check your .env file or your HF Space secrets." |
| ) |
|
|
| print("Initializing model Qwen/Qwen2.5-72B-Instruct:novita via HF Router...") |
| self.model = OpenAIModel( |
| model_id="Qwen/Qwen2.5-72B-Instruct:novita", |
| api_base="https://router.huggingface.co/v1", |
| api_key=token, |
| ) |
|
|
| |
| self.agent = CodeAgent( |
| tools=[DuckDuckGoSearchTool()], |
| model=self.model, |
| add_base_tools=True, |
| max_steps=20, |
| verbosity_level=1, |
| ) |
| print("GAIAAgent ready.") |
|
|
| def __call__(self, question: str) -> str: |
| """Solve a GAIA question and return a short, precise answer. |
| |
| Args: |
| question: The GAIA question text. |
| |
| Returns: |
| Final answer as a short string. |
| """ |
| |
| formatted_question = ( |
| f"{SYSTEM_PROMPT}\n\n" |
| f"Question: {question}\n\n" |
| "Final answer (short and precise):" |
| ) |
|
|
| try: |
| result = self.agent.run(formatted_question) |
| answer = str(result).strip() |
|
|
| |
| for prefix in [ |
| "FINAL ANSWER:", |
| "Final answer:", |
| "Answer:", |
| "The answer is", |
| "The answer is:", |
| ]: |
| if answer.startswith(prefix): |
| answer = answer[len(prefix):].strip() |
|
|
| |
| if len(answer) >= 2 and answer[0] in ('"', "'") and answer[-1] == answer[0]: |
| answer = answer[1:-1].strip() |
|
|
| |
| if "," in answer: |
| answer = ", ".join([item.strip() for item in answer.split(",")]) |
|
|
| |
| if answer.endswith(".") and not answer.endswith("..") and not (len(answer) > 2 and answer[-2].isupper()): |
| answer = answer[:-1].strip() |
|
|
| return answer |
|
|
| except Exception as e: |
| print(f" [error] Failed to process question: {e}") |
| return "" |
|
|