1. High-Level Architecture

Section 1 · deployed path

Whole-system input

Conversation, played tracks, user profile

Retrieve → rank → respond

Typed state → 11 catalog queries → candidate union → LambdaMART → final ordering → response LLM

Output

20 track IDs + one short recommendation

Deployed pipeline

The submission architecture: conversation and played tracks flow through state extraction and entity resolution into eleven LanceDB retrieval branches. Their pool union goes to a 146-feature LambdaMART ranker, final ordering with an exact-track pin and artist check, the top 20, and a response LLM. Weighted RRF appears separately in amber as the baseline and fallback.

Dark adaptation of the architecture figure. The main learned path and the separate RRF baseline/fallback are visually distinguished.

One-turn data flow

Listener

“Find the specific subdued Neko Case song…”

State

Hidden target · Neko Case · mood/lyric/sonic clues

Ranking

Candidate union → learned scores → final ordering → top 20

Experience

Top track + grounded response

What crosses each system boundary

State Extractionconversation historystructured, catalog-groundable state
Retrievalstate + catalogcandidate union
Rankingcandidate rows + featureslearned scores + exact-track/artist guards → ordered top 20
Response Generationtop 1 + latest statelistener-facing response

Sources: paper/main.tex Figure 1; final Blind-B configuration.

2. State Extraction

Section 2 · language → retrieval contract

Input: session

“Subdued, female singer… a sense of place… not it either.”

Earlier: Neko Case; rejected “Calling Cards” and “Man”

State Extraction

Read the whole dialog → preserve facts and feedback → resolve named entities

Output: usable state

Hidden target · Neko Case anchor · two rejected tracks · mood, lyric, and sonic facets

Session → extracted state

SESSION 024a2738-a96c-4e11-adf3-b2cb8311a493 · TURN 3

Conversation excerpt

T1

Listener “It’s a Neko Case track.”

T2

Previous recommendation Neko Case — “Calling Cards”
Listener: “not quite it”

T3

Previous recommendation Neko Case — “Man”
Listener: “Much more subdued… sense of place… stark, almost a cappella… not it either.”

Extracted state

{
  "turn": 3,
  "request_type": "hidden_target",
  "must_use_artist": "Neko Case",
  "avoid_tracks": ["Calling Cards", "Man"],
  "facets": {
    "mood": "subdued",
    "lyrics": "sense of place",
    "sonic": "stark, almost a cappella"
  }
}

Source: retained Blind-B trace, session 024a2738-a96c-4e11-adf3-b2cb8311a493, turn 3; paper/main.tex Figure 2.

Extracted facts

The extractor preserves six kinds of information. This turn produced:

Current askFind a hidden target; keep narrowing.
Named musicNeko Case · “Calling Cards” · “Man”
±FeedbackBoth previous tracks rejected.
ConstraintsArtist must remain Neko Case.
Descriptive cluesSubdued · sense of place · almost a cappella
Search cuesHidden-target + lyric-aware retrieval.

Code contract: mcrs/conversation_state/schema.py. Architecture: docs/architectures/session_state.md.

From extracted facts to retrieval state

1Keep valid factsOptional details can be missing without losing the whole turn.
2Ground namesMatch artists, tracks, albums, and tags to catalog vocabulary.
3Compile search intentCreate anchors, exclusions, filters, text queries, and routing cues.

