fix: limit recommendation scoring

This commit is contained in:
2026-06-16 01:25:46 +02:00
committed by Milas Holsting
parent c1e313d684
commit 7c25907c92
3 changed files with 24 additions and 2 deletions

View File

@@ -6,6 +6,7 @@ const (
maxSeeds = 8
maxRecommendations = 10
candidateFetchLimit = 60
candidateFetchBuffer = 6
TopPickLimit = 18
TopPicksLimit = 60
profileSearchLimit = 8

View File

@@ -64,7 +64,7 @@ func (e engine) getTopPicksForYou(ctx context.Context, userID string, resultLimi
return domain.CatalogSectionData{Animes: []domain.Anime{}}, nil
}
candidates, err := e.scoreRankedCandidates(ctx, now, profile, ranked)
candidates, err := e.scoreRankedCandidates(ctx, now, profile, ranked, resultLimit)
if err != nil {
return domain.CatalogSectionData{}, err
}
@@ -191,8 +191,9 @@ func (e engine) scoreRankedCandidates(
now time.Time,
profile userTasteProfile,
ranked []rankedCandidate,
resultLimit int,
) ([]recommendationCandidate, error) {
limit := min(len(ranked), candidateFetchLimit)
limit := min(len(ranked), candidateScoreLimit(resultLimit))
candidates := make([]recommendationCandidate, 0, limit)
var candidatesMu sync.Mutex
var g errgroup.Group
@@ -244,3 +245,11 @@ func (e engine) scoreRankedCandidates(
return candidates, nil
}
func candidateScoreLimit(resultLimit int) int {
if resultLimit <= 0 {
return 0
}
return min(candidateFetchLimit, resultLimit+candidateFetchBuffer)
}

View File

@@ -174,6 +174,18 @@ func TestRerankRecommendationCandidatesSpreadsRepeatedGenres(t *testing.T) {
}
}
func TestCandidateScoreLimitTracksRequestedResultSize(t *testing.T) {
if got := candidateScoreLimit(TopPickLimit); got != TopPickLimit+candidateFetchBuffer {
t.Fatalf("expected top-pick scoring to fetch a small oversample, got %d", got)
}
if got := candidateScoreLimit(TopPicksLimit); got != candidateFetchLimit {
t.Fatalf("expected full top-picks scoring to keep existing cap, got %d", got)
}
if got := candidateScoreLimit(0); got != 0 {
t.Fatalf("expected zero result limit to skip scoring, got %d", got)
}
}
func testRecommendationAnime(id int, genreID int) jikan.Anime {
return jikan.Anime{
MalID: id,