Parcourir la source

feat:V562实验接入region_1h_all_rov和city_rovn_all_rov召回

以V568为base, V562减法门: 挂region_1h_all_rov + city_rovn_all_rov, 剔除region_1h + city_rovn;
新增CityRovnAllRovRecallStrategy (Redis链路, keyPrefix=city_rovn_all_rov_recall)。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
yangxiaohui il y a 2 jours
Parent
commit
3bfd500d9e

+ 4 - 4
recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/rank/strategy/RankStrategy4RegionMergeModelV562.java

@@ -53,8 +53,8 @@ public class RankStrategy4RegionMergeModelV562 extends RankStrategy4RegionMergeM
         RecallUtils.extractOldSpecialRecall(mergeWeight.getOrDefault("oldSpecialN", (double) param.getSize()).intValue(), param, setVideo, rovRecallRank);
         //-------------------return相似召回------------------
         RecallUtils.extractRecall(mergeWeight.getOrDefault("v6", 5.0).intValue(), param, ReturnVideoRecallStrategy.PUSH_FORM, setVideo, rovRecallRank);
-        //-------------------新地域召回------------------
-        RecallUtils.extractRecall(mergeWeight.getOrDefault("v1", 5.0).intValue(), param, RegionRealtimeRecallStrategyV1.PUSH_FORM, setVideo, rovRecallRank);
+        //-------------------新地域召回 (V562: all_rov, V568 base 用 V1)------------------
+        RecallUtils.extractRecall(mergeWeight.getOrDefault("v1", 5.0).intValue(), param, RegionRealtimeRecallStrategyV1AllRov.PUSH_FROM, setVideo, rovRecallRank);
         //-------------------scene cf rovn------------------
         RecallUtils.extractRecall(mergeWeight.getOrDefault("sceneCFRovn", 5.0).intValue(), param, SceneCFRovnRecallStrategy.PUSH_FORM, setVideo, rovRecallRank);
         //-------------------scene cf rosn------------------
@@ -69,8 +69,8 @@ public class RankStrategy4RegionMergeModelV562 extends RankStrategy4RegionMergeM
         RecallUtils.extractRecall(mergeWeight.getOrDefault("headCate2RecallN", 3.0).intValue(), param, HeadProvinceCate2RecallStrategy.PUSH_FORM, setVideo, rovRecallRank);
         //-------------------head cate2 of rovn------------------
         RecallUtils.extractRecall(mergeWeight.getOrDefault("headCate2Rov", 5.0).intValue(), param, HeadCate2RovRecallStrategy.PUSH_FROM, setVideo, rovRecallRank);
-        //-------------------city rovn------------------
-        RecallUtils.extractRecall(mergeWeight.getOrDefault("cityRov", 5.0).intValue(), param, CityRovnRecallStrategy.PUSH_FROM, setVideo, rovRecallRank);
+        //-------------------city rovn (V562: all_rov, V568 base 用 v1)------------------
+        RecallUtils.extractRecall(mergeWeight.getOrDefault("cityRov", 5.0).intValue(), param, CityRovnAllRovRecallStrategy.PUSH_FROM, setVideo, rovRecallRank);
         //-------------------priori province rovn------------------
         RecallUtils.extractRecall(mergeWeight.getOrDefault("prioriProvinceRov", 3.0).intValue(), param, PrioriProvinceRovnRecallStrategy.PUSH_FROM, setVideo, rovRecallRank);
         //-------------------priori province str------------------

+ 12 - 0
recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/recall/RecallService.java

@@ -150,6 +150,18 @@ public class RecallService implements ApplicationContextAware {
             strategies.add(strategyMap.get(UserDeconstructionKeywordsRecallStrategy.class.getSimpleName()));
         }
 
