agarwalamit081 commited on
Commit
061a038
·
verified ·
1 Parent(s): 94033bf

Update app.py

Browse files

argument descriptions for convert_currency.

Files changed (1) hide show
  1. app.py +113 -103
app.py CHANGED
@@ -5,28 +5,27 @@ 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 (FIXED + ENHANCED)
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
27
 
28
  Returns:
29
- Weather summary including temperature range, conditions, and packing recommendations
30
  """
31
  try:
32
  clean_location = re.sub(r'[^a-zA-Z0-9\s]', '', location).replace(' ', '+')
@@ -42,41 +41,40 @@ def get_weather_forecast(location: str, travel_dates: str) -> str:
42
  humidity = current['humidity']
43
  wind = current['windspeedKmph']
44
 
45
- # Smart packing advice
46
  if temp_c > 25:
47
- packing_advice = "Light clothing, sunscreen, hat, sunglasses, reusable water bottle"
48
  elif temp_c > 15:
49
- packing_advice = "Light layers, light jacket, comfortable walking shoes"
50
  elif temp_c > 5:
51
- packing_advice = "Warm layers, medium jacket, scarf"
52
  else:
53
- packing_advice = "Heavy winter coat, thermal layers, hat, gloves, warm boots"
54
 
55
  if "rain" in conditions.lower() or "shower" in conditions.lower():
56
- packing_advice += ", waterproof jacket, umbrella"
57
- elif "snow" in conditions.lower():
58
- packing_advice += ", waterproof boots, snow gear"
59
 
60
  return (
61
  f"Weather in {location}:\n"
62
  f"• {temp_c}°C (feels like {feels_like}°C) | {conditions}\n"
63
  f"• Humidity: {humidity}% | Wind: {wind} km/h\n"
64
- f"• Packing: {packing_advice}"
65
  )
66
-
67
  except Exception:
68
- return (
69
- f"Typical weather for {location} this season:\n"
70
- f"• Mild temperatures (15-25°C)\n"
71
- f"• Light layers + light jacket recommended\n"
72
- f"• Pack compact umbrella for unexpected showers"
73
- )
74
 
75
 
76
  @tool
77
  def convert_currency(amount: float, from_currency: str, to_currency: str) -> str:
78
  """
79
  Convert currency using Frankfurter API (free ECB data).
 
 
 
 
 
 
 
 
80
  """
81
  try:
82
  from_currency = from_currency.upper()
@@ -92,121 +90,137 @@ def convert_currency(amount: float, from_currency: str, to_currency: str) -> str
92
 
93
  return (
94
  f"💱 {amount:,.2f} {from_currency} = {converted:,.2f} {to_currency}\n"
95
- f" (1 {from_currency} = {rate:.4f} {to_currency})"
96
  )
97
-
98
  except Exception:
99
- fallback = {("USD","EUR"):0.93, ("EUR","USD"):1.07, ("USD","JPY"):150.0}.get((from_currency,to_currency), 1.0)
100
  converted = amount * fallback
101
- return f"⚠️ Estimated: {amount:,.2f} {from_currency} ≈ {converted:,.2f} {to_currency}"
102
 
103
 
104
  @tool
105
- def generate_packing_list(destination: str, weather_summary: str, trip_duration_days: int, trip_type: str = "sightseeing") -> str:
106
  """
107
- Generate a customized packing list. FIXED: Proper f-string evaluation for quantities.
 
 
 
 
 
 
 
 
 
