- About the Project
- 4-Agent Architecture
- Agent Collaboration Flow
- Agent Deep Dive
- Data Pipeline
- Metric Formulas
- Frontend Components
- Tech Stack
- Run Locally
- Project Structure
- Team
ManTarang is a Music Emotion Recognition (MER) system built on a 4-agent collaborative AI architecture. When a user types a natural-language query, four specialized AI agents coordinate in a pipeline β each with a distinct role β to produce ranked, explainable music recommendations.
Each agent contributes its expertise. The Planner leads, two specialists generate candidates, and the Judge delivers the final verdict.
| Query | Planner decides | Agents activated | Output |
|---|---|---|---|
"songs like Radiohead" |
Similarity strategy | Discovery + GenreMood | Genre-DNA matched tracks |
"chill lo-fi for studying" |
Context strategy | GenreMood | lo-fi / chillhop ranked list |
"dark indie rock" |
Genre strategy | GenreMood + Discovery | Confidence-scored results |
"energetic hip hop" |
Mood strategy | GenreMood | High-energy ranked tracks |
graph TD
USER["π€ User Query\nNatural Language Input"]
subgraph AGENTS[" 4-Agent Collaborative System "]
P["π§ Planner Agent\nβββββββββββββββββ\nOrchestrates the entire pipeline\nAnalyses query intent and complexity\nExtracts entities: artist, genre, mood\nCreates agent coordination plan\nDetermines which agents to activate"]
G["πΌ GenreMood Agent\nβββββββββββββββββ\nMood detection and analysis\nGenre matching and filtering\nTag generation and enhancement\nContext-aware intent adaptation\nCandidate generation by genre/mood"]
D["π Discovery Agent\nβββββββββββββββββ\nMulti-hop similarity exploration\nUnderground and hidden gem detection\nSerendipitous discovery beyond mainstream\nNovelty-optimized recommendations\nArtist similarity graph traversal"]
J["βοΈ Judge Agent\nβββββββββββββββββ\nCollects all agent candidates\nScores and ranks with RankingEngine\nOptimizes diversity with DiversityOptimizer\nGenerates human-readable explanations\nDelivers final ranked recommendations"]
end
RESULT["β
Final Recommendations\nRanked Β· Scored Β· Explained"]
USER --> P
P -->|genre/mood query| G
P -->|similarity/discovery query| D
G -->|genre candidates| J
D -->|discovery candidates| J
J --> RESULT
style P fill:#2D1B69,stroke:#C9A227,color:#fff
style G fill:#1e3a5f,stroke:#61DAFB,color:#fff
style D fill:#1a3a1a,stroke:#6ee7b7,color:#fff
style J fill:#3b1515,stroke:#f9a8d4,color:#fff
style AGENTS fill:#0d0d1a,stroke:#7C3AED,color:#fff
sequenceDiagram
actor User
participant P as π§ Planner Agent
participant G as πΌ GenreMood Agent
participant D as π Discovery Agent
participant J as βοΈ Judge Agent
User->>P: Natural language query
Note over P: Analyse intent, extract entities<br/>Determine strategy and complexity<br/>Build coordination plan
P->>G: Activate with genre/mood parameters
P->>D: Activate with similarity parameters
Note over G: Detect mood signals<br/>Match genre tags<br/>Generate genre candidates
Note over D: Explore artist similarity graph<br/>Detect underground gems<br/>Generate discovery candidates
G-->>J: Genre/Mood candidate pool
D-->>J: Discovery candidate pool
Note over J: Merge all candidates<br/>Score with RankingEngine<br/>Optimise diversity<br/>Generate explanations
J-->>User: Final ranked recommendations<br/>with metrics and confidence
The orchestrator. Runs first. Decides everything else.
flowchart TD
QA["QueryAnalyzer\nParse query complexity\nDetect ambiguity\nExtract primary intent"]
CA["ContextAnalyzer\nInterpret context signals\nHandle effective intent overrides\nTransform raw context"]
EP["EntityProcessor\nExtract: artist name\nExtract: genre keywords\nExtract: mood signals\nExtract: context triggers"]
SP["StrategyPlanner\nSelect recommendation strategy\nDecide agent activation order\nSet parameters per agent\nBuild coordination plan"]
QA --> CA --> EP --> SP
Outputs to: GenreMood Agent + Discovery Agent with a structured coordination plan.
The emotion specialist. Translates feelings into music.
flowchart TD
MA["MoodAnalyzer\nDetect mood from query\nhappy / sad / energetic\nchill / romantic / focused"]
GP["GenreProcessor\nMatch genre tags\nExpand via alias maps\nFilter by genre overlap"]
TG["TagGenerator\nGenerate enhanced tags\nCombine genre and mood signals\nContext-aware tag boost"]
UCG["UnifiedCandidateGenerator\nGenerate candidates\nby genre and mood\nfrom dataset"]
QS["QualityScorer\nScore genre fit\nScore mood alignment\nScore popularity balance"]
MA --> TG
GP --> TG
TG --> UCG --> QS
Outputs to: Judge Agent with a pool of genre/mood-matched track candidates.
The explorer. Finds what you didn't know you needed.
flowchart TD
DC["DiscoveryConfig\nSet novelty parameters\nConfigure similarity depth\nSet underground threshold"]
SE["SimilarityExplorer\nMulti-hop artist graph\nExplore genre neighbours\nFind sonic relatives"]
UD["UndergroundDetector\nDetect hidden gems\nScore novelty vs popularity\nFind non-mainstream tracks"]
DF["DiscoveryFilter\nFilter irrelevant candidates\nRemove duplicates\nApply quality threshold"]
DD["DiscoveryDiversity\nManage variety\nPrevent artist clustering\nBalance mainstream vs niche"]
DC --> SE
DC --> UD
SE --> DF
UD --> DF
DF --> DD
Outputs to: Judge Agent with a pool of discovery/similarity candidates.
The final decision maker. Ranks, diversifies, and explains.
flowchart TD
CS["CandidateSelector\nCollect all agent pools\nFilter by quality threshold\nRemove duplicates"]
RE["RankingEngine\nMulti-criteria scoring\nGenre match weight\nPopularity fit weight\nArtist credibility weight"]
DO["DiversityOptimizer\nPrevent artist repetition\nBalance genre spread\nOptimize result variety"]
EG["ExplanationGenerator\nGenerate per-track reasons\nCalculate confidence score\nBuild human-readable text"]
CS --> RE --> DO --> EG
Outputs: Final ranked recommendations with metrics, confidence, and explanations.
flowchart LR
CSV1["track_data_final.csv\n8778 tracks\ntrack + artist + genres\npopularity + followers"]
CSV2["spotify_data clean.csv\nGenre enrichment source"]
PARSE["Parse Genres\nast.literal_eval\nfallback string split"]
MERGE["Build Artist-Genre Map\nMerge both sources\n61% genre coverage"]
ENRICH["Enrich Missing Genres\nBack-fill from merged map"]
INDEX["Index Columns\nartist_lower\ntrack_lower\ngenres_lower"]
RAM["Shared Agent Dataset\nLoaded once at startup\nShared across all agents"]
CSV1 --> PARSE
CSV2 --> PARSE
PARSE --> MERGE
MERGE --> ENRICH
ENRICH --> INDEX
INDEX --> RAM
graph LR
GM["Genre Match\nJaccard overlap x 100\nWeight 45%"]
PF["Popularity Fit\ntrack_popularity / 100\nWeight 30%"]
AS["Artist Score\nlog10 followers / 8 x 100\nWeight 25%"]
RV["Overall Relevance\nGM x 0.45\nPF x 0.30\nAS x 0.25"]
CF["Track Confidence\nGM x 0.50\nAS x 0.30\nPF x 0.20\ndivided by 100"]
GM --> RV
PF --> RV
AS --> RV
GM --> CF
PF --> CF
AS --> CF
| Metric | Formula | Calculated By |
|---|---|---|
| Genre Match | genre_overlap(track, target) x 100 |
GenreMood + Discovery Agents |
| Popularity Fit | popularity / 100 x 100 |
Judge Agent |
| Artist Score | min(100, log10(followers)/8 x 100) |
Judge Agent |
| Overall Relevance | GM x 0.45 + PF x 0.30 + AS x 0.25 |
Judge Agent |
| Track Confidence | (GM x 0.50 + AS x 0.30 + PF x 0.20) / 100 |
Judge Agent |
| System Confidence | avg x 75 + strategy_premium + diversity_bonus |
Judge Agent |
graph TD
APP["App.jsx\nSearch Β· Results Β· State"]
STARS["Stars.jsx\n200 canvas stars\ndrift + twinkle"]
HERO["HeroTitle.jsx\nLetter hover animation\nColor wave + music notes"]
SKEL["SkeletonCard x5\nDomino wave loading\n--wave-delay CSS var"]
QP["QualityPanel\nSystem confidence\nCollapsible metric bars"]
TC["TrackCard x N\nRank Β· Title Β· Artist\nGenre chips Β· Links"]
GC["GlowCard\nMouse spotlight\n--gx --gy CSS vars"]
MB["MetricsBar\nSVG confidence ring\n4 animated progress bars"]
APP --> STARS
APP --> HERO
APP --> SKEL
APP --> QP
APP --> TC
TC --> GC
TC --> MB
| Layer | Technology | Purpose |
|---|---|---|
| π€ Agents | Python 3.11 β 4 agent classes | Planner, GenreMood, Discovery, Judge |
| π Backend | FastAPI + Uvicorn | REST API, routing, lifespan |
| π Data | Pandas + Spotify CSV | 8,778-track shared agent dataset |
| βοΈ Frontend | React 18 + Vite | SPA, hot reload, /api proxy |
| π Animation | Framer Motion | Transitions, AnimatePresence |
| π Canvas | HTML5 Canvas API | 200-star animated starfield |
| π³ Container | Docker multi-stage | Node build then Python serve |
| βοΈ Deploy | HuggingFace Spaces | CPU Basic, free, port 7860 |
# 1. Clone
git clone https://github.com/Ashutosh-177/ManTarang-AI-Powered-Music-Recommendation-System.git
cd ManTarang-AI-Powered-Music-Recommendation-System
# 2. Backend (terminal 1)
pip install -r requirements-hf.txt
uvicorn mantarang.src.api.backend:app --host 0.0.0.0 --port 8000 --reload
# 3. Frontend (terminal 2)
cd mantarang-ui
npm install
npm run dev
# open http://localhost:5173ManTarang/
βββ mantarang/src/
β βββ agents/
β β βββ planner/ β Agent 1: Orchestrates pipeline
β β β βββ agent.py
β β β βββ query_analyzer.py
β β β βββ context_analyzer.py
β β β βββ strategy_planner.py
β β β βββ entity_processor.py
β β βββ genre_mood/ β Agent 2: Emotion and genre specialist
β β β βββ agent.py
β β β βββ components/
β β βββ discovery/ β Agent 3: Similarity and novelty explorer
β β β βββ agent.py
β β β βββ similarity_explorer.py
β β β βββ underground_detector.py
β β βββ judge/ β Agent 4: Ranks and explains results
β β βββ agent.py
β β βββ components/
β β βββ ranking_engine.py
β β βββ diversity_optimizer.py
β β βββ explanation_generator.py
β βββ api/
β βββ backend.py β FastAPI routes
β
βββ mantarang-ui/src/
β βββ App.jsx
β βββ components/
β βββ HeroTitle.jsx
β βββ TrackCard.jsx
β βββ MetricsBar.jsx
β βββ SkeletonCard.jsx
β βββ Stars.jsx
β βββ GlowCard.jsx
β
βββ track_data_final.csv β Shared agent dataset (8,778 tracks)
βββ Dockerfile
βββ METRICS.md
βββ PROJECT_REPORT.md
| Ashutosh Kumar Singh | Enrollment No. 92301733016 |
| Aditya Raj | Enrollment No. 92301733062 |
Music Emotion Recognition (MER) β 2026