Add mood scanner and surprise me features to discover page

Add mood_energy and mood_valence sliders that inject mood context into
AI recommendation prompts. Add "Surprise Me" button that generates
recommendations from a creative, unexpected angle without requiring
any user input. Includes backend endpoints, schema updates, and
full frontend UI integration.
This commit is contained in:
root
2026-03-31 18:31:35 -05:00
parent da94df01da
commit 0b82149b97
5 changed files with 180 additions and 4 deletions

View File

@@ -70,6 +70,7 @@ MODE_PROMPTS = {
"era_bridge": "Suggest classic artists from earlier eras who directly inspired their current favorites. Trace musical lineage — if they love Tame Impala, suggest the 70s psych rock that influenced him. Bridge eras.",
"deep_cuts": "Find B-sides, album tracks, rarities, and lesser-known songs from artists already in their library. Focus on tracks they probably haven't heard even from artists they already know.",
"rising": "Find artists with under 50K monthly listeners who match their taste. Focus on brand new, up-and-coming artists who haven't broken through yet. Think artists who just released their debut album or EP.",
"surprise": "Be wildly creative. Pick ONE obscure, unexpected angle from their taste profile — maybe a specific production technique, a niche sub-genre, a particular era, or an unusual sonic quality — and build all recommendations around that single thread. Start your 'reason' for the first recommendation by explaining the angle you chose. Make it feel like a curated rabbit hole they never knew they wanted.",
}
@@ -92,6 +93,8 @@ async def generate_recommendations(
adventurousness: int = 3,
exclude: str | None = None,
count: int = 5,
mood_energy: int | None = None,
mood_valence: int | None = None,
) -> tuple[list[Recommendation], int | None]:
"""Generate AI music recommendations using Claude."""
@@ -145,7 +148,10 @@ async def generate_recommendations(
disliked_artists = list({a for a in disliked_result.scalars().all()})
# Build prompt
user_request = query or "Find me music I'll love based on my taste profile. Prioritize lesser-known artists and hidden gems."
if mode == "surprise" and not query:
user_request = "Surprise me with something unexpected based on my taste profile. Pick a creative, unusual angle I wouldn't think of myself."
else:
user_request = query or "Find me music I'll love based on my taste profile. Prioritize lesser-known artists and hidden gems."
if bandcamp_mode:
focus_instruction = "IMPORTANT: Strongly prioritize independent and underground artists who release music on Bandcamp. Think DIY, indie labels, self-released artists, and the kind of music you'd find crate-digging on Bandcamp. Focus on artists who self-publish or release on small indie labels."
@@ -158,6 +164,18 @@ async def generate_recommendations(
# Adventurousness instruction
adventurousness_instruction = build_adventurousness_prompt(adventurousness)
# Mood instruction
mood_instruction = ""
if mood_energy is not None or mood_valence is not None:
energy_desc = {1: "very chill and calm", 2: "relaxed", 3: "moderate energy", 4: "upbeat and energetic", 5: "high energy and intense"}
valence_desc = {1: "dark, melancholy, or moody", 2: "introspective or bittersweet", 3: "neutral mood", 4: "positive and uplifting", 5: "happy, euphoric, or celebratory"}
parts = []
if mood_energy is not None:
parts.append(f"Energy: {energy_desc.get(mood_energy, 'moderate energy')}")
if mood_valence is not None:
parts.append(f"Mood: {valence_desc.get(mood_valence, 'neutral mood')}")
mood_instruction = f"\nMatch this mood: {'. '.join(parts)}"
# Exclude genres instruction
exclude_instruction = ""
combined_exclude = exclude or ""
@@ -180,6 +198,7 @@ User request: {user_request}
Discovery mode: {mode_instruction}
{adventurousness_instruction}
{mood_instruction}
IMPORTANT: If the user mentions specific artists or songs in their request, do NOT recommend anything BY those artists. The user already knows them — recommend music by OTHER artists that match the vibe. For example, if they say "I like Sublime", recommend artists similar to Sublime, but NEVER Sublime themselves.