PLBot commited on
Commit
02e041d
·
verified ·
1 Parent(s): ae7a494

Create the travel companion

Browse files
Files changed (1) hide show
  1. app.py +477 -34
app.py CHANGED
@@ -1,69 +1,512 @@
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
+ # Travel Companion AI Agent
2
+ # This agent helps travelers with destination information, local time, weather forecasts,
3
+ # currency conversion, language translation, and visual destination previews.
4
+
5
+ from smolagents import CodeAgent, HfApiModel, load_tool, tool
6
  import datetime
7
  import requests
8
  import pytz
9
  import yaml
10
+ import random
11
+ import json
12
+ import os
13
  from tools.final_answer import FinalAnswerTool
 
14
  from Gradio_UI import GradioUI
15
 
16
+ # Load the image generation tool once, outside the function
17
+ image_generation_tool = load_tool("agents-course/text-to-image", trust_remote_code=True)
18
+
19
+ # ==================== ORIGINAL TOOLS (ENHANCED) ====================
20
+
21
  @tool
22
+ def generate_destination_preview(destination: str) -> str:
23
+ """Generates a vibrant, artistic preview image of a travel destination.
24
+
25
  Args:
26
+ destination: The travel destination to visualize (e.g., 'Paris', 'Tokyo', 'Bali').
27
+
28
+ Returns:
29
+ A link to the generated destination preview image.
30
  """
31
+ # List of visual styles for variety
32
+ styles = [
33
+ "sunrise golden hour",
34
+ "blue hour twilight",
35
+ "vibrant daytime",
36
+ "dramatic sunset",
37
+ "night lights"
38
+ ]
39
+
40
+ # Select a random style for variety
41
+ style = random.choice(styles)
42
+
43
+ # Construct a detailed prompt for the AI model
44
+ prompt = f"A beautiful travel photograph of {destination}, {style}, photorealistic, high-resolution, travel photography, highly detailed landmark view"
45
+
46
+ # Use the pre-loaded image generation tool
47
+ try:
48
+ image_url = image_generation_tool(prompt)
49
+ return f"Here's a preview of {destination}: {image_url}"
50
+ except Exception as e:
51
+ return f"Error generating image of {destination}: {str(e)}"
52
+
53
 
54
  @tool
55
+ def get_local_time(destination: str) -> str:
56
+ """Get the current local time at a travel destination.
57
+
58
  Args:
59
+ destination: A city or location name (e.g., 'Paris', 'Tokyo', 'New York').
60
+
61
+ Returns:
62
+ The current local time at the specified destination.
63
  """
64
+ # Map of common tourist destinations to their timezones
65
+ destination_timezones = {
66
+ "london": "Europe/London",
67
+ "paris": "Europe/Paris",
68
+ "rome": "Europe/Rome",
69
+ "madrid": "Europe/Madrid",
70
+ "berlin": "Europe/Berlin",
71
+ "amsterdam": "Europe/Amsterdam",
72
+ "athens": "Europe/Athens",
73
+ "istanbul": "Europe/Istanbul",
74
+ "dubai": "Asia/Dubai",
75
+ "new delhi": "Asia/Kolkata",
76
+ "mumbai": "Asia/Kolkata",
77
+ "bangkok": "Asia/Bangkok",
78
+ "singapore": "Asia/Singapore",
79
+ "tokyo": "Asia/Tokyo",
80
+ "seoul": "Asia/Seoul",
81
+ "beijing": "Asia/Shanghai",
82
+ "shanghai": "Asia/Shanghai",
83
+ "hong kong": "Asia/Hong_Kong",
84
+ "sydney": "Australia/Sydney",
85
+ "melbourne": "Australia/Melbourne",
86
+ "auckland": "Pacific/Auckland",
87
+ "fiji": "Pacific/Fiji",
88
+ "honolulu": "Pacific/Honolulu",
89
+ "anchorage": "America/Anchorage",
90
+ "los angeles": "America/Los_Angeles",
91
+ "san francisco": "America/Los_Angeles",
92
+ "las vegas": "America/Los_Angeles",
93
+ "denver": "America/Denver",
94
+ "chicago": "America/Chicago",
95
+ "houston": "America/Chicago",
96
+ "new york": "America/New_York",
97
+ "miami": "America/New_York",
98
+ "toronto": "America/Toronto",
99
+ "mexico city": "America/Mexico_City",
100
+ "rio de janeiro": "America/Sao_Paulo",
101
+ "sao paulo": "America/Sao_Paulo",
102
+ "buenos aires": "America/Argentina/Buenos_Aires",
103
+ "cairo": "Africa/Cairo",
104
+ "cape town": "Africa/Johannesburg",
105
+ "johannesburg": "Africa/Johannesburg",
106
+ "nairobi": "Africa/Nairobi"
107
+ }
108
+
109
  try:
