mtoft20 commited on
Commit
bb3d1ab
Β·
verified Β·
1 Parent(s): c64c8cb

Update src/streamlit_app.py

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +67 -1
src/streamlit_app.py CHANGED
@@ -3,6 +3,10 @@ import requests
3
  import pandas as pd
4
  from together import Together
5
  import os
 
 
 
 
6
 
7
  # =============================================================================
8
  # CONFIGURATION - Using Secrets Management
@@ -231,6 +235,51 @@ def extract_unique_names(content_list, field):
231
  unique_names.add(cleaned_name)
232
  return sorted(list(unique_names))
233
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
234
  # =============================================================================
235
  # MAIN APP
236
  # =============================================================================
@@ -276,6 +325,10 @@ def main():
276
  st.error("Could not load Netflix content. Please check your NocoDB connection.")
277
  st.stop()
278
 
 
 
 
 
279
  # Extract unique values for filters
280
  all_ratings = sorted(list(set([c.get('rating') for c in all_content if c.get('rating')])))
281
  all_genres = sorted(list(set(
@@ -413,7 +466,7 @@ def main():
413
  st.write(f"- Cast: {filters['cast']}")
414
  st.write("---")
415
 
416
- # Show first 10 items
417
  for i, content in enumerate(st.session_state.filtered_content[:10]):
418
  with st.expander(f"{content.get('title', 'N/A')} ({content.get('release_year', 'N/A')})"):
419
  # Content details in columns
@@ -434,6 +487,19 @@ def main():
434
  # Description
435
  st.write(f"**πŸ“– Description:**")
436
  st.write(content.get('description', 'N/A'))
 
 
 
 
 
 
 
 
 
 
 
 
 
437
 
438
  if filtered_count > 10:
439
  st.info(f"Showing first 10 of {filtered_count:,} titles. Adjust filters to narrow results.")
 
3
  import pandas as pd
4
  from together import Together
5
  import os
6
+ import numpy as np
7
+ from sentence_transformers import SentenceTransformer
8
+ from sklearn.metrics.pairwise import cosine_similarity
9
+ import pickle
10
 
11
  # =============================================================================
12
  # CONFIGURATION - Using Secrets Management
 
235
  unique_names.add(cleaned_name)
236
  return sorted(list(unique_names))
237
 
238
+ def generate_content_embeddings(content_list, model_name='all-MiniLM-L6-v2'):
239
+ """Generate embeddings for content using sentence transformers"""
240
+ # Check if embeddings already exist
241
+ if os.path.exists('content_embeddings.pkl'):
242
+ with open('content_embeddings.pkl', 'rb') as f:
243
+ return pickle.load(f)
244
+
245
+ # Initialize the model
246
+ model = SentenceTransformer(model_name)
247
+
248
+ # Prepare content descriptions
249
+ descriptions = []
250
+ for content in content_list:
251
+ # Combine relevant text fields for better embedding
252
+ text = f"{content.get('title', '')} {content.get('description', '')} {content.get('listed_in', '')} {content.get('cast', '')} {content.get('director', '')}"
253
+ descriptions.append(text)
254
+
255
+ # Generate embeddings
256
+ embeddings = model.encode(descriptions, show_progress_bar=True)
257
+
258
+ # Save embeddings
259
+ with open('content_embeddings.pkl', 'wb') as f:
260
+ pickle.dump(embeddings, f)
261
+
262
+ return embeddings
263
+
264
+ def get_content_recommendations(content_list, selected_content_idx, embeddings, n_recommendations=5):
265
+ """Get content recommendations based on similarity"""
266
+ # Calculate similarity scores
267
+ similarity_scores = cosine_similarity([embeddings[selected_content_idx]], embeddings)[0]
268
+
269
+ # Get indices of top similar items (excluding self)
270
+ similar_indices = similarity_scores.argsort()[::-1][1:n_recommendations+1]
271
+
272
+ # Get similarity scores for recommended items
273
+ scores = similarity_scores[similar_indices]
274
+
275
+ # Get recommended content items with their similarity scores
276
+ recommendations = [
277
+ (content_list[idx], score)
278
+ for idx, score in zip(similar_indices, scores)
279
+ ]
280
+
281
+ return recommendations
282
+
283
  # =============================================================================
284
  # MAIN APP
285
  # =============================================================================
 
325
  st.error("Could not load Netflix content. Please check your NocoDB connection.")
326
  st.stop()
327
 
328
+ # Generate content embeddings
329
+ with st.spinner("Generating content embeddings (this may take a while the first time)..."):
330
+ embeddings = generate_content_embeddings(all_content)
331
+
332
  # Extract unique values for filters
333
  all_ratings = sorted(list(set([c.get('rating') for c in all_content if c.get('rating')])))
334
  all_genres = sorted(list(set(
 
466
  st.write(f"- Cast: {filters['cast']}")
467
  st.write("---")
468
 
469
+ # Show first 10 items with recommendation buttons
470
  for i, content in enumerate(st.session_state.filtered_content[:10]):
471
  with st.expander(f"{content.get('title', 'N/A')} ({content.get('release_year', 'N/A')})"):
472
  # Content details in columns
 
487
  # Description
488
  st.write(f"**πŸ“– Description:**")
489
  st.write(content.get('description', 'N/A'))
490
+
491
+ # Find content index in original list for recommendations
492
+ try:
493
+ content_idx = all_content.index(content)
494
+ if st.button(f"🎯 Get Similar Content", key=f"rec_{i}"):
495
+ recommendations = get_content_recommendations(all_content, content_idx, embeddings)
496
+ st.write("**🎬 Similar Content You Might Like:**")
497
+ for rec, score in recommendations:
498
+ score_percentage = int(score * 100)
499
+ st.write(f"- **{rec.get('title')}** ({rec.get('release_year')}) - {score_percentage}% match")
500
+ st.write(f" *{rec.get('type')} | {rec.get('listed_in')}*")
501
+ except ValueError:
502
+ st.error("Unable to generate recommendations for this title.")
503
 
504
  if filtered_count > 10:
505
  st.info(f"Showing first 10 of {filtered_count:,} titles. Adjust filters to narrow results.")