N-Kibria commited on
Commit
cd645ae
Β·
verified Β·
1 Parent(s): a3cd8bd

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +16 -182
app.py CHANGED
@@ -1,10 +1,3 @@
1
- """
2
- Gradio App for Hybrid Movie Recommendation System
3
- Deploy to Hugging Face Spaces as 'DataSynthis_Job_task'
4
-
5
- File: app.py
6
- """
7
-
8
  import gradio as gr
9
  import pickle
10
  import pandas as pd
@@ -14,20 +7,13 @@ import torch.nn as nn
14
  import os
15
  from scipy.sparse import csr_matrix
16
 
17
- #==============================================================================
18
- # MODEL CLASS DEFINITIONS (Required for unpickling)
19
- #==============================================================================
20
-
21
  class ItemBasedCF:
22
- """Item-Based Collaborative Filtering"""
23
  pass
24
 
25
  class SVDRecommender:
26
- """SVD Recommender"""
27
  pass
28
 
29
  class NeuralCF(nn.Module):
30
- """Neural Collaborative Filtering Model"""
31
 
32
  def __init__(self, n_users, n_movies, embedding_dim=50, hidden_layers=[64, 32, 16]):
33
  super(NeuralCF, self).__init__()
@@ -60,22 +46,14 @@ class NeuralCF(nn.Module):
60
  return torch.clamp(prediction, 1, 5).item()
61
 
62
  class HybridRecommender:
63
- """Hybrid Recommendation System"""
64
  pass
65
 
66
  class MovieLensDataLoader:
67
- """Data Loader"""
68
  pass
69
 
70
- #==============================================================================
71
- # LOAD MODEL AND DATA
72
- #==============================================================================
73
-
74
  def load_model_and_data():
75
- """Load the trained model and necessary data"""
76
  import os
77
 
78
- # Debug: Check what files exist
79
  print("Checking for files...")
80
  print(f"Current directory: {os.getcwd()}")
81
  print(f"Files in current directory: {os.listdir('.')}")
@@ -86,7 +64,6 @@ def load_model_and_data():
86
  print("ERROR: model_artifacts/ folder does not exist!")
87
 
88
  try:
89
- # Check each file individually
90
  files_to_check = [
91
  'model_artifacts/hybrid_model.pkl',
92
  'model_artifacts/loader.pkl',
@@ -97,10 +74,9 @@ def load_model_and_data():
97
  if not os.path.exists(file_path):
98
  print(f"ERROR: Missing file: {file_path}")
99
  else:
100
- file_size = os.path.getsize(file_path) / (1024*1024) # MB
101
  print(f"Found: {file_path} ({file_size:.2f} MB)")
102
 
103
- # Load files
104
  with open('model_artifacts/hybrid_model.pkl', 'rb') as f:
105
  model = pickle.load(f)
106
  print("βœ“ Loaded hybrid_model.pkl")
@@ -113,7 +89,6 @@ def load_model_and_data():
113
  movies = pickle.load(f)
114
  print("βœ“ Loaded movies.pkl")
115
 
116
- # Get list of users
117
  user_ids = sorted(loader.user_id_map.keys())
118
  print(f"βœ“ Model loaded successfully! {len(user_ids)} users available")
119
 
@@ -128,26 +103,11 @@ def load_model_and_data():
128
  traceback.print_exc()
129
  return None, None, None, []
130
 
131
- # Load everything at startup
132
  print("Loading model and data...")
133
  model, loader, movies_df, user_ids = load_model_and_data()
134
  print(f"Model loaded! Available users: {len(user_ids)}")
135
 
136
- #==============================================================================
137
- # RECOMMENDATION FUNCTION
138
- #==============================================================================
139
-
140
  def get_recommendations(user_id, num_recommendations):
141
- """
142
- Get movie recommendations for a user
143
-
144
- Args:
145
- user_id: User ID (int)
146
- num_recommendations: Number of recommendations to return
147
-
148
- Returns:
149
- Formatted string with recommendations
150
- """
151
  if model is None or loader is None:
152
  return "❌ Error: Model not loaded properly. Please check the model files."
153
 
@@ -155,11 +115,9 @@ def get_recommendations(user_id, num_recommendations):
155
  user_id = int(user_id)
156
  num_recommendations = int(num_recommendations)
157
 
158
- # Check if user exists
159
  if user_id not in loader.user_id_map:
160
  return f"❌ User ID {user_id} not found! Please select a valid user ID."
161
 
162
- # Get recommendations
163
  recommendations = model.recommend_movies(
164
  user_id=user_id,
165
  N=num_recommendations,
@@ -171,7 +129,6 @@ def get_recommendations(user_id, num_recommendations):
171
  if not recommendations:
172
  return f"❌ No recommendations found for User {user_id}"
173
 
174
- # Format output
175
  output = f"🎬 **Top {num_recommendations} Movie Recommendations for User {user_id}**\n\n"
176
  output += "=" * 60 + "\n\n"
177
 
@@ -188,17 +145,7 @@ def get_recommendations(user_id, num_recommendations):
188
  except Exception as e:
189
  return f"❌ Error generating recommendations: {str(e)}"
190
 
191
-
192
  def get_user_history(user_id):
193
- """
194
- Show user's rating history
195
-
196
- Args:
197
- user_id: User ID
198
-
199
- Returns:
200
- Formatted string with user's past ratings
201
- """
202
  if model is None or loader is None:
203
  return "❌ Error: Model not loaded properly."
204
 
@@ -210,14 +157,12 @@ def get_user_history(user_id):
210
 
211
  user_idx = loader.user_id_map[user_id]
212
 
213
- # Get user's ratings from the training data
214
  user_ratings = model.item_cf.user_item_matrix[user_idx].toarray().flatten()
215
  rated_indices = np.where(user_ratings > 0)[0]
216
 
217
  if len(rated_indices) == 0:
218
  return f"No rating history found for User {user_id}"
219
 
220
- # Get movie details
221
  history = []
222
  for movie_idx in rated_indices:
223
  original_movie_id = loader.reverse_movie_map[movie_idx]
@@ -225,10 +170,8 @@ def get_user_history(user_id):
225
  rating = user_ratings[movie_idx]
226
  history.append((title, rating))
227
 
228
- # Sort by rating (highest first)
229
  history.sort(key=lambda x: x[1], reverse=True)
230
 
231
- # Format output
232
  output = f"πŸ“Š **Rating History for User {user_id}**\n\n"
233
  output += f"Total movies rated: {len(history)}\n"
234
  output += f"Average rating: {np.mean([r for _, r in history]):.2f}\n\n"
@@ -244,22 +187,11 @@ def get_user_history(user_id):
244
  except Exception as e:
245
  return f"❌ Error: {str(e)}"
246
 
247
-
248
  def get_movie_info(movie_title_search):
249
- """
250
- Search for movies by title
251
-
252
- Args:
253
- movie_title_search: Search query
254
-
255
- Returns:
256
- Formatted string with matching movies
257
- """
258
  if movies_df is None:
259
  return "❌ Error: Movies data not loaded"
260
 
261
  try:
262
- # Search for movies
263
  matches = movies_df[movies_df['title'].str.contains(movie_title_search, case=False, na=False)]
264
 
265
  if len(matches) == 0:
@@ -280,12 +212,6 @@ def get_movie_info(movie_title_search):
280
  except Exception as e:
281
  return f"❌ Error: {str(e)}"
282
 
283
-
284
- #==============================================================================
285
- # GRADIO INTERFACE
286
- #==============================================================================
287
-
288
- # Create Gradio interface with tabs
289
  with gr.Blocks(theme=gr.themes.Soft(), title="Movie Recommender - DataSynthis") as demo:
290
 
291
  gr.Markdown("""
@@ -300,7 +226,6 @@ with gr.Blocks(theme=gr.themes.Soft(), title="Movie Recommender - DataSynthis")
300
 
301
  with gr.Tabs():
302
 
303
- # TAB 1: Get Recommendations
304
  with gr.Tab("🎯 Get Recommendations"):
305
  gr.Markdown("### Get personalized movie recommendations for any user")
306
 
@@ -345,7 +270,6 @@ with gr.Blocks(theme=gr.themes.Soft(), title="Movie Recommender - DataSynthis")
345
  - Click "Get Recommendations" to see personalized movie suggestions
346
  """)
347
 
348
- # TAB 2: User History
349
  with gr.Tab("πŸ“Š User History"):
350
  gr.Markdown("### View a user's rating history")
351
 
@@ -374,7 +298,6 @@ with gr.Blocks(theme=gr.themes.Soft(), title="Movie Recommender - DataSynthis")
374
  outputs=history_output
375
  )
376
 
377
- # TAB 3: Search Movies
378
  with gr.Tab("πŸ” Search Movies"):
379
  gr.Markdown("### Search for movies in the database")
380
 
@@ -401,7 +324,6 @@ with gr.Blocks(theme=gr.themes.Soft(), title="Movie Recommender - DataSynthis")
401
  outputs=search_output
402
  )