110
+ # Normalize the destination name
111
+ normalized_dest = destination.lower().strip()
112
+
113
+ # Find the closest matching timezone
114
+ timezone = None
115
+ for city, tz in destination_timezones.items():
116
+ if city in normalized_dest or normalized_dest in city:
117
+ timezone = tz
118
+ break
119
+
120
+ if not timezone:
121
+ return f"I don't have timezone information for {destination}. Please try a major city nearby."
122
+
123
  # Get current time in that timezone
124
+ tz = pytz.timezone(timezone)
125
+ local_time = datetime.datetime.now(tz)
126
+
127
+ # Format the result
128
+ formatted_time = local_time.strftime("%I:%M %p on %A, %B %d, %Y")
129
+ time_diff = local_time.utcoffset().total_seconds() / 3600
130
+ sign = "+" if time_diff >= 0 else ""
131
+
132
+ return f"The current local time in {destination} is {formatted_time} (UTC{sign}{int(time_diff)})"
133
+
134
  except Exception as e:
135
+ return f"Error getting local time for {destination}: {str(e)}"
136
 
137
+ # ==================== NEW TRAVEL-SPECIFIC TOOLS ====================
138
 
139
+ @tool
140
+ def get_weather_forecast(destination: str, days: int = 3) -> str:
141
+ """Get the weather forecast for a travel destination.
142
+
143
+ Args:
144
+ destination: City or location name
145
+ days: Number of days to forecast (default: 3)
146
+
147
+ Returns:
148
+ Weather forecast information for trip planning
149
+ """
150
+ try:
151
+ # In a production environment, you would use a real API key
152
+ API_KEY = os.environ.get("WEATHER_API_KEY", "demo_key")
153
+
154
+ # For demo purposes, we'll generate simulated weather data
155
+ # In a real implementation, you would call an actual weather API
156
+ weather_conditions = ["Sunny", "Partly Cloudy", "Cloudy", "Light Rain", "Heavy Rain", "Thunderstorms", "Windy", "Foggy", "Snow", "Clear"]
157
+
158
+ # Create a deterministic but seemingly random forecast based on destination name
159
+ seed = sum(ord(c) for c in destination)
160
+ random.seed(seed)
161
+
162
+ # Generate forecast data
163
+ forecast_text = f"🌦️ Weather forecast for {destination}:\n\n"
164
+
165
+ today = datetime.datetime.now()
166
+ for i in range(days):
167
+ day = today + datetime.timedelta(days=i)
168
+ day_name = day.strftime("%A")
169
+ date = day.strftime("%b %d")
170
+
171
+ # "Random" but deterministic weather for the demo
172
+ condition = weather_conditions[random.randint(0, len(weather_conditions)-1)]
173
+ temp_high = random.randint(15, 35) # Celsius
174
+ temp_low = temp_high - random.randint(5, 15)
175
+ precipitation = random.randint(0, 100) if "Rain" in condition or "Snow" in condition or "Thunder" in condition else 0
176
+
177
+ forecast_text += f"• {day_name}, {date}: {condition}, {temp_low}°C to {temp_high}°C"
178
+ if precipitation > 0:
179
+ forecast_text += f", {precipitation}% chance of precipitation"
180
+ forecast_text += "\n"
181
+
182
+ # Add packing recommendations based on conditions
183
+ coldest = min([forecast_text.count("Snow"), forecast_text.count("0°C")])
184
+ rainiest = forecast_text.count("Rain") + forecast_text.count("Thunder")
185
+
186
+ forecast_text += "\n🧳 Packing tips: "
187
+ if coldest > 0:
188
+ forecast_text += "Bring warm layers and a heavy jacket. "
189
+ elif "5°C" in forecast_text or "6°C" in forecast_text or "7°C" in forecast_text:
190
+ forecast_text += "Pack a warm jacket and layers. "
191
+
192
+ if rainiest > 0:
193
+ forecast_text += "Don't forget an umbrella and waterproof footwear. "
194
+
195
+ if "Sunny" in forecast_text and "30°C" in forecast_text:
196
+ forecast_text += "Bring sunscreen, sunglasses, and light clothing. "
197
+
198
+ return forecast_text
199
+
200
+ except Exception as e:
201
+ return f"Error retrieving weather data for {destination}: {str(e)}"
202
 
 
 
