Spaces:
Sleeping
Sleeping
Download tools/web_search.py from hrodic/First_agent_template: direct link, hf CLI and curl.
- Browser
- Download file 2.85 kB
-
https://huggingface.co/spaces/hrodic/First_agent_template/resolve/main/tools/web_search.py
- Command line
-
hf download hf://spaces/hrodic/First_agent_template/tools/web_search.py
-
curl -L -o web_search.py https://huggingface.co/spaces/hrodic/First_agent_template/resolve/main/tools/web_search.py
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) |