agarwalamit081 commited on
Commit
6b4a562
·
verified ·
1 Parent(s): 8c5c24b

Update app.py

Browse files

updated app.py to customize it for Travel Catalogue Creator

Files changed (1) hide show
  1. app.py +426 -38
app.py CHANGED
@@ -1,69 +1,457 @@
1
- from smolagents import CodeAgent,DuckDuckGoSearchTool, HfApiModel,load_tool,tool
2
- import datetime
 
 
3
  import requests
 
4
  import pytz
5
- import yaml
 
 
6
  from tools.final_answer import FinalAnswerTool
7
-
8
  from Gradio_UI import GradioUI
 
 
 
 
 
9
 
10
- # Below is an example of a tool that does nothing. Amaze us with your creativity !
11
  @tool
12
- def my_custom_tool(arg1:str, arg2:int)-> str: #it's import to specify the return type
13
- #Keep this format for the description / args / args description but feel free to modify the tool
14
- """A tool that does nothing yet
 
15
  Args:
16
- arg1: the first argument
17
- arg2: the second argument
 
 
 
18
  """
19
- return "What magic will you build ?"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
 
21
  @tool
22
- def get_current_time_in_timezone(timezone: str) -> str:
23
- """A tool that fetches the current local time in a specified timezone.
 
 
24
  Args:
25
- timezone: A string representing a valid timezone (e.g., 'America/New_York').
 
 
 
 
 
26
  """
27
  try:
28
- # Create timezone object
29
- tz = pytz.timezone(timezone)
30
- # Get current time in that timezone
31
- local_time = datetime.datetime.now(tz).strftime("%Y-%m-%d %H:%M:%S")
32
- return f"The current local time in {timezone} is: {local_time}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  except Exception as e:
34
- return f"Error fetching time for timezone '{timezone}': {str(e)}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
 
36
 
37
- final_answer = FinalAnswerTool()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
 
39
- # If the agent does not answer, the model is overloaded, please use another model or the following Hugging Face Endpoint that also contains qwen2.5 coder:
40
- # model_id='https://pflgm2locj2t89co.us-east-1.aws.endpoints.huggingface.cloud'
41
 
