import streamlit as st import pandas as pd from typing import Union, List, Dict, Optional from groq import Groq import os from duckduckgo_search import DDGS import json from datetime import datetime, timedelta import time # Set page configuration with fullscreen layout and custom theme st.set_page_config( page_title="SmolAgent Travel Planner", layout="wide", initial_sidebar_state="collapsed", page_icon="βοΈ" ) # Enhanced CSS for a beautiful travel-themed styling st.markdown(""" """, unsafe_allow_html=True) class SmolAgent: """ Base agent class implementing the smol agent architecture. Each agent has a specific role and can collaborate with others. """ def __init__(self, name: str, role: str, llm_client, search_tool): self.name = name self.role = role self.llm = llm_client self.search = search_tool self.status = "idle" self.last_result = None def set_status(self, status: str, message: str = ""): self.status = status self.status_message = message def execute_task(self, task_prompt: str, search_query: str = None) -> str: """Execute a task with optional web search""" try: self.set_status("working", f"Processing {self.role.lower()} task...") # Perform search if needed search_results = "" if search_query: self.set_status("working", "Searching for relevant information...") search_results = self.search(search_query) # Create enhanced prompt with search results enhanced_prompt = f""" Role: {self.role} Task: {task_prompt} {f"Search Results: {search_results}" if search_results else ""} Please provide a detailed response based on your role as {self.role}. """ # Get response from LLM self.set_status("working", "Generating response...") result = self.llm(enhanced_prompt) self.last_result = result self.set_status("complete", "Task completed successfully") return result except Exception as e: self.set_status("error", f"Error: {str(e)}") return f"Error in {self.name}: {str(e)}" class TravelSearchTool: """Enhanced search tool specifically designed for travel planning""" def __init__(self): self.ddgs = DDGS() def __call__(self, query: str, search_type: str = "general", max_results: int = 5) -> str: try: # Customize search based on type if search_type == "flights": query = f"best flight deals {query} 2024 booking sites" elif search_type == "hotels": query = f"best hotels accommodation {query} reviews booking" elif search_type == "activities": query = f"top attractions activities things to do {query} tourist guide" elif search_type == "restaurants": query = f"best restaurants food dining {query} local cuisine" elif search_type == "weather": query = f"weather forecast climate {query} best time to visit" # Perform search search_results = list(self.ddgs.text( query, max_results=max_results, region='wt-wt', safesearch='on' )) if not search_results: return "No relevant information found. Please try a different search." # Format results formatted_results = [] for idx, result in enumerate(search_results, 1): title = result.get('title', 'No title') snippet = result.get('body', 'No description') url = result.get('href', 'No URL') formatted_results.append( f"{idx}. {title}\n" f" Description: {snippet}\n" f" Source: {url}\n" ) return "\n".join(formatted_results) except Exception as e: return f"Search error: {str(e)}" class GroqLLM: """Enhanced LLM client with travel-specific optimizations""" def __init__(self, model_name="llama-3.1-70b-versatile"): self.client = Groq(api_key=os.environ.get("GROQ_API_KEY")) self.model_name = model_name def __call__(self, prompt: Union[str, dict, List[Dict]]) -> str: try: completion = self.client.chat.completions.create( model=self.model_name, messages=[{ "role": "user", "content": str(prompt) }], temperature=0.7, max_tokens=2048, stream=False ) return completion.choices[0].message.content if completion.choices else "No response generated" except Exception as e: return f"LLM Error: {str(e)}" class TravelPlannerSystem: """Main orchestrator for the travel planning system""" def __init__(self): self.llm = GroqLLM() self.search_tool = TravelSearchTool() self.agents = self._initialize_agents() def _initialize_agents(self) -> Dict[str, SmolAgent]: """Initialize specialized travel agents""" return { "destination_expert": SmolAgent( "Destination Expert", "Travel destination researcher and recommender", self.llm, self.search_tool ), "itinerary_planner": SmolAgent( "Itinerary Planner", "Trip itinerary creator and scheduler", self.llm, self.search_tool ), "accommodation_specialist": SmolAgent( "Accommodation Specialist", "Hotel and lodging finder and recommender", self.llm, self.search_tool ), "activity_curator": SmolAgent( "Activity Curator", "Tourist attraction and activity recommender", self.llm, self.search_tool ), "budget_advisor": SmolAgent( "Budget Advisor", "Travel cost estimator and budget optimizer", self.llm, self.search_tool ) } def create_travel_plan(self, destination: str, duration: str, budget: str, travel_style: str, interests: str) -> Dict[str, str]: """Create a comprehensive travel plan using multiple agents""" # Prepare base context for all agents base_context = f""" Destination: {destination} Duration: {duration} Budget: {budget} Travel Style: {travel_style} Interests: {interests} """ results = {} # Agent 1: Destination Research dest_task = f""" Research {destination} as a travel destination. Include: - Best time to visit and current weather - Cultural highlights and local customs - Transportation options - Safety and travel requirements - Local currency and tipping customs Context: {base_context} """ results["destination_info"] = self.agents["destination_expert"].execute_task( dest_task, f"{destination} travel guide weather best time visit" ) # Agent 2: Accommodation Research accommodation_task = f""" Find accommodation options for {destination}. Consider: - Hotels, hostels, and alternative lodging based on budget: {budget} - Location preferences for {travel_style} travelers - Amenities and reviews - Booking tips and best deals Context: {base_context} """ results["accommodation"] = self.agents["accommodation_specialist"].execute_task( accommodation_task, f"{destination} hotels accommodation {budget} {travel_style}" ) # Agent 3: Activities and Attractions activity_task = f""" Curate activities and attractions for {destination} based on interests: {interests} Include: - Must-see attractions and hidden gems - Activities matching {travel_style} style - Local experiences and cultural activities - Restaurant and dining recommendations Context: {base_context} """ results["activities"] = self.agents["activity_curator"].execute_task( activity_task, f"{destination} attractions activities {interests} restaurants" ) # Agent 4: Itinerary Planning itinerary_task = f""" Create a detailed {duration} itinerary for {destination}. Include: - Day-by-day schedule optimized for {travel_style} travelers - Time management and logistics - Mix of planned activities and free time - Transportation between locations Use information about accommodations and activities to create a cohesive plan. Context: {base_context} """ results["itinerary"] = self.agents["itinerary_planner"].execute_task( itinerary_task, f"{destination} {duration} itinerary travel schedule" ) # Agent 5: Budget Planning budget_task = f""" Create a detailed budget breakdown for the {destination} trip: - Accommodation costs based on research - Transportation (flights, local transport) - Food and dining expenses - Activities and attraction fees - Miscellaneous expenses and emergency fund - Money-saving tips and deals Context: {base_context} """ results["budget_breakdown"] = self.agents["budget_advisor"].execute_task( budget_task, f"{destination} travel costs budget {duration} {budget}" ) return results def display_agent_status(agents: Dict[str, SmolAgent]): """Display the status of all agents""" st.markdown("### π€ Agent Status Dashboard") cols = st.columns(len(agents)) for idx, (name, agent) in enumerate(agents.items()): with cols[idx]: status_class = f"status-{agent.status}" if hasattr(agent, 'status') else "status-idle" status_message = getattr(agent, 'status_message', 'Ready') if agent.status == "working": icon = '
' elif agent.status == "complete": icon = 'β ' elif agent.status == "error": icon = 'β' else: icon = 'βΈοΈ' st.markdown(f"""AI-powered travel planning with specialized agents working together to create your perfect trip
SmolAgent Travel Planner v2.0 | Powered by AI Collaboration