feat(taste): phase 2b — taste_overlap candidate arm (#796)
2a re-ranks the existing pool by TasteMatch; this ensures taste-relevant tracks ARE in the pool. Adds a 6th arm to LoadRadioCandidatesV2: in-library tracks by the user's top positively-weighted taste-profile artists ($10 K, weight > 0, deterministic weight-DESC,id order so it doesn't reintroduce same-day nondeterminism). Pool-inclusion only (sim_score 0) — TasteMatch already scores the fit. Empty for cold-start users (no profile). - CandidateSourceLimits.TasteOverlap; default 20 (radio), 80 for For-You via systemForYouSourceLimits. - You-might-like deliberately sets TasteOverlap=0: it surfaces NOT-actively- engaged artists, so flooding its pool with top-taste (mostly already-played) artists would just feed the read-time dedup. - Test: positive-weight artist's track enters via the arm; negative-weight one is excluded (weight > 0). Existing pool tests unaffected (no profile seeded). Deferred within 2b: profile-seeded For-You — marginal given the arm + TasteMatch already inject taste broadly (top-played seed ≈ top-taste artist). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -33,10 +33,14 @@ WHERE t.id <> $2
|
||||
);
|
||||
|
||||
-- name: LoadRadioCandidatesV2 :many
|
||||
-- M4c: similarity-driven candidate pool. 5-way UNION:
|
||||
-- M4c: similarity-driven candidate pool. 6-way UNION:
|
||||
-- $1 user_id, $2 seed_track_id, $3 recently_played_hours,
|
||||
-- $4 exclude (uuid[]), $5 lb_similar K, $6 similar_artists K,
|
||||
-- $7 tag_overlap K, $8 likes_overlap K, $9 random_fill K.
|
||||
-- $7 tag_overlap K, $8 likes_overlap K, $9 random_fill K,
|
||||
-- $10 taste_overlap K (#796 phase 2b — tracks by the user's top
|
||||
-- positively-weighted taste-profile artists, so taste-relevant tracks
|
||||
-- enter the pool even when the similarity/random arms miss them; scored
|
||||
-- in Go via TasteMatch, so sim_score here is 0 pool-inclusion).
|
||||
-- Returns same shape as LoadRadioCandidates plus similarity_score column.
|
||||
|
||||
WITH
|
||||
@@ -109,6 +113,17 @@ likes_overlap AS (
|
||||
ORDER BY random()
|
||||
LIMIT $8
|
||||
),
|
||||
taste_overlap AS (
|
||||
SELECT t.id AS track_id, 0.0::float8 AS sim_score
|
||||
FROM taste_profile_artists tpa
|
||||
JOIN tracks t ON t.artist_id = tpa.artist_id
|
||||
WHERE tpa.user_id = $1
|
||||
AND tpa.weight > 0
|
||||
AND t.id NOT IN (SELECT id FROM excluded_ids)
|
||||
AND t.id <> $2
|
||||
ORDER BY tpa.weight DESC, t.id
|
||||
LIMIT $10
|
||||
),
|
||||
random_fill AS (
|
||||
SELECT t.id AS track_id, 0.0::float8 AS sim_score
|
||||
FROM tracks t
|
||||
@@ -119,6 +134,7 @@ random_fill AS (
|
||||
UNION SELECT track_id FROM similar_artists
|
||||
UNION SELECT track_id FROM tag_overlap
|
||||
UNION SELECT track_id FROM likes_overlap
|
||||
UNION SELECT track_id FROM taste_overlap
|
||||
)
|
||||
ORDER BY random()
|
||||
LIMIT $9
|
||||
@@ -135,6 +151,7 @@ FROM (
|
||||
UNION ALL SELECT track_id, sim_score FROM similar_artists
|
||||
UNION ALL SELECT track_id, sim_score FROM tag_overlap
|
||||
UNION ALL SELECT track_id, sim_score FROM likes_overlap
|
||||
UNION ALL SELECT track_id, sim_score FROM taste_overlap
|
||||
UNION ALL SELECT track_id, sim_score FROM random_fill
|
||||
) u
|
||||
JOIN tracks t ON t.id = u.track_id
|
||||
|
||||
Reference in New Issue
Block a user