403
 
404
- # TAB 4: About
405
  with gr.Tab("ℹ️ About"):
406
  gr.Markdown("""
407
  ## About This System
@@ -446,7 +368,6 @@ with gr.Blocks(theme=gr.themes.Soft(), title="Movie Recommender - DataSynthis")
446
  User IDs range from 1 to 943, and movie IDs range from 1 to 1682.
447
  """)
448
 
449
- # Footer
450
  gr.Markdown("""
451
  ---
452
  <div style='text-align: center'>
@@ -454,20 +375,12 @@ with gr.Blocks(theme=gr.themes.Soft(), title="Movie Recommender - DataSynthis")
454
  </div>
455
  """)
456
 
457
- # Launch the app
458
  if __name__ == "__main__":
459
  demo.launch(
460
  share=False,
461
  server_name="0.0.0.0",
462
  server_port=7860
463
- )"""
464
- Gradio App for Hybrid Movie Recommendation System
465
- Deploy to Hugging Face Spaces as 'DataSynthis_Job_task'
466
-
467
- File: app.py
468
- """
469
-
470
- import gradio as gr
471
  import pickle
472
  import pandas as pd
473
  import numpy as np
@@ -476,20 +389,13 @@ import torch.nn as nn
476
  import os
477
  from scipy.sparse import csr_matrix
478
 
479
- #==============================================================================
480
- # MODEL CLASS DEFINITIONS (Required for unpickling)
481
- #==============================================================================
482
-
483
  class ItemBasedCF:
484
- """Item-Based Collaborative Filtering"""
485
  pass
486
 
487
  class SVDRecommender:
488
- """SVD Recommender"""
489
  pass
490
 
491
  class NeuralCF(nn.Module):
492
- """Neural Collaborative Filtering Model"""
493
 
494
  def __init__(self, n_users, n_movies, embedding_dim=50, hidden_layers=[64, 32, 16]):
495
  super(NeuralCF, self).__init__()
@@ -522,22 +428,14 @@ class NeuralCF(nn.Module):
522
  return torch.clamp(prediction, 1, 5).item()
523
 
524
  class HybridRecommender:
525
- """Hybrid Recommendation System"""
526
  pass
527
 
528
  class MovieLensDataLoader:
529
- """Data Loader"""
530
  pass
531
 
532
- #==============================================================================
533
- # LOAD MODEL AND DATA
534
- #==============================================================================
535
-
536
  def load_model_and_data():
537
- """Load the trained model and necessary data"""
538
  import os
539
 
540
- # Debug: Check what files exist
541
  print("Checking for files...")
542
  print(f"Current directory: {os.getcwd()}")
543
  print(f"Files in current directory: {os.listdir('.')}")
@@ -548,7 +446,6 @@ def load_model_and_data():
548
  print("ERROR: model_artifacts/ folder does not exist!")
549
 
550
  try:
