Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 0 additions & 21 deletions LICENSE

This file was deleted.

48 changes: 41 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,46 @@
# React + Vite
# How to run this application

This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
## Make 3 terminals
```
cd Backend/back2
```
```
cd Backend/back2
```
```
cd frontend/ai-rec
```

Currently, two official plugins are available:
## In first terminal run(uvicorn terminal (api))
```
pip install -r requirements.txt
```

- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) for Fast Refresh
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
## In third terminal run(frontend/ai-rec)
```
npm init -y
npm i

## Expanding the ESLint configuration
```
## Running the application

If you are developing a production application, we recommend using TypeScript with type-aware lint rules enabled. Check out the [TS template](https://github.com/vitejs/vite/tree/main/packages/create-vite/template-react-ts) for information on how to integrate TypeScript and [`typescript-eslint`](https://typescript-eslint.io) in your project.
### In first terminal(uvicorn)
```
uvicorn saas_api:app --reload
```

### In second terminal(mlflow)
```
mlflow ui --backend-store-uri sqlite:///mlflow.db --default-artifact-root ./mlflow_artifacts

```
### In third terminal(frontend)
```
npm run dev
```

## Go to localhost:5173 or frontend luanched port, to view mlflow go to localhost:5000

## Upload dataset and enter into required fields,select ready model and select required fields and click get recommendations

# Finally Peace
87 changes: 87 additions & 0 deletions backend/back2/Collaborative.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import pandas as pd
import numpy as np
from sklearn.decomposition import TruncatedSVD

class CollaborativeFilteringRecommender:
"""
Recommends items using TruncatedSVD after mean-centering the data
to provide personalized recommendations.
"""
def __init__(self, n_components=50):
self.n_components = n_components
self.svd = TruncatedSVD(n_components=self.n_components, random_state=42)

self.user_features = None
self.item_features = None

self.user_means = None
self.item_ids = None
self.user_ids = None

self.original_ratings_pivot = None

def fit(self, df, schema_map):
"""
Pivots the data, de-means it, and fits the SVD model.

Args:
df (pd.DataFrame): Standardized dataframe.
schema_map (dict): Dict with 'user_id', 'item_id', 'rating' keys.
"""
# 1. Create the user-item matrix *with NaNs*
self.original_ratings_pivot = df.pivot_table(
index=schema_map['user_id'],
columns=schema_map['item_id'],
values=schema_map['rating']
)

# 2. Calculate the mean rating for each user
self.user_means = self.original_ratings_pivot.mean(axis=1)

# 3. De-mean the data
demeaned_ratings = self.original_ratings_pivot.subtract(self.user_means, axis=0)

# 4. NOW, fill the NaNs with 0
demeaned_ratings_filled = demeaned_ratings.fillna(0)

# 5. Fit SVD on the de-meaned data
self.user_features = self.svd.fit_transform(demeaned_ratings_filled)
self.item_features = self.svd.components_ # (n_components, n_items)

# Store the user and item IDs in order
self.user_ids = demeaned_ratings_filled.index
self.item_ids = demeaned_ratings_filled.columns

print("✅ Collaborative Filtering (SVD) model fitted on de-meaned data.")

def recommend(self, user_id, n=10):
"""
Gets the top n item recommendations for a given user_id.
"""
if user_id not in self.user_ids:
print(f"User '{user_id}' not found in Collaborative model.")
return []

# 1. Get the user's row index
user_index = self.user_ids.get_loc(user_id)

# 2. Get the user's latent feature vector
user_vector = self.user_features[user_index]

# 3. Predict the *deviations*
predicted_deviations = np.dot(user_vector, self.item_features)

# 4. Add the user's mean back
user_mean = self.user_means.loc[user_id]
predicted_ratings = predicted_deviations + user_mean

# 5. Convert to a Series
predicted_series = pd.Series(predicted_ratings, index=self.item_ids)

# 6. Get items the user has already rated
rated_items = self.original_ratings_pivot.loc[user_id].dropna().index

# 7. Filter out already-rated items and sort
recommendations = predicted_series.drop(rated_items).sort_values(ascending=False)

return recommendations.head(n).index.tolist()
64 changes: 64 additions & 0 deletions backend/back2/Content.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import linear_kernel

class ContentBasedRecommender:
"""Recommends items similar to a given item based on its content."""
def __init__(self):
self.cosine_sim = None
self.indices = None
self.df = None
self.schema_map = {}

def fit(self, df, schema_map):
"""
Builds the TF-IDF and Cosine Similarity matrix from item features.

Args:
df (pd.DataFrame): The standardized dataframe.
schema_map (dict): A dict with 'item_id' and 'feature_cols' keys.
"""
self.df = df
self.schema_map = schema_map
content_feature_columns = schema_map.get('feature_cols', [])

# Create a "soup" of all content features in a single string
df['soup'] = df[content_feature_columns].fillna('').astype(str).agg(' '.join, axis=1)

# Use TF-IDF to convert the text soup into a matrix of feature vectors
tfidf = TfidfVectorizer(stop_words='english')
tfidf_matrix = tfidf.fit_transform(df['soup'])

# Calculate the cosine similarity between all items
self.cosine_sim = linear_kernel(tfidf_matrix, tfidf_matrix)

# Create a mapping from item_id to dataframe index for quick lookups
# Create a mapping from item_title to dataframe index for quick lookups
self.indices = pd.Series(df.index, index=df[schema_map['item_title']]).drop_duplicates()
print("✅ Content-Based model fitted.")

def recommend(self, item_id, n=10):
"""
Gets the top n similar items for a given item_id.
"""
if item_id not in self.indices:
print(f"Item '{item_id}' not found in Content model indices.")
return []

# Get the index of the item that matches the ID
idx = self.indices[item_id]

# Get the pairwise similarity scores of all items with that item
sim_scores = list(enumerate(self.cosine_sim[idx]))

# Sort the items based on the similarity scores
sim_scores = sorted(sim_scores, key=lambda x: x[1], reverse=True)

# Get the scores of the n most similar items (excluding the item itself)
sim_scores = sim_scores[1:n+1]

# Get the item indices
item_indices = [i[0] for i in sim_scores]

# Return the top n most similar item IDs
return self.df[self.schema_map['item_id']].iloc[item_indices].tolist()
26 changes: 26 additions & 0 deletions backend/back2/Hybrid.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import pandas as pd
class HybridRecommender:
"""
Combines recommendations from content-based and collaborative models
to provide a more robust and diverse recommendation list.
"""
def __init__(self, content_model, collab_model):
self.content_model = content_model
self.collab_model = collab_model
print("🤖 HybridRecommender initialized.")

def recommend(self, user_id, item_id_for_content, n=10):
"""
Generates a hybrid list of recommendations.
"""
# 1. Get content-based recommendations
content_recs = self.content_model.recommend(item_id_for_content, n)

# 2. Get collaborative filtering recommendations
collab_recs = self.collab_model.recommend(user_id, n)

# 3. Combine the lists (prioritizing content, filling with collaborative)
combined_recs = list(dict.fromkeys(content_recs + collab_recs))

# 4. Return the final list
return combined_recs[:n]
Binary file not shown.
Binary file added backend/back2/__pycache__/Content.cpython-312.pyc
Binary file not shown.
Binary file added backend/back2/__pycache__/Hybrid.cpython-312.pyc
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added backend/back2/__pycache__/models.cpython-312.pyc
Binary file not shown.
Binary file not shown.
Binary file added backend/back2/__pycache__/schemas.cpython-312.pyc
Binary file not shown.
38 changes: 38 additions & 0 deletions backend/back2/database.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

# Define the SQLite database URL.
# This will create a file named 'user_data.db' in the same directory.
DATABASE_URL = "sqlite:///./user_data.db"

# Create the SQLAlchemy engine
engine = create_engine(
DATABASE_URL,
# required for SQLite
connect_args={"check_same_thread": False}
)

# Create a SessionLocal class, which will be our actual database session
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

# Create a Base class for our models to inherit from
Base = declarative_base()

def get_db():
"""
FastAPI dependency to get a database session.
Yields a session and closes it after the request.
"""
db = SessionLocal()
try:
yield db
finally:
db.close()

def create_db_and_tables():
"""
Utility function to create all tables in the database.
Called on app startup.
"""
Base.metadata.create_all(bind=engine)
Loading