Spaces:
Sleeping
EUMORA β Product Feature Specification
Version 1.0 | May 2026 | Status: In Development
1. What EUMORA Does
EUMORA is a lyric-to-song recommendation engine. A user provides a piece of text β song lyrics, a mood description, a sentence β and EUMORA:
- Classifies the emotional content of the text using a fine-tuned DeBERTa-v3-Base transformer model
- Maps that emotion to a set of Spotify audio feature targets (valence, energy, danceability, tempo, mode)
- Queries the Spotify Recommendations API with those targets to find real songs matching the emotional fingerprint
- Returns a ranked list of track recommendations with per-feature match justification
2. Spotify Audio Features β What We Can and Can't Map
Spotify's /v1/audio-features and /v1/recommendations use the following fields. Our emotion classifier
operates on text only, so mappability depends on whether emotion correlates with that feature:
| Spotify Field | Type | Range | Can We Map? | Reasoning |
|---|---|---|---|---|
valence |
float | 0.0 β 1.0 | β Yes | Directly correlates with positive/negative emotion |
energy |
float | 0.0 β 1.0 | β Yes | High for joy/anger/surprise, low for sadness/neutral |
danceability |
float | 0.0 β 1.0 | β Yes | High for joy/love/surprise, low for sadness/fear |
tempo |
float (BPM) | ~50 β 200 | β Yes | Fast for joy/anger, slow for sadness/fear |
mode |
int | 0 (minor) / 1 (major) | β Yes | Joy/love β major; sadness/anger/fear β minor |
loudness |
float (dB) | -60 β 0 | β οΈ Partial | Anger/joy β louder; sadness/neutral β quieter |
speechiness |
float | 0.0 β 1.0 | β οΈ Partial | Sarcasm/anger skew slightly higher; not strongly correlated |
acousticness |
float | 0.0 β 1.0 | β No | Depends on instrumentation, not text emotion |
instrumentalness |
float | 0.0 β 1.0 | β No | Depends on vocal presence, not text content |
liveness |
float | 0.0 β 1.0 | β No | Live vs. studio recording β unrelated to emotion |
key |
int | 0 β 11 (Pitch) | β No | Musical key β no emotion mapping |
time_signature |
int | 3 β 7 | β No | Rhythmic metre β no emotion mapping |
duration_ms |
int | ms | β No | Song length β unrelated |
Summary: We can confidently map 5 features (valence, energy, danceability, tempo, mode),
partially use 2 more (loudness, speechiness), and skip the remaining 6.
3. Emotion β Spotify Feature Targets
These are the numeric ranges passed as target_* parameters to /v1/recommendations.
Where the classifier returns a full probability distribution, the top-2 emotions are
blended by their probabilities (weighted average) for a more nuanced query.
| Emotion | target_valence |
target_energy |
target_danceability |
target_tempo (BPM) |
target_mode |
seed_genres |
|---|---|---|---|---|---|---|
| joy | 0.85 | 0.82 | 0.80 | 128 | 1 (major) | pop, dance |
| love | 0.75 | 0.52 | 0.62 | 96 | 1 (major) | romance, r-n-b |
| sadness | 0.18 | 0.28 | 0.32 | 72 | 0 (minor) | sad, indie, acoustic |
| anger | 0.18 | 0.88 | 0.58 | 148 | 0 (minor) | metal, hard-rock |
| fear | 0.22 | 0.52 | 0.38 | 88 | 0 (minor) | ambient, dark |
| surprise | 0.62 | 0.80 | 0.70 | 138 | 1 (major) | pop, electronic |
| neutral | 0.50 | 0.38 | 0.50 | 100 | 1 (major) | chill, study |
| sarcasm | 0.45 | 0.60 | 0.55 | 110 | 0 (minor) | alternative, indie |
Blended Query Example
Input: "I'm excited but kind of scared" β Classifier: 52% surprise + 35% fear β Blended targets:
target_valence= (0.52 Γ 0.62) + (0.35 Γ 0.22) = 0.40target_energy= (0.52 Γ 0.80) + (0.35 Γ 0.52) = 0.60target_tempo= (0.52 Γ 138) + (0.35 Γ 88) = 103 BPM
4. Core System Components
4.1 Emotion Classifier (src/predict.py)
- Model: DeBERTa-v3-Base fine-tuned on ~59k samples (GoEmotions + dair-ai/emotion)
- Output: 8 emotion classes β
sadness,joy,love,anger,fear,surprise,neutral,sarcasm - Sarcasm handling: Bayesian prior adjustment (
target_sarcasm_prior) corrects training-domain bias - Output format: Primary emotion + full probability distribution + confidence score + music context
- Current accuracy: ~65.6% weighted F1 on validation; 95%+ on unambiguous direct expressions
4.2 Emotion β Feature Mapper (src/spotify.py β to be built)
- Converts classifier output to numeric Spotify
target_*parameters - Implements probability-weighted blending across top-2 emotions
- Expands confidence score into
min_*/max_*constraint windows:- High confidence (>0.75) β tight window (Β±0.08 around target)
- Medium confidence (0.45β0.75) β medium window (Β±0.15)
- Low confidence (<0.45) β wide window (Β±0.25), broader genre seeds
4.3 Spotify Integration (src/spotify.py β to be built)
Endpoints used:
GET /v1/recommendationsβ Core call withtarget_valence,target_energy,target_danceability,target_tempo,target_mode,seed_genres,limitGET /v1/audio-features/{id}β Fetch actual features of returned tracks for match scoringGET /v1/searchβ Optional seed track lookup by title/artist
Authentication: OAuth 2.0 Client Credentials flow (no user login needed for recommendations)
4.4 Recommendation Ranker (src/spotify.py β to be built)
After Spotify returns candidates, EUMORA re-ranks using:
- Feature distance score: Euclidean distance across [
valence,energy,danceability,tempo_norm] between the emotion target vector and each track's actual audio features - Diversity filter: Max 2 tracks per artist in top-10
- Output: Ordered list of tracks with per-track match score (0β100)
5. Data Flow (End-to-End)
User Input: "City lights blur as I'm driving through the night"
β
[ EmotionPredictor β src/predict.py ]
DeBERTa-v3-Base β 8-class softmax β sarcasm calibration
β
{ emotion: "fear", confidence: 0.54, probabilities: {fear: 0.54, anger: 0.23, ...} }
β
[ Feature Mapper β src/spotify.py ]
Blend top-2 emotions (fear Γ 0.54 + anger Γ 0.23, normalised)
β { target_valence: 0.19, target_energy: 0.73, target_danceability: 0.46,
target_tempo: 122, target_mode: 0, seed_genres: ["dark", "hard-rock"] }
β
[ Spotify Recommendations API ]
GET /v1/recommendations?target_valence=0.19&target_energy=0.73&limit=20&seed_genres=dark,hard-rock
β
20 raw candidate tracks (with audio_features fetched per track)
β
[ Ranker β src/spotify.py ]
Euclidean distance scoring + artist diversity filter
β
Top 10 tracks with match scores + Spotify links
β
User Output (CLI / future: UI)
6. CLI Interface
| Command | What it does |
|---|---|
python main.py predict "text" |
Emotion only (existing) |
python main.py recommend "text" |
Full pipeline β Spotify tracks (to be added) |
python main.py recommend "text" --limit 5 |
Top 5 recommendations |
python main.py recommend "text" --genre rock |
Override seed genre |
python main.py recommend "text" --no-blend |
Use top-1 emotion only, no blending |
7. What It Does NOT Do (Phase 1 Scope)
- Does not map
acousticness,instrumentalness,liveness,key,time_signatureβ no text-to-audio model for these - Does not personalize based on user listening history (no user OAuth)
- Does not analyze audio files or waveforms (text-only)
- Does not stream or play music directly
- Does not guarantee sarcasm accuracy β calibration mitigates it
8. Planned Extensions (Phase 2+)
| Feature | Phase | Description |
|---|---|---|
| User preference learning | 2 | OAuth login; bias toward user's top genres/artists |
| Audio file analysis | 3 | Upload a recording; extract features via librosa |
| Acousticness/instrumentalness mapping | 3 | Infer from audio+lyrics combined model |
| Multimodal fusion | 4 | Combine lyrics emotion + audio features |
| Web UI | 5 | Browser interface with Spotify 30s clip previews |
| Playlist generation | 5 | Multi-text input β coherent 10-track playlist |
9. New Dependencies
| Library | Version | Role |
|---|---|---|
spotipy |
>=2.23.0 |
Spotify Web API client β handles OAuth + all endpoint calls |
Add to requirements.txt:
spotipy>=2.23.0