551
- # Check each file individually
552
  files_to_check = [
553
  'model_artifacts/hybrid_model.pkl',
554
  'model_artifacts/loader.pkl',
@@ -559,10 +456,9 @@ def load_model_and_data():
559
  if not os.path.exists(file_path):
560
  print(f"ERROR: Missing file: {file_path}")
561
  else:
562
- file_size = os.path.getsize(file_path) / (1024*1024) # MB
563
  print(f"Found: {file_path} ({file_size:.2f} MB)")
564
 
565
- # Load files
566
  with open('model_artifacts/hybrid_model.pkl', 'rb') as f:
567
  model = pickle.load(f)
568
  print("βœ“ Loaded hybrid_model.pkl")
@@ -575,7 +471,6 @@ def load_model_and_data():
575
  movies = pickle.load(f)
576
  print("βœ“ Loaded movies.pkl")
577
 
578
- # Get list of users
579
  user_ids = sorted(loader.user_id_map.keys())
580
  print(f"βœ“ Model loaded successfully! {len(user_ids)} users available")
581
 
@@ -590,26 +485,11 @@ def load_model_and_data():
590
  traceback.print_exc()
591
  return None, None, None, []
592
 
593
- # Load everything at startup
594
  print("Loading model and data...")
595
  model, loader, movies_df, user_ids = load_model_and_data()
596
  print(f"Model loaded! Available users: {len(user_ids)}")
597
 
598
- #==============================================================================
599
- # RECOMMENDATION FUNCTION
600
- #==============================================================================
601
-
602
  def get_recommendations(user_id, num_recommendations):
603
- """
604
- Get movie recommendations for a user
605
-
606
- Args:
607
- user_id: User ID (int)
608
- num_recommendations: Number of recommendations to return
609
-
610
- Returns:
611
- Formatted string with recommendations
612
- """
613
  if model is None or loader is None:
614
  return "❌ Error: Model not loaded properly. Please check the model files."
615
 
@@ -617,11 +497,9 @@ def get_recommendations(user_id, num_recommendations):
617
  user_id = int(user_id)
618
  num_recommendations = int(num_recommendations)
619
 
620
- # Check if user exists
621
  if user_id not in loader.user_id_map:
622
  return f"❌ User ID {user_id} not found! Please select a valid user ID."
623
 
624
- # Get recommendations
625
  recommendations = model.recommend_movies(
626
  user_id=user_id,
627
  N=num_recommendations,
@@ -633,7 +511,6 @@ def get_recommendations(user_id, num_recommendations):
633
  if not recommendations:
634
  return f"❌ No recommendations found for User {user_id}"
635
 
636
- # Format output
637
  output = f"🎬 **Top {num_recommendations} Movie Recommendations for User {user_id}**\n\n"
638
  output += "=" * 60 + "\n\n"
639
 
@@ -650,17 +527,7 @@ def get_recommendations(user_id, num_recommendations):
650
  except Exception as e:
651
  return f"❌ Error generating recommendations: {str(e)}"
652
 
653
-
654
  def get_user_history(user_id):
655
- """
656
- Show user's rating history
657
-
658
- Args:
659
- user_id: User ID
660
-
661
- Returns:
662
- Formatted string with user's past ratings
663
- """
664
  if model is None or loader is None:
665
  return "❌ Error: Model not loaded properly."
666
 
@@ -672,14 +539,12 @@ def get_user_history(user_id):
672
 
673
  user_idx = loader.user_id_map[user_id]
674
 
675
- # Get user's ratings from the training data
676
  user_ratings = model.item_cf.user_item_matrix[user_idx].toarray().flatten()
677
  rated_indices = np.where(user_ratings > 0)[0]
678
 
679
  if len(rated_indices) == 0:
680
  return f"No rating history found for User {user_id}"
681
 
682
- # Get movie details
683
  history = []
684
  for movie_idx in rated_indices:
685
  original_movie_id = loader.reverse_movie_map[movie_idx]
@@ -687,10 +552,8 @@ def get_user_history(user_id):
687
  rating = user_ratings[movie_idx]
688
  history.append((title, rating))
689
 
690
- # Sort by rating (highest first)
691
  history.sort(key=lambda x: x[1], reverse=True)
692
 
693
- # Format output
694
  output = f"πŸ“Š **Rating History for User {user_id}**\n\n"
695
  output += f"Total movies rated: {len(history)}\n"
696
  output += f"Average rating: {np.mean([r for _, r in history]):.2f}\n\n"
@@ -706,22 +569,11 @@ def get_user_history(user_id):
706
  except Exception as e:
707
  return f"❌ Error: {str(e)}"
708
 
709
-
710
  def get_movie_info(movie_title_search):
711
- """
712
- Search for movies by title
713
-
714
- Args:
715
- movie_title_search: Search query
716
-
717
- Returns:
718
- Formatted string with matching movies
719
- """
720
  if movies_df is None:
721
  return "❌ Error: Movies data not loaded"
722
 
723
  try:
724
- # Search for movies
725
  matches = movies_df[movies_df['title'].str.contains(movie_title_search, case=False, na=False)]
726
 
727
  if len(matches) == 0:
@@ -742,12 +594,6 @@ def get_movie_info(movie_title_search):
742
  except Exception as e:
743
  return f"❌ Error: {str(e)}"
744
 
745
-
746
- #==============================================================================
747
- # GRADIO INTERFACE
748
- #==============================================================================
749
-
750
- # Create Gradio interface with tabs
751
  with gr.Blocks(theme=gr.themes.Soft(), title="Movie Recommender - DataSynthis") as demo:
752
 
753
  gr.Markdown("""
@@ -762,7 +608,6 @@ with gr.Blocks(theme=gr.themes.Soft(), title="Movie Recommender - DataSynthis")
762
 
763
  with gr.Tabs():
764
 
765
- # TAB 1: Get Recommendations
766
  with gr.Tab("🎯 Get Recommendations"):
767
  gr.Markdown("### Get personalized movie recommendations for any user")
768
 
@@ -807,7 +652,6 @@ with gr.Blocks(theme=gr.themes.Soft(), title="Movie Recommender - DataSynthis")
807
  - Click "Get Recommendations" to see personalized movie suggestions
808
  """)
809
 
810
- # TAB 2: User History
811
  with gr.Tab("πŸ“Š User History"):
812
  gr.Markdown("### View a user's rating history")
813
 
@@ -836,7 +680,6 @@ with gr.Blocks(theme=gr.themes.Soft(), title="Movie Recommender - DataSynthis")
836
  outputs=history_output
837
  )
838
 
839
- # TAB 3: Search Movies
840
  with gr.Tab("πŸ” Search Movies"):
841
  gr.Markdown("### Search for movies in the database")
842
 
@@ -863,40 +706,33 @@ with gr.Blocks(theme=gr.themes.Soft(), title="Movie Recommender - DataSynthis")
863
  outputs=search_output
864
  )
