agarwalamit081 commited on
Commit
f7f3818
·
verified ·
1 Parent(s): 4d246f4

Update app.py

Browse files

updates reled to image generation

Files changed (1) hide show
  1. app.py +291 -102
app.py CHANGED
@@ -1,151 +1,340 @@
1
  #!/usr/bin/env python
2
  # coding=utf-8
 
3
  import re
4
  import requests
 
 
5
  from smolagents import CodeAgent, DuckDuckGoSearchTool, HfApiModel, load_tool, tool
6
- from tools.final_answer import FinalAnswerTool
7
  from Gradio_UI import GradioUI
8
 
9
  # ======================
10
- # MINIMAL COMPLIANT TOOLS (Google-style docstrings REQUIRED)
11
  # ======================
12
 
13
  @tool
14
- def get_weather(location: str, dates: str) -> str:
15
  """
16
- Get weather forecast for destination.
17
-
18
  Args:
19
  location: Destination city (e.g., "Barcelona")
20
- dates: Travel dates (e.g., "October 15-19")
21
-
22
  Returns:
23
- Weather summary with temperature and packing advice
24
  """
 
25
  try:
26
- clean = re.sub(r'[^a-zA-Z0-9\s]', '', location).replace(' ', '+')
27
- data = requests.get(f"http://wttr.in/{clean}?format=j1", timeout=10).json()
28
- temp = int(data['current_condition'][0]['temp_C'])
29
- cond = data['current_condition'][0]['lang_en'][0]['value']
30
- advice = "light layers + jacket" if temp < 22 else "light clothing + sunscreen"
31
- if "rain" in cond.lower():
32
- advice += " + umbrella"
33
- return f"{location}: {temp}°C, {cond}. Pack: {advice}"
34
- except:
35
- return f"{location}: Typical 18-24°C in Oct. Pack light layers + light jacket + umbrella."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
 
38
  @tool
39
- def convert_currency(amount: float, from_curr: str, to_curr: str) -> str:
40
  """
41
- Convert currency using Frankfurter API.
42
-
43
  Args:
44
- amount: Amount to convert (e.g., 1200.0)
45
- from_curr: Source currency code (e.g., "USD")
46
- to_curr: Target currency code (e.g., "EUR")
47
-
48
  Returns:
49
  Formatted conversion result
50
  """
51
  try:
52
- from_curr = from_curr.upper()
53
- to_curr = to_curr.upper()
 
54
  if from_curr == to_curr:
55
  return f"{amount:,.0f} {from_curr}"
56
- rate = requests.get(
57
- f"https://api.frankfurter.app/latest?from={from_curr}&to={to_curr}",
 
 
58
  timeout=10
59
- ).json()['rates'][to_curr]
60
- return f"{amount:,.0f} {from_curr} = {amount*rate:,.0f} {to_curr}"
61
- except:
62
- return f"{amount:,.0f} {from_curr} (≈{amount*0.93:,.0f} EUR est.)"
 
 
 
 
 
63
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
 
65
  @tool
66
- def build_catalogue(destination: str, origin: str, dates: str, budget: str, weather: str, image_url_1: str, image_url_2: str) -> str:
67
  """
68
- Assemble final travel catalogue with embedded images.
69
-
70
  Args:
71
- destination: Destination city (e.g., "Barcelona")
72
- origin: Home city (e.g., "New York")
73
- dates: Travel dates (e.g., "Oct 15-19")
74
- budget: Budget conversion result (e.g., "$1,200 = €1,116")
75
- weather: Weather forecast summary
76
- image_url_1: First generated image URL from image_generation_tool
77
- image_url_2: Second generated image URL from image_generation_tool
 
 
 
78
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
  Returns:
80
- Beautiful Markdown travel catalogue with embedded images
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81
  """
82
  return f"""# 🌍 {destination} Travel Catalogue
83
- *From {origin} • {dates} • Budget: {budget}*
 
 
84
 
85
- ## 🌤️ Weather
 
 
 
 
 
86
  {weather}
87
 
88
- ## 📸 Destination Views
89
- ![{destination} landmark]({image_url_1})
90
- *Generated landmark view*
 
91
 
92
- ![{destination} street scene]({image_url_2})
93
- *Generated street scene*
94
 
95
- > 💡 Pro Tip: Book Sagrada Familia tickets online to skip 2-hour queues!
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96
  """
