import streamlit as st from datetime import datetime, timedelta import base64 import pandas as pd import pydeck as pdk from travel import ( destination_research_task, accommodation_task, transportation_task, activities_task, dining_task, itinerary_task, chatbot_task, run_task ) from geopy.geocoders import Nominatim from io import BytesIO st.set_page_config( page_title="Your AI Agent for Travelling", page_icon="✈️", layout="wide", initial_sidebar_state="expanded" ) # ------------------------------------------------------ # CSS Styles for the App # ------------------------------------------------------ st.markdown(""" """, unsafe_allow_html=True) # ------------------------------------------------------ # Helper Functions # ------------------------------------------------------ def get_download_link(text_content, filename): """Generate a download link for the itinerary text file.""" b64 = base64.b64encode(text_content.encode()).decode() href = f'πŸ“₯ Save Your Itinerary' return href def display_modern_progress(current_step, total_steps=6): """Displays a progress bar and step indicators.""" if 'progress_steps' not in st.session_state: st.session_state.progress_steps = { 0: {'status': 'pending', 'name': "Trip Details"}, 1: {'status': 'pending', 'name': "About"}, 2: {'status': 'pending', 'name': "Travel Style"}, 3: {'status': 'pending', 'name': "Live Agent Outputs"}, 4: {'status': 'pending', 'name': "Download & Share"}, 5: {'status': 'pending', 'name': "Full Itinerary"} } for i in range(total_steps): if i < current_step: st.session_state.progress_steps[i]['status'] = 'complete' elif i == current_step: st.session_state.progress_steps[i]['status'] = 'active' else: st.session_state.progress_steps[i]['status'] = 'pending' progress_percentage = (current_step / total_steps) * 100 st.progress(progress_percentage / 100) # Display step grid st.markdown("""
""", unsafe_allow_html=True) for i, step_info in st.session_state.progress_steps.items(): status = step_info['status'] name = step_info['name'] if status == 'complete': icon = "βœ…" status_class = "complete" elif status == 'active': icon = "πŸ”„" status_class = "active" else: icon = "β­•" status_class = "pending" st.markdown(f"""
{icon} {name}
""", unsafe_allow_html=True) st.markdown('
', unsafe_allow_html=True) return progress_percentage def update_step_status(step_index, status): """Update the status (pending, active, complete) for a given step index.""" if 'progress_steps' in st.session_state and step_index in st.session_state.progress_steps: st.session_state.progress_steps[step_index]['status'] = status def run_task_with_logs(task, input_text, log_container, output_container, results_key=None): """Runs a task with logging in a separate container.""" if 'log_messages' not in st.session_state: st.session_state.log_messages = [] log_message = f"πŸ€– Starting {task.agent.role}..." st.session_state.log_messages.append(log_message) with log_container: st.markdown("### Agent Activity") for msg in st.session_state.log_messages: st.markdown(msg) result = run_task(task, input_text) if results_key: st.session_state.results[results_key] = result log_message = f"βœ… {task.agent.role} completed!" st.session_state.log_messages.append(log_message) with log_container: st.markdown("### Agent Activity") for msg in st.session_state.log_messages: st.markdown(msg) with output_container: st.markdown(f"### {task.agent.role} Output") st.markdown("
" + result + "
", unsafe_allow_html=True) return result # ------------------------------------------------------ # Session State Initialization # ------------------------------------------------------ if 'generated_itinerary' not in st.session_state: st.session_state.generated_itinerary = None if 'generation_complete' not in st.session_state: st.session_state.generation_complete = False if 'current_step' not in st.session_state: st.session_state.current_step = 0 if 'results' not in st.session_state: st.session_state.results = { "destination_info": "", "accommodation_info": "", "transportation_info": "", "activities_info": "", "dining_info": "", "itinerary": "", "final_itinerary": "" } if 'log_messages' not in st.session_state: st.session_state.log_messages = [] if 'current_output' not in st.session_state: st.session_state.current_output = None if 'form_submitted' not in st.session_state: st.session_state.form_submitted = False col1, col2, col3 = st.columns([1,2,1]) with col2: st.image("assets/image.png", width=350) st.markdown(f"""

