feat(enrichment): loose MusicBrainz search fallback (find aliased/romanized artists) - #771
Conversation
…ists)
The MB text search used a strict field-phrase query
(`recording:"<title>" AND artist:"<artist>"`). A field phrase only matches
MusicBrainz's *primary* artist/title — it never searches ALIASES — so a
recording stored under a non-Latin primary name (大橋純子) whose romanized
form ("Junko Ohashi") is only an alias returns ZERO results, even though MB
has it. Whole swaths of a community library (e.g. romanized J-pop / city-pop
charts) were unsearchable.
- `build_recording_query(..., loose=True)` drops the field scoping + phrases
for plain AND-ed term groups (`(telephone number) AND (junko ohashi)`),
which searches the whole document incl. aliases.
- `_mb_search_recordings` runs the strict query first (unchanged, high
precision) and only on an EMPTY result retries once with the loose query —
so mainstream matches are untouched and the extra throttled request is spent
only on a miss. Results are re-scored by rank_candidates, so recall goes up
without lowering match quality (auto-accept still needs the per-field floors).
Verified live: "Junko Ohashi / Telephone Number" and "Anri / Windy Summer"
(both 0 under the strict query) now surface the real records; "AC/DC /
Highway to Hell" still hits strict at score 1.0 with no loose retry.
Follow-up (separate): alias-aware SCORING so these can auto-confirm, not just
appear as manual candidates.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughAdds a ChangesLoose Query Fallback
Estimated code review effort: 2 (Simple) | ~12 minutes Sequence Diagram(s)sequenceDiagram
participant Caller
participant _mb_search_recordings
participant build_recording_query
participant MusicBrainzAPI
Caller->>_mb_search_recordings: search(artist, title)
_mb_search_recordings->>build_recording_query: build_recording_query(artist, title)
build_recording_query-->>_mb_search_recordings: strict query
_mb_search_recordings->>MusicBrainzAPI: GET /recording (strict query)
MusicBrainzAPI-->>_mb_search_recordings: results
alt strict results empty
_mb_search_recordings->>build_recording_query: build_recording_query(artist, title, loose=True)
build_recording_query-->>_mb_search_recordings: loose query
_mb_search_recordings->>MusicBrainzAPI: GET /recording (loose query)
MusicBrainzAPI-->>_mb_search_recordings: results
end
_mb_search_recordings-->>Caller: candidates
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
…fallback # Conflicts: # lib/mb_match.py # server.py
|
Review + fix pass (Claude Code). The loose-fallback logic is correct: Fixed: this branch predated #758 (now merged to main), so it modified the old |
The loose fallback dropped the strict path's -secondarytype:Live filter, so a studio chart whose strict query missed could fall back to — and, since score_candidate doesn't penalize live takes, auto-confirm — a live-only recording. Apply the same live gate to the loose query (skipped only when the source title is itself a live take). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…y artists (#772) * feat(enrichment): loose MusicBrainz search fallback (find aliased artists) The MB text search used a strict field-phrase query (`recording:"<title>" AND artist:"<artist>"`). A field phrase only matches MusicBrainz's *primary* artist/title — it never searches ALIASES — so a recording stored under a non-Latin primary name (大橋純子) whose romanized form ("Junko Ohashi") is only an alias returns ZERO results, even though MB has it. Whole swaths of a community library (e.g. romanized J-pop / city-pop charts) were unsearchable. - `build_recording_query(..., loose=True)` drops the field scoping + phrases for plain AND-ed term groups (`(telephone number) AND (junko ohashi)`), which searches the whole document incl. aliases. - `_mb_search_recordings` runs the strict query first (unchanged, high precision) and only on an EMPTY result retries once with the loose query — so mainstream matches are untouched and the extra throttled request is spent only on a miss. Results are re-scored by rank_candidates, so recall goes up without lowering match quality (auto-accept still needs the per-field floors). Verified live: "Junko Ohashi / Telephone Number" and "Anri / Windy Summer" (both 0 under the strict query) now surface the real records; "AC/DC / Highway to Hell" still hits strict at score 1.0 with no loose retry. Follow-up (separate): alias-aware SCORING so these can auto-confirm, not just appear as manual candidates. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(enrichment): alias-aware scoring (auto-confirm non-Latin-primary artists) Builds on the loose-search fallback: that surfaces a recording stored under a Japanese primary name (大橋純子) via its romanized alias, but the SCORER still compared the reference ("Junko Ohashi") against the primary only → artist similarity 0 → below the auto floor, so it could only ever be a manual candidate, never an auto-fill. - mb_match: `cand_artist_sim` takes the best similarity over the candidate's primary name AND its `artist_aliases`; score_candidate + classify use it. - server: `_mb_artist_aliases(id)` fetches an artist's aliases (one throttled lookup, process-cached — a one-artist discography costs ONE request) and `_alias_enrich` attaches them ONLY to promising near-misses (title agrees, primary artist doesn't) so a normal pass spends zero extra requests. Wired into both the auto-matcher (_enrich_one) and the manual search proxy. Verified live: "Junko Ohashi / Telephone Number" → 大橋純子 candidate goes from score 0.5 (loose-only) to 1.0 (auto-confirmable), ranked #1; "AC/DC / Highway to Hell" unchanged at 1.0 with no alias lookup. Stacks on #771 (feat/mb-loose-search-fallback). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(enrichment): keep live exclusion in the loose search fallback The loose fallback dropped the strict path's -secondarytype:Live filter, so a studio chart whose strict query missed could fall back to — and, since score_candidate doesn't penalize live takes, auto-confirm — a live-only recording. Apply the same live gate to the loose query (skipped only when the source title is itself a live take). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: byrongamatos <xasiklas@gmail.com>
Problem
The MB text search is a strict field-phrase query:
recording:"<title>" AND artist:"<artist>". A field phrase only matches MusicBrainz's primary artist/title — it never searches aliases. So a recording stored under a non-Latin primary name (大橋純子) whose romanized form ("Junko Ohashi") is only an alias returns zero results, even though MB has the record. Large parts of a community library (romanized J-pop / city-pop charts) were effectively unsearchable — searches just came up empty.Fix — strict-then-loose fallback
build_recording_query(..., loose=True)drops the field scoping and phrases for plain AND-ed term groups ((telephone number) AND (junko ohashi)), which searches the whole document including aliases._mb_search_recordingsruns the strict query first (unchanged, high precision); only when it returns nothing does it retry once with the loose query. Mainstream matches are untouched, and the extra throttled request is spent only on a miss. Candidates are re-scored byrank_candidates, so recall rises without lowering match quality (auto-accept still requires the per-field floors).Benefits both the background Refresh-Metadata pass and the manual Fix-match search box.
Verified live
Tests
build_recording_queryloose form (drops field phrases; missing-artist case)._mb_search_recordingsretries loose on an empty strict result, and does not retry when strict hits (no wasted request).Follow-up (separate)
Alias-aware scoring — compare the reference against a candidate's romanized aliases — so these can auto-confirm, not just appear as manual candidates (today the artist-script mismatch keeps the auto score low).
🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Bug Fixes
Tests