97
 
98
  # ======================
99
- # AGENT SETUP (CRITICAL FIXES)
100
  # ======================
101
-
102
- # Load tools
103
- final_answer = FinalAnswerTool()
104
- web_search = DuckDuckGoSearchTool()
105
- image_gen = load_tool("agents-course/text-to-image", trust_remote_code=True)
106
-
107
- # Use minimal system prompt that encourages CODE BLOCKS (not prose)
108
- system_prompt = (
109
- "You are a travel assistant. ALWAYS respond with executable Python code blocks.\n"
110
- "Workflow:\n"
111
- "1. Use DuckDuckGoSearchTool to find attractions\n"
112
- "2. Use get_weather for forecast\n"
113
- "3. Use convert_currency for budget\n"
114
- "4. CALL image_generation_tool TWICE:\n"
115
- " img1 = image_generation_tool('{destination} landmark photorealistic')\n"
116
- " img2 = image_generation_tool('{destination} vibrant street scene')\n"
117
- "5. Use build_catalogue with BOTH image URLs\n"
118
- "NEVER output natural language steps. ONLY output:\n"
119
- "Thoughts: ...\n"
120
- "Code:\n"
121
- "```py\n"
122
- "# executable code\n"
123
- "```"
124
- )
125
-
126
- model = HfApiModel(
127
- max_tokens=1500, # Prevent token exhaustion
128
- temperature=0.2, # Lower = more deterministic code output
129
- model_id="Qwen/Qwen2.5-Coder-32B-Instruct",
130
- )
131
-
132
- agent = CodeAgent(
133
- model=model,
134
- tools=[
135
- final_answer,
136
- web_search,
137
- image_gen, # MUST be in tool list to be callable in code blocks
138
- get_weather,
139
- convert_currency,
140
- build_catalogue,
141
- ],
142
- max_steps=12,
143
- verbosity_level=1,
144
- name="TravelAgent",
145
- description="Creates travel catalogues with images",
146
- prompt_templates={"system_prompt": system_prompt},
147
- )
148
-
149
  if __name__ == "__main__":
150
- print("🚀 Travel Agent with guaranteed image generation")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
151
  GradioUI(agent, file_upload_folder="./uploads").launch()
 
1
  #!/usr/bin/env python
2
  # coding=utf-8
3
+ import os
4
  import re
5
  import requests
6
+ from datetime import datetime, timedelta
7
+ from typing import Optional
8
  from smolagents import CodeAgent, DuckDuckGoSearchTool, HfApiModel, load_tool, tool
 
9
  from Gradio_UI import GradioUI
10
 
11
  # ======================
12
+ # TRAVEL TOOLS (PRODUCTION-GRADE)
13
  # ======================
14
 
15
  @tool
16
+ def get_weather_forecast(location: str, travel_dates: str) -> str:
17
  """
18
+ Get weather forecast using OpenWeatherMap (fallback to wttr.in).
 
19
  Args:
20
  location: Destination city (e.g., "Barcelona")
21
+ travel_dates: Date range (e.g., "2026-10-15 to 2026-10-19")
 
22
  Returns:
23
+ Weather summary with packing advice
24
  """
25
+ api_key = os.environ.get("OPENWEATHER_API_KEY")
26
  try:
27
+ # Parse dates to get start date
28
+ start_date = re.search(r"(\d{4}-\d{2}-\d{2})", travel_dates)
29
+ if not start_date:
30
+ raise ValueError("Invalid date format")
31
+
32
+ # Try OpenWeatherMap first (more reliable)
33
+ if api_key:
34
+ city = re.sub(r"[^a-zA-Z\s]", "", location).strip()
35
+ resp = requests.get(
36
+ f"https://api.openweathermap.org/data/2.5/forecast",
37
+ params={"q": city, "appid": api_key, "units": "metric"},
38
+ timeout=10
39
+ )
40
+ if resp.status_code == 200:
41
+ data = resp.json()
42
+ day1 = data["list"][0]
43
+ temp = day1["main"]["temp"]
44
+ cond = day1["weather"][0]["description"]
45
+ rain = "rain" in cond.lower() or day1.get("rain", {}).get("3h", 0) > 1
46
+ return _generate_packing_advice(location, temp, cond, rain)
47
+
48
+ # Fallback to wttr.in
49
+ clean = re.sub(r"[^a-zA-Z0-9\s]", "", location).replace(" ", "+")
50
+ resp = requests.get(f"http://wttr.in/{clean}?format=j1", timeout=10)
51
+ if resp.status_code == 200:
52
+ data = resp.json()
53
+ cur = data["current_condition"][0]
54
+ temp = int(cur["temp_C"])
55
+ cond = cur["lang_en"][0]["value"]
56
+ rain = "rain" in cond.lower()
57
+ return _generate_packing_advice(location, temp, cond, rain)
58
+
59
+ except Exception:
60
+ pass
61
+
62
+ # Safe fallback
63
+ return f"{location} typical weather: 15-25°C. Pack light layers, light jacket, and compact umbrella."
64
 
