Skip to content

Commit

Permalink
Infrastructural Changes made to the app
Browse files Browse the repository at this point in the history
  • Loading branch information
Talnz007 committed Sep 1, 2024
1 parent 9d03e9f commit 61ff353
Show file tree
Hide file tree
Showing 3 changed files with 205 additions and 61 deletions.
85 changes: 85 additions & 0 deletions app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
from flask import Flask, jsonify, request
import pickle
import redis
from database import load_movies
from scipy.sparse import load_npz
import logging

app = Flask(__name__)

# Set up logging
logging.basicConfig(level=logging.INFO)

# Redis connection setup
redis_client = redis.StrictRedis(
host='redis-14520.c305.ap-south-1-1.ec2.redns.redis-cloud.com',
port=14520,
password='oDEwiX0SSQIKnc4PNJngPJJ9ziRe0gvP',
decode_responses=False # Ensure binary responses
)

# Load sparse similarity matrix from file
similarity = load_npz("similarity_matrix.npz")

# Load the movie list from PostgreSQL
movies = load_movies()


@app.route('/recommend', methods=['GET'])
def recommend():
try:
movie_title = request.args.get('movie')

# Validate movie title
if not movie_title:
return jsonify({"error": "Movie title is required"}), 400

# Check cache first
cached_recommendations = redis_client.get(movie_title)
if cached_recommendations:
try:
if isinstance(cached_recommendations, bytes):
recommendations = pickle.loads(cached_recommendations)
else:
raise TypeError("Cached data is not in bytes format")

return jsonify(recommendations=recommendations)
except pickle.PickleError as e:
logging.error(f"Error decoding cached recommendations: {e}")
return jsonify({"error": "Error decoding cached recommendations"}), 500

# Check if the movie is in the dataset
if movie_title in movies['title'].values:
index = movies[movies['title'] == movie_title].index[0]

# Extract the row of similarities for the given movie
distances = similarity[index].toarray().flatten()

# Get indices and sort by similarity score
distance_with_index = list(enumerate(distances))
distance_with_index.sort(key=lambda x: x[1], reverse=True)

recommendations = []
# Get top 5 similar movies (excluding the queried movie)
for i in distance_with_index[1:6]:
recommend_movie = movies.iloc[i[0]].title
recommendations.append(recommend_movie)

# Cache the recommendations
try:
redis_client.set(movie_title, pickle.dumps(recommendations), ex=86400)
except pickle.PickleError:
return jsonify({"error": "Error encoding recommendations for cache"}), 500

return jsonify(recommendations=recommendations)

else:
return jsonify({"error": "Movie not found"}), 404

except Exception as e:
logging.error(f"An error occurred: {e}")
return jsonify({"error": "An internal server error occurred"}), 500


if __name__ == '__main__':
app.run(debug=True)
66 changes: 66 additions & 0 deletions database.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import psycopg2
from psycopg2.extras import RealDictCursor
import pandas as pd
import logging

# Set up logging
logging.basicConfig(level=logging.INFO)

# Database connection details
url = 'https://qdsijfxkqpidkurjjkwb.supabase.co'
USER = 'postgres.qdsijfxkqpidkurjjkwb'
PASSWORD = 'Onvkw6d32uEr3Nr6'
HOST = 'aws-0-ap-south-1.pooler.supabase.com'
PORT = '6543'


def get_db_connection():
try:
conn = psycopg2.connect(
dbname='postgres',
user=USER,
password=PASSWORD,
host=HOST,
port=PORT
)
return conn
except Exception as e:
logging.error(f"Error connecting to database: {e}")
return None


def insert_movies(movie_list):
conn = get_db_connection()
if conn is None:
return False

try:
with conn.cursor() as cursor:
for movie in movie_list:
cursor.execute("""
INSERT INTO movies (id, title)
VALUES (%s, %s)
ON CONFLICT (title) DO NOTHING;
""", (movie['id'], movie['title']))
conn.commit()
except Exception as e:
logging.error(f"Error inserting movies: {e}")
conn.rollback()
finally:
conn.close()


def load_movies():
conn = get_db_connection()
if conn is None:
return pd.DataFrame()

try:
query = "SELECT id, title FROM movies;"
df = pd.read_sql(query, conn)
return df
except Exception as e:
logging.error(f"Error loading movies: {e}")
return pd.DataFrame()
finally:
conn.close()
115 changes: 54 additions & 61 deletions main.py
Original file line number Diff line number Diff line change
@@ -1,76 +1,69 @@
import streamlit as st
import pickle
import requests
import streamlit.components.v1 as components
from database import load_movies

