AgentX-Travel / travel.py
openfree's picture
Update travel.py
b0a15f7 verified
import os
import json
import logging
from datetime import datetime, timedelta
from langchain_google_genai import ChatGoogleGenerativeAI
from langchain.schema import SystemMessage, HumanMessage
# Setup logging configuration
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")
# -------------------------------------------------------------------------------
# Agent and Task Classes with Type Hints and Docstrings
# -------------------------------------------------------------------------------
class Agent:
def __init__(self, role: str, goal: str, backstory: str, personality: str = "", llm=None) -> None:
"""
Initialize an Agent with role, goal, backstory, personality, and assigned LLM.
"""
self.role = role
self.goal = goal
self.backstory = backstory
self.personality = personality
self.tools = [] # Initialize with empty list for future tool integrations
self.llm = llm
class Task:
def __init__(self, description: str, agent: Agent, expected_output: str, context=None) -> None:
"""
Initialize a Task with its description, the responsible agent, expected output, and optional context.
"""
self.description = description
self.agent = agent
self.expected_output = expected_output
self.context = context or []
# -------------------------------------------------------------------------------
# Initialize LLM
# -------------------------------------------------------------------------------
google_api_key = os.getenv("GEMINI_API_KEY") # μ‹€μ œ Google API ν‚€ μ‚¬μš©
if not google_api_key:
logging.error("GEMINI_API_KEY is not set in the environment variables.")
llm = ChatGoogleGenerativeAI(model="gemini-2.0-flash", google_api_key=google_api_key)
# -------------------------------------------------------------------------------
# Define Travel Agents
# -------------------------------------------------------------------------------
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,
)
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,
)
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,
)
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,
)
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,
)
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,
)
# -------------------------------------------------------------------------------
# Define Chatbot Agent and Task for Interactive Conversation
# -------------------------------------------------------------------------------
chatbot_agent = Agent(
role="Chatbot Agent",
goal="Engage in interactive conversation to answer travel-related queries.",
backstory="A conversational AI assistant who provides instant, accurate travel information and recommendations.",
personality="Friendly, conversational, and knowledgeable about travel.",
llm=llm,
)
chatbot_task = Task(
description="Provide a conversational and detailed response to travel-related queries.",
agent=chatbot_agent,
expected_output="A friendly, helpful response to the user's query."
)
# -------------------------------------------------------------------------------
# Define Other Travel 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."""
)
# -------------------------------------------------------------------------------
# Helper Function to Run a Task with Full Agent & Task Information
# -------------------------------------------------------------------------------
def run_task(task: Task, input_text: str) -> str:
"""
Executes the given task using the associated agent's LLM and returns the response content.
"""
try:
if not isinstance(task, Task):
raise ValueError(f"Expected 'task' to be an instance of Task, got {type(task)}")
if not hasattr(task, 'agent') or not isinstance(task.agent, Agent):
raise ValueError("Task must have a valid 'agent' attribute of type Agent.")
system_input = (
f"Agent Details:\n"
f"Role: {task.agent.role}\n"
f"Goal: {task.agent.goal}\n"
f"Backstory: {task.agent.backstory}\n"
f"Personality: {task.agent.personality}\n"
)
task_input = (
f"Task Details:\n"
f"Task Description: {task.description}\n"
f"Expected Output: {task.expected_output}\n"
f"Input for Task:\n{input_text}\n"
)
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:
logging.error(f"Error in task '{task.agent.role}': {e}")
return f"Error in {task.agent.role}: {e}"
# -------------------------------------------------------------------------------
# User Input Functions
# -------------------------------------------------------------------------------
def get_user_input() -> dict:
"""
Collects user input for travel itinerary generation.
"""
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: dict) -> str:
"""
Generates a personalized travel itinerary by sequentially running defined tasks.
"""
print("\nGenerating your personalized travel itinerary...\n")
# Create input context using f-string formatting
input_context = (
f"Travel Request Details:\n"
f"Origin: {user_input['origin']}\n"
f"Destination: {user_input['destination']}\n"
f"Duration: {user_input['duration']} days\n"
f"Budget Level: {user_input['budget']}\n"
f"Preferences/Interests: {user_input['preferences']}\n"
f"Special Requirements: {user_input['special_requirements']}\n"
)
# Step 1: Destination Research
print("Researching your destination...")
destination_info = run_task(destination_research_task, input_context)
print("βœ“ Destination research completed")
# Step 2: Accommodation Recommendations
print("Finding ideal accommodations...")
accommodation_info = run_task(accommodation_task, input_context)
print("βœ“ Accommodation recommendations completed")
# Step 3: Transportation Planning
print("Planning transportation...")
transportation_info = run_task(transportation_task, input_context)
print("βœ“ Transportation planning completed")
# Step 4: Activities & Attractions
print("Curating activities and attractions...")
activities_info = run_task(activities_task, input_context)
print("βœ“ Activities and attractions curated")
# Step 5: Dining Recommendations
print("Finding dining experiences...")
dining_info = run_task(dining_task, input_context)
print("βœ“ Dining recommendations completed")
# Step 6: Create Day-by-Day Itinerary
print("Creating your day-by-day itinerary...")
combined_info = (
input_context + "\n"
"Destination Information:\n" + destination_info + "\n"
"Accommodation Options:\n" + accommodation_info + "\n"
"Transportation Plan:\n" + transportation_info + "\n"
"Recommended Activities:\n" + activities_info + "\n"
"Dining Recommendations:\n" + dining_info + "\n"
)
itinerary = run_task(itinerary_task, combined_info)
print("βœ“ Itinerary creation completed")
print("βœ“ Itinerary generation completed")
return itinerary
# -------------------------------------------------------------------------------
# Save Itinerary to File
# -------------------------------------------------------------------------------
def save_itinerary_to_file(itinerary: str, user_input: dict, output_dir: str = None) -> str:
"""
Saves the generated itinerary to a text file and returns the filepath.
"""
date_str = datetime.now().strftime("%Y-%m-%d")
filename = f"{user_input['destination'].replace(' ', '_')}_{date_str}_itinerary.txt"
if output_dir:
if not os.path.exists(output_dir):
try:
os.makedirs(output_dir)
logging.info(f"Created output directory: {output_dir}")
except Exception as e:
logging.error(f"Error creating directory {output_dir}: {e}")
return ""
filepath = os.path.join(output_dir, filename)
else:
filepath = filename
try:
with open(filepath, "w", encoding="utf-8") as f:
f.write(itinerary)
logging.info(f"Your itinerary has been saved as: {filepath}")
return filepath
except Exception as e:
logging.error(f"Error saving itinerary: {e}")
return ""
# -------------------------------------------------------------------------------
# Main Function
# -------------------------------------------------------------------------------
def main() -> None:
"""
Main entry point for the travel itinerary generator application.
"""
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()
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() or None
itinerary = generate_travel_itinerary(user_input)
filepath = save_itinerary_to_file(itinerary, user_input, output_dir)
if filepath:
print(f"\nYour personalized travel itinerary is ready! Open {filepath} to view it.")
print("Thank you for using BlockX Travel Itinerary Generator!")
if __name__ == "__main__":
main()