Dell06/movie-songs-demo
Hybrid Cross-Modal Recommender Prototype
A runnable prototype that bridges movie swipe preferences into music recommendations.
Recommendation formula
R(u,s) = alpha * Sim(E_lyrics, E_movie) + beta * Sim(M_audio, M_movieMood)
E_lyrics: candidate song lyric embedding.E_movie: centroid of embeddings from movies the user liked.M_audio: candidate song audio vector (valence, energy, acousticness, instrumentalness, tempo).M_movieMood: averaged mood vector from liked movies.
Repo layout
src/hybrid_recommender.py: profile + ranking math.src/service.py: application service layer.src/app.py: FastAPI API.src/embedding_provider.py: pluggable embedding providers (local,openai).src/ingest.py: raw text -> embedding helper for ingestion pipelines.src/cli.py: local CLI for quick scoring.db/schema.sql: PostgreSQL + pgvector schema.data/movies.json: sample movie catalog.data/songs.json: sample song catalog.tests/: unit tests.
Quick start
1) Install dependencies
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt2) Run CLI prototype
python3 src/cli.py --likes "Interstellar,Blade Runner 2049" --top-k 53) Run API
uvicorn src.app:app --reload --host 0.0.0.0 --port 8000API routes:
GET /landing pageGET /profileprofile setupGET /moviemovie-to-song recommenderGET /auxAux BattleGET /chartstop-50 song pageGET /healthGET /moviesPOST /recommend
Example request:
curl -X POST http://localhost:8000/recommend \
-H "Content-Type: application/json" \
-d '{
"likes": ["Interstellar", "Blade Runner 2049"],
"top_k": 5,
"alpha": 0.65,
"beta": 0.35
}'Embedding providers
Use .env.example as a template.
- Local development:
EMBEDDING_PROVIDER=local- Real provider:
EMBEDDING_PROVIDER=openaiOPENAI_API_KEY=...OPENAI_EMBEDDING_MODEL=text-embedding-3-small
src/ingest.py uses the configured provider for movie plot and lyric text embedding.
Genius API setup
Genius is used here for song search/metadata, not an official Billboard chart feed. The app exposes /charts and /charts/top50; if GENIUS_ACCESS_TOKEN is present, it queries Genius search across genre/chart-style terms. If the token is missing, it falls back to local sample songs.
- Go to
https://genius.com/api-clients. - Create an API client.
- Copy the client access token.
- Add it to your environment:
export GENIUS_ACCESS_TOKEN="your_token_here"
uvicorn src.app:app --reload --host 0.0.0.0 --port 8000For Hugging Face Spaces, add GENIUS_ACCESS_TOKEN as a Space secret.
Dataset conversion
The repo includes a converter for your zipped datasets:
python3 scripts/convert_datasets.py --limit 500It reads:
/Users/abdel/Downloads/data.csv.zip/Users/abdel/Downloads/Movie_combined.csv.zip
It writes:
data/real_songs_sample.jsondata/real_movies_sample.json
Social features
Aux Battle lives at /aux. It lets two users create profiles, choose playlist names, pick songs within a genre, run a familiarity battle, and save unfamiliar songs into a shareable playlist link.
Song appearance scoring is available at POST /songs/appearance-score. The current formula is intentionally simple:
score = aux_battle_appearances + playlist_appearances + streams_since_joining
Database schema (pgvector)
Apply db/schema.sql to create:
movieswithplot_embedding vector(1536)songswithlyric_embedding vector(1536)movie_swipesfor Tinder-style likes/dislikesuser_profilesfor cached hybrid centroids and weights
Tests
python3 -m unittest discover -s testsPublic demo deploy (Render)
- Go to Render, click New + -> Blueprint.
- Connect your GitHub repo
asricka/Movie_songs. - Render will detect
render.yamland create the web service. - Click Apply and wait for deploy to finish.
- Open your live URL:
https://<your-render-service>.onrender.com/healthhttps://<your-render-service>.onrender.com/docs
Manual Render (without Blueprint)
- New Web Service from your GitHub repo.
- Runtime:
Python. - Build Command:
pip install -r requirements.txt - Start Command:
uvicorn src.app:app --host 0.0.0.0 --port $PORT - Add env vars:
EMBEDDING_PROVIDER=localMOVIES_PATH=data/movies.jsonSONGS_PATH=data/songs.json
Alternative host (Railway/Heroku-style)
This repo includes a Procfile:
web: uvicorn src.app:app --host 0.0.0.0 --port $PORT
Hugging Face Spaces deploy
This repo is now configured for a Docker Space:
Dockerfilestarts the FastAPI app on port7860README.mdincludes the Hugging Face Space metadata
Create the Space
- Go to Hugging Face Spaces.
- Choose:
- Owner: your account
- Space name:
movie-songs-demo - SDK:
Docker - Visibility: Public or Private
- Create the Space.
Push this repo to the Space
If your Hugging Face username is asricka, run:
git -C /Users/abdel/Documents/Playground remote add hf https://huggingface.co/spaces/asricka/movie-songs-demo
git -C /Users/abdel/Documents/Playground push hf mainIf you already added an hf remote before, update it instead:
git -C /Users/abdel/Documents/Playground remote set-url hf https://huggingface.co/spaces/asricka/movie-songs-demo
git -C /Users/abdel/Documents/Playground push hf mainYou will be prompted for Hugging Face credentials or a token. After the build finishes, the Space URL will be:
https://huggingface.co/spaces/asricka/movie-songs-demo
GitHub push
After adding your remote:
git push -u origin mainIf your default branch is master, push that instead:
git push -u origin master