| import os
|
| import pickle
|
| import streamlit as st
|
| import requests
|
| import time
|
| from requests.exceptions import RequestException
|
|
|
|
|
| if 'page' not in st.session_state:
|
| st.session_state.page = 1
|
| if 'similar_indices_list' not in st.session_state:
|
| st.session_state.similar_indices_list = []
|
| if 'selected_movie_index' not in st.session_state:
|
| st.session_state.selected_movie_index = None
|
| if 'loaded_recommendations' not in st.session_state:
|
| st.session_state.loaded_recommendations = {'names': [], 'posters': []}
|
|
|
|
|
| @st.cache_data(show_spinner=False)
|
| def fetch_poster(movie_id):
|
| url = f"https://api.themoviedb.org/3/movie/{movie_id}?api_key=8265bd1679663a7ea12ac168da84d2e8&language=en-US"
|
| try:
|
| response = requests.get(url, timeout=5)
|
| response.raise_for_status()
|
| data = response.json()
|
| poster_path = data.get('poster_path')
|
| if poster_path:
|
| return "https://image.tmdb.org/t/p/w500/" + poster_path
|
| else:
|
| return "https://via.placeholder.com/300x450.png?text=No+Poster"
|
| except RequestException as e:
|
| print(f"Error fetching poster for movie ID {movie_id}: {e}")
|
| return "https://via.placeholder.com/300x450.png?text=Error"
|
|
|
|
|
| try:
|
| movies = pickle.load(open('artifacts/movies.pkl', 'rb')).reset_index(drop=True)
|
| similar_indices = pickle.load(open('artifacts/all_neighbors.pkl', 'rb'))
|
| except FileNotFoundError:
|
| st.error("Model files not found. Please make sure the 'artifacts' directory contains the required model files.")
|
| st.stop()
|
|
|
|
|
| def get_similar_indices(movie):
|
| if movie not in movies['title'].values:
|
| return []
|
|
|
| index = movies[movies['title'] == movie].index[0]
|
|
|
| return similar_indices[index][1:101]
|
|
|
|
|
| def load_recommendations_batch(indices, start_idx, batch_size=10):
|
| """Load a batch of movie recommendations"""
|
| end_idx = min(start_idx + batch_size, len(indices))
|
| names = []
|
| posters = []
|
|
|
|
|
| progress_bar = st.progress(0)
|
|
|
| for i, movie_idx in enumerate(indices[start_idx:end_idx]):
|
| movie_id = movies.iloc[movie_idx]['id']
|
| names.append(movies.iloc[movie_idx]['title'])
|
| posters.append(fetch_poster(movie_id))
|
|
|
|
|
| progress = (i + 1) / (end_idx - start_idx)
|
| progress_bar.progress(progress)
|
|
|
|
|
| progress_bar.empty()
|
|
|
| return names, posters, end_idx
|
|
|
|
|
| st.markdown("<h1 style='text-align: center; color: red;'>CineML: Movie Recommender</h1>", unsafe_allow_html=True)
|
|
|
| movie_list = movies['title'].values
|
| selected_movie = st.selectbox("Type or Select a movie to get recommendations", movie_list)
|
|
|
|
|
| if st.session_state.selected_movie_index is None or st.session_state.selected_movie_index != selected_movie:
|
| st.session_state.page = 5
|
| st.session_state.loaded_recommendations = {'names': [], 'posters': []}
|
|
|
| if st.button('Show Recommendations'):
|
|
|
| st.session_state.loaded_recommendations = {'names': [], 'posters': []}
|
| st.session_state.page = 1
|
|
|
|
|
| st.session_state.similar_indices_list = get_similar_indices(selected_movie)
|
| st.session_state.selected_movie_index = selected_movie
|
|
|
| if len(st.session_state.similar_indices_list) > 0:
|
|
|
| names, posters, _ = load_recommendations_batch(
|
| st.session_state.similar_indices_list,
|
| 0,
|
| batch_size=10
|
| )
|
|
|
| st.session_state.loaded_recommendations['names'] = names
|
| st.session_state.loaded_recommendations['posters'] = posters
|
| else:
|
| st.error(f"No recommendations found for {selected_movie}")
|
|
|
|
|
| if len(st.session_state.loaded_recommendations['names']) > 0:
|
| st.subheader(f"Recommendations for '{st.session_state.selected_movie_index}'")
|
|
|
|
|
| total = len(st.session_state.loaded_recommendations['names'])
|
| rows = (total + 4) // 5
|
|
|
| for row in range(rows):
|
| cols = st.columns(5)
|
| for i in range(5):
|
| idx = row * 5 + i
|
| if idx < total:
|
| with cols[i]:
|
| st.text(st.session_state.loaded_recommendations['names'][idx])
|
| st.image(st.session_state.loaded_recommendations['posters'][idx])
|
|
|
|
|
| current_loaded = len(st.session_state.loaded_recommendations['names'])
|
| similar_indices_length = len(st.session_state.similar_indices_list)
|
| if current_loaded < similar_indices_length:
|
| if st.button("Load More Recommendations"):
|
|
|
| names, posters, _ = load_recommendations_batch(
|
| st.session_state.similar_indices_list,
|
| current_loaded,
|
| batch_size=10
|
| )
|
|
|
|
|
| st.session_state.loaded_recommendations['names'].extend(names)
|
| st.session_state.loaded_recommendations['posters'].extend(posters)
|
|
|
|
|
| st.rerun()
|
|
|