RUNTIME

Time in Amaravati:--:--

Say hello

Solo project

H-Tech

Hybrid movie recommender

A movie recommender that blends content-based and collaborative filtering, trained on MovieLens 25M and enriched with TMDB posters and metadata.

LiveNow showingRuntime: 1 min read

The code is in a private repo. Happy to walk you through it: ask me.

The first load can take 30–60 seconds. The backend runs on Google Cloud Run's free tier and needs a moment to wake up.

Context
Solo project
Role
Solo, end to end: data pipelines, models, API, frontend and deployment
Team
Solo
When
July 2026 – September 2026

The problem

Movie recommenders that rely on one signal fail in predictable ways. Collaborative filtering has nothing to say about new users or unrated films, and content-only models can't capture taste. I also wanted to serve it on free tiers, where a PyTorch runtime was too heavy for the API.

Approach

Content-based scoring (tag-genome, TF-IDF and sentence embeddings) and collaborative filtering (SVD and item-kNN), blended per request. A Dockerized FastAPI backend on Google Cloud Run, with PostgreSQL on Supabase, serves a Next.js frontend on Vercel with swipe-card onboarding and semantic search, all on free tiers.

How it works

  1. 01YouSwipe-card onboarding and semantic search
  2. 02Next.js on VercelThe frontend
  3. 03FastAPI on Google Cloud RunRecommendations and ONNX Runtime embeddings
  4. 04Postgres on SupabaseThe data

Key decision

A hybrid recommender that routes each request to the signal that works best for it. New users go to popularity and content instead of collaborative filtering, and serving-time embeddings moved from PyTorch to ONNX Runtime plus the tokenizers library.

Why

Collaborative filtering has nothing to say about new users or unrated films, so those requests go to the signals that can answer them. Running the embedding model through PyTorch added runtime overhead the API didn't need, so the Docker build converts it to ONNX once and PyTorch never ships. That made the image much smaller, but it wasn't the whole answer, and the API still runs at 4 GiB on Cloud Run.

Models

  • Content-based scoringTag-genome, TF-IDF and sentence embeddings (ONNX Runtime)
  • Collaborative filteringSVD and item-kNN, trained on MovieLens 25M
  • Cold-start routingNew users get popularity and content signals

Why I built it

I'm aiming for internships and jobs in AI/ML and software development, and I wanted one project that shows both. A recommender needs data pipelines, several ML models, an API, a frontend and a live deployment. Building it end to end on free-tier limits taught me to design around real constraints like memory, cold starts and cost. I wrote down and measured each decision, so I can explain my choices, not just show that it runs.

Stack

  • Python
  • scikit-learn
  • Polars
  • ONNX Runtime
  • FastAPI
  • SQLAlchemy
  • PostgreSQL
  • Supabase
  • Next.js
  • TypeScript
  • Docker
  • Google Cloud Run
  • Vercel
  • GitHub Actions

Results

  • Item-kNN reached 0.332 precision@10 from a single liked film, against 0.187 for plain popularity and 0.146 for TF-IDF content scoring.
  • Ranking only films with at least 1,000 ratings lifted collaborative filtering's precision@10 from 0.046 to 0.189, with the model untouched.
  • Evaluating the feed as served caught a shipped bug: score-based randomness had cut precision@10 at 50 ratings from 0.338 to 0.187. Sampling by rank brought it back to 0.323, with about 4 of 10 films changing per refresh.
  • On a fresh sample of users that no tuning had seen, the served feed reached 0.319 precision@10 at one liked film.
  • Measured on MovieLens 25M with simulated new users, so the constants are specific to this dataset.