File size: 12,531 Bytes
8a40016
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
import streamlit as st
import os
from dotenv import load_dotenv
from crewai import Agent, Task, Crew, Process
from crewai import LLM
import litellm
from crewai_tools import SerperDevTool
from typing import Any, Dict
import sys
from datetime import datetime
from queue import Queue
import threading
from referral_codes import validate_referral_code

# Page config
st.set_page_config(
    page_title="Travel Planning Agent",
    page_icon="🌍",
    layout="wide"
)

# Load environment variables
load_dotenv()

def initialize_llm():
    # Get API key
    api_key = os.getenv("GEMINI_API_KEY")
    if not api_key:
        raise ValueError("GEMINI_API_KEY not found in environment variables")
    
    st.write(f"Debug: API Key found: {api_key[:10]}...")
    
    # Initialize Gemini LLM with API Key
    return LLM(
        model="gemini/gemini-1.5-pro-latest",
        api_key=api_key,
        temperature=0.7
    )

def create_travel_agent(llm):
    return Agent(
        role="Elite AI Travel Strategist",
        goal=(
            "Design the most optimized, personalized, and budget-conscious travel plans based on the user's unique preferences, "
            "including origin, destination, budget, travel dates, group size, preferred activities, and travel style. "
            "Leverage cutting-edge AI with real-time data from flights, hotels, transport services, local attractions, and events "
            "to craft seamless, time-efficient, and experience-rich itineraries. "
            "Ensure dynamic adaptability to handle disruptions, availability changes, and user modifications, creating a hassle-free travel experience."
        ),
        backstory=(
            "I am an AI-powered **Master Travel Architect** with deep expertise in curating extraordinary journeys tailored to individual tastes, "
            "whether for solo travelers, families, business professionals, or adventure seekers. "
            "With an extensive knowledge of global destinations, cultural insights, seasonal trends, and logistical intricacies, "
            "I meticulously craft itineraries that blend adventure, relaxation, and cultural immersion. "
            "By integrating real-time APIs for flights, accommodations, activities, and local events, "
            "I ensure each recommendation is accurate, cost-effective, and aligned with the traveler’s needs."
        ),
        personality=(
            "Hyper-intelligent, intuitive, and proactive. I am a meticulous planner with a deep understanding of travel logistics, "
            "capable of anticipating potential issues before they arise. "
            "I balance **comfort, adventure, and budget efficiency**, ensuring every itinerary is customized for a truly unique experience. "
            "I dynamically adjust plans based on live travel updates, offer personalized recommendations based on user preferences, "
            "and present a seamless blend of structured scheduling with flexibility. "
            "Whether it’s a luxury escape, an immersive cultural journey, or an action-packed adventure, I craft the **perfect** travel blueprint."
        ),
        tools=[SerperDevTool()],
        allow_delegation=True,
        humaninput=True,
        llm=llm,
        verbose=True
    )

def create_travel_task(agent, user_inputs):
    return Task(
        description=f"""
            You are an **AI Travel Planner** responsible for crafting a **personalized, budget-conscious, and time-efficient travel plan** using advanced tools for data retrieval, analysis, and real-time updates.

            The user has provided the following details:
            - **Origin:** {user_inputs['origin']}
            - **Destination:** {user_inputs['destination']}
            - **Budget:** {user_inputs['budget']} (in local currency)
            - **Preferred Activities:** {user_inputs['activities']}
            - **Transport Preference:** {user_inputs['transport']}
            - **Time Available:** {user_inputs['time']}

            ## **Step 1: Generate an Optimized Itinerary**
            - **Retrieve real-time data** (e.g., weather, crowd levels, and local events) to suggest the best times to visit attractions.
            - Create a **structured, multi-day travel plan** that maximizes available time while balancing **sightseeing, relaxation, and local experiences**.
            - Incorporate **seasonal and cultural insights** to enhance the travel experience.
            - Prioritize **time-efficient routes** using mapping tools.

            ## **Step 2: Smart Transport & Accommodation Planning**
            - Suggest the most **efficient transport options** based on {user_inputs['transport']}.
            - Compare **flights, trains, buses, or car rentals** for cost, duration, and convenience.
            - Recommend **accommodations** within budget, balancing comfort, location, and safety.
            - Provide estimated travel times and **real-time availability** for transport & hotels.
            - Include **relevant booking links** for:
              - **Flights:** Skyscanner, Google Flights, Kayak
              - **Trains & Buses:** Omio, Rail Europe, FlixBus
              - **Car Rentals:** Rentalcars, Turo, Enterprise
              - **Hotels & Stays:** Booking.com, Airbnb, Agoda

            ## **Step 3: Cost Estimation & Budgeting**
            - **Break down estimated costs** for:
              - **Transport:** (flights, public transport, or car rentals)
              - **Accommodation:** (hotels, hostels, or rentals)
              - **Meals & Dining:** (local food spots vs. premium dining)
              - **Activities & Attractions:** (ticket prices, entry fees, and reservations)
            - Offer **budget-friendly vs. premium options** while ensuring the plan stays within {user_inputs['budget']}.
            - Suggest **discount passes, travel cards, and best booking platforms** for savings.
            - Provide **direct booking links for tours, attractions, and dining** using:
              - **Attractions & Tours:** GetYourGuide, Viator, Klook
              - **Restaurant Reservations:** OpenTable, TheFork, Zomato

            ## **Step 4: Flexibility & Real-Time Adjustments**
            - **Retrieve live updates** on:
              - **Transport delays, strikes, or disruptions.**
              - **Weather conditions affecting travel plans.**
              - **Local event schedules & closures.**
            - Include **alternative activity suggestions** in case of last-minute changes.
            - Provide **emergency contacts, visa requirements, safety tips**, and **last-minute booking options**.
            - Offer a **summary dashboard** with real-time insights for easy decision-making.

            ## **Step 5: AI-Powered Personalized Enhancements**
            - Utilize **LLM-based recommendation engines** to personalize the itinerary based on travel history, reviews, and preferences.
            - Suggest **AI-curated food experiences, offbeat destinations, and hidden gems**.
            - Implement **interactive chatbot support** for instant Q&A and local guides.
        """,
        agent=agent,
        expected_output="""
            A structured, **highly optimized travel plan**, including:
            - **Day-by-day itinerary** tailored to user preferences.
            - **Real-time transport & accommodation recommendations** with direct booking links.
            - **Estimated cost breakdown** with budget-conscious choices.
            - **Dining & event recommendations** with reservation links.
            - **Alternative options & live travel insights** for flexibility.
            - **Safety, visa, and emergency contact details.**
            - **Interactive AI-driven suggestions for a hassle-free experience.**
            -**Links to the booking webistes for travel and hotel returned from the serperDevtool**
        """
    )