Source: docs/architectures/session_state.md `1–2.

Entity resolution

LANGUAGE“Watercolors” by Pat Metheny
1

Normalizecase, punctuation, whitespace

2

Match by entity typeartist / track / album against catalog names

3

Fuzzy fallbackartist top-20 · track top-5 · cutoff 80

✓ Artist foundPat Metheny → catalog artist ID

× Track not foundWatercolors remains unresolved

Unresolved names stay visible instead of silently becoming a different catalog item.

Source: retained Blind-B trace; resolver architecture in docs/architectures/session_state.md.

Retrieval contract

Intent

What the listener wants now.

Anchors

Resolved artists/tracks allowed to seed candidates.

Avoid

Played items, explicit rejections, abandoned artists.

Query facets

Tags, mood, lyrics, sonic and temporal cues.

Routing

Which query shapes fit this request.

Known gaps

Facts preserved in text but absent from catalog fields.

The resolved state is the only state object consumed by retrieval and feature construction.

3. Retrieval

Section 3 · one catalog, many query views

Input

Resolved intent, anchors, rejections, tags, history, user vector

11 active branches

BM25 + 3 dense text + CLAP audio + 3 anchor centroids + user CF + 2 lookups

Output

Union of branch pools, each truncated to 500, ready for learned ranking

Lexical BM25/tag resolver · Semantic Qwen text views · Multimodal CLAP/SigLIP · Behavioral CF centroids · Exact catalog lookups

↓ Detail: catalog · branch map · lexical · dense · anchors · candidate union

LanceDB catalog

47,071

tracks

1 table

shared ID namespace

11

active retrieval branches

metadata + vectors

FTS, text, audio, image, CF, b1

Every branch queries the same catalog row and returns the same track_id, which makes union, feature joins, and replay deterministic.

Goal not fully materializedWe wanted one catalog-grounded query plan for the listener’s complete request. In practice, retrieval split the request across branches and the ranker had to recombine their evidence.

Source: paper/main.tex `2; mcrs/qu_modules/catalog_lance.py.

Retrieval branch map

Resolved state

BM25 + tag resolver

Dense text ×3

CLAP text → audio

Anchor centroids ×3

User-CF centroid

Discography + era lookups

Candidate union

Track ID + branch rank + branch score + presence

The final learned path does not use the RRF order as its ranking input; it uses the union and branch evidence.

Source: paper/main.tex Figure 1 and Table 1.

Lexical and tag retrieval

Free-form phrase → catalog tag

1.0Exactnormalized phrase is a catalog tag
0.9Aliascurated synonym maps to a known tag
0.8Substringknown tag appears inside the phrase
≥.60Embeddingtop-3 semantic neighbors, only if lexical tiers fail

SIMPLIFIED BM25 CLAUSES · NEKO CASE TURN

artist_name“Neko Case”× 3.0

track_name“subdued… sense of place…”× 3.0

tag_listresolved descriptive tags× 1.5

Each clause is a separate SHOULD match. Rejected tracks are removed after retrieval.

If no tag resolves, the raw phrase remains in text search so the signal is not dropped.

Source: docs/architectures/v0plus_retrieval.md; final Blind-B config.

Dense and multimodal retrieval

Query view Catalog field searched What it can surface
current request metadata_qwen3_embedding_8b artist, title, album, and broad semantic matches
musical attributes attributes_qwen3_embedding_8b genre, mood, style, and descriptive matches
lyrical theme lyrics_qwen3_embedding_0_6b lyric and narrative similarity
sonic description audio_laion_clap text-to-audio similarity

The 11 modeled branches preserve their own score scales. LambdaMART receives branch-specific rank, score, margin, hit, z-score, and percentile evidence.

Source: paper/main.tex `2 and model feature names.

Anchors, CF, and lookups

Liked-track audio

CLAP centroid of positive anchors.

Liked-track cover art

SigLIP centroid.

Liked-track behavior

CF-BPR centroid.

User behavior

User-CF centroid when available.

Discography

Resolved artist → catalog tracks.

Era

Popularity lookup within the requested period.

Source: paper/main.tex Table 1; final Blind-B config.

Routing and candidate union

Route

Request flags shape query text and enable gated branches.

Union

Deduplicate branch top-500 lists while retaining provenance.

Handoff

Build one candidate row with catalog, state, branch, and embedding evidence.

Weighted RRF over the same branches remains available as an explicit no-training baseline and fallback; the deployed LambdaMART path replaces its final order.

Source: paper/main.tex Figure 1 and Results Table 3.

4. Bi-Encoder

Section 4 · conversation ↔︎ track similarity

Input

Compact conversation rendering + a candidate track card

Shared encoder

Fine-tuned Qwen3-Embedding-4B → two 2560-d unit vectors → cosine

Output

b1_cos, one candidate feature used by LambdaMART

The bi-encoder was feature-only in the submitted path, not a candidate-producing branch.

Two-tower architecture

A conversation rendering and a candidate track card pass through one shared fine-tuned Qwen3 embedding encoder. Last-token pooling and normalization create two unit vectors, whose cosine becomes the b1_cos ranking feature.

Source: paper/main.tex Figure 3; docs/architectures/biencoder.md.

Actual rendered pair

SESSION 024a2738-a96c-4e11-adf3-b2cb8311a493 · TURN 3

Conversation rendering

[prev] “Calling Cards is not quite it”

[now] “More subdued… sense of place… stark almost a cappella”

[prev_track] Neko Case — “Man”

same
encoder
cos

TRACK RENDERING

Bracing For Sunday

Neko Case

album The Worse Things Get, The Harder I Fight, The Harder I Fight, The More I Love You

year unavailable; catalog tag: 2013

alt-countryfemale vocalistsindie rock

Artist context: Neko Case is best known for her alt-country and indie rock style, characterized by her powerful voice and poetic lyrics.

Conversation/track formats: docs/architectures/biencoder.md. Track selected in retained Blind-B Neko Case trace.

Training data and objective

53,885

positive conversation–track pairs

4 hard negatives

per positive

2560-d

normalized vectors

MNRL

contrastive ranking loss

Source: paper/main.tex `2.4; docs/architectures/biencoder.md.

