-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathstreamlit_app.py
More file actions
151 lines (129 loc) · 5.17 KB
/
streamlit_app.py
File metadata and controls
151 lines (129 loc) · 5.17 KB
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
import pickle
import streamlit as st
import requests
# --- Page Configuration ---
st.set_page_config(
page_title="CineSuggest Movie Recommender",
page_icon="🎬",
layout="wide"
)
# --- Custom CSS for Styling ---
def local_css(file_name):
with open(file_name) as f:
st.markdown(f'<style>{f.read()}</style>', unsafe_allow_html=True)
st.markdown("""
<style>
.movie-title {
font-size: 16px;
font-weight: bold;
color: #FFFFFF; /* White text for better contrast on dark theme */
text-align: center;
height: 60px; /* Fixed height to ensure alignment */
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2; /* Limit to 2 lines */
-webkit-box-orient: vertical;
}
.stButton>button {
width: 100%;
border-radius: 20px;
background-color: #FF4B4B;
}
.footer {
text-align: center;
padding: 1.5rem 0;
margin-top: 2rem;
border-top: 1px solid #dee2e6;
color: #6c757d;
}
.social-links {
margin-top: 0.5rem;
}
.social-links a {
margin: 0 10px;
text-decoration: none;
font-size: 1.2rem;
}
</style>
""", unsafe_allow_html=True)
# --- Data Loading (Cached for Performance) ---
@st.cache_data
def load_data():
"""Loads the movie data and similarity matrix from pickle files."""
try:
movies = pickle.load(open('artifacts/movies.pkl', 'rb'))
similarity = pickle.load(open('artifacts/similarity.pkl', 'rb'))
return movies, similarity
except FileNotFoundError:
st.error("Model files not found. Please ensure 'artifacts/movies.pkl' and 'artifacts/similarity.pkl' exist.")
return None, None
movies, similarity = load_data()
# --- API Call to TMDB ---
def fetch_poster(movie_id):
"""Fetches the movie poster path from the TMDB API."""
try:
url = f"https://api.themoviedb.org/3/movie/{movie_id}?api_key={st.secrets["TMDB_API_KEY"]}&language=en-US"
response = requests.get(url)
response.raise_for_status() # Raises an exception for 4XX/5XX errors
movie_data_json = response.json()
poster_path = movie_data_json.get('poster_path')
if poster_path:
full_poster_path = "https://image.tmdb.org/t/p/w500/" + poster_path
return full_poster_path
else:
return "https://via.placeholder.com/500x750.png?text=No+Poster+Available" # Placeholder
except requests.exceptions.RequestException as e:
st.warning(f"Could not fetch poster for movie ID {movie_id}: {e}")
return "https://via.placeholder.com/500x750.png?text=API+Error" # Placeholder for API error
# --- Recommendation Logic ---
def recommend_similar(movie_name):
"""Recommends 5 similar movies based on the selected movie."""
try:
original_idx_in_movies = movies[movies['title'] == movie_name].index[0]
distances = sorted(enumerate(similarity[original_idx_in_movies]), reverse=True, key=lambda x: x[1])
reco_list = []
reco_list_posters = []
for pair in distances[1:6]: # Start from 1 to skip the movie itself
reco_idx_in_matrix = pair[0]
movie_id = movies.iloc[reco_idx_in_matrix].id
reco_list.append(movies.iloc[reco_idx_in_matrix].title)
reco_list_posters.append(fetch_poster(movie_id))
return reco_list, reco_list_posters
except IndexError:
st.error(f"Movie '{movie_name}' not found in the dataset.")
return [], []
# --- UI Layout ---
st.markdown("<h1 style='text-align: center; color: #FF4B4B;'>CineSuggest 🍿</h1>", unsafe_allow_html=True)
st.markdown("<h3 style='text-align: center; color: #FFFFFF;'>Find Your Next Favorite Movie</h3>", unsafe_allow_html=True)
if movies is not None:
movie_list = movies['title'].values
selected_movie = st.selectbox(
'Type or select a movie you like from the dropdown below:',
movie_list
)
if st.button('Get Recommendations'):
with st.spinner('Finding similar movies for you...'):
recommended_movies_name, recommended_movies_poster = recommend_similar(selected_movie)
if recommended_movies_name:
st.subheader("Here are your recommendations:")
cols = st.columns(5)
for i in range(5):
with cols[i]:
st.markdown(f"<p class='movie-title'>{recommended_movies_name[i]}</p>", unsafe_allow_html=True)
st.image(recommended_movies_poster[i])
# --- Footer with Social Links ---
st.markdown("""
<div class="footer">
<h3>Like this Movie Recommender? 🚀</h3>
<p>Let's collaborate on your next ML project!</p>
<div class="social-links">
<a href="https://www.github.com/harsh-c137" target="_blank">
<img src="https://cdn.jsdelivr.net/gh/simple-icons/simple-icons/icons/github.svg" alt="GitHub Icon" width="20" height="20"> GitHub
</a>
<a href="https://www.linkedin.com/in/harsh-deshpande-v1/" target="_blank">
<img src="https://www.svgrepo.com/show/157006/linkedin.svg" alt="LinkedIn Icon" width="20" height="20"> LinkedIn
</a>
</div>
</div>
""", unsafe_allow_html=True)