@@ -117,42 +117,40 @@ export async function generateSeedPlaylist(
117117 // p-limit concurrency of 15
118118 const limit = pLimit ( 15 ) ;
119119
120- let collected = 0 ;
120+ // 0.7 is a good starting point, but you can tune this
121+ const THRESHOLD = 0.7
122+ const MIN_MATCHES = Math . floor ( seedEmbeddings . length / 2 ) + 1
121123
124+ // we want to avoid low quality recommendations so we check that the ai tracks match at least MIN_MATCHES of the original seeds(songs)
122125 const scoredTracks = await Promise . all (
123- aiTracks . map ( ( track ) =>
124- limit ( async ( ) => {
125- if ( collected >= remainingNeeded + 20 ) return null ;
126- // Skip if already generated for this user
127- if ( userId && previouslyGeneratedIds . includes ( track . id ) ) {
128- return null ;
129- }
130-
131- try {
132- const processed = await processSong ( {
133- id : track . id ,
134- title : track . name ,
135- artist : track . artistName ,
136- album : track . albumName ,
137- } ) ;
138-
139- const emb = processed . embeddingData ;
140- if ( ! emb ) return null ;
141-
142- const similarity =
143- seedEmbeddings . reduce ( ( sum , seedEmb ) => {
144- return sum + calculateCosineSimilarity ( emb , seedEmb ) ;
145- } , 0 ) / seedEmbeddings . length ;
146-
147- collected ++ ;
148- return { uri : track . uri , similarity } ;
149- } catch ( e ) {
150- console . error ( `Skipping ${ track . name } due to error` ) ;
151- return null ;
152- }
153- } ) ,
154- ) ,
155- ) ;
126+ aiTracks . map ( track => limit ( async ( ) => {
127+ try {
128+ const processed = await processSong ( {
129+ id : track . id ,
130+ title : track . name ,
131+ artist : track . artistName ,
132+ album : track . albumName ,
133+ } )
134+
135+ const emb = processed . embeddingData
136+ if ( ! emb ) return null
137+
138+ const scores = seedEmbeddings . map ( seedEmb =>
139+ calculateCosineSimilarity ( emb , seedEmb )
140+ )
141+
142+ const matchingSeeds = scores . filter ( s => s >= THRESHOLD ) . length
143+ if ( matchingSeeds < MIN_MATCHES ) return null // doesn't qualify
144+
145+ const maxScore = Math . max ( ...scores )
146+ return { uri : track . uri , similarity : maxScore }
147+
148+ } catch ( e ) {
149+ console . error ( `Skipping ${ track . name } due to error` )
150+ return null
151+ }
152+ } ) )
153+ )
156154
157155 // Sort by similarity descending, filtering out nulls
158156 fallbackTracksUris = (
0 commit comments