Sborole commited on
Commit
216b034
·
verified ·
1 Parent(s): a606330

Update tools/WebSearchTool.py

Browse files
Files changed (1) hide show
  1. tools/WebSearchTool.py +31 -50
tools/WebSearchTool.py CHANGED
@@ -2,23 +2,26 @@ import requests
2
  from smolagents import Tool
3
  import json
4
 
5
- class DuckDuckGoSearchTool(Tool):
6
  """
7
- A tool to perform general web searches using the DuckDuckGo Instant Answer API.
8
- This tool is a free and accessible alternative when other search APIs require keys or payment.
9
- It's best for obtaining quick, summarized facts and related links.
10
  """
11
- name = "duckduckgo_search"
12
- description = "Use DuckDuckGo to find current information and general knowledge, returning summarized answers and relevant search results."
13
 
14
  inputs = {
15
  "query": {"type": "string", "description": "The search term to look up."}
16
  }
17
  output_type = "string"
18
 
 
 
 
19
  def forward(self, query: str) -> str:
20
  """
21
- Executes a DuckDuckGo search query and formats the top results.
22
 
23
  Args:
24
  query: The search term provided by the agent.
@@ -26,63 +29,41 @@ class DuckDuckGoSearchTool(Tool):
26
  Returns:
27
  A formatted string of search results, or an error message.
28
  """
29
- print(f"Executing DuckDuckGo Search for: '{query}'")
30
 
31
- # DuckDuckGo Zero-click API endpoint
32
- search_url = "https://api.duckduckgo.com/"
33
  params = {
34
  "q": query,
35
  "format": "json",
36
- "no_redirect": "1", # Do not redirect to a search page
37
- "no_html": "1", # Remove HTML from results
38
- "t": "smolagents" # Application name for logging
39
  }
40
 
41
  try:
42
  # Make the API request
43
- response = requests.get(search_url, params=params)
44
- response.raise_for_status()
45
  data = response.json()
46
 
47
- results = []
48
-
49
- # 1. Instant Answer (if available)
50
- abstract_text = data.get('AbstractText')
51
- abstract_url = data.get('AbstractURL')
52
-
53
- if abstract_text and abstract_url:
54
- results.append(
55
- f"RESULT 1 (Instant Answer): '{data.get('Heading', 'Summary')}'\n"
56
- f"CONTENT: {abstract_text}\n"
57
- f"SOURCE: {abstract_url}"
58
- )
59
 
60
- # 2. Related Topics (for more search results)
61
- # This often contains deep links or snippets for further reading
62
- topics = data.get('RelatedTopics', [])
63
-
64
- # Filter and take up to the next 2 relevant topics
65
- for i, topic in enumerate(topics[:2]):
66
- # Check for a standard result structure
67
- if 'Result' in topic and 'Text' in topic:
68
- # Parse the snippet/link info from the 'Result' field (usually HTML but 'no_html' helps)
69
- snippet = topic['Text']
70
- link = topic.get('FirstURL', 'N/A')
71
- title = snippet.split(' - ')[0] if ' - ' in snippet else 'Related Topic'
72
-
73
- results.append(
74
- f"RESULT {len(results) + 1}: '{title}'\n"
75
- f"CONTENT: {snippet}\n"
76
- f"SOURCE: {link}"
77
- )
78
-
79
- if not results:
80
  return "XX record info: No results found."
81
 
 
 
 
 
 
 
 
 
 
82
  # Join the results with a clear separator
83
- return "\n\n---SEPARATOR---\n\n".join(results)
84
 
85
  except requests.exceptions.RequestException as e:
86
- return f"Error during DuckDuckGo API Request: {e}"
87
  except Exception as e:
88
- return f"Error processing DuckDuckGo results: {e}"
 
2
  from smolagents import Tool
3
  import json
4
 
5
+ class SearxngSearchTool(Tool):
6
  """
7
+ A metasearch tool that queries multiple search engines (including Google, Bing, etc.)
8
+ through a free, public Searxng instance. This is a robust, keyless alternative
9
+ when specific search APIs are overloaded or require payment/keys.
10
  """
11
+ name = "searxng_search"
12
+ description = "Use a free, keyless metasearch engine (Searxng) to query the web for general knowledge and current information when other search tools are unavailable."
13
 
14
  inputs = {
15
  "query": {"type": "string", "description": "The search term to look up."}
16
  }
17
  output_type = "string"
18
 
19
+ # Note: Using a popular public instance. This may occasionally fail if the instance is down.
20
+ DEFAULT_INSTANCE = "https://searx.be/search"
21
+
22
  def forward(self, query: str) -> str:
23
  """
24
+ Executes a Searxng search query and formats the top results (up to 3).
25
 
26
  Args:
27
  query: The search term provided by the agent.
 
29
  Returns:
30
  A formatted string of search results, or an error message.
31
  """
32
+ print(f"Executing Searxng Search for: '{query}'")
33
 
 
 
34
  params = {
35
  "q": query,
36
  "format": "json",
37
+ "engines": "google,bing,duckduckgo", # Use multiple reliable engines
38
+ "pageno": 1,
 
39
  }
40
 
41
  try:
42
  # Make the API request
43
+ response = requests.get(self.DEFAULT_INSTANCE, params=params)
44
+ response.raise_for_status()
45
  data = response.json()
46
 
47
+ # Extract the search results
48
+ items = data.get('results', [])
 
 
 
 
 
 
 
 
 
 
49
 
50
+ if not items:
51
+ # Return the specific failure message expected by the agent
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
  return "XX record info: No results found."
53
 
54
+ search_results = []
55
+ # Process the top 3 results
56
+ for i, item in enumerate(items[:3]):
57
+ search_results.append(
58
+ f"RESULT {i+1}: '{item.get('title', 'N/A')}'\n"
59
+ f"CONTENT: {item.get('content', 'No snippet available.')}\n"
60
+ f"SOURCE: {item.get('url', 'N/A')}"
61
+ )
62
+
63
  # Join the results with a clear separator
64
+ return "\n\n---SEPARATOR---\n\n".join(search_results)
65
 
66
  except requests.exceptions.RequestException as e:
67
+ return f"Error during Searxng API Request. The instance may be temporarily unavailable: {e}"
68
  except Exception as e:
69
+ return f"Error processing Searxng results: {e}"