# SERVICES KNOWLEDGE BASE **Target:** `backend/app/services/` **Context:** Central business logic, 7+ specialized services, LLM integration. ## OVERVIEW Core logic hub transforming raw music data into metrics, playlists, and AI narratives. - **Data Ingress/Egress**: `SpotifyClient` (OAuth/Player), `GeniusClient` (Lyrics), `ReccoBeatsClient` (Audio Features). - **Analytics**: `StatsService` (HHI, Gini, clustering, heatmaps, skip detection). - **AI/Narrative**: `NarrativeService` (LLM prompt engineering, multi-provider support), `AIService` (Simple Gemini analysis). - **Orchestration**: `PlaylistService` (AI-curated dynamic playlist generation). ## WHERE TO LOOK | Service | File | Key Responsibilities | |---------|------|----------------------| | **Analytics** | `stats_service.py` | Metrics (Volume, Vibe, Time, Taste, LifeCycle). | | **Spotify** | `spotify_client.py` | Auth, Player API, Playlist CRUD. | | **Narrative** | `narrative_service.py` | LLM payload shaping, system prompts, JSON parsing. | | **Playlists** | `playlist_service.py` | Periodic curation logic (6h/24h cycles). | | **Enrichment** | `reccobeats_client.py` | External audio features (energy, valence). | | **Lyrics** | `genius_client.py` | Song/Artist metadata & lyrics search. | ## CONVENTIONS - **Async Everywhere**: All external API clients (`Spotify`, `ReccoBeats`) use `httpx.AsyncClient`. - **Stat Modularization**: `StatsService` splits logic into `compute_X_stats` methods; returns serializable dicts. - **Provider Agnostic AI**: `NarrativeService` detects `OPENAI_API_KEY` vs `GEMINI_API_KEY` automatically. - **Payload Shaping**: AI services aggressively prune stats JSON before sending to LLM to save tokens. - **Fallbacks**: All AI/External calls have explicit fallback/empty return states. ## ANTI-PATTERNS - **Blocking I/O**: `GeniusClient` is synchronous; avoid calling in hot async paths. - **Service Circularity**: `PlaylistService` depends on `StatsService`. Avoid reversing this. - **N+1 DB Hits**: Aggregations in `StatsService` should use `joinedload` or batch queries. - **Missing Checksums**: Audio features assume presence; always check for `None` before math. - **Token Waste**: Never pass raw DB models to `NarrativeService`; use shaped dicts.