MrTravelX commited on
Commit
fb4338a
·
verified ·
1 Parent(s): fa3fc49

Create travel.py

Browse files
Files changed (1) hide show
  1. travel.py +552 -0
travel.py ADDED
@@ -0,0 +1,552 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import json
3
+ from datetime import datetime, timedelta
4
+ from langchain_google_genai import ChatGoogleGenerativeAI
5
+ from langchain.schema import SystemMessage, HumanMessage
6
+
7
+ # ------------------------------------------------------------------------------
8
+ # Agent and Task Classes
9
+ # ------------------------------------------------------------------------------
10
+ class Agent:
11
+ def __init__(self, role, goal, backstory, personality="", llm=None):
12
+ self.role = role
13
+ self.goal = goal
14
+ self.backstory = backstory
15
+ self.personality = personality
16
+ self.tools = [] # Initialize with empty list
17
+ self.llm = llm
18
+
19
+ class Task:
20
+ def __init__(self, description, agent, expected_output, context=None):
21
+ self.description = description
22
+ self.agent = agent
23
+ self.expected_output = expected_output
24
+ self.context = context or []
25
+
26
+ # ------------------------------------------------------------------------------
27
+ # Initialize LLM
28
+ # ------------------------------------------------------------------------------
29
+ google_api_key = "AIzaSyDJV8NtUcfp4YhuqehdcXQ8JgVRtYI8Kf4" # Replace with your actual Google API key
30
+ llm = ChatGoogleGenerativeAI(model="gemini-2.0-flash", google_api_key=google_api_key)
31
+
32
+ # ------------------------------------------------------------------------------
33
+ # Define Travel Agents
34
+ # ------------------------------------------------------------------------------
35
+ # 1. Destination Research Agent
36
+ destination_research_agent = Agent(
37
+ role="Destination Research Agent",
38
+ goal=(
39
+ "Research and provide comprehensive information about the destination including popular attractions, "
40
+ "local culture, weather patterns, best times to visit, and local transportation options."
41
+ ),
42
+ backstory=(
43
+ "An experienced travel researcher with extensive knowledge of global destinations. "
44
+ "I specialize in uncovering both popular attractions and hidden gems that match travelers' interests."
45
+ ),
46
+ personality="Curious, detail-oriented, and knowledgeable about global cultures and travel trends.",
47
+ llm=llm,
48
+ )
49
+
50
+ # 2. Accommodation Agent
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
+ # 3. Transportation Agent
60
+ transportation_agent = Agent(
61
+ role="Transportation Agent",
62
+ goal="Plan efficient transportation between the origin, destination, and all points of interest in the itinerary.",
63
+ backstory="A logistics specialist with knowledge of global transportation systems, from flights to local transit options.",
64
+ personality="Efficient, practical, and detail-oriented.",
65
+ llm=llm,
66
+ )
67
+
68
+ # 4. Activities & Attractions Agent
69
+ activities_agent = Agent(
70
+ role="Activities & Attractions Agent",
71
+ goal="Curate personalized activities and attractions that align with the traveler's interests, preferences, and time constraints.",
72
+ backstory="An enthusiastic explorer who has experienced diverse activities around the world and knows how to match experiences to individual preferences.",
73
+ personality="Enthusiastic, creative, and personable.",
74
+ llm=llm,
75
+ )
76
+
77
+ # 5. Dining & Culinary Agent
78
+ dining_agent = Agent(
79
+ role="Dining & Culinary Agent",
80
+ goal="Recommend dining experiences that showcase local cuisine while accommodating dietary preferences and budget considerations.",
81
+ backstory="A culinary expert with knowledge of global food scenes and an appreciation for authentic local dining experiences.",
82
+ personality="Passionate about food, culturally aware, and attentive to preferences.",
83
+ llm=llm,
84
+ )
85
+
86
+ # 6. Itinerary Integration Agent
87
+ itinerary_agent = Agent(
88
+ role="Itinerary Integration Agent",
89
+ goal="Compile all recommendations into a cohesive, day-by-day itinerary that optimizes time, minimizes travel fatigue, and maximizes enjoyment.",
90
+ backstory="A master travel planner who understands how to balance activities, rest, and logistics to create the perfect travel experience.",
91
+ personality="Organized, balanced, and practical.",
92
+ llm=llm,
93
+ )
94
+
95
+ # 7. Final Report Generation Agent
96
+ final_report_agent = Agent(
97
+ role="Final Report Generation Agent",
98
+ goal="Generate a comprehensive, visually appealing travel itinerary document that is easy to follow and includes all necessary details."
99
+ "1. Compile outputs from all agents into a cohesive travel plan. "
100
+ "2. Create clearly defined, organized daily schedules with times, locations, and activity durations. "
101
+ "3. Include practical information such as estimated costs, contact details, and reservation information. "
102
+ "4. Implement a clean, travel-themed design with proper spacing, alignment, and highlights. "
103
+ "5. Output the final itinerary as valid HTML with inline CSS for styling.",
104
+ backstory="A creative travel document specialist who transforms complex travel plans into beautiful, functional itineraries that enhance the travel experience.",
105
+ personality="Creative, detail-oriented, and user-focused.",
106
+ llm=llm,
107
+ )
108
+
109
+ # ------------------------------------------------------------------------------
110
+ # Define Tasks
111
+ # ------------------------------------------------------------------------------
112
+ destination_research_task = Task(
113
+ description="""Research {destination} thoroughly, considering the traveler's interests in {preferences}.
114
+
115
+ Efficient research parameters:
116
+ - Prioritize research in these critical categories:
117
+ * Top attractions that match specific {preferences} (not generic lists)
118
+ * Local transportation systems with cost-efficiency analysis
119
+ * Neighborhood breakdown with accommodation recommendations by budget tier
120
+ * Seasonal considerations for the specific travel dates
121
+ * Safety assessment with specific areas to embrace or avoid
122
+ * Cultural norms that impact visitor experience (dress codes, tipping, etiquette)
123
+
124
+ - Apply efficiency filters:
125
+ * Focus exclusively on verified information from official tourism boards, recent travel guides, and reliable local sources
126
+ * Analyze recent visitor reviews (< 6 months old) to identify changing conditions
127
+ * Evaluate price-to-experience value for attractions instead of just popularity
128
+ * Identify logistical clusters where multiple interests can be satisfied efficiently
129
+ * Research off-peak times for popular attractions to minimize waiting
130
+ * Evaluate digital tools (apps, passes, reservation systems) that streamline the visit
131
+
132
+ - Create practical knowledge matrices:
133
+ * Transportation method comparison (cost vs. time vs. convenience)
134
+ * Weather impact on specific activities
135
+ * Budget allocation recommendations based on preference priorities
136
+ * Time-saving opportunity identification""",
137
+
138
+ agent=destination_research_agent,
139
+
140
+ expected_output="""Targeted destination brief containing:
141
+ 1. Executive summary highlighting the 5 most relevant aspects based on {preferences}
142
+ 2. Neighborhood analysis with accommodation recommendations mapped to specific interests
143
+ 3. Transportation efficiency guide with cost/convenience matrix
144
+ 4. Cultural briefing focusing only on need-to-know information that impacts daily activities
145
+ 5. Seasonal advantages and challenges specific to travel dates
146
+ 6. Digital resource toolkit (essential apps, websites, reservation systems)
147
+ 7. Budget optimization strategies with price ranges for key experiences
148
+ 8. Safety and health quick-reference including emergency contacts
149
+ 9. Logistics efficiency map showing optimal activity clustering
150
+ 10. Local insider advantage recommendations that save time or money
151
+
152
+ Format should prioritize scannable information with bullet points, comparison tables, and decision matrices rather than lengthy prose."""
153
+ )
154
+
155
+ accommodation_task = Task(
156
+ description="Find suitable accommodations in {destination} based on a {budget} budget and preferences for {preferences}.",
157
+ agent=accommodation_agent,
158
+ expected_output="List of recommended accommodations with details on location, amenities, price range, and availability."
159
+ )
160
+
161
+ transportation_task = Task(
162
+ description="Plan transportation from {origin} to {destination} and local transportation options during the stay.",
163
+ agent=transportation_agent,
164
+ expected_output="Transportation plan including flights/routes to the destination and recommendations for getting around locally."
165
+ )
166
+
167
+ activities_task = Task(
168
+ description="""Suggest activities and attractions in {destination} that align with interests in {preferences}.
169
+
170
+ Detailed requirements:
171
+ - Categorize activities into: Cultural Experiences, Outdoor Adventures, Culinary Experiences,
172
+ Entertainment & Nightlife, Family-Friendly Activities, and Local Hidden Gems
173
+ - For each activity, include:
174
+ * Detailed description with historical/cultural context where relevant
175
+ * Precise location with neighborhood information
176
+ * Operating hours with seasonal variations noted
177
+ * Pricing information with different ticket options/packages
178
+ * Accessibility considerations for travelers with mobility limitations
179
+ * Recommended duration for the activity (minimum and ideal time)
180
+ * Best time of day/week/year to visit
181
+ * Crowd levels by season
182
+ * Photography opportunities and restrictions
183
+ * Required reservations or booking windows
184
+ - Include a mix of iconic must-see attractions and off-the-beaten-path experiences
185
+ - Consider weather patterns in {destination} during travel period
186
+ - Analyze the {preferences} to match specific personality types and interest levels
187
+ - Include at least 2-3 rainy day alternatives for outdoor activities
188
+ - Provide local transportation options to reach each attraction
189
+ - Note authentic local experiences that provide cultural immersion
190
+ - Flag any activities requiring special equipment, permits, or physical fitness levels""",
191
+
192
+ agent=activities_agent,
193
+
194
+ expected_output="""Comprehensive curated list of activities and attractions with:
195
+ 1. Clear categorization by type (cultural, outdoor, culinary, entertainment, family-friendly, hidden gems)
196
+ 2. Detailed descriptions that include historical and cultural context
197
+ 3. Complete practical information (hours, pricing, location, accessibility)
198
+ 4. Time optimization recommendations (best time to visit, how to avoid crowds)
199
+ 5. Personalized matches explaining why each activity aligns with specific {preferences}
200
+ 6. Local transportation details to reach each attraction
201
+ 7. Alternative options for inclement weather or unexpected closures
202
+ 8. Insider tips from locals that enhance the experience
203
+ 9. Suggested combinations of nearby activities for efficient itinerary planning
204
+ 10. Risk level assessment and safety considerations where applicable
205
+ 11. Sustainability impact and responsible tourism notes
206
+ 12. Photographic highlights and optimal viewing points
207
+
208
+ Format should include a summary table for quick reference followed by detailed cards for each activity."""
209
+ )
210
+
211
+ dining_task = Task(
212
+ description="Recommend dining experiences in {destination} that showcase local cuisine while considering {preferences}.",
213
+ agent=dining_agent,
214
+ expected_output="List of recommended restaurants and food experiences with cuisine types, price ranges, and special notes."
215
+ )
216
+
217
+ itinerary_task = Task(
218
+ description="""Create a day-by-day itinerary for a {duration} trip to {destination} from {origin}, incorporating all recommendations.
219
+
220
+ Detailed requirements:
221
+ - Begin with arrival logistics including airport transfer options, check-in times, and first-day orientation activities
222
+ - Structure each day with:
223
+ * Morning, afternoon, and evening activity blocks with precise timing
224
+ * Estimated travel times between locations using various transportation methods
225
+ * Buffer time for rest, spontaneous exploration, and unexpected delays
226
+ * Meal recommendations with reservation details and backup options
227
+ * Sunset/sunrise opportunities for optimal photography or experiences
228
+ - Apply intelligent sequencing to:
229
+ * Group attractions by geographic proximity to minimize transit time
230
+ * Schedule indoor activities strategically for predicted weather patterns
231
+ * Balance high-energy activities with relaxation periods
232
+ * Alternate between cultural immersion and entertainment experiences
233
+ * Account for opening days/hours of attractions and potential closures
234
+ - Include practical timing considerations:
235
+ * Museum/attraction fatigue limitations
236
+ * Jet lag recovery for first 1-2 days
237
+ * Time zone adjustment strategies
238
+ * Local rush hours and traffic patterns to avoid
239
+ * Cultural norms for meal times and business hours
240
+ - End with departure logistics including check-out procedures, airport transfer timing, and luggage considerations
241
+ - Add specialized planning elements:
242
+ * Local festivals or events coinciding with the travel dates
243
+ * Free time blocks for personal exploration or shopping
244
+ * Contingency recommendations for weather disruptions
245
+ * Early booking requirements for popular attractions/restaurants
246
+ * Local emergency contacts and nearby medical facilities""",
247
+
248
+ agent=itinerary_agent,
249
+
250
+ expected_output="""Comprehensive day-by-day itinerary featuring:
251
+ 1. Detailed timeline for each day with hour-by-hour scheduling and transit times
252
+ 2. Color-coded activity blocks that visually distinguish between types of activities
253
+ 3. Intelligent geographic clustering to minimize transportation time
254
+ 4. Strategic meal placements with both reservation-required and casual options
255
+ 5. Built-in flexibility with free time blocks and alternative suggestions
256
+ 6. Weather-adaptive scheduling with indoor/outdoor activity balance
257
+ 7. Energy level considerations throughout the trip arc
258
+ 8. Cultural timing adaptations (accommodating local siesta times, religious observances, etc.)
259
+ 9. Practical logistical details (bag storage options, dress code reminders, etc.)
260
+ 10. Local transportation guidance including transit cards, apps, and pre-booking requirements
261
+ 11. Visual map representation showing daily movement patterns
262
+ 12. Key phrases in local language for each day's activities
263
+
264
+ Format should include both a condensed overview calendar and detailed daily breakdowns with time, activity, location, notes, and contingency plans."""
265
+ )
266
+
267
+ final_report_task = Task(
268
+ description="""Generate a comprehensive, visually appealing travel itinerary document for a {duration} trip to {destination} from {origin}.
269
+
270
+ Technical requirements:
271
+ - Implement using Tailwind CSS for responsive styling and utility classes
272
+ - Enhance with Alpine.js for lightweight interactive components
273
+ - Include Mapbox GL JS integration for interactive maps with points of interest
274
+ - Use Chart.js for visualizing trip budget breakdowns
275
+ - Implement with DaisyUI or Flowbite components for consistent UI elements
276
+ - Ensure cross-browser compatibility and mobile-first responsive design
277
+ - Meet WCAG 2.1 AA accessibility standards
278
+
279
+ UI/UX features:
280
+ - Create collapsible day-by-day itinerary sections
281
+ - Include interactive map with customized markers for attractions, hotels, and restaurants
282
+ - Implement dark/light mode toggle with user preference storage
283
+ - Add weather forecast integration via OpenWeatherMap API
284
+ - Design printable version with QR codes for digital access
285
+ - Include local emergency information in an accessible sidebar
286
+ - Create animated transitions between sections for improved user experience
287
+ - Implement offline capabilities with service workers""",
288
+
289
+ agent=final_report_agent,
290
+
291
+ expected_output="""Complete HTML travel itinerary featuring:
292
+ 1. Responsive layout using Tailwind CSS that adapts to all device sizes
293
+ 2. Interactive components powered by Alpine.js for seamless user interactions
294
+ 3. Dynamic map visualization with Mapbox GL JS showing the complete travel route
295
+ 4. Collapsible sections for daily activities with smooth animations
296
+ 5. Dark/light mode toggle that persists user preferences
297
+ 6. Weather forecast widgets integrated with OpenWeatherMap
298
+ 7. Printable version with optimized styling for physical documents
299
+ 8. Trip budget visualization with interactive charts
300
+ 9. Offline-capable implementation with service worker caching
301
+ 10. Accessibility-compliant design including keyboard navigation and screen reader support
302
+ 11. Performance optimization with lazy-loading images and content
303
+ 12. Custom PDF export functionality
304
+
305
+ All code should be clean, well-commented, and follow modern web development best practices."""
306
+ )
307
+
308
+ # ------------------------------------------------------------------------------
309
+ # Helper Function to Run a Task with Full Agent & Task Information
310
+ # ------------------------------------------------------------------------------
311
+ def run_task(task, input_text):
312
+ try:
313
+ # Ensure 'task' is an instance of the Task class
314
+ if not isinstance(task, Task):
315
+ raise ValueError(f"Expected 'task' to be an instance of Task class, but got {type(task)}")
316
+
317
+ # Ensure 'task.agent' exists and is an instance of Agent
318
+ if not hasattr(task, 'agent') or not isinstance(task.agent, Agent):
319
+ raise ValueError(f"Task must contain a valid 'agent' attribute that is an instance of Agent class.")
320
+
321
+ system_input = f"""Agent Details:
322
+ Role: {task.agent.role}
323
+ Goal: {task.agent.goal}
324
+ Backstory: {task.agent.backstory}
325
+ Personality: {task.agent.personality}
326
+ """
327
+ task_input = f"""Task Details:
328
+ Task Description: {task.description}
329
+ Expected Output: {task.expected_output}
330
+ Input for Task:
331
+ {input_text}
332
+ """
333
+ messages = [
334
+ SystemMessage(content=system_input),
335
+ HumanMessage(content=task_input)
336
+ ]
337
+ response = task.agent.llm.invoke(messages)
338
+ if not response or not response.content:
339
+ raise ValueError("Empty response from LLM.")
340
+ return response.content
341
+ except Exception as e:
342
+ print(f"Error in task '{task.agent.role}': {e}")
343
+ return f"Error in {task.agent.role}: {e}"
344
+
345
+ # ------------------------------------------------------------------------------
346
+ # User Input Functions
347
+ # ------------------------------------------------------------------------------
348
+ def get_user_input():
349
+ print("\n=== Travel Itinerary Generator ===\n")
350
+ origin = input("Enter your origin city/country: ")
351
+ destination = input("Enter your destination city/country: ")
352
+ duration = input("Enter trip duration (number of days): ")
353
+ budget = input("Enter your budget level (budget, moderate, luxury): ")
354
+
355
+ print("\nEnter your travel preferences and interests (comma-separated):")
356
+ print("Examples: museums, hiking, food, shopping, beaches, history, nightlife, family-friendly, etc.")
357
+ preferences = input("> ")
358
+
359
+ special_requirements = input("\nAny special requirements or notes (dietary restrictions, accessibility needs, etc.)? ")
360
+
361
+ return {
362
+ "origin": origin,
363
+ "destination": destination,
364
+ "duration": duration,
365
+ "budget": budget,
366
+ "preferences": preferences,
367
+ "special_requirements": special_requirements
368
+ }
369
+
370
+ # ------------------------------------------------------------------------------
371
+ # Main Function to Generate Travel Itinerary
372
+ # ------------------------------------------------------------------------------
373
+ def generate_travel_itinerary(user_input):
374
+ print("\nGenerating your personalized travel itinerary...\n")
375
+
376
+ # Format the user input for tasks
377
+ input_context = f"""Travel Request Details:
378
+ Origin: {user_input['origin']}
379
+ Destination: {user_input['destination']}
380
+ Duration: {user_input['duration']} days
381
+ Budget Level: {user_input['budget']}
382
+ Preferences/Interests: {user_input['preferences']}
383
+ Special Requirements: {user_input['special_requirements']}
384
+ """
385
+
386
+ # Step 1: Destination Research
387
+ print("Researching your destination...")
388
+ destination_info = run_task(
389
+ destination_research_task,
390
+ input_context.format(
391
+ destination=user_input['destination'],
392
+ preferences=user_input['preferences']
393
+ )
394
+ )
395
+ print("✓ Destination research completed")
396
+
397
+ # Step 2: Accommodation Recommendations
398
+ print("Finding ideal accommodations...")
399
+ accommodation_info = run_task(
400
+ accommodation_task,
401
+ input_context.format(
402
+ destination=user_input['destination'],
403
+ budget=user_input['budget'],
404
+ preferences=user_input['preferences']
405
+ )
406
+ )
407
+ print("✓ Accommodation recommendations completed")
408
+
409
+ # Step 3: Transportation Planning
410
+ print("Planning transportation...")
411
+ transportation_info = run_task(
412
+ transportation_task,
413
+ input_context.format(
414
+ origin=user_input['origin'],
415
+ destination=user_input['destination']
416
+ )
417
+ )
418
+ print("✓ Transportation planning completed")
419
+
420
+ # Step 4: Activities & Attractions
421
+ print("Curating activities and attractions...")
422
+ activities_info = run_task(
423
+ activities_task,
424
+ input_context.format(
425
+ destination=user_input['destination'],
426
+ preferences=user_input['preferences']
427
+ )
428
+ )
429
+ print("✓ Activities and attractions curated")
430
+
431
+ # Step 5: Dining Recommendations
432
+ print("Finding dining experiences...")
433
+ dining_info = run_task(
434
+ dining_task,
435
+ input_context.format(
436
+ destination=user_input['destination'],
437
+ preferences=user_input['preferences']
438
+ )
439
+ )
440
+ print("✓ Dining recommendations completed")
441
+
442
+ # Step 6: Create Day-by-Day Itinerary
443
+ print("Creating your day-by-day itinerary...")
444
+ combined_info = f"""{input_context}
445
+
446
+ Destination Information:
447
+ {destination_info}
448
+
449
+ Accommodation Options:
450
+ {accommodation_info}
451
+
452
+ Transportation Plan:
453
+ {transportation_info}
454
+
455
+ Recommended Activities:
456
+ {activities_info}
457
+
458
+ Dining Recommendations:
459
+ {dining_info}
460
+ """
461
+
462
+ itinerary = run_task(
463
+ itinerary_task,
464
+ combined_info.format(
465
+ duration=user_input['duration'],
466
+ origin=user_input['origin'],
467
+ destination=user_input['destination']
468
+ )
469
+ )
470
+ print("✓ Itinerary creation completed")
471
+
472
+ # Step 7: Generate Final Report
473
+ print("Generating your final travel itinerary document...")
474
+ final_context = f"""{combined_info}
475
+
476
+ Day-by-Day Itinerary:
477
+ {itinerary}
478
+ """
479
+
480
+ final_itinerary = run_task(
481
+ final_report_task,
482
+ final_context.format(
483
+ duration=user_input['duration'],
484
+ origin=user_input['origin'],
485
+ destination=user_input['destination']
486
+ )
487
+ )
488
+ print("✓ Final itinerary document generated")
489
+
490
+ return final_itinerary
491
+
492
+ # ------------------------------------------------------------------------------
493
+ # Save Itinerary to File
494
+ # ------------------------------------------------------------------------------
495
+ def save_itinerary_to_file(itinerary, user_input, output_dir=None):
496
+ # Create a filename based on the destination and date
497
+ date_str = datetime.now().strftime("%Y-%m-%d")
498
+ filename = f"{user_input['destination'].replace(' ', '_')}_{date_str}_itinerary.html"
499
+
500
+ # If output directory is specified, ensure it exists and use it
501
+ if output_dir:
502
+ if not os.path.exists(output_dir):
503
+ try:
504
+ os.makedirs(output_dir)
505
+ print(f"Created output directory: {output_dir}")
506
+ except Exception as e:
507
+ print(f"Error creating directory {output_dir}: {e}")
508
+ return None
509
+
510
+ # Combine the output directory with the filename
511
+ filepath = os.path.join(output_dir, filename)
512
+ else:
513
+ filepath = filename
514
+
515
+ try:
516
+ with open(filepath, "w", encoding="utf-8") as f:
517
+ f.write(itinerary)
518
+ print(f"\nYour itinerary has been saved as: {filepath}")
519
+ return filepath
520
+ except Exception as e:
521
+ print(f"Error saving itinerary: {e}")
522
+ return None
523
+
524
+ # ------------------------------------------------------------------------------
525
+ # Main Function
526
+ # ------------------------------------------------------------------------------
527
+ def main():
528
+ print("Welcome to BlockX Travel Itinerary Generator!")
529
+ print("This AI-powered tool will create a personalized travel itinerary based on your preferences.")
530
+
531
+ user_input = get_user_input()
532
+
533
+ # Ask for output directory
534
+ print("\nWhere would you like to save the itinerary?")
535
+ print("Press Enter to save in the current directory, or specify a path:")
536
+ output_dir = input("> ").strip()
537
+
538
+ # If empty, use current directory
539
+ if not output_dir:
540
+ output_dir = None
541
+ print("Will save in the current directory.")
542
+
543
+ itinerary = generate_travel_itinerary(user_input)
544
+
545
+ filename = save_itinerary_to_file(itinerary, user_input, output_dir)
546
+
547
+ if filename:
548
+ print(f"\nYour personalized travel itinerary is ready! Open {filename} to view it.")
549
+ print("Thank you for using BlockX Travel Itinerary Generator!")
550
+
551
+ if __name__ == "__main__":
552
+ main()