|
|
@@ -335,77 +335,6 @@ public class RankStrategy4RegionMergeModelV562 extends RankStrategy4RegionMergeM
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * V562 实验:拉取粗排分(按 vid → score 返回)。
|
|
|
- *
|
|
|
- * 数据源:alg_vid_recommend_exp_feature_20250212。
|
|
|
- * 表里没有现成 rovn 字段,需要从原子字段 (return_n_uv_*, exp_*) 用 plusSmooth 算出来。
|
|
|
- * 公式 = FeatureV6.oneTypeStatFeature 同口径:rovn = plusSmooth(return_n_uv, exp, plus, 1)
|
|
|
- * 默认 plus=30 与 FeatureV6.largerSmoothPlus 对齐,AB 对比不会因口径不同污染结论。
|
|
|
- *
|
|
|
- * Apollo 可调维度:
|
|
|
- * - coarseRovn1hW / coarseRovn24hW:1h 和 24h 的加权(默认 0.5/0.5)
|
|
|
- * - coarseRovn1hSmoothPlus / coarseRovn24hSmoothPlus:贝叶斯平滑系数(默认 30/30)
|
|
|
- *
|
|
|
- * 缺失自动归一化:单值缺失时剩下的撑起全部权重;两值都缺失则 caller 兜底 RovScore。
|
|
|
- */
|
|
|
- private Map<Long, Double> fetchCoarseRankScores(RankParam param) {
|
|
|
- if (param == null || param.getRecallResult() == null
|
|
|
- || CollectionUtils.isEmpty(param.getRecallResult().getData())) {
|
|
|
- return Collections.emptyMap();
|
|
|
- }
|
|
|
- Map<String, Double> mergeWeight = this.mergeWeight != null ? this.mergeWeight : Collections.emptyMap();
|
|
|
- double w1h = mergeWeight.getOrDefault("coarseRovn1hW", 0.5);
|
|
|
- double w24h = mergeWeight.getOrDefault("coarseRovn24hW", 0.5);
|
|
|
- double plus1h = mergeWeight.getOrDefault("coarseRovn1hSmoothPlus", 30.0);
|
|
|
- double plus24h = mergeWeight.getOrDefault("coarseRovn24hSmoothPlus", 30.0);
|
|
|
- // 只对参与统一截断的 23 路 vid 拉粗排分(跳过流量池 3 路,省 proto + RPC 延迟)
|
|
|
- List<String> vids = param.getRecallResult().getData().stream()
|
|
|
- .filter(d -> d != null && CollectionUtils.isNotEmpty(d.getVideos()))
|
|
|
- .filter(d -> ALL_ROV_PUSH_FROMS.contains(d.getPushFrom()))
|
|
|
- .flatMap(d -> d.getVideos().stream())
|
|
|
- .map(v -> String.valueOf(v.getVideoId()))
|
|
|
- .distinct()
|
|
|
- .collect(Collectors.toList());
|
|
|
- if (vids.isEmpty()) return Collections.emptyMap();
|
|
|
-
|
|
|
- Map<String, Map<String, Map<String, String>>> feats = featureService.getVideoCoarseRankFeature(vids);
|
|
|
- Map<Long, Double> result = new HashMap<>(vids.size());
|
|
|
- for (String vid : vids) {
|
|
|
- Map<String, String> row = feats.getOrDefault(vid, Collections.emptyMap())
|
|
|
- .getOrDefault("alg_vid_recommend_exp_feature_20250212", Collections.emptyMap());
|
|
|
- Double rovn1h = computeRovn(row, "1h", plus1h);
|
|
|
- Double rovn24h = computeRovn(row, "24h", plus24h);
|
|
|
- // 加权平均,缺失自动归一化
|
|
|
- double sumW = (rovn1h != null ? w1h : 0) + (rovn24h != null ? w24h : 0);
|
|
|
- if (sumW <= 0) continue;
|
|
|
- double sumWS = (rovn1h != null ? rovn1h * w1h : 0) + (rovn24h != null ? rovn24h * w24h : 0);
|
|
|
- try {
|
|
|
- result.put(Long.parseLong(vid), sumWS / sumW);
|
|
|
- } catch (NumberFormatException ignore) { }
|
|
|
- }
|
|
|
- return result;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 与 FeatureV6.oneTypeStatFeature 同口径:rovn = plusSmooth(return_n_uv, exp, plus, 1)
|
|
|
- *
|
|
|
- * 字段语义(区分 0 vs null):
|
|
|
- * - exp 是 period 有效性 anchor:null 或 ≤0 → 整个 period 无效(return null)
|
|
|
- * - return_n_uv 缺失视为 0(真实信号"无回访"):rovn=0,参与加权(不会让另一时段兜底)
|
|
|
- */
|
|
|
- private static Double computeRovn(Map<String, String> row, String period, double smoothPlus) {
|
|
|
- Double exp = parseDoubleOrNull(row.get("exp_" + period));
|
|
|
- if (exp == null || exp <= 0) return null;
|
|
|
- Double returnNuv = parseDoubleOrNull(row.get("return_n_uv_" + period));
|
|
|
- return FeatureUtils.plusSmooth(returnNuv != null ? returnNuv : 0, exp, smoothPlus, 1);
|
|
|
- }
|
|
|
-
|
|
|
- private static Double parseDoubleOrNull(String s) {
|
|
|
- if (StringUtils.isBlank(s)) return null;
|
|
|
- try { return Double.parseDouble(s); } catch (NumberFormatException e) { return null; }
|
|
|
- }
|
|
|
-
|
|
|
/**
|
|
|
* 同 V567 极简 fusion:只保留"流量池相关 + 兜底相关"逻辑
|
|
|
* 1. rov 空兜底:rov 池为空时流量池直接顶上 (Basic 段 1)
|
|
|
@@ -477,6 +406,77 @@ public class RankStrategy4RegionMergeModelV562 extends RankStrategy4RegionMergeM
|
|
|
return new RankResult(result);
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * V562 实验:拉取粗排分(按 vid → score 返回)。
|
|
|
+ *
|
|
|
+ * 数据源:alg_vid_recommend_exp_feature_20250212。
|
|
|
+ * 表里没有现成 rovn 字段,需要从原子字段 (return_n_uv_*, exp_*) 用 plusSmooth 算出来。
|
|
|
+ * 公式 = FeatureV6.oneTypeStatFeature 同口径:rovn = plusSmooth(return_n_uv, exp, plus, 1)
|
|
|
+ * 默认 plus=30 与 FeatureV6.largerSmoothPlus 对齐,AB 对比不会因口径不同污染结论。
|
|
|
+ *
|
|
|
+ * Apollo 可调维度:
|
|
|
+ * - coarseRovn1hW / coarseRovn24hW:1h 和 24h 的加权(默认 0.5/0.5)
|
|
|
+ * - coarseRovn1hSmoothPlus / coarseRovn24hSmoothPlus:贝叶斯平滑系数(默认 30/30)
|
|
|
+ *
|
|
|
+ * 缺失自动归一化:单值缺失时剩下的撑起全部权重;两值都缺失则 caller 兜底 RovScore。
|
|
|
+ */
|
|
|
+ private Map<Long, Double> fetchCoarseRankScores(RankParam param) {
|
|
|
+ if (param == null || param.getRecallResult() == null
|
|
|
+ || CollectionUtils.isEmpty(param.getRecallResult().getData())) {
|
|
|
+ return Collections.emptyMap();
|
|
|
+ }
|
|
|
+ Map<String, Double> mergeWeight = this.mergeWeight != null ? this.mergeWeight : Collections.emptyMap();
|
|
|
+ double w1h = mergeWeight.getOrDefault("coarseRovn1hW", 0.5);
|
|
|
+ double w24h = mergeWeight.getOrDefault("coarseRovn24hW", 0.5);
|
|
|
+ double plus1h = mergeWeight.getOrDefault("coarseRovn1hSmoothPlus", 30.0);
|
|
|
+ double plus24h = mergeWeight.getOrDefault("coarseRovn24hSmoothPlus", 30.0);
|
|
|
+ // 只对参与统一截断的 23 路 vid 拉粗排分(跳过流量池 3 路,省 proto + RPC 延迟)
|
|
|
+ List<String> vids = param.getRecallResult().getData().stream()
|
|
|
+ .filter(d -> d != null && CollectionUtils.isNotEmpty(d.getVideos()))
|
|
|
+ .filter(d -> ALL_ROV_PUSH_FROMS.contains(d.getPushFrom()))
|
|
|
+ .flatMap(d -> d.getVideos().stream())
|
|
|
+ .map(v -> String.valueOf(v.getVideoId()))
|
|
|
+ .distinct()
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ if (vids.isEmpty()) return Collections.emptyMap();
|
|
|
+
|
|
|
+ Map<String, Map<String, Map<String, String>>> feats = featureService.getVideoCoarseRankFeature(vids);
|
|
|
+ Map<Long, Double> result = new HashMap<>(vids.size());
|
|
|
+ for (String vid : vids) {
|
|
|
+ Map<String, String> row = feats.getOrDefault(vid, Collections.emptyMap())
|
|
|
+ .getOrDefault("alg_vid_recommend_exp_feature_20250212", Collections.emptyMap());
|
|
|
+ Double rovn1h = computeRovn(row, "1h", plus1h);
|
|
|
+ Double rovn24h = computeRovn(row, "24h", plus24h);
|
|
|
+ // 加权平均,缺失自动归一化
|
|
|
+ double sumW = (rovn1h != null ? w1h : 0) + (rovn24h != null ? w24h : 0);
|
|
|
+ if (sumW <= 0) continue;
|
|
|
+ double sumWS = (rovn1h != null ? rovn1h * w1h : 0) + (rovn24h != null ? rovn24h * w24h : 0);
|
|
|
+ try {
|
|
|
+ result.put(Long.parseLong(vid), sumWS / sumW);
|
|
|
+ } catch (NumberFormatException ignore) { }
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 与 FeatureV6.oneTypeStatFeature 同口径:rovn = plusSmooth(return_n_uv, exp, plus, 1)
|
|
|
+ *
|
|
|
+ * 字段语义(区分 0 vs null):
|
|
|
+ * - exp 是 period 有效性 anchor:null 或 ≤0 → 整个 period 无效(return null)
|
|
|
+ * - return_n_uv 缺失视为 0(真实信号"无回访"):rovn=0,参与加权(不会让另一时段兜底)
|
|
|
+ */
|
|
|
+ private static Double computeRovn(Map<String, String> row, String period, double smoothPlus) {
|
|
|
+ Double exp = parseDoubleOrNull(row.get("exp_" + period));
|
|
|
+ if (exp == null || exp <= 0) return null;
|
|
|
+ Double returnNuv = parseDoubleOrNull(row.get("return_n_uv_" + period));
|
|
|
+ return FeatureUtils.plusSmooth(returnNuv != null ? returnNuv : 0, exp, smoothPlus, 1);
|
|
|
+ }
|
|
|
+
|
|
|
+ private static Double parseDoubleOrNull(String s) {
|
|
|
+ if (StringUtils.isBlank(s)) return null;
|
|
|
+ try { return Double.parseDouble(s); } catch (NumberFormatException e) { return null; }
|
|
|
+ }
|
|
|
+
|
|
|
private UserShareReturnProfile parseUserProfile(Map<String, Map<String, String>> userOriginInfo) {
|
|
|
if (null != userOriginInfo) {
|
|
|
Map<String, String> c9 = userOriginInfo.get("alg_recsys_feature_user_share_return_stat");
|