865
 
866
- # TAB 4: About
867
  with gr.Tab("ℹ️ About"):
868
- gr.Markdown("""
869
- ## About This System
870
 
871
- ### 🎯 Model Architecture
872
- This is a **Hybrid Recommendation System** that combines three powerful approaches:
873
 
874
- 1. **Item-Based Collaborative Filtering**
875
  - Uses cosine similarity between movies
876
  - Recommends movies similar to what you've liked before
877
 
878
- 2. **SVD Matrix Factorization**
879
  - Decomposes the user-movie rating matrix
880
  - Discovers latent factors that explain user preferences
881
 
882
- 3. **Neural Collaborative Filtering (NCF)**
883
  - Deep learning model with user and movie embeddings
884
  - Learns complex non-linear patterns in user behavior
885
 
886
- ### πŸ“Š Dataset
887
- - **MovieLens 100k** dataset
888
- - 100,000 ratings from 943 users on 1,682 movies
889
- - Ratings scale: 1-5 stars
890
-
891
- ### 🎯 Performance Metrics
892
- - **Precision@10**: 26.77%
893
- - **NDCG@10**: 28.50%
894
- - **Model improves recommendations by 40% vs baseline**
895
 
896
- ### πŸ‘¨β€πŸ’» Created For
897
- **DataSynthis Job Task**
 
 
898
 
899
- ### πŸ”— Technologies Used
 
900
  - PyTorch (Neural Networks)
901
  - Scikit-learn (SVD, Similarity)
902
  - Pandas & NumPy (Data Processing)
@@ -908,7 +744,6 @@ with gr.Blocks(theme=gr.themes.Soft(), title="Movie Recommender - DataSynthis")
908
  User IDs range from 1 to 943, and movie IDs range from 1 to 1682.
909
  """)
910
 
911
- # Footer
912
  gr.Markdown("""
913
  ---
914
  <div style='text-align: center'>
@@ -916,7 +751,6 @@ with gr.Blocks(theme=gr.themes.Soft(), title="Movie Recommender - DataSynthis")
916
  </div>
917
  """)
918
 
919
- # Launch the app
920
  if __name__ == "__main__":