Serving

Offline

Precompute all 47,071 track vectors into LanceDB.

Per turn

Encode and cache one conversation vector.

Per candidate

Dot product with cached track vector → b1_cos.

Source: docs/architectures/biencoder.md `Serving.

Measured ranking gain

WITHOUT BI-ENCODER FEATURE0.1970OOF nDCG@20
WITH b1_cos0.2032OOF nDCG@20

+0.0062

The deployed ranker kept b1_cos as one candidate-level similarity feature.

Source: paper/main.tex Tables 2–3. Development evidence only.

5. Ranking

Section 5 · candidate evidence → ordered top 20

Input

Candidate union: up to 500 per branch + 146 features per turn–track pair

Learned scoring

LambdaMART learns one score per candidate within the turn

b1 cosine 59.0% · branch 11.5% · affinity 10.7% · other cosine 8.9%

Final ordering

Exact-track pin + final artist check → ordered top 20

Inference-time ranking

PHASE 1 · CANDIDATE EVIDENCEOne row per trackcandidate union + state + branch evidence + catalog and embedding matches
PHASE 2 · LEARNED SCORINGLambdaMARTone score for every candidate; compared within this conversation turn
PHASE 3 · FINAL ORDERINGScore order → two guards → top 20exact-track pin + final artist check, then return ordered track IDs
Used at inferenceconversation state · branch ranks/scores · catalog metadata · embeddings · played/rejected historyNot usedconversation-goal fields

Candidates are compared only against other candidates from the same conversation turn.

Source: models/reranker_v12_goalfree/model.txt; scripts/rerank/features.py.

Feature gain in the deployed model

Bi-encoder cosine59.0%

Per-branch rank/score11.5%

Session/artist affinity10.7%

Other similarity cosines8.9%

Popularity5.0%

Remaining families: state/intent 2.2%, tag/lexical overlap 2.0%, constraints/rejections 0.7%.

Source: paper/main.tex Table 2; gain recomputed from the deployed model.

Sample features

Family Concrete checked-in features
branch evidence rank__bm25, margin__dense…metadata, hit__lookup…discography
semantic match b1_cos, msg_meta_cos, q06_lyric_cos, clap_centroid
session/artist same_artist_last, same_album_any, artist_played_count
catalog pop_pct, within_artist_pop, release_year, tag_count
request/state request_type, intent_mode, wants_new_artist, year_in_constraint
constraints rejected_track_exact, rejected_artist_exact, violates_new_artist

Source: models/reranker_v12_goalfree/model.txt feature_names.

LambdaMART training and label weights

Binary relevance

The challenge next track is the positive row.

Targeted downweights

×0.3 if next turn rejects the track or says it did not help; ×0.6 for artist-only rejection.

LambdaRank

User-grouped CV; final model fit on all 8,000 development turns.

We also trained a model on fully rejudged labels. It performed worse on development data, so we did not ship it. The shipped model used the targeted downweights above.

Source: paper/main.tex `2.3; scripts/rerank/build_label_weights.py and train_lgbm.py.

6. Response Generation

Section 6 · selected track → listener-facing text

Inputs

Latest extracted state + selected top track + catalog metadata

Single pass

XML item card → Qwen3-30B-A3B-Instruct-2507, temperature 0

Output

1–2 concise sentences about only the selected track

The generator presents the ranking decision; it cannot replace the selected track.

