First_agent_template / tools /web_search.py
hrodic's picture
Update tools/web_search.py
de38426 verified
Raw History Blame Contribute Delete
2.85 kB
import re
from typing import Any, Optional
from smolagents.tools import Tool
try:
from duckduckgo_search import DDGS
except ImportError:
try:
from ddgs import DDGS
except ImportError as e:
raise ImportError(
"You must install package `duckduckgo_search` or `ddgs` to run this tool."
) from e
class DuckDuckGoSearchTool(Tool):
name = "web_search"
description = (
"Performs a DuckDuckGo web search. Returns titles, links, and text snippets."
)
inputs = {
"query": {
"type": "string",
"description": "The search query to perform.",
}
}
output_type = "string"
def __init__(self, max_results: int = 5, **kwargs: Any) -> None:
super().__init__(**kwargs)
self.max_results = max_results
def _sanitize_query(self, query: str) -> str:
"""Fixes common LLM mistakes like putting URL paths inside site: operators."""
# Find site:domain.com/path/to/page and trim it to site:domain.com
def clean_site(match: re.Match) -> str:
domain_part = match.group(1).split("/")[0].strip()
return f"site:{domain_part}"
cleaned = re.sub(r"site:https?://", "site:", query)
cleaned = re.sub(r"site:([^\s]+)", clean_site, cleaned)
return cleaned.strip()
def forward(self, query: str) -> str:
safe_query = self._sanitize_query(query)
headers = {
"User-Agent": (
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36"
)
}
results = []
# Try different backends (html, api, lite) in case one is rate-limited
for backend in ["api", "html", "lite"]:
try:
with DDGS(headers=headers, timeout=10) as ddgs:
res = list(
ddgs.text(
safe_query,
region="wt-wt",
safesearch="moderate",
backend=backend,
max_results=self.max_results,
)
)
if res:
results = res
break
except Exception:
continue
if not results:
return (
f"No results found for query: '{safe_query}'. "
"Instead of retrying generic searches, visit a calendar page directly with `visit_webpage`."
)
postprocessed = [
f"[{r.get('title', 'No Title')}]({r.get('href', '')})\n{r.get('body', '')}"
for r in results
]
return "## Search Results\n\n" + "\n\n".join(postprocessed)