921
  demo.launch(
922
  share=False,
 
 
 
 
 
 
 
 
1
  import gradio as gr
2
  import pickle
3
  import pandas as pd
 
7
  import os
8
  from scipy.sparse import csr_matrix
9
 
 
 
 
 
10
  class ItemBasedCF:
 
11
  pass
12
 
13
  class SVDRecommender:
 
14
  pass
15
 
16
  class NeuralCF(nn.Module):
 
17
 
18
  def __init__(self, n_users, n_movies, embedding_dim=50, hidden_layers=[64, 32, 16]):
19
  super(NeuralCF, self).__init__()
 
46
  return torch.clamp(prediction, 1, 5).item()
47
 
48
  class HybridRecommender:
 
49
  pass
50
 
51
  class MovieLensDataLoader:
 
52
  pass
53
 
 
 
 
 
54
  def load_model_and_data():
 
55
  import os
56
 
 
57
  print("Checking for files...")
58
  print(f"Current directory: {os.getcwd()}")
59
  print(f"Files in current directory: {os.listdir('.')}")
 
64
  print("ERROR: model_artifacts/ folder does not exist!")
65
 
66
  try:
 
67
  files_to_check = [
68
  'model_artifacts/hybrid_model.pkl',
69
  'model_artifacts/loader.pkl',
 
74
  if not os.path.exists(file_path):
75
  print(f"ERROR: Missing file: {file_path}")
76
  else:
77
+ file_size = os.path.getsize(file_path) / (1024*1024)
78
  print(f"Found: {file_path} ({file_size:.2f} MB)")
79
 
 
80
  with open('model_artifacts/hybrid_model.pkl', 'rb') as f:
81
  model = pickle.load(f)
82
  print("βœ“ Loaded hybrid_model.pkl")
 
89
  movies = pickle.load(f)
90
  print("βœ“ Loaded movies.pkl")
91
 
 
92
  user_ids = sorted(loader.user_id_map.keys())
93
  print(f"βœ“ Model loaded successfully! {len(user_ids)} users available")
94
 
 
103
  traceback.print_exc()
104
  return None, None, None, []
105
 
 
106
  print("Loading model and data...")
107
  model, loader, movies_df, user_ids = load_model_and_data()
108
  print(f"Model loaded! Available users: {len(user_ids)}")
109
 
 
 
 
 
110
  def get_recommendations(user_id, num_recommendations):
 
 
 
 
 
 
 
 
 
 
111
  if model is None or loader is None:
112
  return "❌ Error: Model not loaded properly. Please check the model files."
113
 
 
115
  user_id = int(user_id)
116
  num_recommendations = int(num_recommendations)
117
 
 
118
  if user_id not in loader.user_id_map:
119
  return f"❌ User ID {user_id} not found! Please select a valid user ID."
120
 
 
121
  recommendations = model.recommend_movies(
122
  user_id=user_id,
123
  N=num_recommendations,
 
129
  if not recommendations:
130
  return f"❌ No recommendations found for User {user_id}"
131
 
 
132
  output = f"🎬 **Top {num_recommendations} Movie Recommendations for User {user_id}**\n\n"
133
  output += "=" * 60 + "\n\n"
134
 
 
145
  except Exception as e:
146
  return f"❌ Error generating recommendations: {str(e)}"
147
 
 
148
  def get_user_history(user_id):
 
 
 
 
 
 
 
 
 
149
  if model is None or loader is None:
150
  return "❌ Error: Model not loaded properly."
151
 
 
157
 
158
  user_idx = loader.user_id_map[user_id]
159
 
 
160
  user_ratings = model.item_cf.user_item_matrix[user_idx].toarray().flatten()
161
  rated_indices = np.where(user_ratings > 0)[0]
162
 
163
  if len(rated_indices) == 0:
164
  return f"No rating history found for User {user_id}"
165
 
 
166
  history = []
167
  for movie_idx in rated_indices:
168
  original_movie_id = loader.reverse_movie_map[movie_idx]
 
170
  rating = user_ratings[movie_idx]
171
  history.append((title, rating))
172
 
 
173
  history.sort(key=lambda x: x[1], reverse=True)
174
 
 
175
  output = f"πŸ“Š **Rating History for User {user_id}**\n\n"
176
  output += f"Total movies rated: {len(history)}\n"
177
  output += f"Average rating: {np.mean([r for _, r in history]):.2f}\n\n"
 
187
  except Exception as e:
188
  return f"❌ Error: {str(e)}"
189
 
 
190
  def get_movie_info(movie_title_search):
 
 
 
 
 
 
 
 
 
191
  if movies_df is None:
192
  return "❌ Error: Movies data not loaded"
193
 
194
  try:
 
195
  matches = movies_df[movies_df['title'].str.contains(movie_title_search, case=False, na=False)]
196
 
197
  if len(matches) == 0:
 
212
  except Exception as e:
213
  return f"❌ Error: {str(e)}"
214
 
 
 
 
 
 
 
215
  with gr.Blocks(theme=gr.themes.Soft(), title="Movie Recommender - DataSynthis") as demo:
216
 
217
  gr.Markdown("""
 
226
 
227
  with gr.Tabs():
228
 
 
229
  with gr.Tab("🎯 Get Recommendations"):
230
  gr.Markdown("### Get personalized movie recommendations for any user")
231
 
 
270
  - Click "Get Recommendations" to see personalized movie suggestions
271
  """)
272
 
 
273
  with gr.Tab("πŸ“Š User History"):
274
  gr.Markdown("### View a user's rating history")
275
 
 
298
  outputs=history_output
299
  )
300
 
 
301
  with gr.Tab("πŸ” Search Movies"):
302
  gr.Markdown("### Search for movies in the database")
303
 
 
324
  outputs=search_output
325
  )
326
 
 
327
  with gr.Tab("ℹ️ About"):
328
  gr.Markdown("""
329
  ## About This System
 
368
  User IDs range from 1 to 943, and movie IDs range from 1 to 1682.
369
  """)
370
 
 
371
  gr.Markdown("""
372
  ---
373
  <div style='text-align: center'>
 
375
  </div>
376
  """)
377
 
 
378
  if __name__ == "__main__":
379
  demo.launch(
380
  share=False,
381
  server_name="0.0.0.0",
382
  server_port=7860
383
+ )import gradio as gr
 
 
 
 
 
 
 
384
  import pickle
385
  import pandas as pd
386
  import numpy as np
 
389
  import os
390
  from scipy.sparse import csr_matrix
391
 
 
 
 
 
392
  class ItemBasedCF:
 
393
  pass
394
 
395
  class SVDRecommender:
 
396
  pass
397
 
398
  class NeuralCF(nn.Module):
 
399
 
400
  def __init__(self, n_users, n_movies, embedding_dim=50, hidden_layers=[64, 32, 16]):
401
  super(NeuralCF, self).__init__()
 
428
  return torch.clamp(prediction, 1, 5).item()
429
 
430
  class HybridRecommender:
 
431
  pass
432
 
433
  class MovieLensDataLoader:
 
434
  pass
435
 
 
 
 
 
436
  def load_model_and_data():
 
437
  import os
438
 
 
439
  print("Checking for files...")
440
  print(f"Current directory: {os.getcwd()}")
441
  print(f"Files in current directory: {os.listdir('.')}")
 
446
  print("ERROR: model_artifacts/ folder does not exist!")
447
 
448
  try:
 
449
  files_to_check = [
450
  'model_artifacts/hybrid_model.pkl',
451
  'model_artifacts/loader.pkl',
 
456
  if not os.path.exists(file_path):
457
  print(f"ERROR: Missing file: {file_path}")
458
  else:
459
+ file_size = os.path.getsize(file_path) / (1024*1024)
460
  print(f"Found: {file_path} ({file_size:.2f} MB)")
461
 
 
462
  with open('model_artifacts/hybrid_model.pkl', 'rb') as f:
463
  model = pickle.load(f)
464
  print("βœ“ Loaded hybrid_model.pkl")
 
471
  movies = pickle.load(f)
472
  print("βœ“ Loaded movies.pkl")
473
 
 
474
  user_ids = sorted(loader.user_id_map.keys())
475
  print(f"βœ“ Model loaded successfully! {len(user_ids)} users available")
476
 
 
485
  traceback.print_exc()
486
  return None, None, None, []
487
 
 
488
  print("Loading model and data...")
489
  model, loader, movies_df, user_ids = load_model_and_data()
490
  print(f"Model loaded! Available users: {len(user_ids)}")
491
 
 
 
 
 
492
  def get_recommendations(user_id, num_recommendations):
 
 
 
 
 
 
 
 
 
 
493
  if model is None or loader is None:
494
  return "❌ Error: Model not loaded properly. Please check the model files."
495
 
 
497
  user_id = int(user_id)
498
  num_recommendations = int(num_recommendations)
499
 
 
500
  if user_id not in loader.user_id_map:
501
  return f"❌ User ID {user_id} not found! Please select a valid user ID."
502
 
 
503
  recommendations = model.recommend_movies(
504
  user_id=user_id,
505
  N=num_recommendations,
 
511
  if not recommendations:
512
  return f"❌ No recommendations found for User {user_id}"
513
 
 
514
  output = f"🎬 **Top {num_recommendations} Movie Recommendations for User {user_id}**\n\n"
515
  output += "=" * 60 + "\n\n"
516
 
 
527
  except Exception as e:
528
  return f"❌ Error generating recommendations: {str(e)}"
529
 
 
530
  def get_user_history(user_id):
 
 
 
 
 
 
 
 
 
531
  if model is None or loader is None:
532
  return "❌ Error: Model not loaded properly."
533
 
 
539
 
540
  user_idx = loader.user_id_map[user_id]
541
 
 
542
  user_ratings = model.item_cf.user_item_matrix[user_idx].toarray().flatten()
543
  rated_indices = np.where(user_ratings > 0)[0]
544
 
545
  if len(rated_indices) == 0:
546
  return f"No rating history found for User {user_id}"
547
 
 
548
  history = []
549
  for movie_idx in rated_indices:
550
  original_movie_id = loader.reverse_movie_map[movie_idx]
 
552
  rating = user_ratings[movie_idx]
553
  history.append((title, rating))
554
 
 
555
  history.sort(key=lambda x: x[1], reverse=True)
556
 
 
557
  output = f"πŸ“Š **Rating History for User {user_id}**\n\n"
558
  output += f"Total movies rated: {len(history)}\n"
559
  output += f"Average rating: {np.mean([r for _, r in history]):.2f}\n\n"
 
569
  except Exception as e:
570
  return f"❌ Error: {str(e)}"
571
 
 
572
  def get_movie_info(movie_title_search):
 
 
 
 
 
 
 
 
 
573
  if movies_df is None:
574
  return "❌ Error: Movies data not loaded"
575
 
576
  try:
 
577
  matches = movies_df[movies_df['title'].str.contains(movie_title_search, case=False, na=False)]
578
 
579
  if len(matches) == 0:
 
594
  except Exception as e:
595
  return f"❌ Error: {str(e)}"
596
 
 
 
 
 
 
 
597
  with gr.Blocks(theme=gr.themes.Soft(), title="Movie Recommender - DataSynthis") as demo:
598
 
599
  gr.Markdown("""
 
608
 
609
  with gr.Tabs():
610
 
 
611
  with gr.Tab("🎯 Get Recommendations"):
612
  gr.Markdown("### Get personalized movie recommendations for any user")
613
 
 
652
  - Click "Get Recommendations" to see personalized movie suggestions
653
  """)
654
 
 
655
  with gr.Tab("πŸ“Š User History"):
656
  gr.Markdown("### View a user's rating history")
657
 
 
680
  outputs=history_output
681
  )
682
 
 
683
  with gr.Tab("πŸ” Search Movies"):
684
  gr.Markdown("### Search for movies in the database")
685
 
 
706
  outputs=search_output
707
  )
708
 
 
709
  with gr.Tab("ℹ️ About"):
710
+ gr.Markdown(""" About This System
 
711
 
712
+ Model Architecture
713
+ This is a Hybrid Recommendation System that combines three powerful approaches:
714
 
715
+ 1. Item-Based Collaborative Filtering
716
  - Uses cosine similarity between movies
717
  - Recommends movies similar to what you've liked before
718
 
719
+ 2. SVD Matrix Factorization
720
  - Decomposes the user-movie rating matrix
721
  - Discovers latent factors that explain user preferences
722
 
723
+ 3. Neural Collaborative Filtering (NCF)
724
  - Deep learning model with user and movie embeddings
725
  - Learns complex non-linear patterns in user behavior
726
 
727
+
 
 
 
 
 
 
 
 
728
 
729
+ Performance Metrics
730
+ - Precision@10: 26.77%
731
+ - NDCG@10: 28.50%
732
+ - Model improves recommendations by 40% vs baseline**
733
 
734
+
735
+ Technologies Used
736
  - PyTorch (Neural Networks)
737
  - Scikit-learn (SVD, Similarity)
738
  - Pandas & NumPy (Data Processing)
 
744
  User IDs range from 1 to 943, and movie IDs range from 1 to 1682.
745
  """)
746
 
 
747
  gr.Markdown("""
748
  ---
749
  <div style='text-align: center'>
 
751
  </div>
752
  """)
753
 
 
754
  if __name__ == "__main__":
755
  demo.launch(
756
  share=False,