108
  """
109
  has_rain = "rain" in weather_summary.lower() or "umbrella" in weather_summary.lower()
110
  has_cold = "cold" in weather_summary.lower() or "jacket" in weather_summary.lower()
111
- has_hot = "hot" in weather_summary.lower() or "sunscreen" in weather_summary.lower()
112
 
113
- # CRITICAL FIX: Evaluate expressions properly (was broken string interpolation)
114
  tshirt_qty = trip_duration_days // 2 + 1
115
  pants_qty = trip_duration_days // 3 + 1
116
  socks_qty = trip_duration_days // 2 + 1
117
- base_layer_qty = trip_duration_days // 3 + 1
118
 
119
  essentials = [
120
- "• Passport + photocopies (and visa if required)",
121
- "• Travel insurance documents",
122
- "• Credit/debit cards + small local currency",
123
- "• Universal power adapter (Type F for Europe)",
124
  "• Phone + charger + power bank",
125
- "• Reusable water bottle",
126
  ]
127
 
128
  clothing = []
129
- if has_hot:
130
- clothing = [
131
- f"• T-shirts/tanks ({tshirt_qty})",
132
- "• Lightweight breathable pants/shorts",
133
- "• Sun hat + sunglasses",
134
- "• High-SPF sunscreen",
135
- ]
136
- elif has_cold:
137
  clothing = [
138
- f"• Warm base layers ({base_layer_qty})",
139
  "• Insulated jacket",
140
  f"• Warm socks ({socks_qty})",
141
  "• Beanie + gloves",
142
  ]
143
  else:
144
  clothing = [
145
- f"• Versatile tops ({tshirt_qty})",
146
  f"• Comfortable pants ({pants_qty})",
147
- "• Light jacket/sweater (essential for layering)",
148
  ]
149
 
150
  if has_rain:
151
- clothing.extend(["• Compact travel umbrella", "• Light waterproof jacket"])
152
 
153
  if trip_type == "beach":
154
  clothing.extend(["• Swimsuit", "• Beach towel", "• Flip-flops"])
155
  elif trip_type == "hiking":
156
- clothing.extend(["• Sturdy hiking boots", "• Moisture-wicking socks", "• Daypack"])
157
 
158
  toiletries = [
159
- "• Travel-sized toiletries",
160
  "• Toothbrush + toothpaste",
161
  "• Deodorant",
162
- "• Prescription medications",
163
  "• Basic first-aid kit",
164
  ]
165
 
166
- if has_hot:
167
- toiletries.append("• After-sun lotion")
168
-
169
  return (
170
  f"🎒 PACKING LIST: {destination} ({trip_duration_days}-day {trip_type})\n"
171
- f"{'─'*56}\n"
172
- f"ESSENTIALS\n" + "\n".join(essentials) + "\n\n"
173
- f"CLOTHING\n" + "\n".join(clothing) + "\n\n"
174
- f"TOILETRIES\n" + "\n".join(toiletries) + "\n\n"
175
- f"💡 Pro tip: Roll clothes to save space. Use packing cubes!"
176
  )
177
 
178
 
179
  @tool
180
  def build_itinerary(destination: str, attractions: str, weather_summary: str, budget_local_currency: float, trip_duration_days: int) -> str:
181
  """
182
- Create day-by-day itinerary with budget allocation.
 
 
 
 
 
 
 
 
 
 
183
  """
184
  attraction_list = [a.strip() for a in attractions.split(",") if a.strip()]
185
  if not attraction_list:
186
- attraction_list = ["Old Town", "Local museum", "Scenic viewpoint", "Cultural market", "Local cuisine"]
187
 
188
  daily_budget = budget_local_currency / max(trip_duration_days, 1)
189
- activity_budget = daily_budget * 0.4
190
  food_budget = daily_budget * 0.35
191
 
192
- itinerary = [f"🗓️ {trip_duration_days}-DAY ITINERARY: {destination}", "─"*56]
193
 
194
  for day in range(1, trip_duration_days + 1):
195
- focus = "Morning outdoor sights, afternoon indoor museums" if "cold" in weather_summary.lower() else "Outdoor exploration with indoor breaks"
196
  am_act = attraction_list[(day-1) % len(attraction_list)]
197
  pm_act = attraction_list[day % len(attraction_list)]
198
-
199
- itinerary.extend([
200
- f"\nDAY {day}: {focus}",
201
  f" 09:00 {am_act}",
202
  f" 12:30 Lunch (~{food_budget * 0.4:,.0f})",
203
  f" 14:00 {pm_act}",
204
  f" 19:00 Dinner (~{food_budget * 0.6:,.0f})",
205
- f" 💡 Book attractions online to skip lines!",
206
  ])
207
 
208
- itinerary.append(f"\n💰 DAILY BUDGET: {daily_budget:,.0f} ({activity_budget:,.0f} activities | {food_budget:,.0f} food | rest transport/buffer)")
209
- return "\n".join(itinerary)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
210
 
211
 
212
  @tool
@@ -214,41 +228,36 @@ def assemble_travel_catalogue(
214
  destination: str,
215
  origin: str,
216
  travel_dates: str,
217
- budget: str,
218
  weather_info: str,
219
  itinerary: str,
220
  packing_list: str,
221
- image_prompts: str = "landmark, street scene, local food"
222
  ) -> str:
223
  """
