HotelRecommendationSystem / src /streamlit_app.py
handex's picture
Update src/streamlit_app.py
7fcf7cd verified
Raw
History Blame Contribute Delete
5.82 kB
import streamlit as st
import pandas as pd
import pickle
from nltk.tokenize import word_tokenize
from nltk.stem import WordNetLemmatizer
from typing import Dict, Any, List
import nltk
import os
# --- NLTK PATH FIX (CRITICAL) ---
# setup.sh, NLTK verilerini 'src/' içine indirir.
# Uygulamanın da bu klasöre bakması gerektiğini belirtiyoruz.
NLTK_DATA_PATH = os.path.join(os.getcwd(), 'src')
if NLTK_DATA_PATH not in nltk.data.path:
# 'src/' yolunu NLTK arama yollarına ekliyoruz.
nltk.data.path.append(NLTK_DATA_PATH)
# --- Streamlit Sayfa Ayarları ---
st.set_page_config(
# Sayfa başlığına bina emojisi (🏢) eklendi
page_title="🏢 Hotel Recommendation System",
layout="wide",
initial_sidebar_state="collapsed"
)
# ----------------------------------------------------
# 1. Veri ve NLP Araçlarını Yükleme
# ----------------------------------------------------
# Verinin her etkileşimde yeniden yüklenmesini engellemek için önbelleğe alma
@st.cache_resource
def load_data():
"""Pickle dosyalarını yükler ve DataFrame ile NLP araçlarını döndürür."""
try:
# Dosyalar 'src/' içinden okunuyor (Lütfen dosya yollarınızın doğru olduğundan emin olun)
with open('src/hotel_data.pkl', 'rb') as file:
df_loaded = pickle.load(file)
with open('src/nlp_tools.pkl', 'rb') as file:
nlp_tools_loaded = pickle.load(file)
return {
'df': df_loaded,
'stop_words': nlp_tools_loaded['stop_words'],
'lemmatizer': nlp_tools_loaded['lemmatizer']
}
except FileNotFoundError as e:
st.error(f"Error: Required file not found: {e.filename}. Please ensure all required files are in the 'src/' directory.")
return None
except Exception as e:
st.error(f"An error occurred during loading: {e}")
return None
# Load the data bundle and unpack components
data_bundle = load_data()
if data_bundle is not None:
df = data_bundle['df']
# NLP araçları global değişkenlere atanır
STOP_WORDS = data_bundle['stop_words']
LEMMATIZER = data_bundle['lemmatizer']
else:
# Veri yüklenemezse uygulamayı durdur
st.stop()
# ----------------------------------------------------
# 2. Tavsiye Fonksiyonu (Optimize Edilmiş)
# ----------------------------------------------------
def recommend_hotel(location: str, description: str, data_df: pd.DataFrame) -> pd.DataFrame:
"""Kullanıcı açıklamasına göre otel benzerliğini hesaplar ve en iyi 5 öneriyi döndürür."""
if not isinstance(description, str):
return pd.DataFrame({'Error': ['Description must be a string.']})
# 1. Kullanıcı Açıklamasını İşleme
# NLTK, ayarlanmış yol sayesinde verileri bulacaktır.
description_tokens = word_tokenize(description.lower())
user_processed_set = set()
for word in description_tokens:
if word not in STOP_WORDS:
user_processed_set.add(LEMMATIZER.lemmatize(word))
if not user_processed_set:
return pd.DataFrame({'Error': ['Please enter a more descriptive query.']})
# 2. Konuma Göre Filtreleme
country = data_df[data_df['Country'] == location.lower()].copy()
if country.empty:
return pd.DataFrame({'Error': [f"No hotels found in '{location}'."]})
# 3. Benzerlik Hesaplama (Küme Kesişimi)
similarity_scores = country['Processed_Tags'].apply(
lambda hotel_tags: len(hotel_tags.intersection(user_processed_set)))
country['similarity'] = similarity_scores
# 4. Sıralama ve Filtreleme
country.sort_values(by=['similarity', 'Average_Score'],
ascending=[False, False],
inplace=True)
country.drop_duplicates(subset='Hotel_Name', keep='first', inplace=True)
country.reset_index(drop=True, inplace=True)
return country[["Hotel_Name", "Average_Score", "Hotel_Address"]].head(5)
# ----------------------------------------------------
# 3. Streamlit Arayüzü
# ----------------------------------------------------
# Ana başlıkta bina emojisi (🏢)
st.title("🏢 Hotel Recommendation System")
st.markdown("Find the top 5 hotels based on your preferred location and description.")
# --- Kullanıcı Girişleri ---
st.subheader("Find Your Optimal Hotel")
# Mevcut ülke listesini alma
available_countries = sorted(df['Country'].unique().tolist())
default_country = available_countries[0] if available_countries else ""
col1, col2 = st.columns(2)
with col1:
location = st.selectbox(
"Select Location (Country)",
options=available_countries,
# Hata düzeltildi
index=available_countries.index(default_country) if default_country else 0
)
with col2:
description = st.text_area(
"Preference Description",
placeholder="E.g., romantic trip with great breakfast and spa, or: business needs quiet room and gym",
height=100
)
# --- Buton ve Çıktı ---
if st.button("Get Recommendations", type="primary"):
if location and description:
# Tavsiye fonksiyonunu çağır
recommendations_df = recommend_hotel(location, description, df)
st.subheader("Top Recommended Hotels")
# Sonuçları görüntüle
if 'Error' in recommendations_df.columns:
st.error(recommendations_df.iloc[0]['Error'])
else:
# Sütun isimlerini daha okunaklı hale getir
recommendations_df.columns = ["Hotel Name", "Average Score", "Address"]
st.dataframe(recommendations_df, use_container_width=True)
else:
st.warning("Please enter both location and description.")