
AI-Powered Genre Mapping
How we built a smart genre resolution system that maps free-text genres to distributor taxonomies.
ONCE Engineering
Every music distributor has a fixed genre taxonomy. When an artist tells the ONCE chat agent their track is "lo-fi bedroom pop," we need to resolve that to a valid genre in the distributor's catalog before submission. Manual dropdown selection is tedious and error-prone, so we built a smart resolution system that handles it automatically.
The Resolution Cascade
Genre resolution follows a three-step cascade. Each step is a fallback for the one before it:
┌────────────────┐ ┌────────────────┐ ┌────────────────┐
│ Exact Match │────▶│ AI Mapping │────▶│ Fuzzy Matching │
│ (instant) │ │ (GPT) │ │ (Levenshtein) │
└────────────────┘ └────────────────┘ └────────────────┘
1. Exact Match
First, we do a case-insensitive comparison against the distributor's genre catalog. If the user's input matches a known genre exactly, we return immediately with no AI call and no added latency.
2. AI Mapping
If there's no exact match, we fetch the complete genre list from the distributor's API and pass it to GPT along with the user's input. The prompt is tightly constrained:
You are a music genre expert. A user has selected the genre
"{userGenre}" for their music release.
Select the ONE genre from the available list that BEST
represents the user's intent.
Available genres:
- {genreList}
Respond with ONLY the exact genre name from the list.
The model must return a genre that exactly matches one from the catalog. If it doesn't, we reject the response and fall through to the next step.
3. Fuzzy Matching
If the AI fails or returns an invalid genre, we fall back to Levenshtein distance matching. This normalizes both strings (removes diacritics, punctuation, collapses whitespace) and calculates similarity scores against every genre in the catalog. The top match is returned along with the top 5 suggestions.
If all three steps fail, we default to "Unknown" and flag it for review.
No Hardcoded Taxonomies
One important design decision: we don't maintain a hardcoded genre list. The catalog is fetched dynamically from the distributor's API at resolution time. This means if the distributor adds, removes, or renames genres, our system picks it up automatically without a code change.
Validation and Retry
The AI response goes through strict validation. The returned genre must be a case-insensitive exact match against the catalog. We also handle token truncation: if the response appears cut off, we retry with a doubled token budget (up to 1,200 tokens) to make sure we get a clean answer.
Classical Music Detection
Classical releases get special treatment beyond genre mapping. We use pattern matching to detect classical genres ("classical," "opera," "symphony," "chamber music," "baroque," etc.) and trigger enhanced validation rules for Apple Music compliance. Classical metadata has stricter formatting requirements for movements, opus numbers, and performer credits.
Cost Tracking
Every AI genre call is tracked separately from chat and validation agent costs. Each call logs the user, release, and conversation it was triggered from, so we can report genre resolution costs per-user in the admin dashboard.
Performance
- Exact matches: No AI call, instant response
- AI mapping: ~200-500ms additional latency (only when needed)
- Fuzzy fallback: Same performance as before AI was added
In practice, a large percentage of genres resolve via exact match, so the AI only fires when users provide creative or non-standard genre descriptions.
What's Next
We're working on open-sourcing our genre resolution tool as a standalone library. The cascade pattern (exact → AI → fuzzy) is useful beyond music distribution, and we want to make it available for anyone building against fixed taxonomies.
Genre resolution runs automatically during every release submission through ONCE. No user action required.
Try ONCE