feat: surface recommendation rationale
This commit is contained in:
@@ -24,7 +24,7 @@ func rerankRecommendationCandidates(candidates []recommendationCandidate, limit
|
||||
continue
|
||||
}
|
||||
|
||||
selected = append(selected, domain.Anime{Anime: candidate.anime})
|
||||
selected = append(selected, domain.Anime{Anime: candidate.anime, RecommendationRationale: candidate.rationale})
|
||||
features := diversityFeatures(candidate.anime)
|
||||
seen.add(features)
|
||||
recent = append(recent, features)
|
||||
|
||||
@@ -48,9 +48,23 @@ func scoreRecommendationCandidate(
|
||||
themeMatches: themes,
|
||||
studioMatches: studios,
|
||||
demographicMatches: demos,
|
||||
rationale: buildRecommendationRationale(profile, candidate),
|
||||
}
|
||||
}
|
||||
|
||||
func buildRecommendationRationale(profile userTasteProfile, candidate jikan.Anime) []string {
|
||||
rationale := make([]string, 0, 4)
|
||||
rationale = append(rationale, matchedEntityNames(profile.genres, candidate.Genres)...)
|
||||
rationale = append(rationale, matchedEntityNames(profile.themes, candidate.Themes)...)
|
||||
rationale = append(rationale, matchedEntityNames(profile.studios, candidate.Studios)...)
|
||||
rationale = append(rationale, matchedEntityNames(profile.demographics, candidate.Demographics)...)
|
||||
|
||||
if len(rationale) > 4 {
|
||||
return rationale[:4]
|
||||
}
|
||||
return rationale
|
||||
}
|
||||
|
||||
func recommendationCandidateScoreAdjustments(now time.Time, profile userTasteProfile, candidate jikan.Anime) float64 {
|
||||
var score float64
|
||||
|
||||
@@ -115,3 +129,22 @@ func weightedEntityMatch(weights map[int]float64, entities []jikan.NamedEntity)
|
||||
|
||||
return matches, score
|
||||
}
|
||||
|
||||
func matchedEntityNames(weights map[int]float64, entities []jikan.NamedEntity) []string {
|
||||
if len(weights) == 0 {
|
||||
return []string{}
|
||||
}
|
||||
|
||||
names := make([]string, 0, 1)
|
||||
for _, entity := range entities {
|
||||
if entity.Name == "" || weights[entity.MalID] <= 0 {
|
||||
continue
|
||||
}
|
||||
names = append(names, entity.Name)
|
||||
if len(names) >= 1 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return names
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ type recommendationCandidate struct {
|
||||
themeMatches int
|
||||
studioMatches int
|
||||
demographicMatches int
|
||||
rationale []string
|
||||
}
|
||||
|
||||
type userTasteProfile struct {
|
||||
|
||||
Reference in New Issue
Block a user