224
- FINAL STEP: Generate images AND compile a beautiful Markdown catalogue.
225
- This tool MUST be called last to produce the formatted output with images.
226
 
227
  Args:
228
- destination: e.g., "Barcelona"
229
- origin: e.g., "New York"
230
- travel_dates: e.g., "October 15-19, 2026"
231
- budget: e.g., "$1,200 USD"
232
- weather_info: Output from get_weather_forecast
233
- itinerary: Output from build_itinerary
234
- packing_list: Output from generate_packing_list
235
- image_prompts: Comma-separated prompts for image generation (e.g., "Sagrada Familia, La Rambla street food, Park Guell mosaic")
236
 
237
  Returns:
238
- Fully formatted travel catalogue with embedded image placeholders
239
  """
240
- # Generate 3 destination images using the image generation tool
241
- # (Agent will observe these image URLs and include them in final answer)
242
- prompts = [p.strip() for p in image_prompts.split(",")][:3]
243
-
244
  image_section = "\n".join([
245
- f"![{prompt}]({{'image_url_placeholder_{i+1}'}}) \n*{prompt.title()}*"
246
- for i, prompt in enumerate(prompts)
247
- ])
248
 
249
- # Beautiful Markdown catalogue
250
  catalogue = f"""# 🌍 {destination} Travel Catalogue
251
- *From {origin} • {travel_dates} • Budget: {budget}*
252
 
253
  ---
254
 
