BookRecommendationSystem / src /streamlit_app.py
handex's picture
Update src/streamlit_app.py
4e7c7b1 verified
Raw
History Blame Contribute Delete
3.56 kB
import streamlit as st
import pandas as pd
import joblib
import numpy as np
from sklearn.neighbors import NearestNeighbors
from sklearn.preprocessing import MinMaxScaler
import os
# --- Load Assets (Model and Data) ---
# Uses caching to load heavy files (model, idlist, scaler, and large DataFrame) only once.
@st.cache_resource
def load_assets():
# File Names
MODEL_FILENAME = 'src/book_recommendation_model.jobjob'
IDLIST_FILENAME = 'src/knn_idlist.jobjob'
SCALER_FILENAME = 'src/min_max_scaler.jobjob'
DATA_FILENAME = 'src/books.csv'
try:
# 1. Load Saved Objects
model = joblib.load(MODEL_FILENAME)
idlist = joblib.load(IDLIST_FILENAME)
scaler = joblib.load(SCALER_FILENAME)
# 2. Load the DataFrame
df = pd.read_csv(DATA_FILENAME, on_bad_lines='skip')
df.columns = df.columns.str.strip() # Clean column names
# 3. Check for essential column
if 'title' not in df.columns:
st.error("The DataFrame must contain a 'title' column.")
return None, None, None, None
# Successful return of 4 objects
return model, df, idlist, scaler
except FileNotFoundError:
st.error(f"Required files not found. Ensure '{MODEL_FILENAME}', '{IDLIST_FILENAME}', '{SCALER_FILENAME}', and '{DATA_FILENAME}' are in the same directory.")
return None, None, None, None
# Load assets upon application start
loaded_model, df, idlist, scaler = load_assets()
# --- Recommendation Function ---
def get_recommendations(book_name, df_data, id_list_data):
"""
Retrieves the titles of books similar to the given book name.
"""
# Find the index of the input book
try:
book_idx = df_data[df_data['title'] == book_name].index[0]
except IndexError:
return ["Error: The specified book title was not found in the dataset."], False
# Get neighbor indices from the pre-calculated idlist
# Note: idlist[book_idx] contains the indices of the neighbors
neighbor_indices = id_list_data[book_idx]
# Retrieve the titles of the neighboring books
# .unique() helps handle potential duplicates in the dataset
recommended_titles = df_data.loc[neighbor_indices, 'title'].unique().tolist()
# Remove the queried book itself from the list of recommendations
if book_name in recommended_titles:
recommended_titles.remove(book_name)
# Return the top 5 (or N-1 if N neighbors were used) recommendations
return recommended_titles[:5], True
# --- Streamlit Interface ---
if loaded_model is not None and df is not None:
st.title("๐Ÿ“š Book Recommendation System")
st.markdown("This application uses a pre-trained K-Nearest Neighbors model to suggest similar books.")
# Select box options
book_options = df['title'].unique()
selected_book = st.selectbox(
"Please select a book:",
options=book_options,
index=0
)
st.markdown("---")
if st.button("Generate Recommendations"):
with st.spinner('Searching for similar books...'):
recommendations, success = get_recommendations(selected_book, df, idlist)
if success:
st.subheader(f"Recommendations Similar to '{selected_book}':")
# Display recommendations as a numbered list
for i, title in enumerate(recommendations, 1):
st.success(f"{i}. **{title}**")
else:
st.error(recommendations[0])