Spaces:
Running
Running
| import os | |
| import json | |
| from datetime import datetime, timedelta | |
| from langchain_google_genai import ChatGoogleGenerativeAI | |
| from langchain.schema import SystemMessage, HumanMessage | |
| # ------------------------------------------------------------------------------ | |
| # Agent and Task Classes | |
| # ------------------------------------------------------------------------------ | |
| class Agent: | |
| def __init__(self, role, goal, backstory, personality="", llm=None): | |
| self.role = role | |
| self.goal = goal | |
| self.backstory = backstory | |
| self.personality = personality | |
| self.tools = [] # Initialize with empty list | |
| self.llm = llm | |
| class Task: | |
| def __init__(self, description, agent, expected_output, context=None): | |
| self.description = description | |
| self.agent = agent | |
| self.expected_output = expected_output | |
| self.context = context or [] | |
| # ------------------------------------------------------------------------------ | |
| # Initialize LLM | |
| # ------------------------------------------------------------------------------ | |
| google_api_key = "AIzaSyDJV8NtUcfp4YhuqehdcXQ8JgVRtYI8Kf4" # Replace with your actual Google API key | |
| llm = ChatGoogleGenerativeAI(model="gemini-2.0-flash", google_api_key=google_api_key) | |
| # ------------------------------------------------------------------------------ | |
| # Define Travel Agents | |
| # ------------------------------------------------------------------------------ | |
| # 1. Destination Research Agent | |
| destination_research_agent = Agent( | |
| role="Destination Research Agent", | |
| goal=( | |
| "Research and provide comprehensive information about the destination including popular attractions, " | |
| "local culture, weather patterns, best times to visit, and local transportation options." | |
| ), | |
| backstory=( | |
| "An experienced travel researcher with extensive knowledge of global destinations. " | |
| "I specialize in uncovering both popular attractions and hidden gems that match travelers' interests." | |
| ), | |
| personality="Curious, detail-oriented, and knowledgeable about global cultures and travel trends.", | |
| llm=llm, | |
| ) | |
| # 2. Accommodation Agent | |
| accommodation_agent = Agent( | |
| role="Accommodation Agent", | |
| goal="Find and recommend suitable accommodations based on the traveler's preferences, budget, and location requirements.", | |
| backstory="A hospitality expert who understands different types of accommodations and can match travelers with their ideal places to stay.", | |
| personality="Attentive, resourceful, and focused on comfort and value.", | |
| llm=llm, | |
| ) | |
| # 3. Transportation Agent | |
| transportation_agent = Agent( | |
| role="Transportation Agent", | |
| goal="Plan efficient transportation between the origin, destination, and all points of interest in the itinerary.", | |
| backstory="A logistics specialist with knowledge of global transportation systems, from flights to local transit options.", | |
| personality="Efficient, practical, and detail-oriented.", | |
| llm=llm, | |
| ) | |
| # 4. Activities & Attractions Agent | |
| activities_agent = Agent( | |
| role="Activities & Attractions Agent", | |
| goal="Curate personalized activities and attractions that align with the traveler's interests, preferences, and time constraints.", | |
| backstory="An enthusiastic explorer who has experienced diverse activities around the world and knows how to match experiences to individual preferences.", | |
| personality="Enthusiastic, creative, and personable.", | |
| llm=llm, | |
| ) | |
| # 5. Dining & Culinary Agent | |
| dining_agent = Agent( | |
| role="Dining & Culinary Agent", | |
| goal="Recommend dining experiences that showcase local cuisine while accommodating dietary preferences and budget considerations.", | |
| backstory="A culinary expert with knowledge of global food scenes and an appreciation for authentic local dining experiences.", | |
| personality="Passionate about food, culturally aware, and attentive to preferences.", | |
| llm=llm, | |
| ) | |
| # 6. Itinerary Integration Agent | |
| itinerary_agent = Agent( | |
| role="Itinerary Integration Agent", | |
| goal="Compile all recommendations into a cohesive, day-by-day itinerary that optimizes time, minimizes travel fatigue, and maximizes enjoyment.", | |
| backstory="A master travel planner who understands how to balance activities, rest, and logistics to create the perfect travel experience.", | |
| personality="Organized, balanced, and practical.", | |
| llm=llm, | |
| ) | |
| # 7. Final Report Generation Agent | |
| final_report_agent = Agent( | |
| role="Final Report Generation Agent", | |
| goal="Generate a comprehensive, visually appealing travel itinerary document that is easy to follow and includes all necessary details." | |
| "1. Compile outputs from all agents into a cohesive travel plan. " | |
| "2. Create clearly defined, organized daily schedules with times, locations, and activity durations. " | |
| "3. Include practical information such as estimated costs, contact details, and reservation information. " | |
| "4. Implement a clean, travel-themed design with proper spacing, alignment, and highlights. " | |
| "5. Output the final itinerary as valid HTML with inline CSS for styling.", | |
| backstory="A creative travel document specialist who transforms complex travel plans into beautiful, functional itineraries that enhance the travel experience.", | |
| personality="Creative, detail-oriented, and user-focused.", | |
| llm=llm, | |
| ) | |
| # ------------------------------------------------------------------------------ | |
| # Define Tasks | |
| # ------------------------------------------------------------------------------ | |
| destination_research_task = Task( | |
| description="""Research {destination} thoroughly, considering the traveler's interests in {preferences}. | |
| Efficient research parameters: | |
| - Prioritize research in these critical categories: | |
| * Top attractions that match specific {preferences} (not generic lists) | |
| * Local transportation systems with cost-efficiency analysis | |
| * Neighborhood breakdown with accommodation recommendations by budget tier | |
| * Seasonal considerations for the specific travel dates | |
| * Safety assessment with specific areas to embrace or avoid | |
| * Cultural norms that impact visitor experience (dress codes, tipping, etiquette) | |
| - Apply efficiency filters: | |
| * Focus exclusively on verified information from official tourism boards, recent travel guides, and reliable local sources | |
| * Analyze recent visitor reviews (< 6 months old) to identify changing conditions | |
| * Evaluate price-to-experience value for attractions instead of just popularity | |
| * Identify logistical clusters where multiple interests can be satisfied efficiently | |
| * Research off-peak times for popular attractions to minimize waiting | |
| * Evaluate digital tools (apps, passes, reservation systems) that streamline the visit | |
| - Create practical knowledge matrices: | |
| * Transportation method comparison (cost vs. time vs. convenience) | |
| * Weather impact on specific activities | |
| * Budget allocation recommendations based on preference priorities | |
| * Time-saving opportunity identification""", | |
| agent=destination_research_agent, | |
| expected_output="""Targeted destination brief containing: | |
| 1. Executive summary highlighting the 5 most relevant aspects based on {preferences} | |
| 2. Neighborhood analysis with accommodation recommendations mapped to specific interests | |
| 3. Transportation efficiency guide with cost/convenience matrix | |
| 4. Cultural briefing focusing only on need-to-know information that impacts daily activities | |
| 5. Seasonal advantages and challenges specific to travel dates | |
| 6. Digital resource toolkit (essential apps, websites, reservation systems) | |
| 7. Budget optimization strategies with price ranges for key experiences | |
| 8. Safety and health quick-reference including emergency contacts | |
| 9. Logistics efficiency map showing optimal activity clustering | |
| 10. Local insider advantage recommendations that save time or money | |
| Format should prioritize scannable information with bullet points, comparison tables, and decision matrices rather than lengthy prose.""" | |
| ) | |
| accommodation_task = Task( | |
| description="Find suitable accommodations in {destination} based on a {budget} budget and preferences for {preferences}.", | |
| agent=accommodation_agent, | |
| expected_output="List of recommended accommodations with details on location, amenities, price range, and availability." | |
| ) | |
| transportation_task = Task( | |
| description="Plan transportation from {origin} to {destination} and local transportation options during the stay.", | |
| agent=transportation_agent, | |
| expected_output="Transportation plan including flights/routes to the destination and recommendations for getting around locally." | |
| ) | |
| activities_task = Task( | |
| description="""Suggest activities and attractions in {destination} that align with interests in {preferences}. | |
| Detailed requirements: | |
| - Categorize activities into: Cultural Experiences, Outdoor Adventures, Culinary Experiences, | |
| Entertainment & Nightlife, Family-Friendly Activities, and Local Hidden Gems | |
| - For each activity, include: | |
| * Detailed description with historical/cultural context where relevant | |
| * Precise location with neighborhood information | |
| * Operating hours with seasonal variations noted | |
| * Pricing information with different ticket options/packages | |
| * Accessibility considerations for travelers with mobility limitations | |
| * Recommended duration for the activity (minimum and ideal time) | |
| * Best time of day/week/year to visit | |
| * Crowd levels by season | |
| * Photography opportunities and restrictions | |
| * Required reservations or booking windows | |
| - Include a mix of iconic must-see attractions and off-the-beaten-path experiences | |
| - Consider weather patterns in {destination} during travel period | |
| - Analyze the {preferences} to match specific personality types and interest levels | |
| - Include at least 2-3 rainy day alternatives for outdoor activities | |
| - Provide local transportation options to reach each attraction | |
| - Note authentic local experiences that provide cultural immersion | |
| - Flag any activities requiring special equipment, permits, or physical fitness levels""", | |
| agent=activities_agent, | |
| expected_output="""Comprehensive curated list of activities and attractions with: | |
| 1. Clear categorization by type (cultural, outdoor, culinary, entertainment, family-friendly, hidden gems) | |
| 2. Detailed descriptions that include historical and cultural context | |
| 3. Complete practical information (hours, pricing, location, accessibility) | |
| 4. Time optimization recommendations (best time to visit, how to avoid crowds) | |
| 5. Personalized matches explaining why each activity aligns with specific {preferences} | |
| 6. Local transportation details to reach each attraction | |
| 7. Alternative options for inclement weather or unexpected closures | |
| 8. Insider tips from locals that enhance the experience | |
| 9. Suggested combinations of nearby activities for efficient itinerary planning | |
| 10. Risk level assessment and safety considerations where applicable | |
| 11. Sustainability impact and responsible tourism notes | |
| 12. Photographic highlights and optimal viewing points | |
| Format should include a summary table for quick reference followed by detailed cards for each activity.""" | |
| ) | |
| dining_task = Task( | |
| description="Recommend dining experiences in {destination} that showcase local cuisine while considering {preferences}.", | |
| agent=dining_agent, | |
| expected_output="List of recommended restaurants and food experiences with cuisine types, price ranges, and special notes." | |
| ) | |
| itinerary_task = Task( | |
| description="""Create a day-by-day itinerary for a {duration} trip to {destination} from {origin}, incorporating all recommendations. | |
| Detailed requirements: | |
| - Begin with arrival logistics including airport transfer options, check-in times, and first-day orientation activities | |
| - Structure each day with: | |
| * Morning, afternoon, and evening activity blocks with precise timing | |
| * Estimated travel times between locations using various transportation methods | |
| * Buffer time for rest, spontaneous exploration, and unexpected delays | |
| * Meal recommendations with reservation details and backup options | |
| * Sunset/sunrise opportunities for optimal photography or experiences | |
| - Apply intelligent sequencing to: | |
| * Group attractions by geographic proximity to minimize transit time | |
| * Schedule indoor activities strategically for predicted weather patterns | |
| * Balance high-energy activities with relaxation periods | |
| * Alternate between cultural immersion and entertainment experiences | |
| * Account for opening days/hours of attractions and potential closures | |
| - Include practical timing considerations: | |
| * Museum/attraction fatigue limitations | |
| * Jet lag recovery for first 1-2 days | |
| * Time zone adjustment strategies | |
| * Local rush hours and traffic patterns to avoid | |
| * Cultural norms for meal times and business hours | |
| - End with departure logistics including check-out procedures, airport transfer timing, and luggage considerations | |
| - Add specialized planning elements: | |
| * Local festivals or events coinciding with the travel dates | |
| * Free time blocks for personal exploration or shopping | |
| * Contingency recommendations for weather disruptions | |
| * Early booking requirements for popular attractions/restaurants | |
| * Local emergency contacts and nearby medical facilities""", | |
| agent=itinerary_agent, | |
| expected_output="""Comprehensive day-by-day itinerary featuring: | |
| 1. Detailed timeline for each day with hour-by-hour scheduling and transit times | |
| 2. Color-coded activity blocks that visually distinguish between types of activities | |
| 3. Intelligent geographic clustering to minimize transportation time | |
| 4. Strategic meal placements with both reservation-required and casual options | |
| 5. Built-in flexibility with free time blocks and alternative suggestions | |
| 6. Weather-adaptive scheduling with indoor/outdoor activity balance | |
| 7. Energy level considerations throughout the trip arc | |
| 8. Cultural timing adaptations (accommodating local siesta times, religious observances, etc.) | |
| 9. Practical logistical details (bag storage options, dress code reminders, etc.) | |
| 10. Local transportation guidance including transit cards, apps, and pre-booking requirements | |
| 11. Visual map representation showing daily movement patterns | |
| 12. Key phrases in local language for each day's activities | |
| Format should include both a condensed overview calendar and detailed daily breakdowns with time, activity, location, notes, and contingency plans.""" | |
| ) | |
| final_report_task = Task( | |
| description="""Generate a comprehensive, visually appealing travel itinerary document for a {duration} trip to {destination} from {origin}. | |
| Technical requirements: | |
| - Implement using Tailwind CSS for responsive styling and utility classes | |
| - Enhance with Alpine.js for lightweight interactive components | |
| - Include Mapbox GL JS integration for interactive maps with points of interest | |
| - Use Chart.js for visualizing trip budget breakdowns | |
| - Implement with DaisyUI or Flowbite components for consistent UI elements | |
| - Ensure cross-browser compatibility and mobile-first responsive design | |
| - Meet WCAG 2.1 AA accessibility standards | |
| UI/UX features: | |
| - Create collapsible day-by-day itinerary sections | |
| - Include interactive map with customized markers for attractions, hotels, and restaurants | |
| - Implement dark/light mode toggle with user preference storage | |
| - Add weather forecast integration via OpenWeatherMap API | |
| - Design printable version with QR codes for digital access | |
| - Include local emergency information in an accessible sidebar | |
| - Create animated transitions between sections for improved user experience | |
| - Implement offline capabilities with service workers""", | |
| agent=final_report_agent, | |
| expected_output="""Complete HTML travel itinerary featuring: | |
| 1. Responsive layout using Tailwind CSS that adapts to all device sizes | |
| 2. Interactive components powered by Alpine.js for seamless user interactions | |
| 3. Dynamic map visualization with Mapbox GL JS showing the complete travel route | |
| 4. Collapsible sections for daily activities with smooth animations | |
| 5. Dark/light mode toggle that persists user preferences | |
| 6. Weather forecast widgets integrated with OpenWeatherMap | |
| 7. Printable version with optimized styling for physical documents | |
| 8. Trip budget visualization with interactive charts | |
| 9. Offline-capable implementation with service worker caching | |
| 10. Accessibility-compliant design including keyboard navigation and screen reader support | |
| 11. Performance optimization with lazy-loading images and content | |
| 12. Custom PDF export functionality | |
| All code should be clean, well-commented, and follow modern web development best practices.""" | |
| ) | |
| # ------------------------------------------------------------------------------ | |
| # Helper Function to Run a Task with Full Agent & Task Information | |
| # ------------------------------------------------------------------------------ | |
| def run_task(task, input_text): | |
| try: | |
| # Ensure 'task' is an instance of the Task class | |
| if not isinstance(task, Task): | |
| raise ValueError(f"Expected 'task' to be an instance of Task class, but got {type(task)}") | |
| # Ensure 'task.agent' exists and is an instance of Agent | |
| if not hasattr(task, 'agent') or not isinstance(task.agent, Agent): | |
| raise ValueError(f"Task must contain a valid 'agent' attribute that is an instance of Agent class.") | |
| system_input = f"""Agent Details: | |
| Role: {task.agent.role} | |
| Goal: {task.agent.goal} | |
| Backstory: {task.agent.backstory} | |
| Personality: {task.agent.personality} | |
| """ | |
| task_input = f"""Task Details: | |
| Task Description: {task.description} | |
| Expected Output: {task.expected_output} | |
| Input for Task: | |
| {input_text} | |
| """ | |
| messages = [ | |
| SystemMessage(content=system_input), | |
| HumanMessage(content=task_input) | |
| ] | |
| response = task.agent.llm.invoke(messages) | |
| if not response or not response.content: | |
| raise ValueError("Empty response from LLM.") | |
| return response.content | |
| except Exception as e: | |
| print(f"Error in task '{task.agent.role}': {e}") | |
| return f"Error in {task.agent.role}: {e}" | |
| # ------------------------------------------------------------------------------ | |
| # User Input Functions | |
| # ------------------------------------------------------------------------------ | |
| def get_user_input(): | |
| print("\n=== Travel Itinerary Generator ===\n") | |
| origin = input("Enter your origin city/country: ") | |
| destination = input("Enter your destination city/country: ") | |
| duration = input("Enter trip duration (number of days): ") | |
| budget = input("Enter your budget level (budget, moderate, luxury): ") | |
| print("\nEnter your travel preferences and interests (comma-separated):") | |
| print("Examples: museums, hiking, food, shopping, beaches, history, nightlife, family-friendly, etc.") | |
| preferences = input("> ") | |
| special_requirements = input("\nAny special requirements or notes (dietary restrictions, accessibility needs, etc.)? ") | |
| return { | |
| "origin": origin, | |
| "destination": destination, | |
| "duration": duration, | |
| "budget": budget, | |
| "preferences": preferences, | |
| "special_requirements": special_requirements | |
| } | |
| # ------------------------------------------------------------------------------ | |
| # Main Function to Generate Travel Itinerary | |
| # ------------------------------------------------------------------------------ | |
| def generate_travel_itinerary(user_input): | |
| print("\nGenerating your personalized travel itinerary...\n") | |
| # Format the user input for tasks | |
| input_context = f"""Travel Request Details: | |
| Origin: {user_input['origin']} | |
| Destination: {user_input['destination']} | |
| Duration: {user_input['duration']} days | |
| Budget Level: {user_input['budget']} | |
| Preferences/Interests: {user_input['preferences']} | |
| Special Requirements: {user_input['special_requirements']} | |
| """ | |
| # Step 1: Destination Research | |
| print("Researching your destination...") | |
| destination_info = run_task( | |
| destination_research_task, | |
| input_context.format( | |
| destination=user_input['destination'], | |
| preferences=user_input['preferences'] | |
| ) | |
| ) | |
| print("✓ Destination research completed") | |
| # Step 2: Accommodation Recommendations | |
| print("Finding ideal accommodations...") | |
| accommodation_info = run_task( | |
| accommodation_task, | |
| input_context.format( | |
| destination=user_input['destination'], | |
| budget=user_input['budget'], | |
| preferences=user_input['preferences'] | |
| ) | |
| ) | |
| print("✓ Accommodation recommendations completed") | |
| # Step 3: Transportation Planning | |
| print("Planning transportation...") | |
| transportation_info = run_task( | |
| transportation_task, | |
| input_context.format( | |
| origin=user_input['origin'], | |
| destination=user_input['destination'] | |
| ) | |
| ) | |
| print("✓ Transportation planning completed") | |
| # Step 4: Activities & Attractions | |
| print("Curating activities and attractions...") | |
| activities_info = run_task( | |
| activities_task, | |
| input_context.format( | |
| destination=user_input['destination'], | |
| preferences=user_input['preferences'] | |
| ) | |
| ) | |
| print("✓ Activities and attractions curated") | |
| # Step 5: Dining Recommendations | |
| print("Finding dining experiences...") | |
| dining_info = run_task( | |
| dining_task, | |
| input_context.format( | |
| destination=user_input['destination'], | |
| preferences=user_input['preferences'] | |
| ) | |
| ) | |
| print("✓ Dining recommendations completed") | |
| # Step 6: Create Day-by-Day Itinerary | |
| print("Creating your day-by-day itinerary...") | |
| combined_info = f"""{input_context} | |
| Destination Information: | |
| {destination_info} | |
| Accommodation Options: | |
| {accommodation_info} | |
| Transportation Plan: | |
| {transportation_info} | |
| Recommended Activities: | |
| {activities_info} | |
| Dining Recommendations: | |
| {dining_info} | |
| """ | |
| itinerary = run_task( | |
| itinerary_task, | |
| combined_info.format( | |
| duration=user_input['duration'], | |
| origin=user_input['origin'], | |
| destination=user_input['destination'] | |
| ) | |
| ) | |
| print("✓ Itinerary creation completed") | |
| # Step 7: Generate Final Report | |
| print("Generating your final travel itinerary document...") | |
| final_context = f"""{combined_info} | |
| Day-by-Day Itinerary: | |
| {itinerary} | |
| """ | |
| final_itinerary = run_task( | |
| final_report_task, | |
| final_context.format( | |
| duration=user_input['duration'], | |
| origin=user_input['origin'], | |
| destination=user_input['destination'] | |
| ) | |
| ) | |
| print("✓ Final itinerary document generated") | |
| return final_itinerary | |
| # ------------------------------------------------------------------------------ | |
| # Save Itinerary to File | |
| # ------------------------------------------------------------------------------ | |
| def save_itinerary_to_file(itinerary, user_input, output_dir=None): | |
| # Create a filename based on the destination and date | |
| date_str = datetime.now().strftime("%Y-%m-%d") | |
| filename = f"{user_input['destination'].replace(' ', '_')}_{date_str}_itinerary.html" | |
| # If output directory is specified, ensure it exists and use it | |
| if output_dir: | |
| if not os.path.exists(output_dir): | |
| try: | |
| os.makedirs(output_dir) | |
| print(f"Created output directory: {output_dir}") | |
| except Exception as e: | |
| print(f"Error creating directory {output_dir}: {e}") | |
| return None | |
| # Combine the output directory with the filename | |
| filepath = os.path.join(output_dir, filename) | |
| else: | |
| filepath = filename | |
| try: | |
| with open(filepath, "w", encoding="utf-8") as f: | |
| f.write(itinerary) | |
| print(f"\nYour itinerary has been saved as: {filepath}") | |
| return filepath | |
| except Exception as e: | |
| print(f"Error saving itinerary: {e}") | |
| return None | |
| # ------------------------------------------------------------------------------ | |
| # Main Function | |
| # ------------------------------------------------------------------------------ | |
| def main(): | |
| print("Welcome to BlockX Travel Itinerary Generator!") | |
| print("This AI-powered tool will create a personalized travel itinerary based on your preferences.") | |
| user_input = get_user_input() | |
| # Ask for output directory | |
| print("\nWhere would you like to save the itinerary?") | |
| print("Press Enter to save in the current directory, or specify a path:") | |
| output_dir = input("> ").strip() | |
| # If empty, use current directory | |
| if not output_dir: | |
| output_dir = None | |
| print("Will save in the current directory.") | |
| itinerary = generate_travel_itinerary(user_input) | |
| filename = save_itinerary_to_file(itinerary, user_input, output_dir) | |
| if filename: | |
| print(f"\nYour personalized travel itinerary is ready! Open {filename} to view it.") | |
| print("Thank you for using BlockX Travel Itinerary Generator!") | |
| if __name__ == "__main__": | |
| main() | |