Andrei Nazarov
updated prompt
3657cd4
import re
import time
from typing import Any
from smolagents import tool, Tool
import duckduckgo_search
import wikipediaapi
class FinalAnswerTool(Tool):
name = "final_answer"
description = "Provides a final answer to the given problem."
inputs = {'answer': {'type': 'string', 'description': 'The final answer to the problem'}}
output_type = "string"
def forward(self, answer: str) -> str:
"""
Submits the final answer to the user.
"""
print(f"Final Answer: {answer}")
return answer
class DuckDuckGoSearchTool(Tool):
name = "web_search"
description = "Performs a duckduckgo web search based on your query (think a Google search) then returns the top search results."
inputs = {'query': {'type': 'string', 'description': 'The search query to perform.'}}
output_type = "string"
def __init__(self, max_results=10, **kwargs):
super().__init__()
self.max_results = max_results
try:
from duckduckgo_search import DDGS
except ImportError as e:
raise ImportError(
"You must install package `duckduckgo_search` to run this tool: for instance run `pip install duckduckgo-search`."
) from e
self.ddgs = DDGS(**kwargs)
def forward(self, query: str) -> str:
max_retries = 3
retry_delay = 2 # seconds
for attempt in range(max_retries):
try:
results = self.ddgs.text(query, max_results=self.max_results)
if len(results) == 0:
raise Exception("No results found! Try a less restrictive/shorter query.")
postprocessed_results = [f"[{result['title']}]({result['href']})\n{result['body']}" for result in results]
return "## Search Results\n\n" + "\n\n".join(postprocessed_results)
except Exception as e:
error_msg = str(e)
if "202" in error_msg or "rate" in error_msg.lower() or "ratelimit" in error_msg.lower():
if attempt < max_retries - 1:
print(f"Rate limit hit, retrying in {retry_delay} seconds... (attempt {attempt + 1}/{max_retries})")
time.sleep(retry_delay)
retry_delay *= 2 # Exponential backoff
continue
else:
return "## Search Results\n\nRate limit exceeded. Please try again later or use a different search strategy."
else:
# For non-rate-limit errors, don't retry
raise e
return "## Search Results\n\nFailed to get search results after multiple attempts."
class VisitWebpageTool(Tool):
name = "visit_webpage"
description = "Visits a webpage at the given url and reads its content as a markdown string. Use this to browse webpages."
inputs = {'url': {'type': 'string', 'description': 'The url of the webpage to visit.'}}
output_type = "string"
def forward(self, url: str) -> str:
try:
import requests
from markdownify import markdownify
from requests.exceptions import RequestException
from smolagents.utils import truncate_content
except ImportError as e:
raise ImportError(
"You must install packages `markdownify` and `requests` to run this tool: for instance run `pip install markdownify requests`."
) from e
try:
# Send a GET request to the URL with a 20-second timeout
response = requests.get(url, timeout=20)
response.raise_for_status() # Raise an exception for bad status codes
# Convert the HTML content to Markdown
markdown_content = markdownify(response.text).strip()
# Remove multiple line breaks
markdown_content = re.sub(r"\n{3,}", "\n\n", markdown_content)
return truncate_content(markdown_content, 10000)
except requests.exceptions.Timeout:
return "The request timed out. Please try again later or check the URL."
except RequestException as e:
return f"Error fetching the webpage: {str(e)}"
except Exception as e:
return f"An unexpected error occurred: {str(e)}"
def __init__(self, *args, **kwargs):
self.is_initialized = False
class WikipediaSearchTool(Tool):
name = "wikipedia_search"
description = "Searches Wikipedia for a given query and returns the summary of the most relevant page. Use this for questions about specific facts, people, places, or events."
inputs = {'query': {'type': 'string', 'description': 'The search query to perform.'}}
output_type = "string"
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.wiki_wiki = wikipediaapi.Wikipedia(
language='en',
user_agent='SmolAgents-Course-Assignment/1.0'
)
def forward(self, query: str) -> str:
"""
Searches Wikipedia for a given query and returns the summary of the most relevant page.
Use this for questions about specific facts, people, places, or events.
"""
try:
page = self.wiki_wiki.page(query)
if page.exists():
return f"Title: {page.title}\nSummary: {page.summary}"
else:
return f"Could not find a Wikipedia page for '{query}'."
except Exception as e:
return f"An error occurred while searching Wikipedia: {e}"