65
+ def _generate_packing_advice(location: str, temp: float, condition: str, rain: bool) -> str:
66
+ """Helper to generate weather-based packing advice"""
67
+ if temp > 25:
68
+ clothes = "Light clothing, shorts, breathable fabrics"
69
+ elif temp > 15:
70
+ clothes = "Light layers, long sleeves, light jacket"
71
+ else:
72
+ clothes = "Warm layers, jacket, beanie recommended"
73
+
74
+ if rain:
75
+ clothes += " + waterproof jacket + compact umbrella"
76
+
77
+ return f"{location} forecast: {temp:.0f}°C, {condition}. Packing: {clothes}"
78
 
79
  @tool
80
+ def convert_currency(amount: float, from_currency: str, to_currency: str) -> str:
81
  """
82
+ Convert currency using Frankfurter API (no key required).
 
83
  Args:
84
+ amount: Amount to convert
85
+ from_currency: Source currency (e.g., "USD")
86
+ to_currency: Target currency (e.g., "EUR")
 
87
  Returns:
88
  Formatted conversion result
89
  """
90
  try:
91
+ from_curr = from_currency.upper()[:3]
92
+ to_curr = to_currency.upper()[:3]
93
+
94
  if from_curr == to_curr:
95
  return f"{amount:,.0f} {from_curr}"
96
+
97
+ resp = requests.get(
98
+ f"https://api.frankfurter.app/latest",
99
+ params={"from": from_curr, "to": to_curr},
100
  timeout=10
101
+ )
102
+ if resp.status_code == 200:
103
+ rate = resp.json()["rates"][to_curr]
104
+ converted = amount * rate
105
+ return f"{amount:,.0f} {from_curr} = {converted:,.0f} {to_curr} (1 {from_curr} = {rate:.2f} {to_curr})"
106
+ except Exception:
107
+ pass
108
+
109
+ return f"{amount:,.0f} {from_currency} (conversion rate unavailable)"
110
 
111
+ @tool
112
+ def get_time_difference(origin: str, destination: str) -> str:
113
+ """
114
+ Get time difference between origin and destination cities.
115
+ Args:
116
+ origin: Home city
117
+ destination: Travel destination
118
+ Returns:
119
+ Time difference description
120
+ """
121
+ try:
122
+ # Simple heuristic-based approach (no external API required)
123
+ major_cities = {
124
+ "new york": -5, "london": 0, "paris": 1, "tokyo": 9, "sydney": 10,
125
+ "los angeles": -8, "chicago": -6, "mumbai": 5.5, "dubai": 4,
126
+ "singapore": 8, "berlin": 1, "rome": 1, "barcelona": 1, "madrid": 1
127
+ }
128
+
129
+ origin_tz = major_cities.get(origin.lower(), 0)
130
+ dest_tz = major_cities.get(destination.lower(), 0)
131
+ diff = dest_tz - origin_tz
132
+
133
+ if diff == 0:
134
+ return f"No time difference between {origin} and {destination}"
135
+ elif diff > 0:
136
+ return f"{destination} is {diff} hours ahead of {origin} (adjust sleep schedule accordingly)"
137
+ else:
138
+ return f"{destination} is {abs(diff)} hours behind {origin} (prepare for jet lag)"
139
+ except:
140
+ return f"Time difference information unavailable. Check world clock apps before travel."
141
 
142
  @tool