Response-only experiment: changing the text generation setup improved the organizer judge score from 4.20 to 4.70 while recommendations stayed fixed.

Actual input → response

SESSION 024a2738-a96c-4e11-adf3-b2cb8311a493 · TURN 3

STATE

current_request.request_typehidden_target
facts[].artistNeko Case · must use
facts[].moodsubdued
facts[].lyrical_themesense of place
facts[].sonicstark · almost a cappella

TOP 1

Neko Case — “Bracing For Sunday”

SUBMITTED RESPONSE

“You’re looking for something subdued with a strong sense of place and a stark, almost a cappella delivery—and Bracing For Sunday fits that mood perfectly. Neko Case’s haunting, intimate vocals carry the weight of a quiet, specific moment, like a solitary figure in a weathered room, making the song feel both deeply personal and grounded in a distinct place.”

Source: retained Blind-B output; paper/main.tex Figure 2.

Input contract

S
Latest staterequest · facts · constraints · rejections
#1
Top 1the ranker’s selected track · immutable here
Track metadataartist · title · album · year · up to 10 tags
</>
Formattingdelimited XML item block
GENERATORQwen3-30B-A3B-Instruct-2507temperature 0 · no echo retries

Source: final Blind-B config; docs/architectures/explanation_generation.md.

Deployed prompt

SYSTEM INSTRUCTIONS
You are an expert music recommendation assistant. Your task is to understand user preferences and provide personalized music recommendations.

You are the conversational voice of a music recommender — a "track explainer." A separate recommendation system has ALREADY selected one track to play next. Your only job is to write the short listener-facing message that presents that track: acknowledge what the listener just asked, then naturally explain why this track fits their request and taste.

Guidelines:
- Output ONLY the listener-facing message — no labels, headers, quotes, or YAML.
- Brief and conversational: 1-2 concise sentences. Match the listener's tone, energy, and LANGUAGE (reply in the same language they wrote in).
- Ground the "why it fits" in their request/stated taste. You MAY name the title/artist, but do NOT recite a metadata or tag dump (genre/mood/style lists) unless they asked for those details.
- If the track clearly doesn't match, briefly and honestly acknowledge the mismatch — don't oversell.
- Vary your wording across turns. Use only facts supported by the provided track; invent nothing.
- The track may be provided as structured <recommended_track> data. NEVER output that data, the tag list, or any XML verbatim — always write a natural conversational sentence.
STYLE INSTRUCTIONS
Prioritize the latest user request and extracted state over older conversation history.
If the track is reasonably aligned, explain the fit with one specific supported reason.
If it clearly conflicts with an explicit avoid/new-artist constraint, do not oversell it or blame the system; briefly frame the limitation and the closest supported reason.
RUNTIME INPUT · appended per turn
LISTENER CONTEXTlatest request + extracted stateNeko Case · subdued · sense of place · two rejected tracks
SELECTED TRACK XMLNeko Case — “Bracing For Sunday”album · year · tags