+        boolean isHit562Exp = experimentService.judgeHitExp(param.getAppType(), param.getRootSessionId(), abExpCodes, "562");
+        if (isHit562Exp) {
+            strategies.add(strategyMap.get(RegionRealtimeRecallStrategyV1AllRov.class.getSimpleName()));
+            strategies.add(strategyMap.get(CityRovnAllRovRecallStrategy.class.getSimpleName()));
+            // V562: rank 侧用 all_rov 系列替代 region_1h + city_rovn, 这里直接剔除老召回避免无效 OSS/Redis 调用
+            Set<String> v562RemoveSet = new HashSet<>(Arrays.asList(
+                    RegionRealtimeRecallStrategyV1.class.getSimpleName(),
+                    CityRovnRecallStrategy.class.getSimpleName()
+            ));
+            strategies.removeIf(s -> s != null && v562RemoveSet.contains(s.getClass().getSimpleName()));
+        }
+
         boolean isHit564Exp = experimentService.judgeHitExp(param.getAppType(), param.getRootSessionId(), abExpCodes, "564");
         if (isHit564Exp) {
             strategies.add(strategyMap.get(ProvinceRovnRecallStrategy.class.getSimpleName()));

+ 102 - 0
recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/recall/strategy/CityRovnAllRovRecallStrategy.java

@@ -0,0 +1,102 @@
+package com.tzld.piaoquan.recommend.server.service.recall.strategy;
+
+import com.tzld.piaoquan.recommend.server.model.Video;
+import com.tzld.piaoquan.recommend.server.service.filter.FilterParam;
+import com.tzld.piaoquan.recommend.server.service.filter.FilterResult;
+import com.tzld.piaoquan.recommend.server.service.filter.FilterService;
+import com.tzld.piaoquan.recommend.server.service.recall.FilterParamFactory;
+import com.tzld.piaoquan.recommend.server.service.recall.RecallParam;
+import com.tzld.piaoquan.recommend.server.service.recall.RecallStrategy;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.tuple.MutablePair;
+import org.apache.commons.lang3.tuple.Pair;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Component;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+@Component
+@Slf4j
+public class CityRovnAllRovRecallStrategy implements RecallStrategy {
+    private final String CLASS_NAME = this.getClass().getSimpleName();
+    @Autowired
+    private FilterService filterService;
+    @Autowired
+    @Qualifier("redisTemplate")
+    public RedisTemplate<String, String> redisTemplate;
+
+    public static final String PUSH_FROM = "city_rovn_all_rov";
+    public static final String redisKeyPrefix = "city_rovn_all_rov_recall";
+
+    @Override
+    public String pushFrom() {
+        return PUSH_FROM;
+    }
+
+    @Override
+    public List<Video> recall(RecallParam param) {
+        List<Video> videosResult = new ArrayList<>();
+        try {
+            String city = param.getCity().replaceAll("市$", "");
+            String redisKey = String.format("%s:%s", redisKeyPrefix, city);
+            String redisValue = redisTemplate.opsForValue().get(redisKey);
+            if (null == redisValue || redisValue.isEmpty()) {
+                return videosResult;
+            }
+            Pair<List<Long>, Map<Long, Double>> pair = parsePair(redisValue, param.getVideoId(), 100);
+            fillVideoResult(param, pair, videosResult);
+        } catch (Exception e) {
+            log.error("recall is wrong in {}, error={}", CLASS_NAME, e);
+        }
+        return videosResult;
+    }
+
+    private Pair<List<Long>, Map<Long, Double>> parsePair(String data, long headVid, int size) {
+        List<Long> idsList = new ArrayList<>();
+        Map<Long, Double> scoresMap = new HashMap<>();
+        if (!StringUtils.isBlank(data)) {
+            String[] cells = data.split("\t");
+            if (2 == cells.length) {
+                List<Long> ids = Arrays.stream(cells[0].split(",")).map(Long::valueOf).collect(Collectors.toList());
+                List<Double> scores = Arrays.stream(cells[1].split(",")).map(Double::valueOf).collect(Collectors.toList());
+                if (!ids.isEmpty() && ids.size() == scores.size()) {
+                    int minSize = Math.min(size, ids.size());
+                    for (int i = 0; i < minSize; ++i) {
+                        long id = ids.get(i);
+                        double score = scores.get(i);
+                        if (headVid != id && !scoresMap.containsKey(id)) {
+                            idsList.add(id);
+                            scoresMap.put(id, score);
+                        }
+                    }
+                }
+            }
+        }
+        return new MutablePair<>(idsList, scoresMap);
+    }
+
+    private void fillVideoResult(RecallParam param, Pair<List<Long>, Map<Long, Double>> pair, List<Video> videosResult) {
+        if (null != pair) {
+            List<Long> ids = pair.getLeft();
+            Map<Long, Double> scoresMap = pair.getRight();
+            if (null != ids && null != scoresMap && !ids.isEmpty()) {
+                FilterParam filterParam = FilterParamFactory.create(param, ids);
+                FilterResult filterResult = filterService.filter(filterParam);
+                if (null != filterResult && CollectionUtils.isNotEmpty(filterResult.getVideoIds())) {
+                    filterResult.getVideoIds().forEach(vid -> {
+                        Video video = new Video();
+                        video.setVideoId(vid);
+                        video.setRovScore(scoresMap.getOrDefault(vid, 0D));
+                        video.setPushFrom(pushFrom());
+                        videosResult.add(video);
+                    });
+                }
+            }
+        }
+    }
+}