Ver código fonte

渠道ROV召回

jch 1 mês atrás
pai
commit
d6bf961acc

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

@@ -10,7 +10,6 @@ import com.tzld.piaoquan.recommend.server.service.rank.extractor.ExtractorUtils;
 import com.tzld.piaoquan.recommend.server.service.recall.strategy.*;
 import com.tzld.piaoquan.recommend.server.service.score.ScorerUtils;
 import com.tzld.piaoquan.recommend.server.util.CommonCollectionUtils;
-import com.tzld.piaoquan.recommend.server.util.FeatureUtils;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.collections4.MapUtils;
 import org.apache.commons.math3.util.Pair;
@@ -78,17 +77,10 @@ public class RankStrategy4RegionMergeModelV568 extends RankStrategy4RegionMergeM
         sceneCFRosn = sceneCFRosn.subList(0, Math.min(mergeWeight.getOrDefault("sceneCFRosn", 5.0).intValue(), sceneCFRosn.size()));
         rovRecallRank.addAll(sceneCFRosn);
         setVideo.addAll(sceneCFRosn.stream().map(Video::getVideoId).collect(Collectors.toSet()));
-        if (FeatureUtils.lowFissionChannel(param.getRootSourceId()) && FeatureUtils.firstLevel(param.getUserShareDepth())) {
-            // head cate1 str
-            int headCate1StrN = mergeWeight.getOrDefault("headCate1StrN", 5.0).intValue();
-            addRecall(param, headCate1StrN, HeadCate1STRRecallStrategy.PUSH_FORM, setVideo, rovRecallRank);
-            // head cate2 str
-            int headCate2StrN = mergeWeight.getOrDefault("headCate2StrN", 5.0).intValue();
-            addRecall(param, headCate2StrN, HeadCate2STRRecallStrategy.PUSH_FORM, setVideo, rovRecallRank);
-            // province str
-            int provinceStrN = mergeWeight.getOrDefault("provinceStrN", 5.0).intValue();
-            addRecall(param, provinceStrN, ProvinceSTRRecallStrategy.PUSH_FORM, setVideo, rovRecallRank);
-        }
+
+        // channel rov
+        int channelROVN = mergeWeight.getOrDefault("channelROVN", 5.0).intValue();
+        addRecall(param, channelROVN, ChannelROVRecallStrategy.PUSH_FORM, setVideo, rovRecallRank);
 
         //-------------------排-------------------
         //-------------------序-------------------

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

@@ -5,7 +5,6 @@ import com.tzld.piaoquan.recommend.server.common.ThreadPoolFactory;
 import com.tzld.piaoquan.recommend.server.common.enums.AppTypeEnum;
 import com.tzld.piaoquan.recommend.server.model.Video;
 import com.tzld.piaoquan.recommend.server.service.recall.strategy.*;