Your AI Agent for Travelling

✨ Create your personalized AI-powered travel itinerary in minutes! ✨

""", unsafe_allow_html=True) st.markdown('
', unsafe_allow_html=True) with st.sidebar: st.image("assets/image.png", width=250) st.markdown("""

Namude Yatra: The beginning of your dream journey

AI-Powered Agentic Travel Planning

""", unsafe_allow_html=True) st.markdown('', unsafe_allow_html=True) st.markdown('', unsafe_allow_html=True) st.markdown('', unsafe_allow_html=True) # ------------------------------------------------------ # Main Form # ------------------------------------------------------ if not st.session_state.generation_complete: st.markdown('
', unsafe_allow_html=True) st.markdown("

✈️ Create Your Itinerary

", unsafe_allow_html=True) st.markdown("""

Complete the form below for a personalized travel plan.

""", unsafe_allow_html=True) with st.form("travel_form"): col1, col2 = st.columns(2) with col1: st.markdown('

Trip Details

', unsafe_allow_html=True) origin = st.text_input("Origin", placeholder="e.g., New York, USA") destination = st.text_input("Destination", placeholder="e.g., Paris, France") st.markdown('

Travel Dates

', unsafe_allow_html=True) start_date = st.date_input("Start Date", min_value=datetime.now(), label_visibility="collapsed") duration = st.slider("Duration (days)", min_value=1, max_value=30, value=7) end_date = start_date + timedelta(days=duration-1) st.markdown(f'

{start_date.strftime("%b %d")} - {end_date.strftime("%b %d, %Y")}

', unsafe_allow_html=True) with col2: st.markdown('

Preferences

', unsafe_allow_html=True) travelers = st.number_input("Travelers", min_value=1, max_value=15, value=2) budget_options = ["Budget", "Moderate", "Luxury"] budget = st.selectbox("Budget", budget_options, help="Budget: Economy options | Moderate: Mid-range | Luxury: High-end experiences") travel_style = st.multiselect("Travel Style", options=["Culture", "Adventure", "Relaxation", "Food & Dining", "Nature", "Shopping", "Nightlife", "Family-friendly"], default=["Culture", "Food & Dining"]) with st.expander("Additional Preferences"): preferences = st.text_area("Interests", placeholder="History museums, local cuisine, hiking, art...") special_requirements = st.text_area("Special Requirements", placeholder="Dietary restrictions, accessibility needs...") submit_button = st.form_submit_button("πŸš€ Create My Personal Travel Itinerary") st.markdown('
', unsafe_allow_html=True) if submit_button: if not origin or not destination: st.error("Please enter both origin and destination.") else: st.session_state.form_submitted = True st.session_state.destination = destination user_input = { "origin": origin, "destination": destination, "duration": str(duration), "travel_dates": f"{start_date.strftime('%Y-%m-%d')} to {end_date.strftime('%Y-%m-%d')}", "travelers": str(travelers), "budget": budget.lower(), "travel_style": ", ".join(travel_style), "preferences": preferences, "special_requirements": special_requirements } st.session_state.user_input = user_input input_context = f"""Travel Request Details: Origin: {user_input['origin']} Destination: {user_input['destination']} Duration: {user_input['duration']} days Travel Dates: {user_input['travel_dates']} Travelers: {user_input['travelers']} Budget Level: {user_input['budget']} Travel Style: {user_input['travel_style']} Preferences/Interests: {user_input['preferences']} Special Requirements: {user_input['special_requirements']} """ modified_input_context = "Please output the response in English.\n" + input_context # Processing Animation st.markdown("""
""", unsafe_allow_html=True) st.markdown('
', unsafe_allow_html=True) progress_tab, logs_tab, details_tab = st.tabs(["πŸ“Š Progress", "πŸ”„ Live Activity", "πŸ“‹ Your Travel Request"]) with details_tab: st.markdown("#### Your Travel Request") st.markdown("**Destination:** " + user_input['destination']) st.markdown("**From:** " + user_input['origin']) st.markdown("**When:** " + user_input['travel_dates'] + " (" + user_input['duration'] + " days)") st.markdown("**Budget:** " + user_input['budget'].title()) st.markdown("**Travel Style:** " + user_input['travel_style']) if user_input['preferences']: st.markdown("**Interests:** " + user_input['preferences']) if user_input['special_requirements']: st.markdown("**Special Requirements:** " + user_input['special_requirements']) with progress_tab: if 'progress_placeholder' not in st.session_state: st.session_state.progress_placeholder = st.empty() with st.session_state.progress_placeholder.container(): display_modern_progress(st.session_state.current_step) with logs_tab: log_container = st.container() st.session_state.log_messages = [] st.markdown('
', unsafe_allow_html=True) # Output container for the Agents output_container = st.container() with output_container: st.markdown('
', unsafe_allow_html=True) st.markdown("### Live Agent Outputs") st.info("Our AI agents will show their work here as they create your itinerary") st.markdown('
', unsafe_allow_html=True) # Steps st.session_state.current_step = 0 # Step 1: Destination Research update_step_status(0, 'active') with st.session_state.progress_placeholder.container(): display_modern_progress(st.session_state.current_step) destination_info = run_task_with_logs( destination_research_task, modified_input_context.format(destination=user_input['destination'], preferences=user_input['preferences']), log_container, output_container, "destination_info" ) update_step_status(0, 'complete') st.session_state.current_step = 1 # Step 2: Accommodation update_step_status(1, 'active') with st.session_state.progress_placeholder.container(): display_modern_progress(st.session_state.current_step) accommodation_info = run_task_with_logs( accommodation_task, modified_input_context.format(destination=user_input['destination'], budget=user_input['budget'], preferences=user_input['preferences']), log_container, output_container, "accommodation_info" ) update_step_status(1, 'complete') st.session_state.current_step = 2 # Step 3: Transportation update_step_status(2, 'active') with st.session_state.progress_placeholder.container(): display_modern_progress(st.session_state.current_step) transportation_info = run_task_with_logs( transportation_task, modified_input_context.format(origin=user_input['origin'], destination=user_input['destination']), log_container, output_container, "transportation_info" ) update_step_status(2, 'complete') st.session_state.current_step = 3 # Step 4: Activities update_step_status(3, 'active') with st.session_state.progress_placeholder.container(): display_modern_progress(st.session_state.current_step) activities_info = run_task_with_logs( activities_task, modified_input_context.format(destination=user_input['destination'], preferences=user_input['preferences']), log_container, output_container, "activities_info" ) update_step_status(3, 'complete') st.session_state.current_step = 4 # Step 5: Dining update_step_status(4, 'active') with st.session_state.progress_placeholder.container(): display_modern_progress(st.session_state.current_step) dining_info = run_task_with_logs( dining_task, modified_input_context.format(destination=user_input['destination'], preferences=user_input['preferences']), log_container, output_container, "dining_info" ) update_step_status(4, 'complete') st.session_state.current_step = 5 # Step 6: Final Itinerary update_step_status(5, 'active') with st.session_state.progress_placeholder.container(): display_modern_progress(st.session_state.current_step) 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_with_logs( itinerary_task, combined_info.format(duration=user_input['duration'], origin=user_input['origin'], destination=user_input['destination']), log_container, output_container, "itinerary" ) update_step_status(5, 'complete') st.session_state.current_step = 6 with st.session_state.progress_placeholder.container(): display_modern_progress(st.session_state.current_step) # Store the final itinerary st.session_state.generated_itinerary = itinerary st.session_state.generation_complete = True date_str = datetime.now().strftime("%Y-%m-%d") st.session_state.filename = f"{user_input['destination'].replace(' ', '_')}_{date_str}_itinerary.txt" # ------------------------------------------------------ # Display after Itinerary Generation # ------------------------------------------------------ if st.session_state.generation_complete: # Success Animation st.markdown("""