203
 
204
+ @tool
205
+ def convert_currency(amount: float, from_currency: str, to_currency: str) -> str:
206
+ """Convert an amount between currencies for travel budgeting.
207
+
208
+ Args:
209
+ amount: The amount to convert
210
+ from_currency: Source currency code (e.g., USD, EUR)
211
+ to_currency: Target currency code (e.g., JPY, GBP)
212
+
213
+ Returns:
214
+ Converted amount and exchange rate information
215
+ """
216
+ try:
217
+ # In a production environment, you would use a real API key
218
+ # For demo purposes, we'll use fixed exchange rates
219
+ # In a real implementation, you would call an actual currency API
220
+
221
+ # Common exchange rates (as of early 2025, for demo purposes)
222
+ exchange_rates = {
223
+ "USD": {"EUR": 0.92, "GBP": 0.79, "JPY": 149.50, "CAD": 1.35, "AUD": 1.52, "CNY": 7.20, "INR": 83.20, "MXN": 17.05},
224
+ "EUR": {"USD": 1.09, "GBP": 0.86, "JPY": 163.00, "CAD": 1.47, "AUD": 1.66, "CNY": 7.85, "INR": 90.70, "MXN": 18.60},
225
+ "GBP": {"USD": 1.27, "EUR": 1.16, "JPY": 189.30, "CAD": 1.71, "AUD": 1.92, "CNY": 9.10, "INR": 105.30, "MXN": 21.60},
226
+ "JPY": {"USD": 0.0067, "EUR": 0.0061, "GBP": 0.0053, "CAD": 0.0090, "AUD": 0.0102, "CNY": 0.0482, "INR": 0.5565, "MXN": 0.1141},
227
+ "CAD": {"USD": 0.74, "EUR": 0.68, "GBP": 0.58, "JPY": 110.70, "AUD": 1.13, "CNY": 5.33, "INR": 61.60, "MXN": 12.60},
228
+ "AUD": {"USD": 0.66, "EUR": 0.60, "GBP": 0.52, "JPY": 98.40, "CAD": 0.89, "CNY": 4.73, "INR": 54.70, "MXN": 11.20},
229
+ "CNY": {"USD": 0.14, "EUR": 0.13, "GBP": 0.11, "JPY": 20.80, "CAD": 0.19, "AUD": 0.21, "INR": 11.60, "MXN": 2.37},
230
+ "INR": {"USD": 0.012, "EUR": 0.011, "GBP": 0.0095, "JPY": 1.80, "CAD": 0.016, "AUD": 0.018, "CNY": 0.086, "MXN": 0.205},
231
+ "MXN": {"USD": 0.059, "EUR": 0.054, "GBP": 0.046, "JPY": 8.77, "CAD": 0.079, "AUD": 0.089, "CNY": 0.422, "INR": 4.88}
232
+ }
233
+
234
+ # Normalize currency codes
235
+ from_currency = from_currency.upper().strip()
236
+ to_currency = to_currency.upper().strip()
237
+
238
+ # Validate currencies
239
+ if from_currency not in exchange_rates:
240
+ return f"Sorry, I don't have exchange rate data for {from_currency}."
241
+
242
+ if to_currency not in exchange_rates[from_currency] and to_currency != from_currency:
243
+ return f"Sorry, I don't have exchange rate data from {from_currency} to {to_currency}."
244
+
245
+ # If same currency, return original amount
246
+ if from_currency == to_currency:
247
+ return f"{amount} {from_currency} = {amount} {to_currency}"
248
+
249
+ # Get exchange rate and calculate conversion
250
+ rate = exchange_rates[from_currency][to_currency]
251
+ converted_amount = amount * rate
252
+
253
+ # Format the result
254
+ return f"💱 {amount:,.2f} {from_currency} = {converted_amount:,.2f} {to_currency}\n\nExchange rate: 1 {from_currency} = {rate} {to_currency}\n\n(Note: Actual rates may vary. For planning purposes only.)"
255
+
256
+ except Exception as e:
257
+ return f"Error converting currency: {str(e)}"
258
 