-import com.tzld.piaoquan.recommend.server.util.FeatureUtils;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
@@ -110,23 +109,14 @@ public class RecallService implements ApplicationContextAware {
         strategies.add(strategyMap.get(SceneCFRovnRecallStrategy.class.getSimpleName()));
         strategies.add(strategyMap.get(SceneCFRosnRecallStrategy.class.getSimpleName()));
         Set<String> abExpCodes = param.getAbExpCodes();
-        if (CollectionUtils.isNotEmpty(abExpCodes) && abExpCodes.contains("568")) {
-            // strategies.remove(strategyMap.get(ReturnVideoRecallStrategy.class.getSimpleName()));
-            strategies.add(strategyMap.get(RegionRealtimeRecallStrategyV7LongTermV1.class.getSimpleName()));
-            strategies.add(strategyMap.get(RegionRealtimeRecallStrategyROS.class.getSimpleName()));
-        }
         if (CollectionUtils.isNotEmpty(abExpCodes) && abExpCodes.contains("567")) {
             strategies.add(strategyMap.get(UserCate1RecallStrategy.class.getSimpleName()));
             strategies.add(strategyMap.get(UserCate2RecallStrategy.class.getSimpleName()));
             strategies.add(strategyMap.get(HeadProvinceCate1RecallStrategy.class.getSimpleName()));
             strategies.add(strategyMap.get(HeadProvinceCate2RecallStrategy.class.getSimpleName()));
         }
-        if (CollectionUtils.isNotEmpty(abExpCodes) && abExpCodes.contains("568")
-                && FeatureUtils.lowFissionChannel(param.getRootSourceId())
-                && FeatureUtils.firstLevel(param.getUserShareDepth())) {
-            strategies.add(strategyMap.get(HeadCate1STRRecallStrategy.class.getSimpleName()));
-            strategies.add(strategyMap.get(HeadCate2STRRecallStrategy.class.getSimpleName()));
-            strategies.add(strategyMap.get(ProvinceSTRRecallStrategy.class.getSimpleName()));
+        if (CollectionUtils.isNotEmpty(abExpCodes) && abExpCodes.contains("568")) {
+            strategies.add(strategyMap.get(ChannelROVRecallStrategy.class.getSimpleName()));
         }
 
         // 命中用户黑名单不走流量池

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

@@ -0,0 +1,140 @@
+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 com.tzld.piaoquan.recommend.server.util.FeatureUtils;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections4.CollectionUtils;
+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.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+@Component
+@Slf4j
+public class ChannelROVRecallStrategy implements RecallStrategy {
+    private final String CLASS_NAME = this.getClass().getSimpleName();
+    @Autowired
+    private FilterService filterService;
+    @Autowired
+    @Qualifier("redisTemplate")
+    public RedisTemplate<String, String> redisTemplate;
+
+    private static final String channelRegex = "(longArticles_|dyyjs_|touliu_tencent_|touliu_tencentgzh_|touliu_tencentGzhArticle_|GzhTouLiu_Articles_gh)";
+    private static final Pattern channelPattern = Pattern.compile(channelRegex);
+
+    public static final String PUSH_FORM = "recall_strategy_channel";
+    public static final String redisKeyPrefix = "channel_recall";
+    public static final String channelGroupPrefix = "alg_recsys_user_channel_group";
+
+    @Override
+    public String pushFrom() {
+        return PUSH_FORM;
+    }
+
+    @Override
+    public List<Video> recall(RecallParam param) {
+        List<Video> videosResult = new ArrayList<>();
+        try {
+            if (!FeatureUtils.firstLevel(param.getUserShareDepth())) {
+                return videosResult;
+            }
+
+            String channelName = getChannelName(param.getRootSourceId());
+            if (channelName.isEmpty()) {
+                return videosResult;
+            }
+
+            String key = String.format("%s:%s", redisKeyPrefix, channelName);
+            String value = redisTemplate.opsForValue().get(key);
+            if (null == value || value.isEmpty()) {
+                return videosResult;
+            }
+            List<Long> vidList = parseVidList(param.getVideoId(), value);
+            fillVideoResult(param, vidList, videosResult);
+        } catch (Exception e) {
+            log.error("recall is wrong in {}, error={}", CLASS_NAME, e);
+        }
+        return videosResult;
+    }
+
+    private List<Long> parseVidList(Long headVid, String data) {
+        List<Long> vidList = new ArrayList<>();
+        if (null != data && !data.isEmpty()) {
+            String[] pair = data.split("\t");
+            if (2 == pair.length) {
+                Set<Long> hit = new HashSet<>();
+                hit.add(headVid);
+                List<Long> ids = Arrays.stream(pair[0].split(",")).map(Long::valueOf).collect(Collectors.toList());
+                if (!ids.isEmpty()) {
+                    for (Long id : ids) {
+                        if (!hit.contains(id)) {
+                            hit.add(id);
+                            vidList.add(id);
+                        }
+                    }
+                }
+            }
+        }
+        return vidList;
+    }
+
+    private void fillVideoResult(RecallParam param, List<Long> vidList, List<Video> videosResult) {
+        FilterParam filterParam = FilterParamFactory.create(param, vidList);
+        FilterResult filterResult = filterService.filter(filterParam);
+        if (filterResult != null && CollectionUtils.isNotEmpty(filterResult.getVideoIds())) {
+            List<Long> filterIds = filterResult.getVideoIds();
+            int n = filterIds.size();
+            for (int i = 0; i < n; i++) {
+                Video video = new Video();
+                video.setVideoId(filterIds.get(i));
+                video.setRovScore(n - i);
+                video.setPushFrom(pushFrom());
+                videosResult.add(video);
+            }
+        }
+    }
+
+
+    private String getChannelName(String s) {
+        if (null != s && !s.isEmpty()) {
+            Matcher matcher = channelPattern.matcher(s);
+            if (matcher.find()) {
+                switch (matcher.group(0)) {
+                    case "longArticles_":
+                        return getChannelType(s);
+                    case "dyyjs_":
+                        return "公众号代运营-即转";
+                    case "touliu_tencent_":
+                        return "小程序投流";
+                    case "touliu_tencentgzh_":
+                    case "touliu_tencentGzhArticle_":
+                    case "GzhTouLiu_Articles_gh":
+                        return "公众号投流";
+                    default:
+                        return "";
+                }
+            }
+        }
+        return "";
+    }
+
+    private String getChannelType(String s) {
+        String key = String.format("%s:%s", channelGroupPrefix, s);
+        String value = redisTemplate.opsForValue().get(key);
+        if (null != value && value.equals("公众号买号")) {
+            return value;
+        }
+        return "公众号代运营-Daily";
+    }
+}