Spaces:
Running
Running
File size: 22,395 Bytes
fb4338a e5027a8 fb4338a e5027a8 fb4338a e5027a8 fb4338a e5027a8 fb4338a e5027a8 fb4338a e5027a8 fb4338a e5027a8 fb4338a e5027a8 fb4338a e5027a8 fb4338a e5027a8 b0a15f7 e5027a8 fb4338a e5027a8 fb4338a e5027a8 fb4338a e5027a8 fb4338a e5027a8 fb4338a e5027a8 fb4338a e5027a8 fb4338a e5027a8 fb4338a e5027a8 fb4338a e5027a8 fb4338a e5027a8 fb4338a e5027a8 fb4338a e5027a8 fb4338a e5027a8 fb4338a e5027a8 fb4338a e5027a8 fb4338a e5027a8 fb4338a e5027a8 fb4338a e5027a8 fb4338a e5027a8 fb4338a e5027a8 fb4338a e5027a8 fb4338a e5027a8 fb4338a e5027a8 fb4338a 9925925 fb4338a 9925925 fb4338a e5027a8 fb4338a e5027a8 fb4338a 9925925 fb4338a e5027a8 fb4338a e5027a8 fb4338a e5027a8 fb4338a e5027a8 fb4338a e5027a8 fb4338a e5027a8 fb4338a e5027a8 fb4338a e5027a8 fb4338a e5027a8 fb4338a |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 |
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()
|