Browse Source

Merge branch 'feature_20240910_zhaohaipeng_vov_filter' of algorithm/recommend-server into master

zhaohaipeng 7 months ago
parent
commit
6a4d7c012f

+ 5 - 0
recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/filter/AbstractFilterService.java

@@ -127,6 +127,11 @@ public abstract class AbstractFilterService {
                 break;
         }
 
+        // VOV过滤实验
+        if (param.getAbExpCodes().contains("564")) {
+            strategies.add(ServiceBeanFactory.getBean(VovLowerStrategy.class));
+        }
+
         return strategies;
     }
 

+ 114 - 0
recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/filter/strategy/VovLowerStrategy.java

@@ -0,0 +1,114 @@
+package com.tzld.piaoquan.recommend.server.service.filter.strategy;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.TypeReference;
+import com.ctrip.framework.apollo.spring.annotation.ApolloJsonValue;
+import com.tzld.piaoquan.recommend.server.service.filter.FilterParam;
+import com.tzld.piaoquan.recommend.server.service.filter.FilterStrategy;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+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.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+@Slf4j
+@Component
+public class VovLowerStrategy implements FilterStrategy {
+
+    @ApolloJsonValue("${vov.filter.condition:{}}")
+    private Map<String, Double> vovFilterCondition;
+
+    @Autowired
+    @Qualifier("redisTemplate")
+    private RedisTemplate<String, String> redisTemplate;
+
+    private static final String KEY_FORMAT = "redis:vid_vov_daily4filter:%d";
+
+    @Override
+    public List<Long> filter(FilterParam param) {
+
+        List<Long> result = new ArrayList<>();
+
+        List<Long> videoIds = param.getVideoIds();
+        if (CollectionUtils.isEmpty(videoIds)) {
+            log.info("VOV过滤 -- videoIds为空,跳过");
+            return result;
+        }
+
+        List<String> redisKeys = videoIds.stream()
+                .map(r -> String.format(KEY_FORMAT, r))
+                .collect(Collectors.toList());
+        List<String> vovInfos = redisTemplate.opsForValue().multiGet(redisKeys);
+        if (CollectionUtils.isEmpty(vovInfos) || vovInfos.size() != videoIds.size()) {
+            log.info("VOV过滤 -- 获取到的视频VOV信息为空或长度与videoIds长度不一致,跳过: {}, {}", videoIds.size(), vovInfos.size());
+            return result;
+        }
+
+        List<Long> removeIds = new ArrayList<>();
+
+        for (int i = 0; i < videoIds.size(); i++) {
+            Long videoId = videoIds.get(i);
+            String vovInfo = vovInfos.get(i);
+            if (isFilter(vovInfo)) {
+                removeIds.add(videoId);
+                continue;
+            }
+
+            result.add(videoId);
+        }
+
+        log.info("VOV -- 本次召回的ID列表为: {}, 被过滤掉的ID列表为: {}, 剩下的ID列表为: {}", videoIds, removeIds, result);
+
+        return result;
+    }
+
+    private boolean isFilter(String vovInfo) {
+        try {
+
+            if (StringUtils.isEmpty(vovInfo)) {
+                return false;
+            }
+
+            Map<String, Double> vovInfoMap = JSON.parseObject(vovInfo, new TypeReference<Map<String, Double>>() {
+            });
+
+            // 获取阈值
+            double t0ViewPvCondition = vovFilterCondition.getOrDefault("t_0_view_pv", 1000d);
+            double t1ViewPvCondition = vovFilterCondition.getOrDefault("t_1_view_pv", 1000d);
+            double t2ViewPvCondition = vovFilterCondition.getOrDefault("t_2_view_pv", -1d);
+
+            double t0VovCondition = vovFilterCondition.getOrDefault("t_0_vov", 0.34d);
+            double t1VovCondition = vovFilterCondition.getOrDefault("t_1_vov", 0.54d);
+            double t2VovCondition = vovFilterCondition.getOrDefault("t_2_vov", 100000d);
+
+            // 获取视频VOV表现
+            double t0TodayDistViewPv = vovInfoMap.getOrDefault("t_0_today_dist_view_pv", 0d);
+            double t1TodayDistViewPv = vovInfoMap.getOrDefault("t_1_today_dist_view_pv", 0d);
+            double t2TodayDistViewPv = vovInfoMap.getOrDefault("t_2_today_dist_view_pv", 0d);
+
+            double t0AllVov = vovInfoMap.getOrDefault("t_0_all_vov", 0d);
+            double t1AllVov = vovInfoMap.getOrDefault("t_1_all_vov", 0d);
+            double t2AllVov = vovInfoMap.getOrDefault("t_2_all_vov", 0d);
+
+            // 判断曝光是否置信
+            boolean viewResult = (t0TodayDistViewPv > t0ViewPvCondition) && (t1TodayDistViewPv > t1ViewPvCondition) && (t2TodayDistViewPv > t2ViewPvCondition);
+
+            // 判断VOV是否小于阈值
+            boolean vovResult = (t0AllVov < t0VovCondition) && (t1AllVov < t1VovCondition) && (t2AllVov < t2VovCondition);
+
+            // 曝光置信 & VOV小于阈值 & VOV全不为0
+            return viewResult && vovResult;
+        } catch (Exception e) {
+            log.info("VOV过滤 -- 异常: ", e);
+        }
+        return false;
+    }
+
+}

+ 1 - 1
recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/rank/RankRouter.java

@@ -82,7 +82,7 @@ public class RankRouter {
             case "60113": // 563
                 return rankStrategy4RegionMergeModelV563.rank(param);
             case "60114": // 564
-                return rankStrategy4RegionMergeModelV564.rank(param);
+                return rankStrategy4RegionMergeModelV552.rank(param);
             case "60115": // 565
                 return rankStrategy4RegionMergeModelV565.rank(param);
             case "60116": // 566