259
 
260
+ @tool
261
+ def translate_phrase(text: str, language: str) -> str:
262
+ """Translate common travel phrases to a local language.
263
+
264
+ Args:
265
+ text: Text to translate (e.g., "Hello", "Thank you", "Where is the bathroom?")
266
+ language: Target language (e.g., 'Spanish', 'Japanese', 'French')
267
+
268
+ Returns:
269
+ Translated text with pronunciation guide
270
+ """
271
+ try:
272
+ # Common travel phrases in various languages
273
+ # In a production environment, you would use a real translation API
274
+ language = language.lower().strip()
275
+ text_lower = text.lower().strip()
276
+
277
+ phrase_translations = {
278
+ "hello": {
279
+ "spanish": {"text": "Hola", "pronunciation": "oh-lah"},
280
+ "french": {"text": "Bonjour", "pronunciation": "bohn-zhoor"},
281
+ "italian": {"text": "Ciao", "pronunciation": "chow"},
282
+ "german": {"text": "Hallo", "pronunciation": "hah-loh"},
283
+ "japanese": {"text": "こんにちは (Konnichiwa)", "pronunciation": "kohn-nee-chee-wah"},
284
+ "mandarin": {"text": "你好 (Nǐ hǎo)", "pronunciation": "nee how"},
285
+ "arabic": {"text": "مرحبا (Marhaba)", "pronunciation": "mar-ha-ba"},
286
+ "russian": {"text": "Здравствуйте (Zdravstvuyte)", "pronunciation": "zdrah-stvooy-tye"},
287
+ "portuguese": {"text": "Olá", "pronunciation": "oh-lah"},
288
+ "thai": {"text": "สวัสดี (Sawatdee)", "pronunciation": "sa-wat-dee"}
289
+ },
290
+ "thank you": {
291
+ "spanish": {"text": "Gracias", "pronunciation": "grah-see-ahs"},
292
+ "french": {"text": "Merci", "pronunciation": "mair-see"},
293
+ "italian": {"text": "Grazie", "pronunciation": "graht-see-eh"},
294
+ "german": {"text": "Danke", "pronunciation": "dahn-kuh"},
295
+ "japanese": {"text": "ありがとう (Arigatou)", "pronunciation": "ah-ree-gah-toh"},
296
+ "mandarin": {"text": "谢谢 (Xièxiè)", "pronunciation": "shyeh-shyeh"},
297
+ "arabic": {"text": "شكرا (Shukran)", "pronunciation": "shoo-kran"},
298
+ "russian": {"text": "Спасибо (Spasibo)", "pronunciation": "spah-see-boh"},
299
+ "portuguese": {"text": "Obrigado/a", "pronunciation": "oh-bree-gah-doo/dah"},
300
+ "thai": {"text": "ขอบคุณ (Khop khun)", "pronunciation": "kop-koon"}
301
+ },
302
+ "excuse me": {
303
+ "spanish": {"text": "Disculpe", "pronunciation": "dees-kool-peh"},
304
+ "french": {"text": "Excusez-moi", "pronunciation": "ex-koo-zay mwah"},
305
+ "italian": {"text": "Scusi", "pronunciation": "skoo-zee"},
306
+ "german": {"text": "Entschuldigung", "pronunciation": "ent-shool-di-goong"},
307
+ "japanese": {"text": "すみません (Sumimasen)", "pronunciation": "soo-mee-mah-sen"},
308
+ "mandarin": {"text": "对不起 (Duìbùqǐ)", "pronunciation": "dway-boo-chee"},
309
+ "arabic": {"text": "عفوا (Afwan)", "pronunciation": "af-wan"},
310
+ "russian": {"text": "Извините (Izvinite)", "pronunciation": "eez-vee-nee-tye"},
311
+ "portuguese": {"text": "Com licença", "pronunciation": "com lee-sen-sah"},
312
+ "thai": {"text": "ขอโทษ (Kho thot)", "pronunciation": "kor-toht"}
313
+ },
314
+ "where is the bathroom": {
315
+ "spanish": {"text": "¿Dónde está el baño?", "pronunciation": "don-deh es-tah el ban-yo"},
316
+ "french": {"text": "Où sont les toilettes?", "pronunciation": "oo son lay twa-let"},
317
+ "italian": {"text": "Dov'è il bagno?", "pronunciation": "doh-veh eel ban-yo"},
318
+ "german": {"text": "Wo ist die Toilette?", "pronunciation": "vo ist dee twa-let-te"},
319
+ "japanese": {"text": "トイレはどこですか (Toire wa doko desu ka)", "pronunciation": "toy-reh wah doh-koh des-kah"},
320
+ "mandarin": {"text": "厕所在哪里 (Cèsuǒ zài nǎlǐ)", "pronunciation": "tsuh-swor dzeye nah-lee"},
321
+ "arabic": {"text": "أين الحمام (Ayna al-hammam)", "pronunciation": "eye-nah al-ham-mam"},
322
+ "russian": {"text": "Где туалет (Gde tualet)", "pronunciation": "g-dyeh too-ah-lyet"},
323
+ "portuguese": {"text": "Onde fica o banheiro?", "pronunciation": "on-jee fee-ka oo ban-yay-roo"},
324
+ "thai": {"text": "ห้องน้ำอยู่ที่ไหน (Hong nam yu tee nai)", "pronunciation": "hong nam yoo tee nai"}
325
+ },
326
+ "how much": {
327
+ "spanish": {"text": "¿Cuánto cuesta?", "pronunciation": "kwan-toh kwes-tah"},
328
+ "french": {"text": "Combien ça coûte?", "pronunciation": "kom-bee-en sa koot"},
329
+ "italian": {"text": "Quanto costa?", "pronunciation": "kwan-toh kos-tah"},
330
+ "german": {"text": "Wie viel kostet das?", "pronunciation": "vee feel kos-tet das"},
331
+ "japanese": {"text": "いくらですか (Ikura desu ka)", "pronunciation": "ee-koo-rah des-kah"},
332
+ "mandarin": {"text": "多少钱 (Duōshǎo qián)", "pronunciation": "dwor-shaow chyen"},
333
+ "arabic": {"text": "كم الثمن (Kam althaman)", "pronunciation": "kam al-tha-man"},
334
+ "russian": {"text": "Сколько это стоит (Skol'ko eto stoit)", "pronunciation": "skol-ka eh-ta stoh-eet"},
335
+ "portuguese": {"text": "Quanto custa?", "pronunciation": "kwan-too koos-tah"},
336
+ "thai": {"text": "ราคาเท่าไหร่ (Raka tao rai)", "pronunciation": "ra-ka tao-rai"}
337
+ }
338
+ }
339
+
340
+ # Find the phrase key that most closely matches the input text
341
+ matched_phrase = None
342
+ for phrase in phrase_translations:
343
+ if phrase in text_lower or text_lower in phrase:
344
+ matched_phrase = phrase
345
+ break
346
+
347
+ if not matched_phrase:
348
+ return f"I don't have a translation for '{text}'. Try common travel phrases like 'hello', 'thank you', 'excuse me', etc."
349
+
350
+ # Find the language that most closely matches the input language
351
+ matched_language = None
352
+ for lang in phrase_translations[matched_phrase]:
353
+ if lang in language or language in lang:
354
+ matched_language = lang
355
+ break
356
+
357
+ if not matched_language:
358
+ return f"I don't have translations for {language}. Try languages like Spanish, French, Italian, German, Japanese, etc."
359
+
360
+ # Get the translation
361
+ translation = phrase_translations[matched_phrase][matched_language]
362
+
363
+ return f"🗣️ '{text}' in {matched_language.capitalize()}:\n\n{translation['text']}\n\nPronunciation: {translation['pronunciation']}"
364
+
365
+ except Exception as e:
366
+ return f"Error translating text: {str(e)}"
367
+
368
+
369
+ @tool
370
+ def get_visa_requirements(nationality: str, destination: str) -> str:
371
+ """Check visa requirements for traveling to a destination.
372
+
373
+ Args:
374
+ nationality: Traveler's passport country (e.g., 'US', 'UK', 'Canada')
375
+ destination: Country to visit (e.g., 'Japan', 'France', 'Brazil')
376
+
377
+ Returns:
378
+ Visa requirement information
379
+ """
380
+ try:
381
+ # Normalize inputs
382
+ nationality = nationality.lower().strip()
383
+ destination = destination.lower().strip()
384
+
385
+ # Map of common country names to their normalized forms
386
+ country_mapping = {
387
+ "us": "united states", "usa": "united states", "united states of america": "united states",
388
+ "uk": "united kingdom", "britain": "united kingdom", "great britain": "united kingdom",
389
+ "uae": "united arab emirates",
390
+ # Add more mappings as needed
391
+ }
392
+
393
+ # Apply mappings if available
394
+ nationality = country_mapping.get(nationality, nationality)
395
+ destination = country_mapping.get(destination, destination)
396
+
397
+ # Skip if same country (generally no visa needed for citizens)
398
+ if nationality == destination:
399
+ return f"As a citizen of {nationality.title()}, you generally don't need a visa to visit your own country."
400
+
401
+ # Sample visa requirement data
402
+ # In a production environment, this would be a comprehensive database or API call
403
+ visa_data = {
404
+ "united states": {
405
+ "european union": "No visa required for stays up to 90 days",
406
+ "united kingdom": "No visa required for stays up to 6 months",
407
+ "japan": "No visa required for stays up to 90 days",
408
+ "australia": "Electronic Travel Authority (ETA) required",
409
+ "china": "Visa required, must apply in advance",
410
+ "india": "e-Visa available, apply online before travel",
411
+ "brazil": "No visa required for stays up to 90 days",
412
+ "mexico": "No visa required for stays up to 180 days",
413
+ "south africa": "No visa required for stays up to 90 days",
414
+ "thailand": "No visa required for stays up to 30 days"
415
+ },
416
+ "united kingdom": {
417
+ "european union": "No visa required for stays up to 90 days",
418
+ "united states": "ESTA required for entry",
419
+ "japan": "No visa required for stays up to 90 days",
420
+ "australia": "eVisitor visa required",
421
+ "china": "Visa required, must apply in advance",
422
+ "india": "e-Visa available, apply online before travel",
423
+ "brazil": "No visa required for stays up to 90 days",
424
+ "mexico": "No visa required for stays up to 180 days",
425
+ "south africa": "No visa required for stays up to 90 days",
426
+ "thailand": "No visa required for stays up to 30 days"
427
+ },
428
+ # Add more countries as needed
429
+ }
430
+
431
+ # Check if we have data for this nationality
432
+ if nationality not in visa_data:
433
+ return f"I don't have specific visa information for citizens of {nationality.title()}. Please check with the embassy of {destination.title()} for accurate visa requirements."
434
+
435
+ # Check if we have data for this destination
436
+ if destination not in visa_data[nationality]:
437
+ return f"I don't have specific visa information for {nationality.title()} citizens traveling to {destination.title()}. Please check with the embassy of {destination.title()} for accurate visa requirements."
438
+
439
+ # Get the visa requirements
440
+ requirements = visa_data[nationality][destination]
441
+
442
+ return f"🛂 Visa requirements for {nationality.title()} citizens traveling to {destination.title()}:\n\n{requirements}\n\n(Note: Visa requirements may change. Always verify with the official embassy or consulate before travel.)"
443
+
444
+ except Exception as e:
445
+ return f"Error retrieving visa information: {str(e)}"
446
+
447
+ # ==================== AGENT SETUP ====================
448
+
449
+ final_answer = FinalAnswerTool()
450
+
451
+ # Model initialization
452
+ model = HfApiModel(
453
+ max_tokens=2096,
454
+ temperature=0.7, # Slightly higher temperature for more creative responses
455
+ model_id='Qwen/Qwen2.5-Coder-32B-Instruct',
456
+ custom_role_conversions=None,
457
+ )
458
 