@@ -257,12 +266,12 @@ def assemble_travel_catalogue(
257
 
258
  ---
259
 
260
- ## 🗓️ Itinerary Highlights
261
  {itinerary}
262
 
263
  ---
264
 
265
- ## 🎒 Packing Essentials
266
  {packing_list}
267
 
268
  ---
@@ -272,8 +281,7 @@ def assemble_travel_catalogue(
272
 
273
  ---
274
 
275
- > ✈️ *Tip: Book flights/accommodation 6-8 weeks in advance for best prices.
276
- > 💳 Use no-foreign-transaction-fee cards to avoid extra charges.*
277
  """
278
  return catalogue
279
 
@@ -295,32 +303,34 @@ model = HfApiModel(
295
  with open("prompts.yaml", 'r') as stream:
296
  prompt_templates = yaml.safe_load(stream)
297
 
298
- # CRITICAL: Add assemble_travel_catalogue as the FINAL tool to force image generation + formatting
299
  agent = CodeAgent(
300
  model=model,
301
  tools=[
302
  final_answer,
303
  web_search,
304
- image_generation_tool, # Must be available BEFORE assembler tool
305
  get_weather_forecast,
306
  convert_currency,
307
  generate_packing_list,
308
  build_itinerary,
309
- assemble_travel_catalogue, # This triggers final formatted output WITH images
 
310
  ],
311
- max_steps=15, # Allow extra steps for image generation
312
  verbosity_level=1,
313
  grammar=None,
314
  planning_interval=None,
315
  name="TravelCatalogueCreator",
316
  description=(
317
- "Creates beautiful travel catalogues. ALWAYS use assemble_travel_catalogue as the FINAL step "
318
- "to generate images and format the output as a visually appealing Markdown catalogue."
 
 
319
  ),
320
  prompt_templates=prompt_templates,
321
  )
322
 
323
  if __name__ == "__main__":
324
  print("🚀 Travel Catalogue Creator Agent starting...")
325
- print("💡 Example query: 'Create a 4-day Barcelona travel catalogue from New York with $1200 budget for October 15-19'")
326
  GradioUI(agent, file_upload_folder="./uploads").launch()
 
5
  import requests
6
  import datetime
7
  import pytz
8
+ from typing import List
 
9
  from smolagents import CodeAgent, DuckDuckGoSearchTool, HfApiModel, load_tool, tool
10
  from tools.final_answer import FinalAnswerTool
11
  from Gradio_UI import GradioUI
12
  import yaml
13
 
14
  # ======================
15
+ # CUSTOM TRAVEL TOOLS (FULLY COMPLIANT WITH SMOLAGENTS)
16
  # ======================
17
 
18
  @tool
19
  def get_weather_forecast(location: str, travel_dates: str) -> str:
20
  """
21
+ Get weather forecast for a destination during travel dates using wttr.in.
22
 
23
  Args:
24
  location: Destination city name (e.g., "Paris", "Tokyo")
25
+ travel_dates: Travel date range (e.g., "October 15-19" or "June 2026")
26
 
27
  Returns:
28
+ Weather summary with temperature, conditions, and packing recommendations
29
  """
30
  try:
31
  clean_location = re.sub(r'[^a-zA-Z0-9\s]', '', location).replace(' ', '+')
 
41
  humidity = current['humidity']
42
  wind = current['windspeedKmph']
43
 
 
44
  if temp_c > 25:
45
+ packing = "Light clothing, sunscreen, hat, sunglasses"
46
  elif temp_c > 15:
47
+ packing = "Light layers, light jacket, comfortable walking shoes"
48
  elif temp_c > 5:
49
+ packing = "Warm layers, medium jacket, scarf"
50
  else:
51
+ packing = "Heavy winter coat, thermal layers, hat, gloves"
52
 
53
  if "rain" in conditions.lower() or "shower" in conditions.lower():
54
+ packing += ", waterproof jacket, umbrella"
 
 
55
 
56
  return (
57
  f"Weather in {location}:\n"
58
  f"• {temp_c}°C (feels like {feels_like}°C) | {conditions}\n"
59
  f"• Humidity: {humidity}% | Wind: {wind} km/h\n"
60
+ f"• Packing tip: {packing}"
61
  )
 
62
  except Exception:
63
+ return f"Typical {location} weather: Mild (15-25°C). Pack light layers + light jacket + umbrella."
 
 
 
 
 
64
 
65
 
66
  @tool
67
  def convert_currency(amount: float, from_currency: str, to_currency: str) -> str:
68
  """
69
  Convert currency using Frankfurter API (free ECB data).
70
+
71
+ Args:
72
+ amount: Amount to convert (e.g., 1000.0)
73
+ from_currency: Source currency code (e.g., "USD", "EUR")
74
+ to_currency: Target currency code (e.g., "JPY", "EUR")
75
+
76
+ Returns:
77
+ Conversion result with exchange rate and formatted amounts
78
  """
79
  try:
80
  from_currency = from_currency.upper()
 
90
 
91
  return (
92
  f"💱 {amount:,.2f} {from_currency} = {converted:,.2f} {to_currency}\n"
93
+ f" (Rate: 1 {from_currency} = {rate:.4f} {to_currency})"
94
  )
 
95
  except Exception:
96
+ fallback = {("USD", "EUR"): 0.93, ("EUR", "USD"): 1.07}.get((from_currency, to_currency), 1.0)
97
  converted = amount * fallback
98
+ return f"⚠️ Est: {amount:,.2f} {from_currency} ≈ {converted:,.2f} {to_currency}"
99
 
100
 
101
  @tool
102
+ def generate_packing_list(destination: str, weather_summary: str, trip_duration_days: int, trip_type: str) -> str:
103
  """
104
+ Generate a customized packing list based on weather and trip type.
105
+
106
+ Args:
107
+ destination: Travel destination name (e.g., "Barcelona")
108
+ weather_summary: Weather conditions from get_weather_forecast tool
109
+ trip_duration_days: Length of trip in days (e.g., 4)
110
+ trip_type: Type of trip: "sightseeing", "beach", "hiking", or "business"
111
+
112
+ Returns:
113
+ Formatted packing checklist with quantities
114
  """
115
  has_rain = "rain" in weather_summary.lower() or "umbrella" in weather_summary.lower()
116
  has_cold = "cold" in weather_summary.lower() or "jacket" in weather_summary.lower()
 
117
 
118
+ # FIXED: Proper quantity calculation (was broken string interpolation)
119
  tshirt_qty = trip_duration_days // 2 + 1
120
  pants_qty = trip_duration_days // 3 + 1
121
  socks_qty = trip_duration_days // 2 + 1
 
122
 
123
  essentials = [
124
+ "• Passport + copies",
125
+ "• Travel insurance",
126
+ "• Credit cards + small local cash",
127
+ "• Universal power adapter",
128
  "• Phone + charger + power bank",
 
129
  ]
130
 
131
  clothing = []
132
+ if has_cold:
 
 
 
 
 
 
 
133
  clothing = [
134
+ f"• Warm base layers ({trip_duration_days // 3 + 1})",
135
  "• Insulated jacket",
136
  f"• Warm socks ({socks_qty})",
137
  "• Beanie + gloves",
138
  ]
139
  else:
140
  clothing = [
141
+ f"• T-shirts ({tshirt_qty})",
142
  f"• Comfortable pants ({pants_qty})",
143
+ "• Light jacket (essential for layering)",
144
  ]
145
 
146
  if has_rain:
147
+ clothing.extend(["• Compact umbrella", "• Light waterproof jacket"])
148
 
149
  if trip_type == "beach":
150
  clothing.extend(["• Swimsuit", "• Beach towel", "• Flip-flops"])
151
  elif trip_type == "hiking":
152
+ clothing.extend(["• Hiking boots", "• Moisture-wicking socks", "• Daypack"])
153
 
154
  toiletries = [
155
+ "• Travel-sized shampoo/conditioner",
156
  "• Toothbrush + toothpaste",
157
  "• Deodorant",
158
+ "• Prescription meds",
159
  "• Basic first-aid kit",
160
  ]
161
 
 
 
 
162
  return (
163
  f"🎒 PACKING LIST: {destination} ({trip_duration_days}-day {trip_type})\n"
164
+ f"{'─'*56}\nESSENTIALS\n" + "\n".join(essentials) + "\n\nCLOTHING\n" + "\n".join(clothing) + "\n\nTOILETRIES\n" + "\n".join(toiletries)
 
 
 
 
165
  )
166
 
167
 
168
  @tool
169
  def build_itinerary(destination: str, attractions: str, weather_summary: str, budget_local_currency: float, trip_duration_days: int) -> str:
170
  """
171
+ Create a day-by-day travel itinerary with budget allocation.
172
+
173
+ Args:
174
+ destination: Destination city name (e.g., "Barcelona")
175
+ attractions: Comma-separated list of attractions (e.g., "Sagrada Familia, Park Guell")
176
+ weather_summary: Weather conditions to optimize daily activities
177
+ budget_local_currency: Total budget in destination currency (e.g., 1200.0)
178
+ trip_duration_days: Length of trip in days (e.g., 4)
179
+
180
+ Returns:
181
+ Formatted day-by-day itinerary with time slots and cost estimates
182
  """
183
  attraction_list = [a.strip() for a in attractions.split(",") if a.strip()]
184
  if not attraction_list:
185
+ attraction_list = ["Old Town", "Local museum", "Scenic viewpoint", "Cultural market"]
186
 
187
  daily_budget = budget_local_currency / max(trip_duration_days, 1)
 
188
  food_budget = daily_budget * 0.35
189
 
190
+ lines = [f"🗓️ {trip_duration_days}-DAY ITINERARY: {destination}", "─"*56]
191
 
192
  for day in range(1, trip_duration_days + 1):
 
193
  am_act = attraction_list[(day-1) % len(attraction_list)]
194
  pm_act = attraction_list[day % len(attraction_list)]
195
+ lines.extend([
196
+ f"\nDAY {day}",
 
197
  f" 09:00 {am_act}",
198
  f" 12:30 Lunch (~{food_budget * 0.4:,.0f})",
199
  f" 14:00 {pm_act}",
200
  f" 19:00 Dinner (~{food_budget * 0.6:,.0f})",
 
201
  ])
202
 
203
+ lines.append(f"\n💰 Daily budget: ~{daily_budget:,.0f} (activities + food + transport)")
204
+ return "\n".join(lines)
205
+
206
+
207
+ @tool
208
+ def generate_destination_images(destination: str, image_prompts: str) -> str:
209
+ """
210
+ Generate 3 representative images for the destination using text-to-image tool.
211
+
212
+ Args:
213
+ destination: Destination name (e.g., "Barcelona")
214
+ image_prompts: Comma-separated prompts for images (e.g., "Sagrada Familia exterior, La Rambla street scene, Park Guell mosaic art")
215
+
216
+ Returns:
217
+ Instructions for the agent to call image_generation_tool 3 times with these prompts
218
+ """
219
+ prompts = [p.strip() for p in image_prompts.split(",")][:3]
220
+ return (
221
+ f"Generate 3 images for {destination} using image_generation_tool with these prompts:\n"
222
+ + "\n".join([f"{i+1}. '{prompt}'" for i, prompt in enumerate(prompts)])
223
+ )
224
 
225
 
226
  @tool
 
228
  destination: str,
229
  origin: str,
230
  travel_dates: str,
231
+ budget_summary: str,
232
  weather_info: str,
233
  itinerary: str,
234
  packing_list: str,
235
+ image_urls: str,
236
  ) -> str:
237
  """
238
+ Compile all travel information into a beautifully formatted Markdown catalogue.
 
239
 
240
  Args:
241
+ destination: Destination city (e.g., "Barcelona")
242
+ origin: Traveler's home city (e.g., "New York")
243
+ travel_dates: Travel date range (e.g., "October 15-19, 2026")
244
+ budget_summary: Budget conversion result (e.g., "$1,200 USD = €1,116 EUR")
245
+ weather_info: Weather forecast summary
246
+ itinerary: Day-by-day itinerary plan
247
+ packing_list: Customized packing checklist
248
+ image_urls: Comma-separated URLs of generated images
249
 
250
  Returns:
251
+ Complete travel catalogue in Markdown format with embedded images
252
  """
253
+ image_list = [url.strip() for url in image_urls.split(",") if url.strip()]
 
 
 
254
  image_section = "\n".join([
255
+ f"![{destination} view]({url}) \n*Generated image {i+1}*"
256
+ for i, url in enumerate(image_list[:3])
257
+ ]) if image_list else "*Images will appear here after generation*"
258
 
 
259
  catalogue = f"""# 🌍 {destination} Travel Catalogue
260
+ *From {origin} • {travel_dates} • {budget_summary}*
261
 
262
  ---
263
 
 
266
 
267
  ---
268
 
269
+ ## 🗓️ Itinerary
270
  {itinerary}
271
 
272
  ---
273
 
274
+ ## 🎒 Packing List
275
  {packing_list}
276
 
277
  ---
 
281
 
282
  ---
283
 
284
+ > 💡 Pro Tips: Book attractions online to skip lines. Use public transport passes for savings.
 
285
  """
286
  return catalogue
287
 
 
303
  with open("prompts.yaml", 'r') as stream:
304
  prompt_templates = yaml.safe_load(stream)
305
 
 
306
  agent = CodeAgent(
307
  model=model,
308
  tools=[
309
  final_answer,
310
  web_search,
311
+ image_generation_tool,
312
  get_weather_forecast,
313
  convert_currency,
314
  generate_packing_list,
315
  build_itinerary,
316
+ generate_destination_images,
317
+ assemble_travel_catalogue,
318
  ],
319
+ max_steps=18, # Extra steps for image generation
320
  verbosity_level=1,
321
  grammar=None,
322
  planning_interval=None,
323
  name="TravelCatalogueCreator",
324
  description=(
325
+ "Expert travel planner that creates beautiful catalogues. "
326
+ "ALWAYS follow this sequence: 1) research 2) weather 3) currency 4) itinerary "
327
+ "5) packing list 6) generate_destination_images 7) assemble_travel_catalogue. "
328
+ "NEVER skip image generation."
329
  ),
330
  prompt_templates=prompt_templates,
331
  )
332
 
333
  if __name__ == "__main__":
334
  print("🚀 Travel Catalogue Creator Agent starting...")
335
+ print("💡 Example: 'Create a 4-day Barcelona travel catalogue from New York with $1200 budget for October 15-19'")
336
  GradioUI(agent, file_upload_folder="./uploads").launch()