✈️ Flight4u – Intelligent Flight Search ApplicationΒΆ

🎯 Project Goal¢

Flight4u is an application that helps users find the most suitable flight offers based on their preferences. Data can be input via voice or text. The app transforms natural language input into filtering and sorting parameters and matches flight offers in real time.


🧰 Technologies and Tools¢

Category Technology Purpose
UI streamlit User interface
Voice Whisper, audiorecorder Handling audio recordings
AI OpenAI GPT-4o Semantic processing
Embeddings text-embedding-3-large Creating preference vectors
Vector Database Qdrant Vector-based database
Processing pandas, datetime, re Flight filtering and analysis

🧠 Converting Preferences and Adding to Database¢

Before user data can be processed by the app, the text must be:

  • transformed into a vector embedding (semantic representation),
  • numerically encoded for filtering (e.g., climate β†’ number),
  • stored in the Qdrant vector database as a new point.
# Create text embedding
def user_text_to_embedings(text):
    response = openai_client.embeddings.create(
        model="text-embedding-3-large",
        input=text,
        dimensions=1536
    )
    return response.data[0].embedding

# Add embedding + text to Qdrant database
def add_note_to_db(text_to_emb, text_to_db):
    qdrant_client = QdrantClient(
        url=env["QDRANT_URL"],
        api_key=env["QDRANT_API_KEY"]
    )

    points_count = qdrant_client.count(
        collection_name=QDRANT_COLLECTION_NAME,
        exact=True,
    )

    qdrant_client.upsert(
        collection_name=QDRANT_COLLECTION_NAME,
        points=[
            PointStruct(
                id=points_count.count + 1,
                vector=user_text_to_embedings(text_to_emb),
                payload=text_to_db
            )
        ]
    )

πŸ“₯ Data Input in the AppΒΆ

Users can:

  • type their preferences (e.g., β€œLooking for a warm vacation in July, max $2000”)
  • use the voice recording button 🎀

πŸ“Έ UI screenshot of preference input:
image.png


πŸ”’ Converting User Data into Numerical ValuesΒΆ

Some user input (e.g., climate, continent, season, time of day) is converted into numerical values to allow comparison and processing in filtering algorithms.

Example: Converting continents into numbers:

def classify_continent_number(time_of_flight_and_arrival):
    if time_of_flight_and_arrival == "Europe":
        return 0
    elif time_of_flight_and_arrival == "Africa":
        return 5
    elif time_of_flight_and_arrival == "Asia":
        return 10
    elif time_of_flight_and_arrival == "North America":
        return 15
    else:
        return 20

πŸ—ƒοΈ Retrieving Data from the Vector DatabaseΒΆ

Based on the user query (text or voice), an embedding is created and the most relevant flight options are retrieved from the Qdrant database.

Function for retrieving from the database:

def flights_from_db(query):
    flights = qdrant_client.search(
        collection_name=QDRANT_COLLECTION_NAME,
        query_vector=user_text_to_embedings(query),
        limit=400,
    )
    result = []
    for flight in flights:
        result.append({
            "destination": flight.payload["destination"], 
            "continent_of_destination": flight.payload["continent_of_destination"],
            "classify_continent_number": flight.payload["classify_continent_number"],
            "temperature_of_destination": flight.payload["temperature_of_destination"],
            "classify_climat_number": flight.payload["classify_climat_number"],
            "cost_of_both_flights": flight.payload["cost_of_both_flights"], 
            "amount_of_days_vacation": int(flight.payload["amount_of_days_vacation"]), 
            "categorized_dep_time_poland": flight.payload["categorized_dep_time_poland"],
            "categorized_dep_time_poland_number": flight.payload["categorized_dep_time_poland_number"],
            "categorized_dep_time_abroad": flight.payload["categorized_dep_time_abroad"], 
            "categorized_dep_time_abroad_number": flight.payload["categorized_dep_time_abroad_number"], 
            "when_flight": flight.payload["time_of_flight_and_arrival"],
            "when_flight_number": flight.payload["amount_of_days_when_flight_number"],
            "season_of_flight": flight.payload["season_of_departure"],
            "season_of_flight_number": flight.payload["season_of_departure_number"],
            "month_of_flight": flight.payload["month_of_flight"],
            "month_of_flight_number": flight.payload["month_of_flight_number"],
            "score": flight.score,
        })
    result_df = pd.DataFrame(result)
    return result_df

🧠 Filtering Results Based on User Preferences¢

After selecting the 400 most similar results via embeddings, the app filters these using additional user preferences (climate, budget, time of day, vacation duration) to find the best matches.

πŸ” How Does Filtering Work?ΒΆ

In each category (e.g., climate, continent, vacation length, flight time):

  1. User preferences are converted to numerical values.
  2. For each offer, the difference between the user's value and the offer’s value is calculated.
  3. The absolute value of this difference is computed.
  4. All differences are summed and stored in the preference_score column.
  5. The data is sorted ascendingly by preference_score.

πŸ’‘ The lower the preference_score, the better the match.


πŸ“¦ Example of Matching AlgorithmΒΆ

User input:

"I want to go on vacation to a warm country in July, preferably in the morning, for around 7 days, max $2000"

The app:

  • Creates an embedding and selects the 400 most similar records.
  • Then checks each offer:
Category User Preference Offer Value Absolute Difference
Climate 10 (warm) 8 (very warm) abs(10 - 8) = 2
Departure Time (PL) 0 (morning) 3 (afternoon) abs(0 - 3) = 3
Budget ≀ $2000 $1950 βœ… within limit
Vacation Duration 7 days 6 days abs(7 - 6) = 1
  • Total preference_score = 2 + 3 + 1 = 6
  • Offers with lowest scores appear at the top.

πŸ“ˆ Visual OutputΒΆ

After identifying the best-matching offers, the application presents them clearly and attractively in the user interface using Streamlit’s HTML component.

πŸ“Έ Screenshot of an offer presentation:

image-2.png

πŸš€ Potential App ImprovementsΒΆ

While the application already works efficiently, several enhancements could improve its functionality:

  • πŸ” Multi-criteria search – allow users to prioritize (e.g., "climate is more important than price").
  • πŸ“… Real-time availability checks – integrate with airline APIs to show only live offers.
  • πŸ“Š Comparative visualizations – interactive charts comparing prices, durations, and weather.

πŸ’‘ With these upgrades, the app could become even smarter, more useful, and competitive in the travel market! '''