AgentX-Papers / app.py
MrTravelX's picture
Create app.py
a3b693b verified
raw
history blame
16.7 kB
import streamlit as st
import os
import json
from datetime import datetime, timedelta
import base64
from travel import (
destination_research_task, accommodation_task, transportation_task,
activities_task, dining_task, itinerary_task, final_report_task,
run_task
)
# Set page configuration
st.set_page_config(
page_title="BlockX Travel Itinerary Generator",
page_icon="✈️",
layout="wide",
initial_sidebar_state="expanded"
)
# Custom CSS for better styling
st.markdown("""
<style>
.main-header {
font-size: 2.5rem;
color: #1E88E5;
text-align: center;
margin-bottom: 1rem;
}
.sub-header {
font-size: 1.5rem;
color: #0D47A1;
margin-top: 2rem;
margin-bottom: 1rem;
}
.info-box {
background-color: #E3F2FD;
padding: 1rem;
border-radius: 0.5rem;
margin-bottom: 1rem;
}
.success-box {
background-color: #E8F5E9;
padding: 1rem;
border-radius: 0.5rem;
margin-bottom: 1rem;
border-left: 5px solid #4CAF50;
}
.progress-container {
margin: 1rem 0;
}
.step-complete {
color: #4CAF50;
font-weight: bold;
}
.step-pending {
color: #9E9E9E;
}
.step-active {
color: #1E88E5;
font-weight: bold;
}
.agent-log {
background-color: #F5F5F5;
border-left: 3px solid #1E88E5;
padding: 0.5rem;
margin-bottom: 0.5rem;
font-family: monospace;
}
.agent-output {
background-color: #E8F5E9;
border-left: 5px solid #4CAF50;
padding: 1rem;
margin: 1rem 0;
border-radius: 0.5rem;
max-height: 400px;
overflow-y: auto;
}
.footer {
text-align: center;
margin-top: 3rem;
color: #757575;
font-size: 0.8rem;
}
.stButton button {
background-color: #1E88E5;
color: white;
font-weight: bold;
}
</style>
""", unsafe_allow_html=True)
# Helper function to download HTML file
def get_download_link(html_content, filename):
b64 = base64.b64encode(html_content.encode()).decode()
href = f'<a href="data:text/html;base64,{b64}" download="{filename}">Download Itinerary as HTML</a>'
return href
# Helper function to display progress
def display_progress(current_step, total_steps=7):
progress_html = '<div class="progress-container">'
steps = [
"Destination Research",
"Accommodation",
"Transportation",
"Activities",
"Dining",
"Itinerary Creation",
"Final Report"
]
for i, step in enumerate(steps):
if i < current_step:
progress_html += f'<p class="step-complete">✓ {step} - Complete</p>'
elif i == current_step:
progress_html += f'<p class="step-active">⟳ {step} - In Progress...</p>'
else:
progress_html += f'<p class="step-pending">○ {step} - Pending</p>'
progress_html += '</div>'
return progress_html
# Custom run_task function that updates the UI with logs and shows live agent outputs
def run_task_with_logs(task, input_text, log_container, output_container, results_key=None):
# Add log message
log_message = f"🤖 Starting {task.agent.role}..."
st.session_state.log_messages.append(log_message)
# Update the log container
with log_container:
st.markdown("### Agent Activity")
for msg in st.session_state.log_messages:
st.markdown(msg)
# Run the actual task
result = run_task(task, input_text)
# Store result if needed
if results_key:
st.session_state.results[results_key] = result
# Add completion log message
log_message = f"✅ {task.agent.role} completed!"
st.session_state.log_messages.append(log_message)
# Update the log container again
with log_container:
st.markdown("### Agent Activity")
for msg in st.session_state.log_messages:
st.markdown(msg)
# Display the agent's output in the output container
with output_container:
st.markdown(f"### {task.agent.role} Output")
st.markdown("""<div class='agent-output'>""" + result + """</div>""", unsafe_allow_html=True)
return result
# Initialize session state
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
# Header
st.markdown('<h1 class="main-header">BlockX Travel Itinerary Generator</h1>', unsafe_allow_html=True)
st.markdown('<p style="text-align: center;">Create your personalized AI-powered travel itinerary in minutes!</p>', unsafe_allow_html=True)
# Sidebar with information
with st.sidebar:
st.image("https://img.icons8.com/fluency/96/travel-card.png", width=80)
st.markdown("### About")
st.info(
"This AI-powered tool creates a personalized travel itinerary based on your preferences. "
"Fill in the form and let our specialized travel agents plan your perfect trip!"
)
st.markdown("### How it works")
st.markdown(
"1. Enter your travel details\n"
"2. Our AI agents analyze your preferences\n"
"3. Receive a comprehensive itinerary\n"
"4. Download and enjoy your trip!"
)
st.markdown("### Travel Agents")
st.markdown(
"- 🔍 Destination Research Agent\n"
"- 🏨 Accommodation Agent\n"
"- 🚗 Transportation Agent\n"
"- 🎭 Activities & Attractions Agent\n"
"- 🍽️ Dining & Culinary Agent\n"
"- 📅 Itinerary Integration Agent\n"
"- 📄 Final Report Generation Agent"
)
# Input Form
if not st.session_state.generation_complete:
st.markdown('<h2 class="sub-header">Enter Your Travel Details</h2>', unsafe_allow_html=True)
col1, col2 = st.columns(2)
with col1:
origin = st.text_input("Origin City/Country", placeholder="e.g., New York, USA")
destination = st.text_input("Destination City/Country", placeholder="e.g., Paris, France")
duration = st.number_input("Trip Duration (days)", min_value=1, max_value=30, value=7)
with col2:
budget_options = ["Budget", "Moderate", "Luxury"]
budget = st.selectbox("Budget Level", budget_options)
preferences = st.text_area("Travel Preferences & Interests",
placeholder="e.g., museums, hiking, food, shopping, beaches, history, nightlife, family-friendly")
special_requirements = st.text_area("Special Requirements",
placeholder="e.g., dietary restrictions, accessibility needs, etc.")
# Generate button
if st.button("Generate My Travel Itinerary"):
if not origin or not destination:
st.error("Please enter both origin and destination.")
else:
user_input = {
"origin": origin,
"destination": destination,
"duration": str(duration),
"budget": budget.lower(),
"preferences": preferences,
"special_requirements": special_requirements
}
# 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']}
"""
# Create containers for progress, logs, and live output
col1, col2 = st.columns([1, 2])
with col1:
progress_placeholder = st.empty()
progress_placeholder.markdown(display_progress(0), unsafe_allow_html=True)
log_container = st.container()
st.session_state.log_messages = []
with col2:
output_container = st.container()
with output_container:
st.markdown("### Live Agent Outputs")
st.info("Agent outputs will appear here as they are generated")
# Step 1: Destination Research
st.session_state.current_step = 0
progress_placeholder.markdown(display_progress(st.session_state.current_step), unsafe_allow_html=True)
destination_info = run_task_with_logs(
destination_research_task,
input_context.format(
destination=user_input['destination'],
preferences=user_input['preferences']
),
log_container,
output_container,
"destination_info"
)
st.session_state.current_step = 1
progress_placeholder.markdown(display_progress(st.session_state.current_step), unsafe_allow_html=True)
# Step 2: Accommodation Recommendations
accommodation_info = run_task_with_logs(
accommodation_task,
input_context.format(
destination=user_input['destination'],
budget=user_input['budget'],
preferences=user_input['preferences']
),
log_container,
output_container,
"accommodation_info"
)
st.session_state.current_step = 2
progress_placeholder.markdown(display_progress(st.session_state.current_step), unsafe_allow_html=True)
# Step 3: Transportation Planning
transportation_info = run_task_with_logs(
transportation_task,
input_context.format(
origin=user_input['origin'],
destination=user_input['destination']
),
log_container,
output_container,
"transportation_info"
)
st.session_state.current_step = 3
progress_placeholder.markdown(display_progress(st.session_state.current_step), unsafe_allow_html=True)
# Step 4: Activities & Attractions
activities_info = run_task_with_logs(
activities_task,
input_context.format(
destination=user_input['destination'],
preferences=user_input['preferences']
),
log_container,
output_container,
"activities_info"
)
st.session_state.current_step = 4
progress_placeholder.markdown(display_progress(st.session_state.current_step), unsafe_allow_html=True)
# Step 5: Dining Recommendations
dining_info = run_task_with_logs(
dining_task,
input_context.format(
destination=user_input['destination'],
preferences=user_input['preferences']
),
log_container,
output_container,
"dining_info"
)
st.session_state.current_step = 5
progress_placeholder.markdown(display_progress(st.session_state.current_step), unsafe_allow_html=True)
# Step 6: Create 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_with_logs(
itinerary_task,
combined_info.format(
duration=user_input['duration'],
origin=user_input['origin'],
destination=user_input['destination']
),
log_container,
output_container,
"itinerary"
)
st.session_state.current_step = 6
progress_placeholder.markdown(display_progress(st.session_state.current_step), unsafe_allow_html=True)
# Step 7: Generate Final Report
final_context = f"""{combined_info}
Day-by-Day Itinerary:
{itinerary}
"""
final_itinerary = run_task_with_logs(
final_report_task,
final_context.format(
duration=user_input['duration'],
origin=user_input['origin'],
destination=user_input['destination']
),
log_container,
output_container,
"final_itinerary"
)
# Save the generated itinerary to session state
st.session_state.generated_itinerary = final_itinerary
st.session_state.generation_complete = True
# Create a filename based on the destination and date
date_str = datetime.now().strftime("%Y-%m-%d")
st.session_state.filename = f"{user_input['destination'].replace(' ', '_')}_{date_str}_itinerary.html"
# No need to rerun, we'll update the UI directly
# Display results if generation is complete
if st.session_state.generation_complete:
st.markdown('<h2 class="sub-header">Your Travel Itinerary is Ready! 🎉</h2>', unsafe_allow_html=True)
# Display download link
st.markdown(
get_download_link(st.session_state.generated_itinerary, st.session_state.filename),
unsafe_allow_html=True
)
# Option to view the itinerary directly
with st.expander("Preview Your Itinerary", expanded=True):
st.components.v1.html(st.session_state.generated_itinerary, height=600, scrolling=True)
# Option to view individual agent outputs
with st.expander("View Detailed Agent Outputs"):
agent_tabs = st.tabs([
"Destination", "Accommodation", "Transportation",
"Activities", "Dining", "Day-by-Day"
])
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"])
with agent_tabs[5]:
st.markdown("### Day-by-Day Itinerary")
st.markdown(st.session_state.results["itinerary"])
# Option to start over
if st.button("Create Another Itinerary"):
# Reset session state
st.session_state.generated_itinerary = None
st.session_state.generation_complete = False
st.session_state.current_step = 0
st.session_state.results = {
"destination_info": "",
"accommodation_info": "",
"transportation_info": "",
"activities_info": "",
"dining_info": "",
"itinerary": "",
"final_itinerary": ""
}
st.rerun()
# Footer
st.markdown('<div class="footer">BlockX Travel Itinerary Generator © 2025</div>', unsafe_allow_html=True)