143
+ def generate_packing_list(destination: str, weather_summary: str, trip_days: int, trip_type: str) -> str:
144
  """
145
+ Generate customized packing list.
 
146
  Args:
147
+ destination: Destination name
148
+ weather_summary: Weather conditions
149
+ trip_days: Duration in days
150
+ trip_type: "city", "beach", "mountain", or "mixed"
151
+ Returns:
152
+ Formatted packing checklist
153
+ """
154
+ cold = any(w in weather_summary.lower() for w in ["cold", "cool", "jacket", "10°c", "11°c", "12°c", "13°c", "14°c"])
155
+ rain = any(w in weather_summary.lower() for w in ["rain", "shower", "umbrella", "drizzle"])
156
+ hot = any(w in weather_summary.lower() for w in ["hot", "warm", "25°c", "26°c", "27°c", "28°c", "29°c", "30°c"])
157
 
158
+ # Clothing calculations
159
+ tops = min(trip_days, trip_days // 2 + 2)
160
+ bottoms = min(trip_days // 2 + 1, 4)
161
+
162
+ clothes = [f"• Tops ({tops})", f"• Bottoms ({bottoms})"]
163
+ if cold:
164
+ clothes.extend(["• Warm jacket", "• Long underwear (if very cold)"])
165
+ elif hot:
166
+ clothes.extend(["• Light breathable fabrics", "• Sun hat"])
167
+ else:
168
+ clothes.append("• Light jacket (essential)")
169
+
170
+ if rain:
171
+ clothes.extend(["• Compact umbrella", "• Quick-dry clothing"])
172
+
173
+ if trip_type == "beach":
174
+ clothes.extend(["• Swimsuit (x2)", "• Flip-flops", "• Reef-safe sunscreen"])
175
+ elif trip_type == "mountain":
176
+ clothes.extend(["• Sturdy hiking shoes", "• Moisture-wicking layers", "• Trekking poles (optional)"])
177
+
178
+ return (
179
+ f"🎒 SMART PACKING LIST ({trip_days}-day {trip_type} trip to {destination})\n"
180
+ "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"
181
+ "ESSENTIALS\n"
182
+ "• Passport + photocopies + digital scans\n"
183
+ "• Credit/debit cards + local currency (small amount)\n"
184
+ "• Universal power adapter\n"
185
+ "• Phone + portable charger + cables\n"
186
+ "• Travel insurance documents\n"
187
+ "\nCLOTHING\n" + "\n".join(clothes) + "\n"
188
+ "\nHEALTH & HYGIENE\n"
189
+ "• Prescription medications (in original packaging)\n"
190
+ "• Basic first-aid kit\n"
191
+ "• Hand sanitizer + tissues\n"
192
+ "• Travel-sized toiletries\n"
193
+ "\n💡 Pro tip: Roll clothes to save space. Pack one versatile outfit per day + 1 extra."
194
+ )
195
+
196
+ @tool
197
+ def build_itinerary(destination: str, attractions: str, budget_local: float, days: int) -> str:
198
+ """
199
+ Create realistic day-by-day itinerary.
200
+ Args:
201
+ destination: City name
202
+ attractions: Comma-separated attractions
203
+ budget_local: Daily budget in local currency
204
+ days: Trip duration
205
  Returns:
206
+ Formatted itinerary
207
+ """
208
+ atts = [a.strip() for a in attractions.split(",") if a.strip()]
209
+ if not atts:
210
+ atts = ["Old Town exploration", "Local museum", "Scenic viewpoint", "Local market"]
211
+
212
+ daily_budget = budget_local / max(days, 1)
213
+ lines = [f"🗓️ {days}-DAY REALISTIC ITINERARY: {destination}", "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"]
214
+
215
+ for d in range(1, days + 1):
216
+ # Alternate between major and minor attractions
217
+ primary = atts[(d - 1) % len(atts)]
218
+ secondary = atts[d % len(atts)] if len(atts) > 1 else "Leisurely café break"
219
+
220
+ lines.extend([
221
+ f"\nDAY {d} | Budget: ~{daily_budget:,.0f} local currency",
222
+ f" 09:00 - 12:00 {primary}",
223
+ f" 12:30 - 14:00 Lunch at local spot",
224
+ f" 14:30 - 17:00 {secondary}",
225
+ f" 19:00+ Dinner + evening stroll"
226
+ ])
227
+
228
+ lines.append("\n💡 Book major attractions online in advance to skip lines!")
229
+ return "\n".join(lines)
230
+
231
+ @tool
232
+ def assemble_catalogue(
233
+ destination: str,
234
+ origin: str,
235
+ dates: str,
236
+ budget_summary: str,
237
+ weather: str,
238
+ timezone_info: str,
239
+ itinerary: str,
240
+ packing: str,
241
+ image_url_1: str,
242
+ image_url_2: str
243
+ ) -> str:
244
+ """
245
+ Compile final travel catalogue with embedded images.
246
  """
247
  return f"""# 🌍 {destination} Travel Catalogue
248
+ *From {origin} • {dates} • {budget_summary}*
249
+
250
+ ---
251
 
252
+ ## Time Zone Adjustment
253
+ {timezone_info}
254
+
255
+ ---
256
+
257
+ ## 🌤️ Weather & Packing Guidance
258
  {weather}
259
 
260
+ ---
261
+
262
+ ## 🗓️ Your Personalized Itinerary
263
+ {itinerary}
264
 
265
+ ---
 
266
 
267
+ ## 🎒 Packing Checklist
268
+ {packing}
269
+
270
+ ---
271
+
272
+ ## 📸 Visual Inspiration
273
+ <div style="display: flex; gap: 20px; margin: 20px 0;">
274
+ <div style="flex: 1; text-align: center;">
275
+ <img src="{image_url_1}" alt="{destination} landmark" style="max-width: 100%; border-radius: 8px; box-shadow: 0 4px 8px rgba(0,0,0,0.1);">
276
+ <p><em>Iconic {destination} landmark</em></p>
277
+ </div>
278
+ <div style="flex: 1; text-align: center;">
279
+ <img src="{image_url_2}" alt="{destination} street scene" style="max-width: 100%; border-radius: 8px; box-shadow: 0 4px 8px rgba(0,0,0,0.1);">
280
+ <p><em>Vibrant street life</em></p>
281
+ </div>
282
+ </div>
283
+
284
+ ---
285
+
286
+ > 💡 **Travel Pro Tips**
287
+ > • Download offline maps before departure
288
+ > • Learn 5 basic phrases in the local language
289
+ > • Keep digital copies of important documents in cloud storage
290
+ > • Budget 10-15% extra for unexpected experiences
291
+ > • Public transport passes often save 30%+ vs single tickets
292
  """
293
 
294
  # ======================
295
+ # AGENT SETUP
296
  # ======================
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
297
  if __name__ == "__main__":
298
+ print("🚀 Initializing Travel Catalogue Creator...")
299
+
300
+ # Load tools
301
+ try:
302
+ image_gen = load_tool("black-forest-labs/FLUX.1-schnell", trust_remote_code=True)
303
+ except:
304
+ # Fallback to stable tool
305
+ image_gen = load_tool("stabilityai/stable-diffusion-3-medium", trust_remote_code=True)
306
+
307
+ web_search = DuckDuckGoSearchTool()
308
+ model = HfApiModel(
309
+ max_tokens=2048,
310
+ temperature=0.3, # Lower for reliable tool usage
311
+ model_id="Qwen/Qwen2.5-Coder-32B-Instruct",
312
+ )
313
+
314
+ # System prompt enforces strict workflow
315
+ with open("prompts.yaml", "r") as f:
316
+ import yaml
317
+ prompt_templates = yaml.safe_load(f)
318
+
319
+ agent = CodeAgent(
320
+ model=model,
321
+ tools=[
322
+ web_search,
323
+ image_gen,
324
+ get_weather_forecast,
325
+ convert_currency,
326
+ get_time_difference,
327
+ generate_packing_list,
328
+ build_itinerary,
329
+ assemble_catalogue,
330
+ ],
331
+ max_steps=25, # Allow room for image generation + retries
332
+ verbosity_level=1,
333
+ name="TravelCatalogueCreator",
334
+ description="Creates comprehensive, personalized travel catalogues with images",
335
+ prompt_templates=prompt_templates,
336
+ )
337
+
338
+ # Launch UI
339
+ os.makedirs("./uploads", exist_ok=True)
340
  GradioUI(agent, file_upload_folder="./uploads").launch()