music_rec_sys: MoodTunes Turns Feelings Into a Playlist, Then Protects the Vibe With Hard-Nosed Feedback

Inside an open-source music recommender that maps language to emotion, uses Rocchio to reshape taste in real time, and encrypts Spotify tokens so personalization does not come at the cost of trust.

8 min read • View on GitHub • More from rutuchaudhari06

A person stands before a turntable built from concentric emotional rings while song cards are pulled inward or pushed away by magnetic forces. One card is repelled more forcefully than the others, showing that the system cares just as much about avoiding the wrong song as finding the right one.
MoodTunes is built around emotional rejection as much as emotional matching. The strongest signal is often the track that should not be there.
Key Takeaways

Why MoodTunes Cares More About Ruining the Vibe Than Finding the Perfect Song

Most recommenders optimize for relevance. MoodTunes optimizes for continuity. That difference matters because mood is brittle. One off-track recommendation can break the session faster than a mediocre but adjacent one ever could.

The repo’s core belief is simple: negative space is the real control surface. It is easier to keep a playlist emotionally coherent by removing the wrong candidates than by endlessly searching for the perfect one.

Traditional recommenderMoodTunes
Find songs you may likeKeep the current mood intact
Positive preference dominatesNegative feedback is weighted harder
Success means higher relevanceSuccess means fewer emotional interruptions
Wrong results are toleratedWrong results are treated as disruptive
User intent is broadUser intent is a narrow vibe boundary

The pipeline is not just classification. It is translation, compression, and correction, with feedback that deliberately pushes harder on what the user rejects.

How Text Becomes a Mood Vector

The translation stack starts with emotion.py. A RoBERTa model classifies the text into 28 emotions, which are then mapped into valence-arousal space. That gives the system a geometry for feelings instead of a single label.

From there, the project collapses those 28 emotions into seven user-facing vibe buckets. That move is smart product design. The model gets to think in detail, while the interface speaks in a smaller emotional vocabulary.

# Conceptual flow from emotion.py
text -> roberta_go_emotions -> 28_emotion_scores
28_emotion_scores -> valence_arousal_point
valence_arousal_point -> vibe_bucket

# Example idea:
# joy + excitement -> high valence, high arousal
# sadness + fatigue -> low valence, low arousal
A mechanical translator device breaks a spoken phrase into many small tokens, then compresses them into seven larger vibe tiles before sending them through a weighted filter. The filter shows that some signals are treated as much heavier than others, which explains how language becomes a steerable mood representation.
MoodTunes does not read emotion as a single label. It compresses language into a smaller emotional shape that the recommender can work with.

The Recommender Does Three Things at Once

The scorer is hybrid by design. It blends emotion alignment, preference similarity, and popularity into one final rank. That is a practical concession. Mood alone is not enough to pick tracks, and taste alone is not enough to preserve the session’s emotional target.

The other moving part is Rocchio-style feedback. Seed tracks initialize the profile, likes nudge it toward similar tracks, and dislikes push it away. The repo’s distinctive choice is how hard that push happens.

SignalRole in rankingBehavior in MoodTunes
Emotion scoreTracks the target vibeKeeps results aligned to the current mood
Preference scoreTracks the user profileMoves with likes, dislikes, and seed tracks
Popularity scoreAdds a coarse fallbackPrevents the list from becoming too narrow
Rocchio updateRewrites the profile vectorUses stronger negative correction than positive reward

Why the System Favors Dislikes

This is the repo’s boldest product choice: dislikes carry a weight of -4.0 while likes sit at +1.0. That asymmetry is not a bug. It is a statement about what mood products are supposed to do.

If the user is trying to stay in a specific emotional lane, a bad track is more damaging than a good one is helpful. MoodTunes encodes that reality directly. It does not merely learn what the user likes. It learns what would break the session.

Positive feedbackNegative feedback
+1.0 moves the profile closer+4.0 equivalent push moves it away harder
Adds signalRemoves risk
Useful for refinementCrucial for containment
Helpful in many recommendersMore important in a vibe-first system

That logic is why the project feels coherent. The system is not trying to maximize delight in the abstract. It is trying to preserve a fragile emotional boundary.

From Recommendation to Playlist, With Tokens Locked Down

The Spotify layer turns model output into something usable. OAuth handles authorization, encrypted token storage protects credentials, and playlist creation batches track adds so the system can hand off a finished result instead of just a ranked list.

The privacy detail matters because it changes the product story. Encryption is not a decorative security feature here. It is part of the trust contract required for personalized music software.

Plaintext tokensEncrypted tokens
Readable if the database leaksProtected by Fernet before storage
Easy to misuseHarder to extract and reuse
Fast to implementMore credible for a personalization app
Treats security as afterthoughtTreats security as part of product design

Why the Prototype Feels More Mature Than Its Scale Suggests

The stack is small, but it is not sloppy. FastAPI, Pydantic, SQLAlchemy, SQLite, Hugging Face, Parquet, and NumPy fit together into a clean path from ingestion to inference to playlist creation. The repo reads like someone built the boring parts carefully.

That said, the current design is still an in-memory system at heart. It is quick and elegant for a prototype. It will not stay elegant once the catalog and user base grow much larger.

What works nowWhat would need to change at scale
In-memory vector mathVector database or retrieval layer
Single-user fast iterationDistributed inference
Local Parquet datasetMore robust ingestion and indexing
SQLite simplicityStronger concurrency and storage strategy

What Would Have to Change for MoodTunes to Scale

The main ceiling is retrieval. As the song catalog and user activity grow, the current approach will need better indexing, more durable storage, and a way to keep the preference vector responsive without loading everything into memory.

But the idea itself scales well. MoodTunes has a clear product thesis, a legible feedback loop, and a trust layer that matches the intimacy of the use case. That is a strong foundation, even before the infrastructure catches up.