ソースを参照

fix: 粗排截断后把统一粗排分写回 Video.rovScore (5 个 rank 类受益)

extractAllAndTruncateByCoarseRank 之前只在 sort 时读粗排分, picked 后没有
回写 Video.rovScore, 后续精排公式 / 重排读到的是召回阶段写的值 (位置分 / 真实分),
跟统一粗排公式 (rovn = plusSmooth(return_n_uv, exp, ...)) 的主信号不一致.

funnel 漏斗 entry.score 已经在 markCoarseRankAttribution 内覆盖为粗排分,
但 Video.rovScore 这条链路被遗忘. 这次补齐.

picked 后循环 setRovScore(coarseScore), 粗排 map miss 的 vid 保留召回阶段
rovScore 作为兜底 (null check), 避免极端情况下 score 急剧下沉.

V562 / V564 / V565 / V566 / V569 全部 5 个用了粗排截断的 rank 类自动受益,
精排公式 / 重排 / 后续阶段看到的统一是粗排分.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
yangxiaohui 3 日 前
コミット
9229b583a7

+ 10 - 0
recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/util/RecallUtils.java

@@ -145,6 +145,16 @@ public class RecallUtils {
         all.sort(Comparator.comparingDouble((Video v) -> coarseMap.getOrDefault(v.getVideoId(), v.getRovScore())).reversed());
         List<Video> picked = all.size() <= topN ? all : all.subList(0, topN);
 
+        // 把粗排分写回 picked Video.rovScore, 让后续阶段 (精排公式 / 重排 / funnel)
+        // 看到统一的粗排信号, 不再受召回阶段位置分/真实分差异影响.
+        // 粗排 map miss 的 vid 保留召回阶段 rovScore 作为兜底.
+        for (Video v : picked) {
+            Double coarseScore = coarseMap.get(v.getVideoId());
+            if (coarseScore != null) {
+                v.setRovScore(coarseScore);
+            }
+        }
+
         Set<Long> pickedIds = picked.stream().map(Video::getVideoId).collect(Collectors.toSet());
         rovRecallRank.addAll(picked);
         setVideo.addAll(pickedIds);