Your Travel Itinerary is Ready! πŸŽ‰

We've created a personalized travel experience just for you. Explore your itinerary below.

""", unsafe_allow_html=True) # Tabs itinerary_tab, details_tab, download_tab, map_tab, chatbot_tab = st.tabs([ "πŸ—’οΈ Full Itinerary", "πŸ’Ό Details", "πŸ’Ύ Download & Share", "πŸ—ΊοΈ Map & Visualization", "πŸ€– Chatbot Interface" ]) # Full Itinerary with itinerary_tab: st.text_area("Your Itinerary", st.session_state.generated_itinerary, height=600) # Details (Destination, Accommodation, etc.) with details_tab: agent_tabs = st.tabs(["🌎 Destination", "🏨 Accommodation", "πŸš— Transportation", "🎭 Activities", "🍽️ Dining"]) with agent_tabs[0]: st.markdown("### 🌎 Destination Research") st.markdown(st.session_state.results["destination_info"]) with agent_tabs[1]: st.markdown("### 🏨 Accommodation Options") st.markdown(st.session_state.results["accommodation_info"]) with agent_tabs[2]: st.markdown("### πŸš— Transportation Plan") st.markdown(st.session_state.results["transportation_info"]) with agent_tabs[3]: st.markdown("### 🎭 Recommended Activities") st.markdown(st.session_state.results["activities_info"]) with agent_tabs[4]: st.markdown("### 🍽️ Dining Recommendations") st.markdown(st.session_state.results["dining_info"]) # Download & Share Tab (No QR code) with download_tab: col1, col2 = st.columns([2, 1]) with col1: st.markdown("### Save Your Itinerary") st.markdown("Download your personalized travel plan to access it offline or share with your travel companions.") st.markdown("""

