ApeMaster commited on
Commit
ad57bc7
·
verified ·
1 Parent(s): 3401eb9

Update app.py

Browse files

updated Brower tool duckduckgo had issues

Files changed (1) hide show
  1. app.py +35 -28
app.py CHANGED
@@ -1,6 +1,5 @@
1
  from smolagents import (
2
  CodeAgent,
3
- DuckDuckGoSearchTool,
4
  HfApiModel,
5
  load_tool,
6
  tool,
@@ -14,10 +13,20 @@ from tools.final_answer import FinalAnswerTool
14
 
15
  from Gradio_UI import GradioUI
16
 
17
-
18
  # ---------------------------------------------------------------------------
19
- # Custom tool 1: Real-time weather (Open-Meteo — free, no API key required)
20
  # ---------------------------------------------------------------------------
 
 
 
 
 
 
 
 
 
 
 
21
  # ---------------------------------------------------------------------------
22
  # Custom tool 1: Real-time weather (Open-Meteo — free, no API key required)
23
  # ---------------------------------------------------------------------------
@@ -28,7 +37,6 @@ def get_weather(city: str) -> str:
28
  city: the name of the city (e.g. 'Paris', 'New York').
29
  """
30
  try:
31
- # 1) Geocode the city name into lat/lon
32
  geo = requests.get(
33
  "https://geocoding-api.open-meteo.com/v1/search",
34
  params={"name": city, "count": 1, "language": "en", "format": "json"},
@@ -39,7 +47,6 @@ def get_weather(city: str) -> str:
39
  loc = geo["results"][0]
40
  lat, lon = loc["latitude"], loc["longitude"]
41
 
42
- # 2) Fetch current weather at that location (request imperial units directly)
43
  weather = requests.get(
44
  "https://api.open-meteo.com/v1/forecast",
45
  params={
@@ -58,7 +65,6 @@ def get_weather(city: str) -> str:
58
  windspeed = cur.get("windspeed")
59
  wmo = cur.get("weathercode", 0)
60
 
61
- # Map WMO weather codes to readable descriptions
62
  descriptions = {
63
  0: "clear sky", 1: "mainly clear", 2: "partly cloudy", 3: "overcast",
64
  45: "fog", 48: "depositing rime fog",
@@ -127,7 +133,7 @@ def get_current_time_in_timezone(timezone: str) -> str:
127
 
128
 
129
  # ---------------------------------------------------------------------------
130
- # Custom tool 4: Browse a webpage and return readable text
131
  # ---------------------------------------------------------------------------
132
  @tool
133
  def browse_webpage(url: str) -> str:
@@ -140,16 +146,28 @@ def browse_webpage(url: str) -> str:
140
  Args:
141
  url: The full URL of the web page to read, starting with http:// or https://.
142
  """
143
- MAX_CHARS = 5000 # hardcoded — avoids confusing the tool schema
144
 
 
145
  headers = {
146
  "User-Agent": (
147
  "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
148
  "AppleWebKit/537.36 (KHTML, like Gecko) "
149
  "Chrome/122.0.0.0 Safari/537.36"
150
  ),
151
- "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
 
 
 
152
  "Accept-Language": "en-US,en;q=0.9",
 
 
 
 
 
 
 
 
153
  }
154
 
155
  if not url.startswith(("http://", "https://")):
@@ -166,12 +184,12 @@ def browse_webpage(url: str) -> str:
166
  if resp.status_code != 200:
167
  return (
168
  f"Error: '{url}' returned HTTP {resp.status_code}. "
169
- f"The site may be blocking automated access — try a different URL."
 
170
  )
171
 
172
  content_type = resp.headers.get("Content-Type", "").lower()
173
 
174
- # Plain text / JSON endpoints
175
  if "json" in content_type or "text/plain" in content_type:
176
  text = resp.text
177
  if len(text) > MAX_CHARS:
@@ -184,14 +202,12 @@ def browse_webpage(url: str) -> str:
184
  except Exception as e:
185
  return f"Error parsing HTML from '{url}': {e}"
186
 
187
- # Title (safe: get_text() never raises on nested tags)
188
  title = url
189
  if soup.title is not None:
190
  title_text = soup.title.get_text(strip=True)
191
  if title_text:
192
  title = title_text
193
 
194
- # Strip noise
195
  for tag_name in (
196
  "script", "style", "noscript", "header", "footer",
197
  "nav", "aside", "form", "iframe", "svg", "button",
@@ -199,7 +215,6 @@ def browse_webpage(url: str) -> str:
199
  for tag in soup.find_all(tag_name):
200
  tag.decompose()
201
 
202
- # Prefer main content — explicit `is not None` checks (NOT `or`)
203
  main = soup.find("main")
204
  if main is None:
205
  main = soup.find("article")
@@ -211,8 +226,6 @@ def browse_webpage(url: str) -> str:
211
  main = soup
212
 
213
  text = main.get_text(separator="\n", strip=True)
214
-
215
- # Collapse blank lines
216
  lines = [ln.strip() for ln in text.splitlines() if ln.strip()]
217
  cleaned = "\n".join(lines)
218
 
@@ -227,10 +240,6 @@ def browse_webpage(url: str) -> str:
227
 
228
  final_answer = FinalAnswerTool()
229
 
230
- # If the agent does not answer, the model is overloaded, please use another model
231
- # or the following Hugging Face Endpoint that also contains qwen2.5 coder:
232
- # model_id='https://pflgm2locj2t89co.us-east-1.aws.endpoints.huggingface.cloud'
233
-
234
  model = HfApiModel(
235
  max_tokens=2096,
236
  temperature=0.5,
@@ -238,7 +247,6 @@ model = HfApiModel(
238
  custom_role_conversions=None,
239
  )
240
 
241
- # Import tool from Hub
242
  image_generation_tool = load_tool("agents-course/text-to-image", trust_remote_code=True)
243
 
244
  with open("prompts.yaml", 'r') as stream:
@@ -247,13 +255,13 @@ with open("prompts.yaml", 'r') as stream:
247
  agent = CodeAgent(
248
  model=model,
249
  tools=[
250
- final_answer, # don't remove
251
- DuckDuckGoSearchTool(), # 🔍 search the web
252
  browse_webpage, # 🌐 read a result URL
253
- image_generation_tool, # 🎨 text-to-image
254
- get_current_time_in_timezone, # 🕒 current time in any timezone
255
- get_weather, # 🌤️ real-time weather
256
- convert_currency, # 💱 currency conversion
257
  ],
258
  max_steps=10,
259
  verbosity_level=2,
@@ -264,5 +272,4 @@ agent = CodeAgent(
264
  prompt_templates=prompt_templates,
265
  )
266
 
267
-
268
  GradioUI(agent).launch()
 
1
  from smolagents import (
2
  CodeAgent,
 
3
  HfApiModel,
4
  load_tool,
5
  tool,
 
13
 
14
  from Gradio_UI import GradioUI
15
 
 
16
  # ---------------------------------------------------------------------------
17
+ # Search tool: try Bing first (via WebSearchTool), fallback to DuckDuckGo
18
  # ---------------------------------------------------------------------------
19
+ try:
20
+ from smolagents import WebSearchTool
21
+ search_tool = WebSearchTool(engine="bing")
22
+ print("Using Bing search engine via WebSearchTool")
23
+ except ImportError:
24
+ # smolagents < 1.16.0 does not have WebSearchTool
25
+ from smolagents import DuckDuckGoSearchTool
26
+ search_tool = DuckDuckGoSearchTool()
27
+ print("Using DuckDuckGo search engine (upgrade smolagents for Bing)")
28
+
29
+
30
  # ---------------------------------------------------------------------------
31
  # Custom tool 1: Real-time weather (Open-Meteo — free, no API key required)
32
  # ---------------------------------------------------------------------------
 
37
  city: the name of the city (e.g. 'Paris', 'New York').
38
  """
39
  try:
 
40
  geo = requests.get(
41
  "https://geocoding-api.open-meteo.com/v1/search",
42
  params={"name": city, "count": 1, "language": "en", "format": "json"},
 
47
  loc = geo["results"][0]
48
  lat, lon = loc["latitude"], loc["longitude"]
49
 
 
50
  weather = requests.get(
51
  "https://api.open-meteo.com/v1/forecast",
52
  params={
 
65
  windspeed = cur.get("windspeed")
66
  wmo = cur.get("weathercode", 0)
67
 
 
68
  descriptions = {
69
  0: "clear sky", 1: "mainly clear", 2: "partly cloudy", 3: "overcast",
70
  45: "fog", 48: "depositing rime fog",
 
133
 
134
 
135
  # ---------------------------------------------------------------------------
136
+ # Custom tool 4: Browse a webpage (Chrome‑mimicking headers)
137
  # ---------------------------------------------------------------------------
138
  @tool
139
  def browse_webpage(url: str) -> str:
 
146
  Args:
147
  url: The full URL of the web page to read, starting with http:// or https://.
148
  """
149
+ MAX_CHARS = 5000
150
 
151
+ # Full Chrome‑like header set — this is what actually gets past many bot checks
152
  headers = {
153
  "User-Agent": (
154
  "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
155
  "AppleWebKit/537.36 (KHTML, like Gecko) "
156
  "Chrome/122.0.0.0 Safari/537.36"
157
  ),
158
+ "Accept": (
159
+ "text/html,application/xhtml+xml,application/xml;q=0.9,"
160
+ "image/avif,image/webp,image/apng,*/*;q=0.8"
161
+ ),
162
  "Accept-Language": "en-US,en;q=0.9",
163
+ "Accept-Encoding": "gzip, deflate, br",
164
+ "Connection": "keep-alive",
165
+ "Upgrade-Insecure-Requests": "1",
166
+ "Sec-Fetch-Dest": "document",
167
+ "Sec-Fetch-Mode": "navigate",
168
+ "Sec-Fetch-Site": "none",
169
+ "Sec-Fetch-User": "?1",
170
+ "Cache-Control": "max-age=0",
171
  }
172
 
173
  if not url.startswith(("http://", "https://")):
 
184
  if resp.status_code != 200:
185
  return (
186
  f"Error: '{url}' returned HTTP {resp.status_code}. "
187
+ f"The site may be blocking automated access — try a different URL "
188
+ f"or use a search result that does not require a login."
189
  )
190
 
191
  content_type = resp.headers.get("Content-Type", "").lower()
192
 
 
193
  if "json" in content_type or "text/plain" in content_type:
194
  text = resp.text
195
  if len(text) > MAX_CHARS:
 
202
  except Exception as e:
203
  return f"Error parsing HTML from '{url}': {e}"
204
 
 
205
  title = url
206
  if soup.title is not None:
207
  title_text = soup.title.get_text(strip=True)
208
  if title_text:
209
  title = title_text
210
 
 
211
  for tag_name in (
212
  "script", "style", "noscript", "header", "footer",
213
  "nav", "aside", "form", "iframe", "svg", "button",
 
215
  for tag in soup.find_all(tag_name):
216
  tag.decompose()
217
 
 
218
  main = soup.find("main")
219
  if main is None:
220
  main = soup.find("article")
 
226
  main = soup
227
 
228
  text = main.get_text(separator="\n", strip=True)
 
 
229
  lines = [ln.strip() for ln in text.splitlines() if ln.strip()]
230
  cleaned = "\n".join(lines)
231
 
 
240
 
241
  final_answer = FinalAnswerTool()
242
 
 
 
 
 
243
  model = HfApiModel(
244
  max_tokens=2096,
245
  temperature=0.5,
 
247
  custom_role_conversions=None,
248
  )
249
 
 
250
  image_generation_tool = load_tool("agents-course/text-to-image", trust_remote_code=True)
251
 
252
  with open("prompts.yaml", 'r') as stream:
 
255
  agent = CodeAgent(
256
  model=model,
257
  tools=[
258
+ final_answer,
259
+ search_tool, # 🔍 Bing (or DuckDuckGo fallback)
260
  browse_webpage, # 🌐 read a result URL
261
+ image_generation_tool,
262
+ get_current_time_in_timezone,
263
+ get_weather,
264
+ convert_currency,
265
  ],
266
  max_steps=10,
267
  verbosity_level=2,
 
272
  prompt_templates=prompt_templates,
273
  )
274
 
 
275
  GradioUI(agent).launch()