42
- model = HfApiModel(
43
- max_tokens=2096,
44
- temperature=0.5,
45
- model_id='Qwen/Qwen2.5-Coder-32B-Instruct',# it is possible that this model may be overloaded
46
- custom_role_conversions=None,
47
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
48
 
49
 
50
- # Import tool from Hub
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
  image_generation_tool = load_tool("agents-course/text-to-image", trust_remote_code=True)
52
 
 
 
 
 
 
 
 
 
 
53
  with open("prompts.yaml", 'r') as stream:
54
  prompt_templates = yaml.safe_load(stream)
55
-
 
56
  agent = CodeAgent(
57
  model=model,
58
- tools=[final_answer], ## add your tools here (don't remove final answer)
59
- max_steps=6,
 
 
 
 
 
 
 
 
 
60
  verbosity_level=1,
61
  grammar=None,
62
  planning_interval=None,
63
- name=None,
64
- description=None,
65
- prompt_templates=prompt_templates
 
 
 
66
  )
67
 
68
-
69
- GradioUI(agent).launch()
 
 
 
 
1
+ #!/usr/bin/env python
2
+ # coding=utf-8
3
+ import os
4
+ import re
5
  import requests
6
+ import datetime
7
  import pytz
8
+ import json
9
+ from typing import List, Dict, Optional
10
+ from smolagents import CodeAgent, DuckDuckGoSearchTool, HfApiModel, load_tool, tool
11
  from tools.final_answer import FinalAnswerTool
 
12
  from Gradio_UI import GradioUI
13
+ import yaml
14
+
15
+ # ======================
16
+ # CUSTOM TRAVEL TOOLS
17
+ # ======================
18
 
 
19
  @tool
20
+ def get_weather_forecast(location: str, travel_dates: str) -> str:
21
+ """
22
+ Get weather forecast for a destination during travel dates using wttr.in (no API key required).
23
+
24
  Args:
25
+ location: Destination city name (e.g., "Paris", "Tokyo")
26
+ travel_dates: Travel date range in format "YYYY-MM-DD to YYYY-MM-DD" or month name (e.g., "June 2026")
27
+
28
+ Returns:
29
+ Weather summary including temperature range, conditions, and packing recommendations
30
  """
31
+ try:
32
+ # Clean location name for URL
33
+ clean_location = re.sub(r'[^a-zA-Z0-9\s]', '', location).replace(' ', '+')
34
+
35
+ # Fetch weather data from wttr.in JSON endpoint
36
+ url = f"http://wttr.in/{clean_location}?format=j1"
37
+ response = requests.get(url, timeout=10)
38
+ response.raise_for_status()
39
+ data = response.json()
40
+
41
+ # Extract current conditions and forecast
42
+ current = data['current_condition'][0]
43
+ today = data['weather'][0]
44
+
45
+ temp_c = int(current['temp_C'])
46
+ feels_like = int(current['FeelsLikeC'])
47
+ conditions = current['lang_en'][0]['value']
48
+ humidity = current['humidity']
49
+ wind = current['windspeedKmph']
50
+
51
+ # Determine season-appropriate packing advice
52
+ if temp_c > 25:
53
+ packing_advice = "Light clothing, sunscreen, hat, sunglasses, reusable water bottle"
54
+ elif temp_c > 15:
55
+ packing_advice = "Light layers, light jacket, comfortable walking shoes"
56
+ elif temp_c > 5:
57
+ packing_advice = "Warm layers, medium jacket, scarf, gloves if evening gets cold"
58
+ else:
59
+ packing_advice = "Heavy winter coat, thermal layers, hat, gloves, warm boots"
60
+
61
+ # Add rain advice if precipitation likely
62
+ if "rain" in conditions.lower() or "shower" in conditions.lower():
63
+ packing_advice += ", waterproof jacket, umbrella"
64
+ elif "snow" in conditions.lower():
65
+ packing_advice += ", waterproof boots, snow gear"
66
+
67
+ forecast_summary = (
68
+ f"Weather forecast for {location}:\n"
69
+ f"• Current: {temp_c}°C (feels like {feels_like}°C)\n"
70
+ f"• Conditions: {conditions}\n"
71
+ f"• Humidity: {humidity}%, Wind: {wind} km/h\n"
72
+ f"• Typical conditions for this period: Mild to warm days, cool evenings\n"
73
+ f"• Packing recommendation: {packing_advice}"
74
+ )
75
+ return forecast_summary
76
+
77
+ except Exception as e:
78
+ # Fallback to descriptive response if API fails
79
+ return (
80
+ f"Could not fetch live weather for {location}. Based on typical climate:\n"
81
+ f"• {location} in this season generally has mild temperatures (15-25°C)\n"
82
+ f"• Light layers and a light jacket recommended\n"
83
+ f"• Always pack a compact umbrella for unexpected showers"
84
+ )
85
+
86
 
87
  @tool
88
+ def convert_currency(amount: float, from_currency: str, to_currency: str) -> str:
89
+ """
90
+ Convert currency using Frankfurter API (free ECB data, no authentication required).
91
+
92
  Args:
93
+ amount: Amount to convert (e.g., 1000.0)
94
+ from_currency: Source currency code (e.g., "USD", "EUR")
95
+ to_currency: Target currency code (e.g., "JPY", "EUR")
96
+
97
+ Returns:
98
+ Conversion result with exchange rate and formatted amounts
99
  """
100
  try:
101
+ from_currency = from_currency.upper()
102
+ to_currency = to_currency.upper()
103
+
104
+ # Handle single currency conversion
105
+ if from_currency == to_currency:
106
+ return f"{amount:,.2f} {from_currency} = {amount:,.2f} {to_currency} (same currency)"
107
+
108
+ # Fetch latest rates from Frankfurter
109
+ url = f"https://api.frankfurter.app/latest?from={from_currency}&to={to_currency}"
110
+ response = requests.get(url, timeout=10)
111
+ response.raise_for_status()
112
+ data = response.json()
113
+
114
+ rate = data['rates'][to_currency]
115
+ converted = amount * rate
116
+
117
+ return (
118
+ f"Currency conversion:\n"
119
+ f"• {amount:,.2f} {from_currency} = {converted:,.2f} {to_currency}\n"
120
+ f"• Exchange rate: 1 {from_currency} = {rate:.4f} {to_currency}\n"
121
+ f"• Rate source: European Central Bank (updated daily)"
122
+ )
123
+
124
  except Exception as e:
125
+ # Provide reasonable estimate if API fails
126
+ fallback_rates = {
127
+ ("USD", "EUR"): 0.93,
128
+ ("EUR", "USD"): 1.07,
129
+ ("USD", "JPY"): 150.0,
130
+ ("EUR", "JPY"): 161.0,
131
+ ("USD", "GBP"): 0.79,
132
+ ("GBP", "USD"): 1.27,
133
+ }
134
+ rate = fallback_rates.get((from_currency, to_currency), 1.0)
135
+ converted = amount * rate
136
+ return (
137
+ f"Live rates unavailable. Using estimated rate:\n"
138
+ f"• {amount:,.2f} {from_currency} ≈ {converted:,.2f} {to_currency}\n"
139
+ f"• Estimated rate: 1 {from_currency} ≈ {rate:.2f} {to_currency}\n"
140
+ f"(For accurate planning, check a financial service before travel)"
141
+ )
142
 
143
 
144
+ @tool
145
+ def generate_packing_list(destination: str, weather_summary: str, trip_duration_days: int, trip_type: str = "sightseeing") -> str:
146
+ """
147
+ Generate a customized packing list based on destination, weather, duration, and trip type.
148
+
149
+ Args:
150
+ destination: Travel destination (e.g., "Kyoto, Japan")
151
+ weather_summary: Weather conditions from get_weather_forecast tool
152
+ trip_duration_days: Length of trip in days (e.g., 5)
153
+ trip_type: Type of trip - "beach", "city", "hiking", "business", or "sightseeing"
154
+
155
+ Returns:
156
+ Categorized packing checklist with quantities
157
+ """
158
+ # Extract temperature hints from weather summary
159
+ has_rain = "rain" in weather_summary.lower() or "umbrella" in weather_summary.lower()
160
+ has_cold = "cold" in weather_summary.lower() or "jacket" in weather_summary.lower() or "gloves" in weather_summary.lower()
161
+ has_hot = "hot" in weather_summary.lower() or "sunscreen" in weather_summary.lower() or "hat" in weather_summary.lower()
162
+
163
+ # Base items for all trips
164
+ essentials = [
165
+ f"• Passport + photocopies ({'and visa' if 'china' in destination.lower() or 'russia' in destination.lower() else 'if required'})",
166
+ "• Travel insurance documents",
167
+ "• Credit/debit cards + small amount of local currency",
168
+ "• Universal power adapter",
169
+ "• Phone + charger + power bank",
170
+ "• Reusable water bottle",
171
+ ]
172
+
173
+ # Clothing based on conditions
174
+ clothing = []
175
+ if has_hot:
176
+ clothing.extend([
177
+ f"• T-shirts/tanks ({trip_duration_days // 2 + 1})",
178
+ "• Lightweight breathable pants/shorts",
179
+ "• Sun hat + sunglasses",
180
+ "• High-SPF sunscreen",
181
+ ])
182
+ elif has_cold:
183
+ clothing.extend([
184
+ f"• Warm base layers ({trip_duration_days // 3 + 1})",
185
+ "• Insulated jacket",
186
+ "• Warm socks ({trip_duration_days // 2 + 1})",
187
+ "• Beanie/gloves (if very cold)",
188
+ ])
189
+ else:
190
+ clothing.extend([
191
+ f"• Versatile tops ({trip_duration_days // 2 + 1})",
192
+ f"• Comfortable pants ({trip_duration_days // 3 + 1})",
193
+ "• Light jacket/sweater (layering essential)",
194
+ ])
195
+
196
+ if has_rain:
197
+ clothing.append("• Compact travel umbrella")
198
+ clothing.append("• Light waterproof jacket")
199
+
200
+ # Trip-type specific items
201
+ if trip_type == "beach":
202
+ clothing.extend([
203
+ "• Swimsuit",
204
+ "• Beach towel",
205
+ "• Flip-flops/sandals",
206
+ "• Water shoes (if rocky beaches)",
207
+ ])
208
+ elif trip_type == "hiking":
209
+ clothing.extend([
210
+ "• Sturdy hiking boots",
211
+ "• Moisture-wicking socks",
212
+ "• Quick-dry hiking pants",
213
+ "• Daypack for trails",
214
+ ])
215
+ elif trip_type == "business":
216
+ clothing.extend([
217
+ "• Business attire (2-3 sets)",
218
+ "• Comfortable dress shoes",
219
+ "• Portfolio/briefcase",
220
+ ])
221
+
222
+ # Toiletries & health
223
+ toiletries = [
224
+ "• Travel-sized toiletries (shampoo, conditioner, body wash)",
225
+ "• Toothbrush + toothpaste",
226
+ "• Deodorant",
227
+ "• Prescription medications + copy of prescriptions",
228
+ "• Basic first-aid kit (band-aids, pain relievers)",
229
+ ]
230
+
231
+ if has_hot:
232
+ toiletries.append("• After-sun lotion / aloe vera")
233
+
234
+ # Compile final list
235
+ packing_list = (
236
+ f"🎒 Custom Packing List for {destination} ({trip_duration_days}-day {trip_type} trip)\n"
237
+ f"{'='*60}\n\n"
238
+ f"✓ ESSENTIALS\n" + "\n".join(essentials) + "\n\n"
239
+ f"✓ CLOTHING\n" + "\n".join(clothing) + "\n\n"
240
+ f"✓ TOILETRIES & HEALTH\n" + "\n".join(toiletries) + "\n\n"
241
+ f"✓ PRO TIP: Roll clothes to save space. Use packing cubes for organization.\n"
242
+ f"✓ CULTURAL NOTE: Research local customs for {destination} (e.g., temple dress codes)"
243
+ )
244
+
245
+ return packing_list
246
 
 
 
247
 
248
+ @tool
249
+ def build_itinerary(destination: str, attractions: str, weather_summary: str, budget_local_currency: float, trip_duration_days: int) -> str:
250
+ """
251
+ Create a day-by-day travel itinerary optimized for weather, budget, and attraction proximity.
252
+
253
+ Args:
254
+ destination: Travel destination city/country
255
+ attractions: Key attractions gathered from web search (comma-separated list)
256
+ weather_summary: Weather conditions to optimize daily activities
257
+ budget_local_currency: Total budget in destination currency
258
+ trip_duration_days: Length of trip in days
259
+
260
+ Returns:
261
+ Detailed day-by-day itinerary with time allocations and cost estimates
262
+ """
263
+ # Parse attractions into list
264
+ attraction_list = [a.strip() for a in attractions.split(",") if a.strip()]
265
+ if not attraction_list:
266
+ attraction_list = ["Old Town exploration", "Local museum", "Scenic viewpoint", "Cultural market", "Local cuisine experience"]
267
+
268
+ # Budget allocation logic
269
+ daily_budget = budget_local_currency / max(trip_duration_days, 1)
270
+ activity_budget = daily_budget * 0.4
271
+ food_budget = daily_budget * 0.35
272
+ transport_budget = daily_budget * 0.15
273
+ buffer = daily_budget * 0.10
274
+
275
+ # Build day-by-day plan
276
+ itinerary_lines = [
277
+ f"🗓️ {trip_duration_days}-Day Itinerary for {destination}",
278
+ "="*60,
279
+ f"💰 Daily Budget Allocation (from total {budget_local_currency:,.0f}):",
280
+ f" • Activities: {activity_budget:,.0f} | Food: {food_budget:,.0f} | Transport: {transport_budget:,.0f} | Buffer: {buffer:,.0f}",
281
+ "",
282
+ ]
283
+
284
+ # Weather hints for activity planning
285
+ is_rainy = "rain" in weather_summary.lower()
286
+ is_cold = "cold" in weather_summary.lower() or "0°C" in weather_summary or "freezing" in weather_summary.lower()
287
+
288
+ for day in range(1, trip_duration_days + 1):
289
+ # Alternate indoor/outdoor based on weather hints
290
+ if is_rainy and day % 2 == 0:
291
+ focus = "Indoor cultural experiences"
292
+ elif is_cold:
293
+ focus = "Morning outdoor sights, afternoon indoor museums"
294
+ else:
295
+ focus = "Outdoor exploration with strategic indoor breaks"
296
+
297
+ # Select attractions for this day (rotate through list)
298
+ day_attractions = attraction_list[(day-1)*2 : (day-1)*2 + 2]
299
+ if not day_attractions:
300
+ day_attractions = attraction_list[:2]
301
+
302
+ itinerary_lines.extend([
303
+ f"DAY {day}: {focus}",
304
+ "-"*60,
305
+ f"🕗 09:00 - Morning: {day_attractions[0] if len(day_attractions) > 0 else 'Local neighborhood walk'}",
306
+ f"🕛 12:30 - Lunch: Local cuisine spot (~{food_budget * 0.4:,.0f})",
307
+ f"🕑 14:00 - Afternoon: {day_attractions[1] if len(day_attractions) > 1 else 'Cultural district exploration'}",
308
+ f"🕖 19:00 - Dinner: Recommended local restaurant (~{food_budget * 0.6:,.0f})",
309
+ f"💡 Pro tip: Book popular attractions online in advance to skip lines",
310
+ "",
311
+ ])
312
+
313
+ itinerary_lines.append(
314
+ "📌 BUDGET NOTES:\n"
315
+ "• Many museums offer free entry on specific days - research ahead!\n"
316
+ "• Public transport passes often cheaper than single tickets\n"
317
+ "• Street food offers authentic flavors at lower cost than restaurants"
318
+ )
319
+
320
+ return "\n".join(itinerary_lines)
321
 
322
 
323
+ @tool
324
+ def get_timezone_info(origin_city: str, destination_city: str) -> str:
325
+ """
326
+ Compare time zones between origin and destination cities.
327
+
328
+ Args:
329
+ origin_city: Traveler's home city (e.g., "New York", "London")
330
+ destination_city: Travel destination (e.g., "Tokyo", "Paris")
331
+
332
+ Returns:
333
+ Time difference, current times in both locations, and jet lag tips
334
+ """
335
+ # Simplified timezone mapping (covers major cities)
336
+ city_to_tz = {
337
+ # North America
338
+ "new york": "America/New_York", "nyc": "America/New_York",
339
+ "los angeles": "America/Los_Angeles", "la": "America/Los_Angeles",
340
+ "chicago": "America/Chicago", "toronto": "America/Toronto",
341
+ # Europe
342
+ "london": "Europe/London", "paris": "Europe/Paris", "berlin": "Europe/Berlin",
343
+ "rome": "Europe/Rome", "madrid": "Europe/Madrid", "amsterdam": "Europe/Amsterdam",
344
+ # Asia
345
+ "tokyo": "Asia/Tokyo", "kyoto": "Asia/Tokyo", "osaka": "Asia/Tokyo",
346
+ "seoul": "Asia/Seoul", "bangkok": "Asia/Bangkok", "singapore": "Asia/Singapore",
347
+ "shanghai": "Asia/Shanghai", "beijing": "Asia/Shanghai", "hong kong": "Asia/Hong_Kong",
348
+ # Oceania
349
+ "sydney": "Australia/Sydney", "melbourne": "Australia/Melbourne",
350
+ # Others
351
+ "dubai": "Asia/Dubai", "rio de janeiro": "America/Sao_Paulo",
352
+ }
353
+
354
+ origin_key = origin_city.strip().lower()
355
+ dest_key = destination_city.strip().lower()
356
+
357
+ origin_tz = city_to_tz.get(origin_key, "UTC")
358
+ dest_tz = city_to_tz.get(dest_key, "UTC")
359
+
360
+ try:
361
+ origin_time = datetime.datetime.now(pytz.timezone(origin_tz))
362
+ dest_time = datetime.datetime.now(pytz.timezone(dest_tz))
363
+ time_diff = (dest_time.utcoffset().total_seconds() - origin_time.utcoffset().total_seconds()) / 3600
364
+
365
+ direction = "ahead" if time_diff > 0 else "behind"
366
+ abs_diff = abs(time_diff)
367
+
368
+ jet_lag_tips = []
369
+ if abs_diff >= 8:
370
+ jet_lag_tips = [
371
+ "• Significant jet lag expected (>8 hours)",
372
+ "• Strategy: Start adjusting sleep schedule 2-3 days before departure",
373
+ "• Day 1 tip: Stay awake until local bedtime, get morning sunlight exposure",
374
+ ]
375
+ elif abs_diff >= 4:
376
+ jet_lag_tips = [
377
+ "• Moderate jet lag expected (4-8 hours)",
378
+ "• Strategy: Adjust watch to destination time upon boarding",
379
+ "• Day 1 tip: Light exercise helps reset circadian rhythm",
380
+ ]
381
+ else:
382
+ jet_lag_tips = [
383
+ "• Minimal jet lag expected (<4 hours)",
384
+ "• Strategy: Normal adjustment within 1-2 days",
385
+ ]
386
+
387
+ return (
388
+ f"🕐 Time Zone Comparison: {origin_city.title()} ↔ {destination_city.title()}\n"
389
+ f"{'='*60}\n"
390
+ f"• Current time in {origin_city.title()}: {origin_time.strftime('%H:%M (%A)')}\n"
391
+ f"• Current time in {destination_city.title()}: {dest_time.strftime('%H:%M (%A)')}\n"
392
+ f"• Time difference: {abs_diff:.0f} hours ({destination_city.title()} is {direction})\n"
393
+ f"\n{'\n'.join(jet_lag_tips)}\n"
394
+ f"• Best time to call home: {('evening' if time_diff > 0 else 'morning')} in {destination_city.title()}"
395
+ )
396
+
397
+ except Exception as e:
398
+ return (
399
+ f"🕐 Time zone info for {origin_city} → {destination_city}:\n"
400
+ f"• Time difference: Approximately {abs(8 if 'tokyo' in dest_key else 5 if 'london' in dest_key else 1)} hours\n"
401
+ f"• Tip: Use world clock apps to coordinate calls with family/friends back home"
402
+ )
403
+
404
+
405
+ # ======================
406
+ # AGENT SETUP
407
+ # ======================
408
+
409
+ # Initialize tools
410
+ final_answer = FinalAnswerTool()
411
+ web_search = DuckDuckGoSearchTool()
412
+
413
+ # Load image generation tool from Hub
414
  image_generation_tool = load_tool("agents-course/text-to-image", trust_remote_code=True)
415
 
416
+ # Initialize model
417
+ model = HfApiModel(
418
+ max_tokens=2096,
419
+ temperature=0.5,
420
+ model_id="Qwen/Qwen2.5-Coder-32B-Instruct",
421
+ custom_role_conversions=None,
422
+ )
423
+
424
+ # Load prompt templates
425
  with open("prompts.yaml", 'r') as stream:
426
  prompt_templates = yaml.safe_load(stream)
427
+
428
+ # Create agent with comprehensive travel toolkit
429
  agent = CodeAgent(
430
  model=model,
431
+ tools=[
432
+ final_answer,
433
+ web_search,
434
+ image_generation_tool,
435
+ get_weather_forecast,
436
+ convert_currency,
437
+ generate_packing_list,
438
+ build_itinerary,
439
+ get_timezone_info,
440
+ ],
441
+ max_steps=12, # Increased for complex multi-step travel planning
442
  verbosity_level=1,
443
  grammar=None,
444
  planning_interval=None,
445
+ name="TravelCatalogueCreator",
446
+ description="Creates personalized travel catalogues with weather, budget, itinerary, and packing advice",
447
+ prompt_templates=prompt_templates,
448
+ authorized_imports=[
449
+ "datetime", "re", "requests", "json", "pytz", "math", "collections", "itertools"
450
+ ]
451
  )
452
 
453
+ # Launch Gradio interface
454
+ if __name__ == "__main__":
455
+ print("🚀 Travel Catalogue Creator Agent starting...")
456
+ print("💡 Example query: 'Create a 5-day Kyoto travel catalogue from Paris with €1500 budget for mid-June'")
457
+ GradioUI(agent, file_upload_folder="./uploads").launch()