Source: deployed response template quoted in paper/main.tex `2.5.

7. Examples

Section 7 · traces across the full system

Input evidence

Four retained Blind-B listener requests and their extracted states

Trace view

Session → state → resolved constraints → top predictions → response

Output insight

One constraint-preserving trace; three distinct architectural failure boundaries

Constraint-preserving trace: Neko Case

SESSION 024a2738-a96c-4e11-adf3-b2cb8311a493 · TURN 3

Session

“Subdued… female singer… sense of place… stark almost a cappella… not it either.”

Compiled state

current_request.request_typehidden_target
facts[].artistNeko Case · must use
exclusions[].trackCalling Cards · Man
facts[].lyrical_themesense of place
routing.lyric_searchtrue

Top 5

  1. Bracing For Sunday Selected Top 1
  2. Maybe Sparrow
  3. I Wish I Was the Moon
  4. Lady Pilot
  5. Lion’s Jaws

Selected Top 1 Blind-B relevance labels · unavailable

All five preserve the required Neko Case artist constraint, and the response carries forward the request’s concrete clues. Because Blind-B relevance labels are unavailable, this trace demonstrates constraint preservation—not target correctness.

Source: retained Blind-B trace/output, session 024a… turn 3.

Constraint lost: Kamelot album

LISTENER REQUEST

“The Kamelot track from Silverthorn…”

EXTRACTED STATEfacts[].artist Kamelotfacts[].album Silverthorn
RETRIEVAL QUERYresolved.artist Kamelotalbum_filter missing

TOP 5 · ALL VIOLATE THE ALBUM CONSTRAINT

  1. Fallen Star Haven
  2. This Pain The Black Halo
  3. Moonlight The Black Halo
  4. Soul Society The Black Halo
  5. The Haunting The Black Halo

The state understood the album. Retrieval and ranking did not enforce it.

Source: retained Blind-B trace/output, session 5c066e… turn 2.

Missing metadata: extracted but unenforceable

Source: retained Blind-B traces bf27… turn 8 and b267… turn 5; catalog schema.

Exact-track request recognized, but Watercolors was not found

SESSION 954de66b-4f3a-4cc7-8e93-f58c2b6e64b9 · TURN 2

EXACT REQUEST

“I wanted ‘Watercolors’ by Pat Metheny specifically.”

Artist exact matchPat Metheny exists in the catalog.

×

Track not foundNo catalog track matched “Watercolors.”

TOP 1 + SUBMITTED RESPONSE

Pat Metheny — “Alfie”

“Got it — here’s "Alfie" by Pat Metheny, a smooth, introspective piece from his What’s It All About album…”

The artist match produced substitutes, while the response sounded as if the exact request had been fulfilled.

Source: retained Blind-B trace/output, session 954de6… turn 2.

8. Label Audit

Section 8 · request fit of the training target

Problem observed

Our model kept returning the same artist after listeners asked to move on.

Question

Was the model learning that behavior from the challenge’s next-track labels?

Audit

Rejudge request fit and artist anchoring; test a cleaner-label model.

Why we did this: anchoring appeared in our recommendations, and the training target sometimes rewarded the same behavior.

↓ Detail: Bonobo example · judge flow · counts · outcome

Training-label failure examples

SESSION 016099ac-567c-4cd7-81f5-d385be38a4bc
T1

Previously played
Bonobo — “Antenna”

T2

Previously played
Bonobo — “Cirrus”

T3

Listener
“Similar chill, electronic vibe… but from a different artist?”

Ground truth
Bonobo — “Jets” MOVES toward goal

T4

Listener
“‘Jets’ is cool, but… a different artist this time…”

Ground truth
Bonobo — “Pieces” MOVES toward goal

The ground truth repeats the artist the listener explicitly asked to leave.

ANOTHER RELEASED TRAINING EXAMPLE

Listener: “Could you suggest some other artists… with a similar acoustic folk sound?”

Played label: Kings of Convenience — “Singing Softly To Me” same artist · originally liked

Audit: artist anchoring → NEGATIVE

CONSTRAINT EXAMPLE

Asked: slow, smooth 90s R&B

Played label: Post Malone — “Broken Whiskey Glass” 2016 · wrong genre/era

Audit: request mismatch → NEGATIVE

Source: paper/main.tex Figure 4.

Two-judge and arbitration flow

Turn + candidate label

Request, context, played track

G Gemma-4-26B

request fit + anchoring

D DeepSeek-V4-Flash

request fit + anchoring

Conflict gate

Agree → keep
Disagree → send to Opus

DISAGREEMENT ONLY

OClaude Opus

Final label, blind to synthetic reaction

Source: data/anchor_labels_v1 reports/flow.html and reproducible release scripts.

Audit counts

113,393

train + dev turns judged

106,393

training turns

61,063

negative labels (57.4%)

18,222

artist-anchoring negatives

After fixing the conflict gate, 3,486 additional disagreements were sent to Opus. The correction reduced the anchoring count from 19,813 to 18,222.

Source: data/anchor_labels_v1/README.md and DATASET_CARD.md.

What shipped

WE TESTEDFully rejudged labelsTrain an alternative reranker on the released audit labels.
×

It performed worse on development data, so we did not ship it.The audit remains useful evidence, but it did not improve our model.

WE SHIPPEDOriginal target + targeted downweights×0.3 for clear rejection / no progress; ×0.6 for artist-only rejection.

Source: paper/main.tex `4.2; scripts/rerank/build_label_weights.py.

9. References

Section 9 · source index

Architecture details: State · Retrieval · Bi-Encoder · Ranking reproduction · Response Generation

Blind-A and Blind-B appear here as audit references only; the deck documents one final submission architecture.