|
|
import gradio as gr |
|
|
import os |
|
|
import pickle |
|
|
import numpy as np |
|
|
from surprise import SVDpp |
|
|
from sklearn.metrics.pairwise import cosine_similarity |
|
|
|
|
|
|
|
|
def download_kaggle_model(): |
|
|
kaggle_username = os.environ.get("KAGGLE_USERNAME") |
|
|
kaggle_key = os.environ.get("KAGGLE_KEY") |
|
|
if not kaggle_username or not kaggle_key: |
|
|
raise ValueError("Set KAGGLE_USERNAME and KAGGLE_KEY as HF secrets!") |
|
|
|
|
|
os.system("mkdir -p ~/.kaggle") |
|
|
with open("/root/.kaggle/kaggle.json", "w") as f: |
|
|
f.write(f'{{"username":"{kaggle_username}","key":"{kaggle_key}"}}') |
|
|
os.chmod("/root/.kaggle/kaggle.json", 0o600) |
|
|
|
|
|
|
|
|
print("π₯ Downloading model from Kaggle...") |
|
|
os.system("kaggle datasets download -d <your-username>/<your-model-dataset> -p ./model --unzip") |
|
|
|
|
|
|
|
|
def load_models(): |
|
|
with open("./model/svdpp_model.pkl", "rb") as f: |
|
|
svdpp_model = pickle.load(f) |
|
|
|
|
|
with open("./model/content_features.pkl", "rb") as f: |
|
|
content_features = pickle.load(f) |
|
|
|
|
|
with open("./model/mappings.pkl", "rb") as f: |
|
|
mappings = pickle.load(f) |
|
|
|
|
|
return svdpp_model, content_features, mappings |
|
|
|
|
|
|
|
|
def hybrid_predict(user_id, book_id, alpha=0.7): |
|
|
try: |
|
|
uid = user_encoder.transform([user_id])[0] |
|
|
iid = item_encoder.transform([book_id])[0] |
|
|
except: |
|
|
return "Unknown user_id or book_id" |
|
|
|
|
|
svd_pred = svdpp_model.predict(uid, iid).est |
|
|
|
|
|
user_liked = np.where(svdpp_model.trainset.ur[uid])[0] |
|
|
if len(user_liked) == 0: |
|
|
content_score = 0 |
|
|
else: |
|
|
similarities = cosine_similarity(content_features[iid], content_features[user_liked]) |
|
|
content_score = np.mean(similarities) |
|
|
|
|
|
hybrid_score = alpha * svd_pred + (1 - alpha) * content_score * 5 |
|
|
return round(hybrid_score, 2) |
|
|
|
|
|
|
|
|
def recommend(user_id, book_id, alpha=0.7): |
|
|
return f"Predicted Rating: {hybrid_predict(user_id, book_id, alpha)}" |
|
|
|
|
|
|
|
|
download_kaggle_model() |
|
|
svdpp_model, content_features, mappings = load_models() |
|
|
user_encoder = mappings["user_encoder"] |
|
|
item_encoder = mappings["item_encoder"] |
|
|
|
|
|
|
|
|
demo = gr.Interface( |
|
|
fn=recommend, |
|
|
inputs=[ |
|
|
gr.Textbox(label="User ID"), |
|
|
gr.Textbox(label="Book ID"), |
|
|
gr.Slider(0, 1, value=0.7, step=0.1, label="Hybrid Weight (alpha)") |
|
|
], |
|
|
outputs="text", |
|
|
title="π Hybrid Book Recommender", |
|
|
description="Enter a user_id and book_id to get a predicted rating using a Hybrid SVD++ and Content-based model." |
|
|
) |
|
|
|
|
|
demo.launch() |
|
|
|