BetsyFromR commited on
Commit
13e61d2
·
verified ·
1 Parent(s): 6ccdf45

Update tools/web_search.py

Browse files
Files changed (1) hide show
  1. tools/web_search.py +44 -18
tools/web_search.py CHANGED
@@ -1,6 +1,8 @@
1
  from typing import Any, Optional
2
  from smolagents.tools import Tool
3
  import duckduckgo_search
 
 
4
 
5
 
6
  class DuckDuckGoSearchTool(Tool):
@@ -9,10 +11,21 @@ class DuckDuckGoSearchTool(Tool):
9
  inputs = {'query': {'type': 'string', 'description': 'The search query to perform.'}}
10
  output_type = "string"
11
 
12
- def __init__(self, max_results=10, backend="auto", **kwargs):
 
 
 
 
 
 
 
 
13
  super().__init__()
14
  self.max_results = max_results
15
- self.backend = backend
 
 
 
16
  try:
17
  from duckduckgo_search import DDGS
18
  except ImportError as e:
@@ -21,23 +34,36 @@ class DuckDuckGoSearchTool(Tool):
21
  ) from e
22
  self.ddgs = DDGS(**kwargs)
23
 
 
 
 
 
 
 
 
 
 
24
  def forward(self, query: str) -> str:
25
- backends_to_try = [self.backend] + [b for b in ("auto", "lite", "html", "api") if b != self.backend]
26
  last_error = None
27
- for backend in backends_to_try:
28
- try:
29
- results = list(
30
- self.ddgs.text(query, max_results=self.max_results, backend=backend)
31
- )
32
- except Exception as e:
33
- last_error = e
34
- continue
35
- if results:
36
- postprocessed_results = [
37
- f"[{result['title']}]({result['href']})\n{result['body']}"
38
- for result in results
39
- ]
40
- return "## Search Results\n\n" + "\n\n".join(postprocessed_results)
 
 
 
 
 
41
  if last_error is not None:
42
  return (
43
  "Web search failed. This can happen if outbound network access is blocked or the "
@@ -45,6 +71,6 @@ class DuckDuckGoSearchTool(Tool):
45
  )
46
  return (
47
  "No results found. This may indicate network restrictions or a temporary "
48
- f"DuckDuckGo issue. Try a shorter query or retry later. {backend}"
49
  )
50
 
 
1
  from typing import Any, Optional
2
  from smolagents.tools import Tool
3
  import duckduckgo_search
4
+ import random
5
+ import time
6
 
7
 
8
  class DuckDuckGoSearchTool(Tool):
 
11
  inputs = {'query': {'type': 'string', 'description': 'The search query to perform.'}}
12
  output_type = "string"
13
 
14
+ def __init__(
15
+ self,
16
+ max_results=10,
17
+ backends=None,
18
+ retries=2,
19
+ min_delay=0.2,
20
+ max_delay=0.8,
21
+ **kwargs,
22
+ ):
23
  super().__init__()
24
  self.max_results = max_results
25
+ self.backends = backends or ["auto", "lite", "html", "api"]
26
+ self.retries = retries
27
+ self.min_delay = min_delay
28
+ self.max_delay = max_delay
29
  try:
30
  from duckduckgo_search import DDGS
31
  except ImportError as e:
 
34
  ) from e
35
  self.ddgs = DDGS(**kwargs)
36
 
37
+ def _format_results(self, results) -> str:
38
+ postprocessed_results = []
39
+ for result in results:
40
+ title = result.get("title") or "Untitled"
41
+ href = result.get("href") or result.get("url") or ""
42
+ body = result.get("body") or result.get("snippet") or ""
43
+ postprocessed_results.append(f"[{title}]({href})\n{body}".strip())
44
+ return "## Search Results\n\n" + "\n\n".join(postprocessed_results)
45
+
46
  def forward(self, query: str) -> str:
 
47
  last_error = None
48
+ for backend in self.backends:
49
+ for attempt in range(self.retries + 1):
50
+ try:
51
+ results = list(
52
+ self.ddgs.text(query, max_results=self.max_results, backend=backend)
53
+ )
54
+ except Exception as e:
55
+ last_error = e
56
+ # Jittered backoff to reduce rate-limit issues.
57
+ sleep_for = min(
58
+ self.max_delay,
59
+ self.min_delay * (2 ** attempt) + random.random() * 0.1,
60
+ )
61
+ time.sleep(sleep_for)
62
+ continue
63
+ if results:
64
+ return self._format_results(results)
65
+ # Empty results can happen; try next backend.
66
+ break
67
  if last_error is not None:
68
  return (
69
  "Web search failed. This can happen if outbound network access is blocked or the "
 
71
  )
72
  return (
73
  "No results found. This may indicate network restrictions or a temporary "
74
+ "DuckDuckGo issue. Try a shorter query or retry later."
75
  )
76