| import os |
| import requests |
| from smolagents import CodeAgent, Tool, InferenceClientModel |
| from dotenv import load_dotenv |
| from bs4 import BeautifulSoup |
|
|
| |
| |
|
|
| |
| hf_token = os.getenv("HF_TOKEN") |
| if not hf_token: |
| raise RuntimeError("Set HF_TOKEN in your Space secrets") |
|
|
| |
| model = InferenceClientModel( |
| model_id="Qwen/Qwen2.5-72B-Instruct", |
| token=hf_token, |
| timeout=120 |
| ) |
|
|
| |
| class MultiplyTool(Tool): |
| name = "multiply" |
| description = "Multiplies two numbers together. Takes two arguments: a (first number) and b (second number)." |
| inputs = {"a": {"type": "number", "description": "First number"}, |
| "b": {"type": "number", "description": "Second number"}} |
| output_type = "number" |
|
|
| def forward(self, a: float, b: float) -> float: |
| return a * b |
|
|
| class AddTool(Tool): |
| name = "add" |
| description = "Adds two numbers together. Takes two arguments: a (first number) and b (second number)." |
| inputs = {"a": {"type": "number", "description": "First number"}, |
| "b": {"type": "number", "description": "Second number"}} |
| output_type = "number" |
|
|
| def forward(self, a: float, b: float) -> float: |
| return a + b |
|
|
| class SubtractTool(Tool): |
| name = "subtract" |
| description = "Subtracts b from a. Takes two arguments: a (first number) and b (second number)." |
| inputs = {"a": {"type": "number", "description": "First number"}, |
| "b": {"type": "number", "description": "Second number"}} |
| output_type = "number" |
|
|
| def forward(self, a: float, b: float) -> float: |
| return a - b |
|
|
| class DivideTool(Tool): |
| name = "divide" |
| description = "Divides a by b. Takes two arguments: a (first number) and b (second number)." |
| inputs = {"a": {"type": "number", "description": "First number"}, |
| "b": {"type": "number", "description": "Second number"}} |
| output_type = "number" |
|
|
| def forward(self, a: float, b: float) -> float: |
| if b == 0: |
| raise ValueError("Cannot divide by zero.") |
| return a / b |
|
|
| class ModulusTool(Tool): |
| name = "modulus" |
| description = "Calculates the modulus (remainder) of a divided by b. Takes two arguments: a (first number) and b (second number)." |
| inputs = {"a": {"type": "number", "description": "First number"}, |
| "b": {"type": "number", "description": "Second number"}} |
| output_type = "number" |
|
|
| def forward(self, a: float, b: float) -> float: |
| return a % b |
|
|
| class WikipediaSearchTool(Tool): |
| name = "wikipedia_search" |
| description = "Searches Wikipedia for a given query and returns relevant information." |
| inputs = {"query": {"type": "string", "description": "The search query"}} |
| output_type = "string" |
|
|
| def forward(self, query: str) -> str: |
| try: |
| import wikipedia |
| wikipedia.set_lang("en") |
| results = wikipedia.search(query, results=2) |
| if not results: |
| return "No results found." |
| |
| summaries = [] |
| for result in results[:2]: |
| try: |
| page = wikipedia.page(result, auto_suggest=False) |
| summaries.append(f"Title: {page.title}\n{page.summary[:500]}") |
| except: |
| continue |
| |
| return "\n\n---\n\n".join(summaries) if summaries else "No content found." |
| except Exception as e: |
| return f"Error searching Wikipedia: {str(e)}" |
|
|
| class WebSearchTool(Tool): |
| name = "web_search" |
| description = "Searches the web using DuckDuckGo and returns relevant results." |
| inputs = {"query": {"type": "string", "description": "The search query"}} |
| output_type = "string" |
|
|
| def forward(self, query: str) -> str: |
| try: |
| from duckduckgo_search import DDGS |
| results = DDGS().text(query, max_results=3) |
| |
| formatted_results = [] |
| for result in results: |
| formatted_results.append( |
| f"Title: {result.get('title', 'N/A')}\n" |
| f"Content: {result.get('body', 'N/A')}\n" |
| f"URL: {result.get('href', 'N/A')}" |
| ) |
| |
| return "\n\n---\n\n".join(formatted_results) if formatted_results else "No results found." |
| except Exception as e: |
| return f"Error searching web: {str(e)}" |
|
|
| class FetchURLTool(Tool): |
| name = "fetch_url_content" |
| description = "Fetches and returns the text content from a given webpage URL." |
| inputs = {"url": {"type": "string", "description": "The URL to fetch content from"}} |
| output_type = "string" |
|
|
| def forward(self, url: str) -> str: |
| try: |
| response = requests.get(url, timeout=10, headers={'User-Agent': 'Mozilla/5.0'}) |
| response.raise_for_status() |
| soup = BeautifulSoup(response.text, 'html.parser') |
| |
| |
| for script in soup(["script", "style", "meta", "link"]): |
| script.decompose() |
| |
| text = soup.get_text(separator='\n', strip=True) |
| |
| return text[:3000] + ("..." if len(text) > 3000 else "") |
| except Exception as e: |
| return f"Error fetching URL: {str(e)}" |
|
|
| |
| tools = [ |
| MultiplyTool(), |
| AddTool(), |
| SubtractTool(), |
| DivideTool(), |
| ModulusTool(), |
| WikipediaSearchTool(), |
| WebSearchTool(), |
| FetchURLTool(), |
| ] |
|
|
| class GAIAAgent: |
| def __init__(self): |
| try: |
| self.agent = CodeAgent( |
| tools=tools, |
| model=model, |
| max_steps=10, |
| verbosity_level=2 |
| ) |
| except Exception as e: |
| print(f"Error creating agent: {e}") |
| raise |
|
|
| def __call__(self, question: str) -> str: |
| try: |
| result = self.agent.run(question) |
| |
| |
| answer = str(result).strip() |
| |
| |
| prefixes_to_remove = [ |
| "The answer is:", |
| "The final answer is:", |
| "Final Answer:", |
| "Answer:", |
| ] |
| |
| for prefix in prefixes_to_remove: |
| if answer.startswith(prefix): |
| answer = answer[len(prefix):].strip() |
| |
| return answer |
| except Exception as e: |
| print(f"Error invoking agent: {e}") |
| return f"Error: {str(e)}" |
|
|