Your Itinerary File

Text format - Can be opened in any text editor

""", unsafe_allow_html=True) # Download link st.markdown( "
" + get_download_link(st.session_state.generated_itinerary, st.session_state.filename) + "
", unsafe_allow_html=True ) st.markdown("
", unsafe_allow_html=True) st.markdown("### Share Your Itinerary") st.markdown("*Coming soon: Additional sharing features (email, phone, etc.)*") with col2: st.markdown("### Save for Mobile") st.markdown("*Coming soon: Additional mobile features such as a dedicated app or push notifications*") # Map & Visualization Tab with map_tab: st.markdown("### Destination Map") dest = st.session_state.get("destination", "Paris") try: geolocator = Nominatim(user_agent="travel_app") location = geolocator.geocode(dest) if location: lat, lon = location.latitude, location.longitude else: st.error("The destination could not be found. Using default coordinates.") lat, lon = 48.8566, 2.3522 except Exception as e: st.error("Geocoding error: " + str(e)) lat, lon = 48.8566, 2.3522 map_data = pd.DataFrame({ "lat": [lat], "lon": [lon], "name": [dest] }) st.map(map_data) st.markdown("#### Interactive Map with Pydeck") layer = pdk.Layer( "ScatterplotLayer", data=map_data, get_position='[lon, lat]', get_color='[200, 30, 0, 160]', get_radius=200, ) view_state = pdk.ViewState( latitude=lat, longitude=lon, zoom=12, pitch=50, ) deck_chart = pdk.Deck(layers=[layer], initial_view_state=view_state) st.pydeck_chart(deck_chart) # Chatbot Interface with chatbot_tab: st.markdown("### AI Chatbot Interface") if "chat_history" not in st.session_state: st.session_state.chat_history = [] user_message = st.text_input("Enter your message:", key="chat_input") if st.button("Send", key="send_button"): if user_message: response = run_task(chatbot_task, user_message) st.session_state.chat_history.append({ "speaker": "User", "message": user_message, "time": datetime.now() }) st.session_state.chat_history.append({ "speaker": "AI", "message": response, "time": datetime.now() }) st.markdown("
", unsafe_allow_html=True) for chat in st.session_state.chat_history: time_str = chat["time"].strftime("%H:%M:%S") st.markdown(f"**{chat['speaker']}** ({time_str}): {chat['message']}") st.markdown("
", unsafe_allow_html=True) # Footer st.markdown("""

Built with ❀️ for you

""", unsafe_allow_html=True)