diff --git "a/app-backup.py" "b/app-backup.py"
--- "a/app-backup.py"
+++ "b/app-backup.py"
@@ -1,1224 +1,1225 @@
-import streamlit as st
-import os
-import json
-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
-)
-
-# st.set_page_config() must be called before any other Streamlit functions
-st.set_page_config(
- page_title="Your AI Agent for Travelling",
- page_icon="✈️",
- layout="wide",
- initial_sidebar_state="expanded"
-)
-
-# ------------------------------------------
-# Translation dictionary and helper functions
-# ------------------------------------------
-translations = {
- "en": {
- "page_title": "Your AI Agent for Travelling",
- "header": "Your AI Agent for Travelling",
- "create_itinerary": "Create Your Itinerary",
- "trip_details": "Trip Details",
- "origin": "Origin",
- "destination": "Destination",
- "travel_dates": "Travel Dates",
- "duration": "Duration (days)",
- "preferences": "Preferences",
- "additional_preferences": "Additional Preferences",
- "interests": "Interests",
- "special_requirements": "Special Requirements",
- "submit": "🚀 Create My Personal Travel Itinerary",
- "request_details": "Your Travel Request",
- "from": "From",
- "when": "When",
- "budget": "Budget",
- "travel_style": "Travel Style",
- "live_agent_outputs": "Live Agent Outputs",
- "full_itinerary": "Full Itinerary",
- "details": "Details",
- "download_share": "Download & Share",
- "save_itinerary": "Save Your Itinerary",
- "plan_another_trip": "🔄 Plan Another Trip",
- "about": "About",
- "how_it_works": "How it works",
- "travel_agents": "Travel Agents",
- "share_itinerary": "Share Your Itinerary",
- "save_for_mobile": "Save for Mobile",
- "built_with": "Built with ❤️ for you",
- # Additional text related to output
- "itinerary_ready": "Your Travel Itinerary is Ready! 🎉",
- "personalized_experience": "We've created a personalized travel experience just for you. Explore your itinerary below.",
- "agent_activity": "Agent Activity",
- "error_origin_destination": "Please enter both origin and destination.",
- "your_itinerary_file": "Your Itinerary File",
- "text_format": "Text format - Can be opened in any text editor"
- },
- "ko": {
- "page_title": "당신의 여행을 위한 AI 에이전트",
- "header": "당신의 여행을 위한 AI 에이전트",
- "create_itinerary": "여행 일정 생성",
- "trip_details": "여행 세부 정보",
- "origin": "출발지",
- "destination": "목적지",
- "travel_dates": "여행 날짜",
- "duration": "기간 (일수)",
- "preferences": "선호사항",
- "additional_preferences": "추가 선호사항",
- "interests": "관심사",
- "special_requirements": "특별 요구사항",
- "submit": "🚀 나만의 여행 일정 생성",
- "request_details": "여행 요청 정보",
- "from": "출발지",
- "when": "여행 기간",
- "budget": "예산",
- "travel_style": "여행 스타일",
- "live_agent_outputs": "실시간 에이전트 결과",
- "full_itinerary": "전체 일정",
- "details": "세부사항",
- "download_share": "다운로드 및 공유",
- "save_itinerary": "일정 저장",
- "plan_another_trip": "🔄 다른 여행 계획",
- "about": "소개",
- "how_it_works": "작동 방식",
- "travel_agents": "여행 에이전트",
- "share_itinerary": "일정 공유",
- "save_for_mobile": "모바일 저장",
- "built_with": "당신을 위해 ❤️ 만들어졌습니다",
- # Additional text related to output
- "itinerary_ready": "여행 일정이 준비되었습니다! 🎉",
- "personalized_experience": "당신만을 위한 맞춤형 여행 경험이 만들어졌습니다. 아래에서 일정을 확인하세요.",
- "agent_activity": "에이전트 활동",
- "error_origin_destination": "출발지와 목적지를 모두 입력하세요.",
- "your_itinerary_file": "당신의 여행 일정 파일",
- "text_format": "텍스트 형식 - 모든 텍스트 편집기에서 열 수 있습니다."
- },
- "ja": {
- "page_title": "あなたの旅行のためのAIエージェント",
- "header": "あなたの旅行のためのAIエージェント",
- "create_itinerary": "旅行プラン作成",
- "trip_details": "旅行詳細",
- "origin": "出発地",
- "destination": "目的地",
- "travel_dates": "旅行日程",
- "duration": "期間(日数)",
- "preferences": "好み",
- "additional_preferences": "追加の好み",
- "interests": "興味",
- "special_requirements": "特別な要件",
- "submit": "🚀 私のための旅行プラン作成",
- "request_details": "旅行リクエスト",
- "from": "出発地",
- "when": "旅行期間",
- "budget": "予算",
- "travel_style": "旅行スタイル",
- "live_agent_outputs": "リアルタイムエージェント出力",
- "full_itinerary": "全行程",
- "details": "詳細",
- "download_share": "ダウンロードと共有",
- "save_itinerary": "旅行プランを保存",
- "plan_another_trip": "🔄 他の旅行を計画",
- "about": "概要",
- "how_it_works": "使い方",
- "travel_agents": "旅行エージェント",
- "share_itinerary": "旅行プランを共有",
- "save_for_mobile": "モバイル保存",
- "built_with": "愛を込めて作られました",
- # Additional text related to output
- "itinerary_ready": "旅行プランの準備ができました! 🎉",
- "personalized_experience": "あなたのためにパーソナライズされた旅行体験を作成しました。下のプランをご覧ください。",
- "agent_activity": "エージェントアクティビティ",
- "error_origin_destination": "出発地と目的地の両方を入力してください。",
- "your_itinerary_file": "あなたの旅行プランファイル",
- "text_format": "テキスト形式 - 任意のテキストエディタで開けます。"
- },
- "zh": {
- "page_title": "您的旅行 AI 代理",
- "header": "您的旅行 AI 代理",
- "create_itinerary": "创建您的行程",
- "trip_details": "旅行详情",
- "origin": "出发地",
- "destination": "目的地",
- "travel_dates": "旅行日期",
- "duration": "天数",
- "preferences": "偏好",
- "additional_preferences": "其他偏好",
- "interests": "兴趣",
- "special_requirements": "特殊需求",
- "submit": "🚀 创建我的个性化行程",
- "request_details": "您的旅行请求",
- "from": "出发地",
- "when": "旅行时间",
- "budget": "预算",
- "travel_style": "旅行风格",
- "live_agent_outputs": "实时代理输出",
- "full_itinerary": "完整行程",
- "details": "详情",
- "download_share": "下载与分享",
- "save_itinerary": "保存行程",
- "plan_another_trip": "🔄 计划另一趟旅行",
- "about": "关于",
- "how_it_works": "工作原理",
- "travel_agents": "旅行代理",
- "share_itinerary": "分享行程",
- "save_for_mobile": "保存到手机",
- "built_with": "用❤️为您制作",
- # Additional text related to output
- "itinerary_ready": "您的旅行行程已准备就绪! 🎉",
- "personalized_experience": "我们已为您创建了个性化的旅行体验,请在下方查看您的行程。",
- "agent_activity": "代理活动",
- "error_origin_destination": "请输入出发地和目的地。",
- "your_itinerary_file": "您的行程文件",
- "text_format": "文本格式 - 可在任何文本编辑器中打开。"
- },
- "es": {
- "page_title": " Tu Agente de IA para Viajar",
- "header": " Tu Agente de IA para Viajar",
- "create_itinerary": "Crea Tu Itinerario",
- "trip_details": "Detalles del Viaje",
- "origin": "Origen",
- "destination": "Destino",
- "travel_dates": "Fechas del Viaje",
- "duration": "Duración (días)",
- "preferences": "Preferencias",
- "additional_preferences": "Preferencias Adicionales",
- "interests": "Intereses",
- "special_requirements": "Requisitos Especiales",
- "submit": "🚀 Crea Mi Itinerario Personalizado",
- "request_details": "Tu Solicitud de Viaje",
- "from": "Desde",
- "when": "Cuándo",
- "budget": "Presupuesto",
- "travel_style": "Estilo de Viaje",
- "live_agent_outputs": "Salidas en Vivo del Agente",
- "full_itinerary": "Itinerario Completo",
- "details": "Detalles",
- "download_share": "Descargar y Compartir",
- "save_itinerary": "Guardar Itinerario",
- "plan_another_trip": "🔄 Planear Otro Viaje",
- "about": "Acerca de",
- "how_it_works": "Cómo Funciona",
- "travel_agents": "Agentes de Viaje",
- "share_itinerary": "Compartir Itinerario",
- "save_for_mobile": "Guardar para Móvil",
- "built_with": "Hecho con ❤️ para ti",
- # Additional text related to output
- "itinerary_ready": "¡Tu itinerario de viaje está listo! 🎉",
- "personalized_experience": "Hemos creado una experiencia de viaje personalizada solo para ti. Explora tu itinerario a continuación.",
- "agent_activity": "Actividad del Agente",
- "error_origin_destination": "Por favor, ingresa tanto el origen como el destino.",
- "your_itinerary_file": "Tu Archivo de Itinerario",
- "text_format": "Formato de texto - Se puede abrir en cualquier editor de texto."
- },
- "fr": {
- "page_title": " Votre Agent IA pour Voyager",
- "header": " Votre Agent IA pour Voyager",
- "create_itinerary": "Créez Votre Itinéraire",
- "trip_details": "Détails du Voyage",
- "origin": "Origine",
- "destination": "Destination",
- "travel_dates": "Dates du Voyage",
- "duration": "Durée (jours)",
- "preferences": "Préférences",
- "additional_preferences": "Préférences Supplémentaires",
- "interests": "Centres d'intérêt",
- "special_requirements": "Exigences Spéciales",
- "submit": "🚀 Créez Mon Itinéraire Personnalisé",
- "request_details": "Votre Demande de Voyage",
- "from": "De",
- "when": "Quand",
- "budget": "Budget",
- "travel_style": "Style de Voyage",
- "live_agent_outputs": "Résultats en Direct de l'Agent",
- "full_itinerary": "Itinéraire Complet",
- "details": "Détails",
- "download_share": "Télécharger et Partager",
- "save_itinerary": "Enregistrer l'Itinéraire",
- "plan_another_trip": "🔄 Planifier un Autre Voyage",
- "about": "À Propos",
- "how_it_works": "Fonctionnement",
- "travel_agents": "Agents de Voyage",
- "share_itinerary": "Partager l'Itinéraire",
- "save_for_mobile": "Enregistrer pour Mobile",
- "built_with": "Conçu avec ❤️ pour vous",
- # Additional text related to output
- "itinerary_ready": "Votre itinéraire de voyage est prêt ! 🎉",
- "personalized_experience": "Nous avons créé une expérience de voyage personnalisée rien que pour vous. Découvrez votre itinéraire ci-dessous.",
- "agent_activity": "Activité de l'Agent",
- "error_origin_destination": "Veuillez saisir à la fois le lieu de départ et la destination.",
- "your_itinerary_file": "Votre Fichier d'Itinéraire",
- "text_format": "Format texte - Peut être ouvert dans n'importe quel éditeur de texte."
- },
- "de": {
- "page_title": "Ihr KI-Reiseassistent",
- "header": " Ihr KI-Reiseassistent",
- "create_itinerary": "Erstellen Sie Ihre Reiseroute",
- "trip_details": "Reisedetails",
- "origin": "Abfahrtsort",
- "destination": "Zielort",
- "travel_dates": "Reisedaten",
- "duration": "Dauer (Tage)",
- "preferences": "Vorlieben",
- "additional_preferences": "Zusätzliche Vorlieben",
- "interests": "Interessen",
- "special_requirements": "Besondere Anforderungen",
- "submit": "🚀 Erstellen Sie meine personalisierte Reiseroute",
- "request_details": "Ihre Reiseanfrage",
- "from": "Von",
- "when": "Wann",
- "budget": "Budget",
- "travel_style": "Reisestil",
- "live_agent_outputs": "Live Agent Ausgaben",
- "full_itinerary": "Komplette Reiseroute",
- "details": "Details",
- "download_share": "Herunterladen & Teilen",
- "save_itinerary": "Reiseroute speichern",
- "plan_another_trip": "🔄 Plane eine weitere Reise",
- "about": "Über",
- "how_it_works": "Wie es funktioniert",
- "travel_agents": "Reiseassistenten",
- "share_itinerary": "Reiseroute teilen",
- "save_for_mobile": "Für Mobilgeräte speichern",
- "built_with": "Mit ❤️ für Sie gebaut",
- # Additional text related to output
- "itinerary_ready": "Ihre Reiseroute ist fertig! 🎉",
- "personalized_experience": "Wir haben eine personalisierte Reiseerfahrung nur für Sie erstellt. Entdecken Sie Ihre Reiseroute unten.",
- "agent_activity": "Agentenaktivität",
- "error_origin_destination": "Bitte geben Sie sowohl den Abfahrtsort als auch das Ziel ein.",
- "your_itinerary_file": "Ihre Reise-Datei",
- "text_format": "Textformat – Kann in jedem Texteditor geöffnet werden."
- },
- "ar": {
- "page_title": " وكيل السفر الذكي الخاص بك",
- "header": " وكيل السفر الذكي الخاص بك",
- "create_itinerary": "إنشاء خط سير الرحلة",
- "trip_details": "تفاصيل الرحلة",
- "origin": "المغادرة من",
- "destination": "الوجهة",
- "travel_dates": "تواريخ السفر",
- "duration": "المدة (بالأيام)",
- "preferences": "التفضيلات",
- "additional_preferences": "تفضيلات إضافية",
- "interests": "الاهتمامات",
- "special_requirements": "المتطلبات الخاصة",
- "submit": "🚀 إنشاء خط سير الرحلة الشخصي",
- "request_details": "طلب السفر الخاص بك",
- "from": "من",
- "when": "متى",
- "budget": "الميزانية",
- "travel_style": "أسلوب السفر",
- "live_agent_outputs": "مخرجات الوكيل المباشرة",
- "full_itinerary": "خط سير الرحلة الكامل",
- "details": "التفاصيل",
- "download_share": "تنزيل ومشاركة",
- "save_itinerary": "حفظ خط سير الرحلة",
- "plan_another_trip": "🔄 خطط لرحلة أخرى",
- "about": "حول",
- "how_it_works": "كيف يعمل",
- "travel_agents": "وكلاء السفر",
- "share_itinerary": "شارك خط سير الرحلة",
- "save_for_mobile": "حفظ للهاتف المحمول",
- "built_with": "مصنوع بحب من أجلك",
- # Additional text related to output
- "itinerary_ready": "تم تجهيز خط سير رحلتك! 🎉",
- "personalized_experience": "لقد أنشأنا تجربة سفر مخصصة لك. استعرض خط سير رحلتك أدناه.",
- "agent_activity": "نشاط الوكيل",
- "error_origin_destination": "يرجى إدخال نقطة الانطلاق والوجهة.",
- "your_itinerary_file": "ملف خط سير رحلتك",
- "text_format": "تنسيق نصي - يمكن فتحه في أي محرر نصوص."
- }
-}
-
-def t(key):
- lang = st.session_state.get("selected_language", "en")
- return translations[lang].get(key, key)
-
-# ------------------------------------------
-# Session initialization
-# ------------------------------------------
-if 'selected_language' not in st.session_state:
- st.session_state.selected_language = "en" # Default is English
-
-# ------------------------------------------
-# Add language selection widget to sidebar
-# ------------------------------------------
-with st.sidebar:
- language = st.selectbox(
- "Language / 언어 / 言語 / 语言 / Idioma / Langue / Sprache / اللغة",
- ["English", "한국어", "日本語", "中文", "Español", "Français", "Deutsch", "العربية"]
- )
- lang_map = {
- "English": "en",
- "한국어": "ko",
- "日本語": "ja",
- "中文": "zh",
- "Español": "es",
- "Français": "fr",
- "Deutsch": "de",
- "العربية": "ar"
- }
- st.session_state.selected_language = lang_map.get(language, "en")
-
-# ------------------------------------------
-# Start of Streamlit UI code
-# ------------------------------------------
-
-# Modern CSS with refined color scheme and sleek animations
-st.markdown("""
-
-""", unsafe_allow_html=True)
-
-# Helper function to download HTML file
-def get_download_link(text_content, filename):
- b64 = base64.b64encode(text_content.encode()).decode()
- href = f'📥 {t("save_itinerary")}'
- return href
-
-# Updated helper function to display modern progress with a single UI element
-def display_modern_progress(current_step, total_steps=6):
- if 'progress_steps' not in st.session_state:
- st.session_state.progress_steps = {
- 0: {'status': 'pending', 'name': t("trip_details")},
- 1: {'status': 'pending', 'name': t("about")},
- 2: {'status': 'pending', 'name': t("travel_style")},
- 3: {'status': 'pending', 'name': t("live_agent_outputs")},
- 4: {'status': 'pending', 'name': t("download_share")},
- 5: {'status': 'pending', 'name': t("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)
-
- st.markdown("""
-
-
- """, unsafe_allow_html=True)
-
- 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):
- 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):
- log_message = f"🤖 Starting {task.agent.role}..."
- st.session_state.log_messages.append(log_message)
-
- with log_container:
- st.markdown("### " + t("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("### " + t("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 초기화
-# ------------------------------------------
-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
-
-# Modern animated header
-st.markdown(f"""
-
-
-

-
-
{t("header")}
-
- ✨ Create your personalized AI-powered travel itinerary in minutes! ✨
-
-
-""", unsafe_allow_html=True)
-
-st.markdown('
', unsafe_allow_html=True)
-
-with st.sidebar:
- st.markdown("""
-
-

-
Your AI Agent for Travelling
-
AI-Powered Travel Planning
-
- """, unsafe_allow_html=True)
-
- st.markdown('', unsafe_allow_html=True)
- st.markdown("### 🌟 " + t("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('
', unsafe_allow_html=True)
-
- st.markdown('', unsafe_allow_html=True)
- st.markdown("### 🔍 " + t("how_it_works"))
- st.markdown("""
-
- - 🖊️ Enter your travel details
- - 🧠 AI analysis of your preferences
- - 📋 Generate comprehensive itinerary
- - 📥 Download and enjoy your trip!
-
- """, unsafe_allow_html=True)
- st.markdown('
', unsafe_allow_html=True)
-
- st.markdown('', unsafe_allow_html=True)
- st.markdown("### 🤖 Travel Agents")
- agents = [
- ("🔭 Research Specialist", "Finds the best destinations based on your preferences"),
- ("🏨 Accommodation Expert", "Suggests suitable hotels and stays"),
- ("🚆 Transportation Planner", "Plans efficient travel routes"),
- ("🎯 Activities Curator", "Recommends activities tailored to your interests"),
- ("🍽️ Dining Connoisseur", "Finds the best dining experiences"),
- ("📅 Itinerary Creator", "Puts everything together in a daily plan")
- ]
- for name, desc in agents:
- st.markdown("**" + name + "**")
- st.markdown("" + desc + "", unsafe_allow_html=True)
- st.markdown('
', unsafe_allow_html=True)
-
-if not st.session_state.generation_complete:
- st.markdown('', unsafe_allow_html=True)
- st.markdown("
✈️ " + t("create_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(t("origin"), placeholder="e.g., New York, USA")
- destination = st.text_input(t("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(t("duration"), min_value=1, max_value=30, value=7)
- end_date = start_date + timedelta(days=duration-1)
- st.markdown('
' + 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", expanded=False):
- 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(t("submit"))
- st.markdown('
', unsafe_allow_html=True)
-
- if submit_button:
- if not origin or not destination:
- st.error(t("error_origin_destination"))
- else:
- st.session_state.form_submitted = True
- 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
- }
- # 기존의 여행 요청 프롬프트
- 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']}
-"""
-
- llm_language_instructions = {
- "en": "Please output the response in English.",
- "ko": "한국어로 출력해 주세요.",
- "ja": "日本語で出力してください。",
- "zh": "请用中文输出。",
- "es": "Por favor, responda en español.",
- "fr": "Veuillez répondre en français.",
- "de": "Bitte antworten Sie auf Deutsch.",
- "ar": "يرجى الرد باللغة العربية."
- }
- selected_lang = st.session_state.get("selected_language", "en")
- language_instruction = llm_language_instructions.get(selected_lang, "Please output the response in English.")
- modified_input_context = language_instruction + "\n" + input_context
-
- st.markdown("""
-
-
- """, unsafe_allow_html=True)
-
- st.markdown('', unsafe_allow_html=True)
- progress_tab, logs_tab, details_tab = st.tabs(["📊 Progress", "🔄 Live Activity", "📋 " + t("request_details")])
- with details_tab:
- st.markdown("#### " + t("request_details"))
- st.markdown("**" + t("destination") + ":** " + user_input['destination'])
- st.markdown("**" + t("from") + ":** " + user_input['origin'])
- st.markdown("**" + t("when") + ":** " + user_input['travel_dates'] + " (" + user_input['duration'] + " days)")
- st.markdown("**" + t("budget") + ":** " + user_input['budget'].title())
- st.markdown("**" + t("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(0)
- with logs_tab:
- log_container = st.container()
- st.session_state.log_messages = []
- st.markdown('
', unsafe_allow_html=True)
- output_container = st.container()
- with output_container:
- st.markdown('', unsafe_allow_html=True)
- st.markdown("### 🌟 " + t("live_agent_outputs"))
- st.info("Our AI agents will show their work here as they create your itinerary")
- st.markdown('
', unsafe_allow_html=True)
- st.session_state.current_step = 0
-
- 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
- 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
- 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
- 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
- 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
- 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)
- 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"
-
-if st.session_state.generation_complete:
- st.markdown("""
-
-
-
""" + t("itinerary_ready") + """
-
""" + t("personalized_experience") + """
-
-
-
- """, unsafe_allow_html=True)
-
-
- itinerary_tab, details_tab, download_tab, map_tab, chatbot_tab = st.tabs([
- "🗒️ " + t("full_itinerary"),
- "💼 " + t("details"),
- "💾 " + t("download_share"),
- "🗺️ 지도 및 시각화",
- "🤖 챗봇 인터페이스"
- ])
-
-
- with itinerary_tab:
- st.text_area("Your Itinerary", st.session_state.generated_itinerary, height=600)
-
- 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"])
-
-
- with download_tab:
- col1, col2 = st.columns([2, 1])
- with col1:
- st.markdown("### " + t("save_itinerary"))
- st.markdown("Download your personalized travel plan to access it offline or share with your travel companions.")
- st.markdown("""
-
-
""" + t("your_itinerary_file") + """
-
""" + t("text_format") + """
- """, unsafe_allow_html=True)
- 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("### " + t("share_itinerary"))
- st.markdown("*Coming soon: Email your itinerary or share via social media.*")
- with col2:
- st.markdown("### " + t("save_for_mobile"))
- st.markdown("*Coming soon: QR code for easy access on your phone*")
-
-
- with map_tab:
- st.markdown("### Destination Map")
- # Example: Coordinate data for major attractions near destination (can be dynamically fetched via API or DB)
- map_data = pd.DataFrame({
- "lat": [48.8584, 48.8606, 48.8529],
- "lon": [2.2945, 2.3376, 2.3500],
- "name": ["Eiffel Tower", "Louvre Museum", "Notre Dame"]
- })
- # Default map output (st.map)
- st.map(map_data)
-
- st.markdown("#### Interactive Map with Pydeck")
- view_state = pdk.ViewState(
- latitude=48.8584,
- longitude=2.2945,
- zoom=12,
- pitch=50
- )
-
- # AI Chatbot interface tab (using Gemini)
- with chatbot_tab:
- st.markdown("### AI Chatbot Interface")
- # Store conversation history in session state (message, sender, timestamp)
- if "messages" not in st.session_state:
- st.session_state.messages = []
-
- # User input field and send button
- user_question = st.text_input("Ask me about your travel plans:", key="chat_input")
-
- # Gemini-based chatbot response: use run_task() to query chatbot_task
- if user_question and st.button("Ask", key="ask_button"):
- response = run_task(chatbot_task, user_question)
- st.session_state.messages.append({
- "speaker": "User",
- "message": user_question,
- "time": datetime.now()
- })
- st.session_state.messages.append({
- "speaker": "AI",
- "message": response,
- "time": datetime.now()
- })
-
- # Conversation history output (including timestamp, scrollable area)
- st.markdown("", unsafe_allow_html=True)
- for chat in st.session_state.messages:
- time_str = chat["time"].strftime("%H:%M:%S")
- st.markdown(f"**{chat['speaker']}** ({time_str}): {chat['message']}")
- st.markdown("
", unsafe_allow_html=True)
-
- st.markdown("""
-
-
""" + t("built_with") + """
-
- """, unsafe_allow_html=True)
+import streamlit as st
+import streamlit as st
+import os
+import json
+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
+)
+
+# st.set_page_config() must be called before any other Streamlit functions
+st.set_page_config(
+ page_title="Your AI Agent for Travelling",
+ page_icon="✈️",
+ layout="wide",
+ initial_sidebar_state="expanded"
+)
+
+# ------------------------------------------
+# Translation dictionary and helper functions
+# ------------------------------------------
+translations = {
+ "en": {
+ "page_title": "Your AI Agent for Travelling",
+ "header": "Your AI Agent for Travelling",
+ "create_itinerary": "Create Your Itinerary",
+ "trip_details": "Trip Details",
+ "origin": "Origin",
+ "destination": "Destination",
+ "travel_dates": "Travel Dates",
+ "duration": "Duration (days)",
+ "preferences": "Preferences",
+ "additional_preferences": "Additional Preferences",
+ "interests": "Interests",
+ "special_requirements": "Special Requirements",
+ "submit": "🚀 Create My Personal Travel Itinerary",
+ "request_details": "Your Travel Request",
+ "from": "From",
+ "when": "When",
+ "budget": "Budget",
+ "travel_style": "Travel Style",
+ "live_agent_outputs": "Live Agent Outputs",
+ "full_itinerary": "Full Itinerary",
+ "details": "Details",
+ "download_share": "Download & Share",
+ "save_itinerary": "Save Your Itinerary",
+ "plan_another_trip": "🔄 Plan Another Trip",
+ "about": "About",
+ "how_it_works": "How it works",
+ "travel_agents": "Travel Agents",
+ "share_itinerary": "Share Your Itinerary",
+ "save_for_mobile": "Save for Mobile",
+ "built_with": "Built with ❤️ for you",
+ # Additional text related to output
+ "itinerary_ready": "Your Travel Itinerary is Ready! 🎉",
+ "personalized_experience": "We've created a personalized travel experience just for you. Explore your itinerary below.",
+ "agent_activity": "Agent Activity",
+ "error_origin_destination": "Please enter both origin and destination.",
+ "your_itinerary_file": "Your Itinerary File",
+ "text_format": "Text format - Can be opened in any text editor"
+ },
+ "ko": {
+ "page_title": "당신의 여행을 위한 AI 에이전트",
+ "header": "당신의 여행을 위한 AI 에이전트",
+ "create_itinerary": "여행 일정 생성",
+ "trip_details": "여행 세부 정보",
+ "origin": "출발지",
+ "destination": "목적지",
+ "travel_dates": "여행 날짜",
+ "duration": "기간 (일수)",
+ "preferences": "선호사항",
+ "additional_preferences": "추가 선호사항",
+ "interests": "관심사",
+ "special_requirements": "특별 요구사항",
+ "submit": "🚀 나만의 여행 일정 생성",
+ "request_details": "여행 요청 정보",
+ "from": "출발지",
+ "when": "여행 기간",
+ "budget": "예산",
+ "travel_style": "여행 스타일",
+ "live_agent_outputs": "실시간 에이전트 결과",
+ "full_itinerary": "전체 일정",
+ "details": "세부사항",
+ "download_share": "다운로드 및 공유",
+ "save_itinerary": "일정 저장",
+ "plan_another_trip": "🔄 다른 여행 계획",
+ "about": "소개",
+ "how_it_works": "작동 방식",
+ "travel_agents": "여행 에이전트",
+ "share_itinerary": "일정 공유",
+ "save_for_mobile": "모바일 저장",
+ "built_with": "당신을 위해 ❤️ 만들어졌습니다",
+ # Additional text related to output
+ "itinerary_ready": "여행 일정이 준비되었습니다! 🎉",
+ "personalized_experience": "당신만을 위한 맞춤형 여행 경험이 만들어졌습니다. 아래에서 일정을 확인하세요.",
+ "agent_activity": "에이전트 활동",
+ "error_origin_destination": "출발지와 목적지를 모두 입력하세요.",
+ "your_itinerary_file": "당신의 여행 일정 파일",
+ "text_format": "텍스트 형식 - 모든 텍스트 편집기에서 열 수 있습니다."
+ },
+ "ja": {
+ "page_title": "あなたの旅行のためのAIエージェント",
+ "header": "あなたの旅行のためのAIエージェント",
+ "create_itinerary": "旅行プラン作成",
+ "trip_details": "旅行詳細",
+ "origin": "出発地",
+ "destination": "目的地",
+ "travel_dates": "旅行日程",
+ "duration": "期間(日数)",
+ "preferences": "好み",
+ "additional_preferences": "追加の好み",
+ "interests": "興味",
+ "special_requirements": "特別な要件",
+ "submit": "🚀 私のための旅行プラン作成",
+ "request_details": "旅行リクエスト",
+ "from": "出発地",
+ "when": "旅行期間",
+ "budget": "予算",
+ "travel_style": "旅行スタイル",
+ "live_agent_outputs": "リアルタイムエージェント出力",
+ "full_itinerary": "全行程",
+ "details": "詳細",
+ "download_share": "ダウンロードと共有",
+ "save_itinerary": "旅行プランを保存",
+ "plan_another_trip": "🔄 他の旅行を計画",
+ "about": "概要",
+ "how_it_works": "使い方",
+ "travel_agents": "旅行エージェント",
+ "share_itinerary": "旅行プランを共有",
+ "save_for_mobile": "モバイル保存",
+ "built_with": "愛を込めて作られました",
+ # Additional text related to output
+ "itinerary_ready": "旅行プランの準備ができました! 🎉",
+ "personalized_experience": "あなたのためにパーソナライズされた旅行体験を作成しました。下のプランをご覧ください。",
+ "agent_activity": "エージェントアクティビティ",
+ "error_origin_destination": "出発地と目的地の両方を入力してください。",
+ "your_itinerary_file": "あなたの旅行プランファイル",
+ "text_format": "テキスト形式 - 任意のテキストエディタで開けます。"
+ },
+ "zh": {
+ "page_title": "您的旅行 AI 代理",
+ "header": "您的旅行 AI 代理",
+ "create_itinerary": "创建您的行程",
+ "trip_details": "旅行详情",
+ "origin": "出发地",
+ "destination": "目的地",
+ "travel_dates": "旅行日期",
+ "duration": "天数",
+ "preferences": "偏好",
+ "additional_preferences": "其他偏好",
+ "interests": "兴趣",
+ "special_requirements": "特殊需求",
+ "submit": "🚀 创建我的个性化行程",
+ "request_details": "您的旅行请求",
+ "from": "出发地",
+ "when": "旅行时间",
+ "budget": "预算",
+ "travel_style": "旅行风格",
+ "live_agent_outputs": "实时代理输出",
+ "full_itinerary": "完整行程",
+ "details": "详情",
+ "download_share": "下载与分享",
+ "save_itinerary": "保存行程",
+ "plan_another_trip": "🔄 计划另一趟旅行",
+ "about": "关于",
+ "how_it_works": "工作原理",
+ "travel_agents": "旅行代理",
+ "share_itinerary": "分享行程",
+ "save_for_mobile": "保存到手机",
+ "built_with": "用❤️为您制作",
+ # Additional text related to output
+ "itinerary_ready": "您的旅行行程已准备就绪! 🎉",
+ "personalized_experience": "我们已为您创建了个性化的旅行体验,请在下方查看您的行程。",
+ "agent_activity": "代理活动",
+ "error_origin_destination": "请输入出发地和目的地。",
+ "your_itinerary_file": "您的行程文件",
+ "text_format": "文本格式 - 可在任何文本编辑器中打开。"
+ },
+ "es": {
+ "page_title": " Tu Agente de IA para Viajar",
+ "header": " Tu Agente de IA para Viajar",
+ "create_itinerary": "Crea Tu Itinerario",
+ "trip_details": "Detalles del Viaje",
+ "origin": "Origen",
+ "destination": "Destino",
+ "travel_dates": "Fechas del Viaje",
+ "duration": "Duración (días)",
+ "preferences": "Preferencias",
+ "additional_preferences": "Preferencias Adicionales",
+ "interests": "Intereses",
+ "special_requirements": "Requisitos Especiales",
+ "submit": "🚀 Crea Mi Itinerario Personalizado",
+ "request_details": "Tu Solicitud de Viaje",
+ "from": "Desde",
+ "when": "Cuándo",
+ "budget": "Presupuesto",
+ "travel_style": "Estilo de Viaje",
+ "live_agent_outputs": "Salidas en Vivo del Agente",
+ "full_itinerary": "Itinerario Completo",
+ "details": "Detalles",
+ "download_share": "Descargar y Compartir",
+ "save_itinerary": "Guardar Itinerario",
+ "plan_another_trip": "🔄 Planear Otro Viaje",
+ "about": "Acerca de",
+ "how_it_works": "Cómo Funciona",
+ "travel_agents": "Agentes de Viaje",
+ "share_itinerary": "Compartir Itinerario",
+ "save_for_mobile": "Guardar para Móvil",
+ "built_with": "Hecho con ❤️ para ti",
+ # Additional text related to output
+ "itinerary_ready": "¡Tu itinerario de viaje está listo! 🎉",
+ "personalized_experience": "Hemos creado una experiencia de viaje personalizada solo para ti. Explora tu itinerario a continuación.",
+ "agent_activity": "Actividad del Agente",
+ "error_origin_destination": "Por favor, ingresa tanto el origen como el destino.",
+ "your_itinerary_file": "Tu Archivo de Itinerario",
+ "text_format": "Formato de texto - Se puede abrir en cualquier editor de texto."
+ },
+ "fr": {
+ "page_title": " Votre Agent IA pour Voyager",
+ "header": " Votre Agent IA pour Voyager",
+ "create_itinerary": "Créez Votre Itinéraire",
+ "trip_details": "Détails du Voyage",
+ "origin": "Origine",
+ "destination": "Destination",
+ "travel_dates": "Dates du Voyage",
+ "duration": "Durée (jours)",
+ "preferences": "Préférences",
+ "additional_preferences": "Préférences Supplémentaires",
+ "interests": "Centres d'intérêt",
+ "special_requirements": "Exigences Spéciales",
+ "submit": "🚀 Créez Mon Itinéraire Personnalisé",
+ "request_details": "Votre Demande de Voyage",
+ "from": "De",
+ "when": "Quand",
+ "budget": "Budget",
+ "travel_style": "Style de Voyage",
+ "live_agent_outputs": "Résultats en Direct de l'Agent",
+ "full_itinerary": "Itinéraire Complet",
+ "details": "Détails",
+ "download_share": "Télécharger et Partager",
+ "save_itinerary": "Enregistrer l'Itinéraire",
+ "plan_another_trip": "🔄 Planifier un Autre Voyage",
+ "about": "À Propos",
+ "how_it_works": "Fonctionnement",
+ "travel_agents": "Agents de Voyage",
+ "share_itinerary": "Partager l'Itinéraire",
+ "save_for_mobile": "Enregistrer pour Mobile",
+ "built_with": "Conçu avec ❤️ pour vous",
+ # Additional text related to output
+ "itinerary_ready": "Votre itinéraire de voyage est prêt ! 🎉",
+ "personalized_experience": "Nous avons créé une expérience de voyage personnalisée rien que pour vous. Découvrez votre itinéraire ci-dessous.",
+ "agent_activity": "Activité de l'Agent",
+ "error_origin_destination": "Veuillez saisir à la fois le lieu de départ et la destination.",
+ "your_itinerary_file": "Votre Fichier d'Itinéraire",
+ "text_format": "Format texte - Peut être ouvert dans n'importe quel éditeur de texte."
+ },
+ "de": {
+ "page_title": "Ihr KI-Reiseassistent",
+ "header": " Ihr KI-Reiseassistent",
+ "create_itinerary": "Erstellen Sie Ihre Reiseroute",
+ "trip_details": "Reisedetails",
+ "origin": "Abfahrtsort",
+ "destination": "Zielort",
+ "travel_dates": "Reisedaten",
+ "duration": "Dauer (Tage)",
+ "preferences": "Vorlieben",
+ "additional_preferences": "Zusätzliche Vorlieben",
+ "interests": "Interessen",
+ "special_requirements": "Besondere Anforderungen",
+ "submit": "🚀 Erstellen Sie meine personalisierte Reiseroute",
+ "request_details": "Ihre Reiseanfrage",
+ "from": "Von",
+ "when": "Wann",
+ "budget": "Budget",
+ "travel_style": "Reisestil",
+ "live_agent_outputs": "Live Agent Ausgaben",
+ "full_itinerary": "Komplette Reiseroute",
+ "details": "Details",
+ "download_share": "Herunterladen & Teilen",
+ "save_itinerary": "Reiseroute speichern",
+ "plan_another_trip": "🔄 Plane eine weitere Reise",
+ "about": "Über",
+ "how_it_works": "Wie es funktioniert",
+ "travel_agents": "Reiseassistenten",
+ "share_itinerary": "Reiseroute teilen",
+ "save_for_mobile": "Für Mobilgeräte speichern",
+ "built_with": "Mit ❤️ für Sie gebaut",
+ # Additional text related to output
+ "itinerary_ready": "Ihre Reiseroute ist fertig! 🎉",
+ "personalized_experience": "Wir haben eine personalisierte Reiseerfahrung nur für Sie erstellt. Entdecken Sie Ihre Reiseroute unten.",
+ "agent_activity": "Agentenaktivität",
+ "error_origin_destination": "Bitte geben Sie sowohl den Abfahrtsort als auch das Ziel ein.",
+ "your_itinerary_file": "Ihre Reise-Datei",
+ "text_format": "Textformat – Kann in jedem Texteditor geöffnet werden."
+ },
+ "ar": {
+ "page_title": " وكيل السفر الذكي الخاص بك",
+ "header": " وكيل السفر الذكي الخاص بك",
+ "create_itinerary": "إنشاء خط سير الرحلة",
+ "trip_details": "تفاصيل الرحلة",
+ "origin": "المغادرة من",
+ "destination": "الوجهة",
+ "travel_dates": "تواريخ السفر",
+ "duration": "المدة (بالأيام)",
+ "preferences": "التفضيلات",
+ "additional_preferences": "تفضيلات إضافية",
+ "interests": "الاهتمامات",
+ "special_requirements": "المتطلبات الخاصة",
+ "submit": "🚀 إنشاء خط سير الرحلة الشخصي",
+ "request_details": "طلب السفر الخاص بك",
+ "from": "من",
+ "when": "متى",
+ "budget": "الميزانية",
+ "travel_style": "أسلوب السفر",
+ "live_agent_outputs": "مخرجات الوكيل المباشرة",
+ "full_itinerary": "خط سير الرحلة الكامل",
+ "details": "التفاصيل",
+ "download_share": "تنزيل ومشاركة",
+ "save_itinerary": "حفظ خط سير الرحلة",
+ "plan_another_trip": "🔄 خطط لرحلة أخرى",
+ "about": "حول",
+ "how_it_works": "كيف يعمل",
+ "travel_agents": "وكلاء السفر",
+ "share_itinerary": "شارك خط سير الرحلة",
+ "save_for_mobile": "حفظ للهاتف المحمول",
+ "built_with": "مصنوع بحب من أجلك",
+ # Additional text related to output
+ "itinerary_ready": "تم تجهيز خط سير رحلتك! 🎉",
+ "personalized_experience": "لقد أنشأنا تجربة سفر مخصصة لك. استعرض خط سير رحلتك أدناه.",
+ "agent_activity": "نشاط الوكيل",
+ "error_origin_destination": "يرجى إدخال نقطة الانطلاق والوجهة.",
+ "your_itinerary_file": "ملف خط سير رحلتك",
+ "text_format": "تنسيق نصي - يمكن فتحه في أي محرر نصوص."
+ }
+}
+
+def t(key):
+ lang = st.session_state.get("selected_language", "en")
+ return translations[lang].get(key, key)
+
+# ------------------------------------------
+# Session initialization
+# ------------------------------------------
+if 'selected_language' not in st.session_state:
+ st.session_state.selected_language = "en" # Default is English
+
+# ------------------------------------------
+# Add language selection widget to sidebar
+# ------------------------------------------
+with st.sidebar:
+ language = st.selectbox(
+ "Language / 언어 / 言語 / 语言 / Idioma / Langue / Sprache / اللغة",
+ ["English", "한국어", "日本語", "中文", "Español", "Français", "Deutsch", "العربية"]
+ )
+ lang_map = {
+ "English": "en",
+ "한국어": "ko",
+ "日本語": "ja",
+ "中文": "zh",
+ "Español": "es",
+ "Français": "fr",
+ "Deutsch": "de",
+ "العربية": "ar"
+ }
+ st.session_state.selected_language = lang_map.get(language, "en")
+
+# ------------------------------------------
+# Start of Streamlit UI code
+# ------------------------------------------
+
+# Modern CSS with refined color scheme and sleek animations
+st.markdown("""
+
+""", unsafe_allow_html=True)
+
+# Helper function to download HTML file
+def get_download_link(text_content, filename):
+ b64 = base64.b64encode(text_content.encode()).decode()
+ href = f'📥 {t("save_itinerary")}'
+ return href
+
+# Updated helper function to display modern progress with a single UI element
+def display_modern_progress(current_step, total_steps=6):
+ if 'progress_steps' not in st.session_state:
+ st.session_state.progress_steps = {
+ 0: {'status': 'pending', 'name': t("trip_details")},
+ 1: {'status': 'pending', 'name': t("about")},
+ 2: {'status': 'pending', 'name': t("travel_style")},
+ 3: {'status': 'pending', 'name': t("live_agent_outputs")},
+ 4: {'status': 'pending', 'name': t("download_share")},
+ 5: {'status': 'pending', 'name': t("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)
+
+ st.markdown("""
+
+
+ """, unsafe_allow_html=True)
+
+ 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):
+ 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):
+ log_message = f"🤖 Starting {task.agent.role}..."
+ st.session_state.log_messages.append(log_message)
+
+ with log_container:
+ st.markdown("### " + t("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("### " + t("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 초기화
+# ------------------------------------------
+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
+
+# Modern animated header
+st.markdown(f"""
+
+
+

+
+
{t("header")}
+
+ ✨ Create your personalized AI-powered travel itinerary in minutes! ✨
+
+
+""", unsafe_allow_html=True)
+
+st.markdown('
', unsafe_allow_html=True)
+
+with st.sidebar:
+ st.markdown("""
+
+

+
Your AI Agent for Travelling
+
AI-Powered Travel Planning
+
+ """, unsafe_allow_html=True)
+
+ st.markdown('', unsafe_allow_html=True)
+ st.markdown("### 🌟 " + t("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('
', unsafe_allow_html=True)
+
+ st.markdown('', unsafe_allow_html=True)
+ st.markdown("### 🔍 " + t("how_it_works"))
+ st.markdown("""
+
+ - 🖊️ Enter your travel details
+ - 🧠 AI analysis of your preferences
+ - 📋 Generate comprehensive itinerary
+ - 📥 Download and enjoy your trip!
+
+ """, unsafe_allow_html=True)
+ st.markdown('
', unsafe_allow_html=True)
+
+ st.markdown('', unsafe_allow_html=True)
+ st.markdown("### 🤖 Travel Agents")
+ agents = [
+ ("🔭 Research Specialist", "Finds the best destinations based on your preferences"),
+ ("🏨 Accommodation Expert", "Suggests suitable hotels and stays"),
+ ("🚆 Transportation Planner", "Plans efficient travel routes"),
+ ("🎯 Activities Curator", "Recommends activities tailored to your interests"),
+ ("🍽️ Dining Connoisseur", "Finds the best dining experiences"),
+ ("📅 Itinerary Creator", "Puts everything together in a daily plan")
+ ]
+ for name, desc in agents:
+ st.markdown("**" + name + "**")
+ st.markdown("" + desc + "", unsafe_allow_html=True)
+ st.markdown('
', unsafe_allow_html=True)
+
+if not st.session_state.generation_complete:
+ st.markdown('', unsafe_allow_html=True)
+ st.markdown("
✈️ " + t("create_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(t("origin"), placeholder="e.g., New York, USA")
+ destination = st.text_input(t("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(t("duration"), min_value=1, max_value=30, value=7)
+ end_date = start_date + timedelta(days=duration-1)
+ st.markdown('
' + 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", expanded=False):
+ 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(t("submit"))
+ st.markdown('
', unsafe_allow_html=True)
+
+ if submit_button:
+ if not origin or not destination:
+ st.error(t("error_origin_destination"))
+ else:
+ st.session_state.form_submitted = True
+ 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
+ }
+ # 기존의 여행 요청 프롬프트
+ 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']}
+"""
+
+ llm_language_instructions = {
+ "en": "Please output the response in English.",
+ "ko": "한국어로 출력해 주세요.",
+ "ja": "日本語で出力してください。",
+ "zh": "请用中文输出。",
+ "es": "Por favor, responda en español.",
+ "fr": "Veuillez répondre en français.",
+ "de": "Bitte antworten Sie auf Deutsch.",
+ "ar": "يرجى الرد باللغة العربية."
+ }
+ selected_lang = st.session_state.get("selected_language", "en")
+ language_instruction = llm_language_instructions.get(selected_lang, "Please output the response in English.")
+ modified_input_context = language_instruction + "\n" + input_context
+
+ st.markdown("""
+
+
+ """, unsafe_allow_html=True)
+
+ st.markdown('', unsafe_allow_html=True)
+ progress_tab, logs_tab, details_tab = st.tabs(["📊 Progress", "🔄 Live Activity", "📋 " + t("request_details")])
+ with details_tab:
+ st.markdown("#### " + t("request_details"))
+ st.markdown("**" + t("destination") + ":** " + user_input['destination'])
+ st.markdown("**" + t("from") + ":** " + user_input['origin'])
+ st.markdown("**" + t("when") + ":** " + user_input['travel_dates'] + " (" + user_input['duration'] + " days)")
+ st.markdown("**" + t("budget") + ":** " + user_input['budget'].title())
+ st.markdown("**" + t("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(0)
+ with logs_tab:
+ log_container = st.container()
+ st.session_state.log_messages = []
+ st.markdown('
', unsafe_allow_html=True)
+ output_container = st.container()
+ with output_container:
+ st.markdown('', unsafe_allow_html=True)
+ st.markdown("### 🌟 " + t("live_agent_outputs"))
+ st.info("Our AI agents will show their work here as they create your itinerary")
+ st.markdown('
', unsafe_allow_html=True)
+ st.session_state.current_step = 0
+
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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)
+ 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"
+
+if st.session_state.generation_complete:
+ st.markdown("""
+
+
+
""" + t("itinerary_ready") + """
+
""" + t("personalized_experience") + """
+
+
+
+ """, unsafe_allow_html=True)
+
+
+ itinerary_tab, details_tab, download_tab, map_tab, chatbot_tab = st.tabs([
+ "🗒️ " + t("full_itinerary"),
+ "💼 " + t("details"),
+ "💾 " + t("download_share"),
+ "🗺️ 지도 및 시각화",
+ "🤖 챗봇 인터페이스"
+ ])
+
+
+ with itinerary_tab:
+ st.text_area("Your Itinerary", st.session_state.generated_itinerary, height=600)
+
+ 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"])
+
+
+ with download_tab:
+ col1, col2 = st.columns([2, 1])
+ with col1:
+ st.markdown("### " + t("save_itinerary"))
+ st.markdown("Download your personalized travel plan to access it offline or share with your travel companions.")
+ st.markdown("""
+
+
""" + t("your_itinerary_file") + """
+
""" + t("text_format") + """
+ """, unsafe_allow_html=True)
+ 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("### " + t("share_itinerary"))
+ st.markdown("*Coming soon: Email your itinerary or share via social media.*")
+ with col2:
+ st.markdown("### " + t("save_for_mobile"))
+ st.markdown("*Coming soon: QR code for easy access on your phone*")
+
+
+ with map_tab:
+ st.markdown("### Destination Map")
+ # Example: Coordinate data for major attractions near destination (can be dynamically fetched via API or DB)
+ map_data = pd.DataFrame({
+ "lat": [48.8584, 48.8606, 48.8529],
+ "lon": [2.2945, 2.3376, 2.3500],
+ "name": ["Eiffel Tower", "Louvre Museum", "Notre Dame"]
+ })
+ # Default map output (st.map)
+ st.map(map_data)
+
+ st.markdown("#### Interactive Map with Pydeck")
+ view_state = pdk.ViewState(
+ latitude=48.8584,
+ longitude=2.2945,
+ zoom=12,
+ pitch=50
+ )
+
+ # AI Chatbot interface tab (using Gemini)
+ with chatbot_tab:
+ st.markdown("### AI Chatbot Interface")
+ # Store conversation history in session state (message, sender, timestamp)
+ if "messages" not in st.session_state:
+ st.session_state.messages = []
+
+ # User input field and send button
+ user_question = st.text_input("Ask me about your travel plans:", key="chat_input")
+
+ # Gemini-based chatbot response: use run_task() to query chatbot_task
+ if user_question and st.button("Ask", key="ask_button"):
+ response = run_task(chatbot_task, user_question)
+ st.session_state.messages.append({
+ "speaker": "User",
+ "message": user_question,
+ "time": datetime.now()
+ })
+ st.session_state.messages.append({
+ "speaker": "AI",
+ "message": response,
+ "time": datetime.now()
+ })
+
+ # Conversation history output (including timestamp, scrollable area)
+ st.markdown("", unsafe_allow_html=True)
+ for chat in st.session_state.messages:
+ time_str = chat["time"].strftime("%H:%M:%S")
+ st.markdown(f"**{chat['speaker']}** ({time_str}): {chat['message']}")
+ st.markdown("
", unsafe_allow_html=True)
+
+ st.markdown("""
+
+
""" + t("built_with") + """
+
+ """, unsafe_allow_html=True)