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() | |