AdithyaSNair commited on
Commit
ce832ec
·
verified ·
1 Parent(s): b4726a6

Create travel.py

Browse files
Files changed (1) hide show
  1. travel.py +454 -0
travel.py ADDED
@@ -0,0 +1,454 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import logging
3
+ from datetime import datetime, timedelta
4
+ from langchain_google_genai import ChatGoogleGenerativeAI
5
+ from langchain.schema import SystemMessage, HumanMessage
6
+ from dotenv import load_dotenv
7
+ import qrcode
8
+ from qrcode.constants import ERROR_CORRECT_M
9
+
10
+ load_dotenv()
11
+
12
+ logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")
13
+
14
+ class Agent:
15
+ def __init__(self, role: str, goal: str, backstory: str, personality: str = "", llm=None) -> None:
16
+ self.role = role
17
+ self.goal = goal
18
+ self.backstory = backstory
19
+ self.personality = personality
20
+ self.tools = []
21
+ self.llm = llm
22
+
23
+ class Task:
24
+ def __init__(self, description: str, agent: Agent, expected_output: str, context=None) -> None:
25
+ self.description = description
26
+ self.agent = agent
27
+ self.expected_output = expected_output
28
+ self.context = context or []
29
+
30
+ google_api_key = os.getenv("GEMINI_API_KEY")
31
+ if not google_api_key:
32
+ logging.error("GEMINI_API_KEY is not set in the environment variables.")
33
+
34
+ # IMPORTANT: Ensure the model name is valid for your account.
35
+ llm = ChatGoogleGenerativeAI(model="gemini-2.0-pro-exp-02-05", google_api_key=google_api_key)
36
+
37
+ destination_research_agent = Agent(
38
+ role="Destination Research Agent",
39
+ goal=(
40
+ "Research and provide comprehensive information about the destination including popular attractions, "
41
+ "local culture, weather patterns, best times to visit, and local transportation options."
42
+ ),
43
+ backstory=(
44
+ "An experienced travel researcher with extensive knowledge of global destinations. "
45
+ "I specialize in uncovering both popular attractions and hidden gems that match travelers' interests."
46
+ ),
47
+ personality="Curious, detail-oriented, and knowledgeable about global cultures and travel trends.",
48
+ llm=llm,
49
+ )
50
+
51
+ accommodation_agent = Agent(
52
+ role="Accommodation Agent",
53
+ goal="Find and recommend suitable accommodations based on the traveler's preferences, budget, and location requirements.",
54
+ backstory="A hospitality expert who understands different types of accommodations and can match travelers with their ideal places to stay.",
55
+ personality="Attentive, resourceful, and focused on comfort and value.",
56
+ llm=llm,
57
+ )
58
+
59
+ transportation_agent = Agent(
60
+ role="Transportation Agent",
61
+ goal="Plan efficient transportation between the origin, destination, and all points of interest in the itinerary.",
62
+ backstory="A logistics specialist with knowledge of global transportation systems, from flights to local transit options.",
63
+ personality="Efficient, practical, and detail-oriented.",
64
+ llm=llm,
65
+ )
66
+
67
+ activities_agent = Agent(
68
+ role="Activities & Attractions Agent",
69
+ goal="Curate personalized activities and attractions that align with the traveler's interests, preferences, and time constraints.",
70
+ backstory="An enthusiastic explorer who has experienced diverse activities around the world and knows how to match experiences to individual preferences.",
71
+ personality="Enthusiastic, creative, and personable.",
72
+ llm=llm,
73
+ )
74
+
75
+ dining_agent = Agent(
76
+ role="Dining & Culinary Agent",
77
+ goal="Recommend dining experiences that showcase local cuisine while accommodating dietary preferences and budget considerations.",
78
+ backstory="A culinary expert with knowledge of global food scenes and an appreciation for authentic local dining experiences.",
79
+ personality="Passionate about food, culturally aware, and attentive to preferences.",
80
+ llm=llm,
81
+ )
82
+
83
+ itinerary_agent = Agent(
84
+ role="Itinerary Integration Agent",
85
+ goal="Compile all recommendations into a cohesive, day-by-day itinerary that optimizes time, minimizes travel fatigue, and maximizes enjoyment.",
86
+ backstory="A master travel planner who understands how to balance activities, rest, and logistics to create the perfect travel experience.",
87
+ personality="Organized, balanced, and practical.",
88
+ llm=llm,
89
+ )
90
+
91
+ chatbot_agent = Agent(
92
+ role="Chatbot Agent",
93
+ goal="Engage in interactive conversation to answer travel-related queries.",
94
+ backstory="A conversational AI assistant who provides instant, accurate travel information and recommendations.",
95
+ personality="Friendly, conversational, and knowledgeable about travel.",
96
+ llm=llm,
97
+ )
98
+
99
+ chatbot_task = Task(
100
+ description="Provide a conversational and detailed response to travel-related queries.",
101
+ agent=chatbot_agent,
102
+ expected_output="A friendly, helpful response to the user's query."
103
+ )
104
+
105
+ destination_research_task = Task(
106
+ description="""Research {destination} thoroughly, considering the traveler's interests in {preferences}.
107
+
108
+ Efficient research parameters:
109
+ - Prioritize research in these critical categories:
110
+ * Top attractions that match specific {preferences} (not generic lists)
111
+ * Local transportation systems with cost-efficiency analysis
112
+ * Neighborhood breakdown with accommodation recommendations by budget tier
113
+ * Seasonal considerations for the specific travel dates
114
+ * Safety assessment with specific areas to embrace or avoid
115
+ * Cultural norms that impact visitor experience (dress codes, tipping, etiquette)
116
+
117
+ - Apply efficiency filters:
118
+ * Focus exclusively on verified information from official tourism boards, recent travel guides, and reliable local sources
119
+ * Analyze recent visitor reviews (< 6 months old) to identify changing conditions
120
+ * Evaluate price-to-experience value for attractions instead of just popularity
121
+ * Identify logistical clusters where multiple interests can be satisfied efficiently
122
+ * Research off-peak times for popular attractions to minimize waiting
123
+ * Evaluate digital tools (apps, passes, reservation systems) that streamline the visit
124
+
125
+ - Create practical knowledge matrices:
126
+ * Transportation method comparison (cost vs. time vs. convenience)
127
+ * Weather impact on specific activities
128
+ * Budget allocation recommendations based on preference priorities
129
+ * Time-saving opportunity identification""",
130
+ agent=destination_research_agent,
131
+ expected_output="""Targeted destination brief containing:
132
+ 1. Executive summary highlighting the 5 most relevant aspects based on {preferences}
133
+ 2. Neighborhood analysis with accommodation recommendations mapped to specific interests
134
+ 3. Transportation efficiency guide with cost/convenience matrix
135
+ 4. Cultural briefing focusing only on need-to-know information that impacts daily activities
136
+ 5. Seasonal advantages and challenges specific to travel dates
137
+ 6. Digital resource toolkit (essential apps, websites, reservation systems)
138
+ 7. Budget optimization strategies with price ranges for key experiences
139
+ 8. Safety and health quick-reference including emergency contacts
140
+ 9. Logistics efficiency map showing optimal activity clustering
141
+ 10. Local insider advantage recommendations that save time or money
142
+
143
+ Format should prioritize scannable information with bullet points, comparison tables, and decision matrices rather than lengthy prose."""
144
+ )
145
+
146
+ accommodation_task = Task(
147
+ description="Find suitable accommodations in {destination} based on a {budget} budget and preferences for {preferences}.",
148
+ agent=accommodation_agent,
149
+ expected_output="List of recommended accommodations with details on location, amenities, price range, and availability."
150
+ )
151
+
152
+ transportation_task = Task(
153
+ description="Plan transportation from {origin} to {destination} and local transportation options during the stay.",
154
+ agent=transportation_agent,
155
+ expected_output="Transportation plan including flights/routes to the destination and recommendations for getting around locally."
156
+ )
157
+
158
+ activities_task = Task(
159
+ description="""Suggest activities and attractions in {destination} that align with interests in {preferences}.
160
+
161
+ Detailed requirements:
162
+ - Categorize activities into: Cultural Experiences, Outdoor Adventures, Culinary Experiences,
163
+ Entertainment & Nightlife, Family-Friendly Activities, and Local Hidden Gems
164
+ - For each activity, include:
165
+ * Detailed description with historical/cultural context where relevant
166
+ * Precise location with neighborhood information
167
+ * Operating hours with seasonal variations noted
168
+ * Pricing information with different ticket options/packages
169
+ * Accessibility considerations for travelers with mobility limitations
170
+ * Recommended duration for the activity (minimum and ideal time)
171
+ * Best time of day/week/year to visit
172
+ * Crowd levels by season
173
+ * Photography opportunities and restrictions
174
+ * Required reservations or booking windows
175
+ - Include a mix of iconic must-see attractions and off-the-beaten-path experiences
176
+ - Consider weather patterns in {destination} during travel period
177
+ - Analyze the {preferences} to match specific personality types and interest levels
178
+ - Include at least 2-3 rainy day alternatives for outdoor activities
179
+ - Provide local transportation options to reach each attraction
180
+ - Note authentic local experiences that provide cultural immersion
181
+ - Flag any activities requiring special equipment, permits, or physical fitness levels""",
182
+ agent=activities_agent,
183
+ expected_output="""Comprehensive curated list of activities and attractions with:
184
+ 1. Clear categorization by type (cultural, outdoor, culinary, entertainment, family-friendly, hidden gems)
185
+ 2. Detailed descriptions that include historical and cultural context
186
+ 3. Complete practical information (hours, pricing, location, accessibility)
187
+ 4. Time optimization recommendations (best time to visit, how to avoid crowds)
188
+ 5. Personalized matches explaining why each activity aligns with specific {preferences}
189
+ 6. Local transportation details to reach each attraction
190
+ 7. Alternative options for inclement weather or unexpected closures
191
+ 8. Insider tips from locals that enhance the experience
192
+ 9. Suggested combinations of nearby activities for efficient itinerary planning
193
+ 10. Risk level assessment and safety considerations where applicable
194
+ 11. Sustainability impact and responsible tourism notes
195
+ 12. Photographic highlights and optimal viewing points
196
+
197
+ Format should include a summary table for quick reference followed by detailed cards for each activity."""
198
+ )
199
+
200
+ dining_task = Task(
201
+ description="Recommend dining experiences in {destination} that showcase local cuisine while considering {preferences}.",
202
+ agent=dining_agent,
203
+ expected_output="List of recommended restaurants and food experiences with cuisine types, price ranges, and special notes."
204
+ )
205
+
206
+ itinerary_task = Task(
207
+ description="""Create a day-by-day itinerary for a {duration} trip to {destination} from {origin}, incorporating all recommendations.
208
+
209
+ Detailed requirements:
210
+ - Begin with arrival logistics including airport transfer options, check-in times, and first-day orientation activities
211
+ - Structure each day with:
212
+ * Morning, afternoon, and evening activity blocks with precise timing
213
+ * Estimated travel times between locations using various transportation methods
214
+ * Buffer time for rest, spontaneous exploration, and unexpected delays
215
+ * Meal recommendations with reservation details and backup options
216
+ * Sunset/sunrise opportunities for optimal photography or experiences
217
+ - Apply intelligent sequencing to:
218
+ * Group attractions by geographic proximity to minimize transit time
219
+ * Schedule indoor activities strategically for predicted weather patterns
220
+ * Balance high-energy activities with relaxation periods
221
+ * Alternate between cultural immersion and entertainment experiences
222
+ * Account for opening days/hours of attractions and potential closures
223
+ - Include practical timing considerations:
224
+ * Museum/attraction fatigue limitations
225
+ * Jet lag recovery for first 1-2 days
226
+ * Time zone adjustment strategies
227
+ * Local rush hours and traffic patterns to avoid
228
+ * Cultural norms for meal times and business hours
229
+ - End with departure logistics including check-out procedures, airport transfer timing, and luggage considerations
230
+ - Add specialized planning elements:
231
+ * Local festivals or events coinciding with the travel dates
232
+ * Free time blocks for personal exploration or shopping
233
+ * Contingency recommendations for weather disruptions
234
+ * Early booking requirements for popular attractions/restaurants
235
+ * Local emergency contacts and nearby medical facilities""",
236
+ agent=itinerary_agent,
237
+ expected_output="""Comprehensive day-by-day itinerary featuring:
238
+ 1. Detailed timeline for each day with hour-by-hour scheduling and transit times
239
+ 2. Color-coded activity blocks that visually distinguish between types of activities
240
+ 3. Intelligent geographic clustering to minimize transportation time
241
+ 4. Strategic meal placements with both reservation-required and casual options
242
+ 5. Built-in flexibility with free time blocks and alternative suggestions
243
+ 6. Weather-adaptive scheduling with indoor/outdoor activity balance
244
+ 7. Energy level considerations throughout the trip arc
245
+ 8. Cultural timing adaptations (accommodating local siesta times, religious observances, etc.)
246
+ 9. Practical logistical details (bag storage options, dress code reminders, etc.)
247
+ 10. Local transportation guidance including transit cards, apps, and pre-booking requirements
248
+ 11. Visual map representation showing daily movement patterns
249
+ 12. Key phrases in local language for each day's activities
250
+
251
+ Format should include both a condensed overview calendar and detailed daily breakdowns with time, activity, location, notes, and contingency plans."""
252
+ )
253
+
254
+ def get_weather_forecast(destination: str, start_date: datetime, duration: int) -> str:
255
+ """
256
+ Stub function for weather forecast.
257
+ Replace with actual API call if needed.
258
+ """
259
+ forecast = f"Expected weather for {destination}: Mostly sunny with occasional clouds. Average temperature: 24°C."
260
+ return forecast
261
+
262
+ def generate_qr_code(itinerary_text: str, output_file: str = "itinerary_qr.png") -> str:
263
+ """
264
+ Generates a QR code image encoding the itinerary text.
265
+ Uses version=40 and ERROR_CORRECT_M for maximum capacity.
266
+ Returns the output file path.
267
+ """
268
+ try:
269
+ qr = qrcode.QRCode(
270
+ version=40,
271
+ error_correction=ERROR_CORRECT_M,
272
+ box_size=10,
273
+ border=4
274
+ )
275
+ qr.add_data(itinerary_text)
276
+ qr.make(fit=True)
277
+ img = qr.make_image(fill_color="black", back_color="white")
278
+ img.save(output_file)
279
+ logging.info(f"QR code saved as: {output_file}")
280
+ return output_file
281
+ except Exception as e:
282
+ logging.error(f"Error generating QR code: {e}")
283
+ return ""
284
+
285
+ def run_task(task: Task, input_text: str) -> str:
286
+ """
287
+ Invokes the assigned LLM for the given task using system and human messages.
288
+ """
289
+ try:
290
+ if not isinstance(task, Task):
291
+ raise ValueError(f"Expected 'task' to be an instance of Task, got {type(task)}")
292
+ if not hasattr(task, 'agent') or not isinstance(task.agent, Agent):
293
+ raise ValueError("Task must have a valid 'agent' attribute of type Agent.")
294
+
295
+ system_input = (
296
+ f"Agent Details:\n"
297
+ f"Role: {task.agent.role}\n"
298
+ f"Goal: {task.agent.goal}\n"
299
+ f"Backstory: {task.agent.backstory}\n"
300
+ f"Personality: {task.agent.personality}\n"
301
+ )
302
+ task_input = (
303
+ f"Task Details:\n"
304
+ f"Task Description: {task.description}\n"
305
+ f"Expected Output: {task.expected_output}\n"
306
+ f"Input for Task:\n{input_text}\n"
307
+ )
308
+ messages = [
309
+ SystemMessage(content=system_input),
310
+ HumanMessage(content=task_input)
311
+ ]
312
+ response = task.agent.llm.invoke(messages)
313
+ if not response or not response.content:
314
+ raise ValueError("Empty response from LLM.")
315
+ return response.content
316
+ except Exception as e:
317
+ logging.error(f"Error in task '{task.agent.role}': {e}")
318
+ return f"Error in {task.agent.role}: {e}"
319
+
320
+ def get_user_input() -> dict:
321
+ print("\n=== Travel Itinerary Generator ===\n")
322
+ origin = input("Enter your origin city/country: ")
323
+ destination = input("Enter your destination city/country: ")
324
+ duration = input("Enter trip duration (number of days): ")
325
+ budget = input("Enter your budget level (budget, moderate, luxury): ")
326
+
327
+ print("\nEnter your travel preferences and interests (comma-separated):")
328
+ print("Examples: museums, hiking, food, shopping, beaches, history, nightlife, family-friendly, etc.")
329
+ preferences = input("> ")
330
+
331
+ special_requirements = input("\nAny special requirements or notes (dietary restrictions, accessibility needs, etc.)? ")
332
+
333
+ return {
334
+ "origin": origin,
335
+ "destination": destination,
336
+ "duration": duration,
337
+ "budget": budget,
338
+ "preferences": preferences,
339
+ "special_requirements": special_requirements
340
+ }
341
+
342
+ def generate_travel_itinerary(user_input: dict) -> str:
343
+ print("\nGenerating your personalized travel itinerary...\n")
344
+
345
+ input_context = (
346
+ f"Travel Request Details:\n"
347
+ f"Origin: {user_input['origin']}\n"
348
+ f"Destination: {user_input['destination']}\n"
349
+ f"Duration: {user_input['duration']} days\n"
350
+ f"Budget Level: {user_input['budget']}\n"
351
+ f"Preferences/Interests: {user_input['preferences']}\n"
352
+ f"Special Requirements: {user_input['special_requirements']}\n"
353
+ )
354
+
355
+ try:
356
+ travel_start = datetime.now() # For demonstration purposes.
357
+ duration_int = int(user_input['duration'])
358
+ weather_info = get_weather_forecast(user_input['destination'], travel_start, duration_int)
359
+ input_context += f"Weather Forecast: {weather_info}\n"
360
+ except Exception as e:
361
+ logging.error(f"Error getting weather info: {e}")
362
+
363
+ # Step 1: Destination Research
364
+ print("Researching your destination...")
365
+ destination_info = run_task(destination_research_task, input_context)
366
+ print("✓ Destination research completed")
367
+
368
+ # Step 2: Accommodation Recommendations
369
+ print("Finding ideal accommodations...")
370
+ accommodation_info = run_task(accommodation_task, input_context)
371
+ print("✓ Accommodation recommendations completed")
372
+
373
+ # Step 3: Transportation Planning
374
+ print("Planning transportation...")
375
+ transportation_info = run_task(transportation_task, input_context)
376
+ print("✓ Transportation planning completed")
377
+
378
+ # Step 4: Activities & Attractions
379
+ print("Curating activities and attractions...")
380
+ activities_info = run_task(activities_task, input_context)
381
+ print("✓ Activities and attractions curated")
382
+
383
+ # Step 5: Dining Recommendations
384
+ print("Finding dining experiences...")
385
+ dining_info = run_task(dining_task, input_context)
386
+ print("✓ Dining recommendations completed")
387
+
388
+ # Step 6: Create Day-by-Day Itinerary
389
+ print("Creating your day-by-day itinerary...")
390
+ combined_info = (
391
+ input_context + "\n"
392
+ "Destination Information:\n" + destination_info + "\n"
393
+ "Accommodation Options:\n" + accommodation_info + "\n"
394
+ "Transportation Plan:\n" + transportation_info + "\n"
395
+ "Recommended Activities:\n" + activities_info + "\n"
396
+ "Dining Recommendations:\n" + dining_info + "\n"
397
+ )
398
+ itinerary = run_task(itinerary_task, combined_info)
399
+ print("✓ Itinerary creation completed")
400
+ print("✓ Itinerary generation completed")
401
+
402
+ return itinerary
403
+
404
+ def save_itinerary_to_file(itinerary: str, user_input: dict, output_dir: str = None) -> str:
405
+ date_str = datetime.now().strftime("%Y-%m-%d")
406
+ filename = f"{user_input['destination'].replace(' ', '_')}_{date_str}_itinerary.txt"
407
+
408
+ if output_dir:
409
+ if not os.path.exists(output_dir):
410
+ try:
411
+ os.makedirs(output_dir)
412
+ logging.info(f"Created output directory: {output_dir}")
413
+ except Exception as e:
414
+ logging.error(f"Error creating directory {output_dir}: {e}")
415
+ return ""
416
+ filepath = os.path.join(output_dir, filename)
417
+ else:
418
+ filepath = filename
419
+
420
+ try:
421
+ with open(filepath, "w", encoding="utf-8") as f:
422
+ f.write(itinerary)
423
+ logging.info(f"Your itinerary has been saved as: {filepath}")
424
+ return filepath
425
+ except Exception as e:
426
+ logging.error(f"Error saving itinerary: {e}")
427
+ return ""
428
+
429
+ def main() -> None:
430
+ print("Welcome to BlockX Travel Itinerary Generator!")
431
+ print("This AI-powered tool will create a personalized travel itinerary based on your preferences.")
432
+
433
+ user_input = get_user_input()
434
+
435
+ print("\nWhere would you like to save the itinerary?")
436
+ print("Press Enter to save in the current directory, or specify a path:")
437
+ output_dir = input("> ").strip() or None
438
+
439
+ itinerary = generate_travel_itinerary(user_input)
440
+
441
+ filepath = save_itinerary_to_file(itinerary, user_input, output_dir)
442
+ if filepath:
443
+ print(f"\nYour itinerary has been saved as: {filepath}")
444
+
445
+ # Generate QR Code for the itinerary
446
+ print("\nGenerating QR code for your itinerary...")
447
+ qr_image_path = generate_qr_code(itinerary)
448
+ if qr_image_path:
449
+ print(f"QR Code image is available at: {qr_image_path}")
450
+
451
+ print("\nThank you for using BlockX Travel Itinerary Generator!")
452
+
453
+ if __name__ == "__main__":
454
+ main()