def log_status(container, message):
    """Simple function to log status messages using Streamlit's native components"""
    timestamp = datetime.now().strftime("%H:%M:%S")
    container.info(f"[{timestamp}] {message}")

def main():
    # Ensure environment variables are loaded
    load_dotenv()
    
    st.title("🌍 AI Travel Planning Assistant")
    
    # Session state for referral code validation
    if 'referral_validated' not in st.session_state:
        st.session_state.referral_validated = False
        st.session_state.user_type = None
    
    # Debug information in sidebar
    st.sidebar.title("Debug Information")
    st.sidebar.write(f"GEMINI_API_KEY present: {bool(os.getenv('GEMINI_API_KEY'))}")
    
    # Referral code validation
    if not st.session_state.referral_validated:
        st.write("Welcome! Please enter your referral code to access the travel planner.")
        with st.form("referral_form"):
            referral_code = st.text_input("Referral Code", key="referral_input")
            submit_code = st.form_submit_button("Submit")
            
            if submit_code:
                is_valid, user_type, message = validate_referral_code(referral_code)
                if is_valid:
                    st.session_state.referral_validated = True
                    st.session_state.user_type = user_type
                    st.success(f"Welcome! You have {user_type.title()} access.")
                    st.experimental_rerun()
                else:
                    st.error(message)
        return
    
    # Show user type in sidebar
    st.sidebar.write(f"Access Level: {st.session_state.user_type.title()}")
    
    st.write("Let me help you plan your perfect trip!")

    # Input form
    with st.form("travel_form"):
        col1, col2 = st.columns(2)
        
        with col1:
            origin = st.text_input("Origin", placeholder="e.g., New York")
            destination = st.text_input("Destination", placeholder="e.g., Paris")
            budget = st.number_input("Budget (in local currency)", min_value=0.0, value=1000.0, step=100.0)
        
        with col2:
            activities = st.text_input("Preferred Activities", placeholder="e.g., cultural, adventure, leisure")
            transport = st.text_input("Preferred Transport", placeholder="e.g., flight, train, bus")
            time = st.text_input("Time Available", placeholder="e.g., 5 days")

        submit_button = st.form_submit_button("Generate Travel Plan")

    if submit_button:
        if not all([origin, destination, activities, transport, time]):
            st.error("Please fill in all the fields!")
            return

        user_inputs = {
            "origin": origin,
            "destination": destination,
            "budget": budget,
            "activities": activities,
            "transport": transport,
            "time": time
        }

        with st.spinner("🤖 Generating your personalized travel plan... This may take a few minutes."):
            try:
                # Create an expander for logs
                with st.expander("Progress Updates", expanded=True):
                    status_container = st.empty()
                    
                    # Initialize components
                    log_status(status_container, "Initializing LLM...")
                    llm = initialize_llm()
                    
                    log_status(status_container, "Creating travel agent...")
                    travel_agent = create_travel_agent(llm)
                    
                    log_status(status_container, "Creating travel task...")
                    travel_task = create_travel_task(travel_agent, user_inputs)

                    log_status(status_container, "Setting up crew...")
                    crew = Crew(
                        agents=[travel_agent],
                        tasks=[travel_task],
                        verbose=True,
                        process=Process.sequential
                    )

                    log_status(status_container, "Starting travel plan generation...")
                    results = crew.kickoff()
                    
                    log_status(status_container, "✨ Travel plan generation completed!")

                # Display results
                st.success("✨ Your travel plan is ready!")
                st.markdown(results)

            except Exception as e:
                st.error(f"An error occurred: {str(e)}")
                st.error("Please try again or contact support if the problem persists.")

if __name__ == "__main__":
    main()