459
+ # Load prompts
460
  with open("prompts.yaml", 'r') as stream:
461
  prompt_templates = yaml.safe_load(stream)
462
+
463
+ # Add travel companion specific instructions to the prompt templates
464
+ travel_agent_prompt = """
465
+ You are TravelBuddy, an AI travel companion designed to help travelers plan and navigate their journeys.
466
+ Your goal is to provide helpful, accurate information about destinations, local customs, and practical travel advice.
467
+
468
+ You have access to these capabilities:
469
+ 1. Generate visual previews of destinations
470
+ 2. Check local time at travel destinations
471
+ 3. Provide weather forecasts for trip planning
472
+ 4. Convert currencies for travel budgeting
473
+ 5. Translate common travel phrases
474
+ 6. Check visa requirements
475
+
476
+ When users ask about a destination, try to provide comprehensive information by combining multiple tools.
477
+ For example, if someone asks about Tokyo, consider providing the local time, weather, and a visual preview.
478
+
479
+ Always be enthusiastic about travel while remaining practical and informative.
480
+ Suggest off-the-beaten-path experiences when appropriate, but prioritize the specific information requested.
481
+ """
482
+
483
+ # Add the travel agent prompt to the existing templates
484
+ if "system_prompt" in prompt_templates:
485
+ prompt_templates["system_prompt"] = travel_agent_prompt + "\n\n" + prompt_templates.get("system_prompt", "")
486
+ else:
487
+ prompt_templates["system_prompt"] = travel_agent_prompt
488
+
489
+ # Agent setup with all travel tools
490
  agent = CodeAgent(
491
  model=model,
492
+ tools=[
493
+ final_answer,
494
+ generate_destination_preview, # Enhanced version of original image tool
495
+ get_local_time, # Enhanced version of original time tool
496
+ get_weather_forecast, # New travel tool
497
+ convert_currency, # New travel tool
498
+ translate_phrase, # New travel tool
499
+ get_visa_requirements, # New travel tool
500
+ ],
501
+ max_steps=8, # Increased to allow for more tool usage in a single query
502
  verbosity_level=1,
503
  grammar=None,
504
  planning_interval=None,
505
+ name="TravelBuddy",
506
+ description="Your AI travel companion",
507
  prompt_templates=prompt_templates
508
  )
509
 
510
+ # Launch the UI
511
+ print("Launching TravelBuddy - Your AI Travel Companion")
512
  GradioUI(agent).launch()