# Load movie list
try:
movies_df = load_movies() # This should return a DataFrame
if movies_df.empty:
st.error("No movies found in the database.")
st.stop()
except Exception as e:
st.error(f"Error loading movie list: {e}")
st.stop()

def fetch_poster(movie_id):
url = "https://api.themoviedb.org/3/movie/{}?api_key=c7ec19ffdd3279641fb606d19ceb9bb1&language=en-US".format(
movie_id)
data = requests.get(url)
data = data.json()
poster_path = data['poster_path']
full_path = "https://image.tmdb.org/t/p/w500/" + poster_path
return full_path
# Prepare movie titles and IDs
movies_dict = {row['title']: row['id'] for _, row in movies_df.iterrows()}

def fetch_poster(movie_id):
try:
url = f"https://api.themoviedb.org/3/movie/{movie_id}?api_key=c7ec19ffdd3279641fb606d19ceb9bb1&language=en-US"
response = requests.get(url)
response.raise_for_status() # Raise an exception for HTTP errors
data = response.json()
poster_path = data.get('poster_path')
if poster_path:
return f"https://image.tmdb.org/t/p/w500/{poster_path}"
except requests.RequestException as e:
st.error(f"Error fetching poster: {e}")
return None

movies = pickle.load(open("movies_list.pkl", 'rb'))
similarity = pickle.load(open("similarity.pkl", 'rb'))
movies_list = movies['title'].values
def fetch_recommendations(movie_title):
try:
# Replace with your actual Flask API URL
response = requests.get(f'http://127.0.0.1:5000/recommend?movie={movie_title}')
response.raise_for_status() # Raise an exception for HTTP errors
return response.json().get('recommendations', [])
except requests.RequestException as e:
st.error(f"Error fetching recommendations: {e}")
return []

st.header("Movie Recommender System")

import streamlit.components.v1 as components

# Example carousel component usage (assuming correct implementation)
imageCarouselComponent = components.declare_component("image-carousel-component", path="frontend/public")

imageUrls = [
fetch_poster(1632),
fetch_poster(299536),
fetch_poster(17455),
fetch_poster(2830),
fetch_poster(429422),
fetch_poster(9722),
fetch_poster(13972),
fetch_poster(240),
fetch_poster(155),
fetch_poster(598),
fetch_poster(914),
fetch_poster(255709),
fetch_poster(572154)

]

# Replace with your dynamic image URLs
imageUrls = [fetch_poster(movie_id) for movie_id in [1632, 299536, 17455, 2830, 429422, 9722, 13972, 240, 155, 598, 914, 255709, 572154]]
imageUrls = [url for url in imageUrls if url is not None] # Filter out None values
imageCarouselComponent(imageUrls=imageUrls, height=200)
selectvalue = st.selectbox("Select movie from dropdown", movies_list)


def recommend(movie):
index = movies[movies['title'] == movie].index[0]
distance = sorted(list(enumerate(similarity[index])), reverse=True, key=lambda vector: vector[1])
recommend_movie = []
recommend_poster = []
for i in distance[1:6]:
movies_id = movies.iloc[i[0]].id
recommend_movie.append(movies.iloc[i[0]].title)
recommend_poster.append(fetch_poster(movies_id))
return recommend_movie, recommend_poster

selectvalue = st.selectbox("Pick movie from dropdown", list(movies_dict.keys()))

if st.button("Show Recommend"):
movie_name, movie_poster = recommend(selectvalue)
col1, col2, col3, col4, col5 = st.columns(5)
with col1:
st.text(movie_name[0])
st.image(movie_poster[0])
with col2:
st.text(movie_name[1])
st.image(movie_poster[1])
with col3:
st.text(movie_name[2])
st.image(movie_poster[2])
with col4:
st.text(movie_name[3])
st.image(movie_poster[3])
with col5:
st.text(movie_name[4])
st.image(movie_poster[4])
recommendations = fetch_recommendations(selectvalue)
if recommendations:
cols = st.columns(5)
for i, movie in enumerate(recommendations[:5]):
if i < 5:
movie_id = movies_dict.get(movie)
poster_url = fetch_poster(movie_id) if movie_id else None
with cols[i]:
st.text(movie)
if poster_url:
st.image(poster_url)
else:
st.text("Poster not available")
else:
st.error("No recommendations found")

0 comments on commit 61ff353

Please sign in to comment.