浏览代码

ADD: 新增节日内容召回

sunxy 1 年之前
父节点
当前提交
4d404ed978

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

@@ -48,6 +48,9 @@ public class RankRouter {
                 return rankStrategyFlowThompsonModel.rank(param);
             case "60120": // 576
                 return rankStrategy4RegionMerge.rank(param);
+            case "60130":
+                // 先走默认排序,后续需要优化祝福类的视频排序
+                return rankService.rank(param);
             default:
                 break;
         }

+ 4 - 0
recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/rank/RankService.java

@@ -148,6 +148,7 @@ public class RankService {
                 || param.getAbCode().equals("60117")
                 || param.getAbCode().equals("60118")
                 || param.getAbCode().equals("60119")
+                || param.getAbCode().equals("60130")
         ) {
             // 地域召回要做截取,再做融合排序
             removeDuplicate(rovRecallRank);
@@ -165,6 +166,9 @@ public class RankService {
                 rovRecallRank.addAll(extractAndSort(param, FlowPoolLastDayTopRecallStrategy.PUSH_FORM));
                 rovRecallRank.addAll(extractAndSort(param, TopGoodPerformanceVideoRecallStrategy.PUSH_FORM));
             }
+            if (param.getAbCode().equals("60130")) {
+                rovRecallRank.addAll(extractAndSort(param, FestivalRecallStrategyV1.PUSH_FORM));
+            }
             removeDuplicate(rovRecallRank);
 
             // 融合排序

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

@@ -155,6 +155,11 @@ public class RecallService implements ApplicationContextAware {
                     strategies.add(strategyMap.get(SimHotVideoRecallStrategy.class.getSimpleName()));
                     strategies.add(strategyMap.get(ReturnVideoRecallStrategy.class.getSimpleName()));
                     break;
+                case "60130":
+                    strategies.add(strategyMap.get(SimHotVideoRecallStrategy.class.getSimpleName()));
+                    strategies.add(strategyMap.get(ReturnVideoRecallStrategy.class.getSimpleName()));
+                    strategies.add(strategyMap.get(FestivalRecallStrategyV1.class.getSimpleName()));
+                    break;
                 default:
                     // todo 做兜底吗?
                     break;

+ 2 - 15
recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/recall/strategy/FestivalRecallStrategyV1.java

@@ -25,6 +25,7 @@ import java.util.*;
 @Slf4j
 @Component
 public class FestivalRecallStrategyV1 implements RecallStrategy {
+    public static final String PUSH_FORM = "recall_strategy_festival";
     @Autowired
     private RegionFilterService filterService;
     @Override
@@ -69,25 +70,11 @@ public class FestivalRecallStrategyV1 implements RecallStrategy {
         Collections.sort(videosResult, Comparator.comparingDouble(o -> -o.getRovScore()));
         return videosResult;
     }
-    public static final String PUSH_FORM = "recall_strategy_festival";
+
     @Override
     public String pushFrom(){
         return PUSH_FORM;
     }
 
 
-    public static List<List<Long>> groupKeys(Map<Long, Double> videoMap, int groupSize) {
-        List<List<Long>> result = new ArrayList<>();
-        List<Long> keys = new ArrayList<>(videoMap.keySet());
-
-        int size = keys.size();
-        for (int i = 0; i < size; i += groupSize) {
-            int endIndex = Math.min(i + groupSize, size);
-            List<Long> group = keys.subList(i, endIndex);
-            result.add(group);
-        }
-
-        return result;
-    }
-
 }

+ 202 - 8
recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/score4recall/strategy/FestivalRecallScore.java

@@ -3,18 +3,131 @@ package com.tzld.piaoquan.recommend.server.service.score4recall.strategy;
 import com.tzld.piaoquan.recommend.server.service.score.ScorerConfigInfo;
 import com.tzld.piaoquan.recommend.server.service.score4recall.AbstractScorer4Recall;
 import com.tzld.piaoquan.recommend.server.service.score4recall.model4recall.Model4RecallKeyValue;
+import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.tuple.Pair;
 
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.*;
 
 
 public class FestivalRecallScore extends AbstractScorer4Recall {
 
+    private static final Map<String, List<String>> FESTIVAL_TIME_MAP = new HashMap<String, List<String>>() {
+        {
+            put("晚安", Arrays.asList("daily 21:00-24:00"));
+            put("晚上好", Arrays.asList("daily 18:00-20:00"));
+            put("下午好", Arrays.asList("daily 15:00-16:00"));
+            put("中午好 ", Arrays.asList("daily 11:00-13:00"));
+            put("早上好", Arrays.asList("daily 00:00-08:00"));
+            put("圣诞节", Arrays.asList("2024-12-20 00:00~2024-12-25 08:00", "2025-12-20 00:00~2025-12-25 08:00", "2026-12-20 " +
+                    "00:00~2026-12-25 08:00"));
+            put("平安夜", Arrays.asList("2024-12-19 00:00~2024-12-24 08:00", "2025-12-19 00:00~2025-12-24 08:00", "2026-12-19 " +
+                    "00:00~2026-12-24 08:00"));
+            put("冬至", Arrays.asList("2024-12-19 00:00~2024-12-21 08:00", "2025-12-19 00:00~2025-12-21 08:00", "2026-12-20 " +
+                    "00:00~2026-12-22 08:00"));
+            put("公祭日", Arrays.asList("2024-12-08 00:00~2024-12-13 08:00", "2025-12-08 00:00~2025-12-13 08:00", "2026-12-08 " +
+                    "00:00~2026-12-13 08:00"));
+            put("大雪", Arrays.asList("2024-12-04 00:00~2024-12-06 08:00", "2025-12-05 00:00~2025-12-07 08:00", "2026-12-05 " +
+                    "00:00~2026-12-07 08:00"));
+            put("感恩节", Arrays.asList("2024-11-23 00:00~2024-11-28 08:00", "2025-11-22 00:00~2025-11-27 08:00", "2026-11-21 " +
+                    "00:00~2026-11-26 08:00"));
+            put("小雪", Arrays.asList("2024-11-20 00:00~2024-11-22 08:00", "2025-11-20 00:00~2025-11-22 08:00", "2026-11-20 " +
+                    "00:00~2026-11-22 08:00"));
+            put("立冬", Arrays.asList("2024-11-05 00:00~2024-11-07 08:00", "2025-11-05 00:00~2025-11-07 08:00", "2026-11-05 " +
+                    "00:00~2026-11-07 08:00"));
+            put("霜降", Arrays.asList("2024-10-21 00:00~2024-10-23 08:00", "2025-10-21 00:00~2025-10-23 08:00", "2026-10-21 " +
+                    "00:00~2026-10-23 08:00"));
+            put("重阳节", Arrays.asList("2024-10-06 00:00~2024-10-11 08:00", "2025-10-24 00:00~2025-10-29 08:00", "2026-10-13 " +
+                    "00:00~2026-10-18 08:00"));
+            put("寒露", Arrays.asList("2024-10-06 00:00~2024-10-08 08:00", "2025-10-06 00:00~2025-10-08 08:00", "2026-10-06 " +
+                    "00:00~2026-10-08 08:00"));
+            put("国庆节", Arrays.asList("2024-09-26 00:00~2024-10-01 08:00", "2025-09-26 00:00~2025-10-01 08:00", "2026-09-26 " +
+                    "00:00~2026-10-01 08:00"));
+            put("秋分", Arrays.asList("2024-09-20 00:00~2024-09-22 08:00", "2025-09-21 00:00~2025-09-23 08:00", "2026-09-21 " +
+                    "00:00~2026-09-23 08:00"));
+            put("中秋节", Arrays.asList("2024-09-12 00:00~2024-09-17 08:00", "2025-10-01 00:00~2025-10-06 08:00", "2026-09-20 " +
+                    "00:00~2026-09-25 08:00"));
+            put("白露", Arrays.asList("2024-09-05 00:00~2024-09-07 08:00", "2025-09-05 00:00~2025-09-07 08:00", "2026-09-05 " +
+                    "00:00~2026-09-07 08:00"));
+            put("处暑", Arrays.asList("2024-08-20 00:00~2024-08-22 08:00", "2025-08-21 00:00~2025-08-23 08:00", "2026-08-21 " +
+                    "00:00~2026-08-23 08:00"));
+            put("中元节", Arrays.asList("2024-08-13 00:00~2024-08-18 08:00", "2025-09-01 00:00~2025-09-06 08:00", "2026-08-22 " +
+                    "00:00~2026-08-27 08:00"));
+            put("七夕节", Arrays.asList("2024-08-05 00:00~2024-08-10 08:00", "2025-08-24 00:00~2025-08-29 08:00", "2026-08-14 " +
+                    "00:00~2026-08-19 08:00"));
+            put("立秋", Arrays.asList("2024-08-05 00:00~2024-08-07 08:00", "2025-08-05 00:00~2025-08-07 08:00", "2026-08-05 " +
+                    "00:00~2026-08-07 08:00"));
+            put("建军节", Arrays.asList("2024-07-27 00:00~2024-08-01 08:00", "2025-07-27 00:00~2025-08-01 08:00", "2026-07-27 " +
+                    "00:00~2026-08-01 08:00"));
+            put("大暑", Arrays.asList("2024-07-20 00:00~2024-07-22 08:00", "2025-07-20 00:00~2025-07-22 08:00", "2026-07-21 " +
+                    "00:00~2026-07-23 08:00"));
+            put("小暑", Arrays.asList("2024-07-04 00:00~2024-07-06 08:00", "2025-07-05 00:00~2025-07-07 08:00", "2026-07-05 " +
+                    "00:00~2026-07-07 08:00"));
+            put("七七事变",Arrays.asList("2024-07-02 00:00~2024-07-07 08:00", "2025-07-02 00:00~2025-07-07 08:00", "2026" +
+                    "-07-02 " +
+                    "00:00~2026-07-07 08:00"));
+            put("建党节", Arrays.asList("2024-06-26 00:00~2024-07-01 08:00", "2025-06-26 00:00~2025-07-01 08:00", "2026-06-26 " +
+                    "00:00~2026-07-01 08:00"));
+            put("夏至", Arrays.asList("2024-06-19 00:00~2024-06-21 08:00", "2025-06-19 00:00~2025-06-21 08:00", "2026-06-19 " +
+                    "00:00~2026-06-21 08:00"));
+            put("父亲节", Arrays.asList("2024-06-11 00:00~2024-06-16 08:00", "2025-06-10 00:00~2025-06-15 08:00", "2026-06-16 " +
+                    "00:00~2026-06-21 08:00"));
+            put("端午节", Arrays.asList("2024-06-05 00:00~2024-06-10 08:00", "2025-05-26 00:00~2025-05-31 08:00", "2026-06-14 " +
+                    "00:00~2026-06-19 08:00"));
+            put("芒种", Arrays.asList("2024-06-03 00:00~2024-06-05 08:00", "2025-06-03 00:00~2025-06-05 08:00", "2026-06-03 " +
+                    "00:00~2026-06-05 08:00"));
+            put("儿童节", Arrays.asList("2024-05-27 00:00~2024-06-01 08:00", "2025-05-27 00:00~2025-06-01 08:00", "2026-05-27 " +
+                    "00:00~2026-06-01 08:00"));
+            put("小满", Arrays.asList("2024-05-18 00:00~2024-05-20 08:00", "2025-05-19 00:00~2025-05-21 08:00", "2026-05-19 " +
+                    "00:00~2026-05-21 08:00"));
+            put("母亲节", Arrays.asList("2024-05-07 00:00~2024-05-12 08:00", "2025-05-06 00:00~2025-05-11 08:00", "2026-05-05 " +
+                    "00:00~2026-05-10 08:00"));
+            put("立夏", Arrays.asList("2024-05-03 00:00~2024-05-05 08:00", "2025-05-03 00:00~2025-05-05 08:00", "2026-05-03 " +
+                    "00:00~2026-05-05 08:00"));
+            put("劳动节", Arrays.asList("2024-04-26 00:00~2024-05-01 08:00", "2025-04-26 00:00~2025-05-01 08:00", "2026-04-26 " +
+                    "00:00~2026-05-01 08:00"));
+            put("谷雨", Arrays.asList("2024-04-17 00:00~2024-04-19 08:00", "2025-04-18 00:00~2025-04-20 08:00", "2026-04-18 " +
+                    "00:00~2026-04-20 08:00"));
+            put("清明", Arrays.asList("2024-04-02 00:00~2024-04-04 08:00", "2025-04-02 00:00~2025-04-04 08:00", "2026-04-03 " +
+                    "00:00~2026-04-05 08:00"));
+            put("春分", Arrays.asList("2024-03-18 00:00~2024-03-20 08:00", "2025-03-18 00:00~2025-03-20 08:00", "2026-03-18 " +
+                    "00:00~2026-03-20 08:00"));
+            put("龙抬头", Arrays.asList("2024-03-06 00:00~2024-03-11 08:00", "2025-02-24 00:00~2025-03-01 08:00", "2026-03-15 " +
+                    "00:00~2026-03-20 08:00"));
+            put("妇女节", Arrays.asList("2024-03-03 00:00~2024-03-08 08:00", "2025-03-03 00:00~2025-03-08 08:00", "2026-03-03 " +
+                    "00:00~2026-03-08 08:00"));
+            put("惊蛰", Arrays.asList("2024-03-03 00:00~2024-03-05 08:00", "2025-03-03 00:00~2025-03-05 08:00", "2026-03-03 " +
+                    "00:00~2026-03-05 08:00"));
+            put("元宵节", Arrays.asList("2024-02-19 00:00~2024-02-24 08:00", "2025-02-17 00:00~2025-02-22 08:00", "2026-02-26 " +
+                    "00:00~2026-03-03 08:00"));
+            put("雨水", Arrays.asList("2024-02-17 00:00~2024-02-19 08:00", "2025-02-16 00:00~2025-02-18 08:00", "2026-02-16 " +
+                    "00:00~2026-02-18 08:00"));
+            put("情人节", Arrays.asList("2024-02-09 00:00~2024-02-14 08:00", "2025-02-09 00:00~2025-02-14 08:00", "2026-02-09 " +
+                    "00:00~2026-02-14 08:00"));
+            put("春节", Arrays.asList("2024-02-05 00:00~2024-02-10 08:00", "2025-01-24 00:00~2025-01-29 08:00", "2026-02-12 " +
+                    "00:00~2026-02-17 08:00"));
+            put("除夕", Arrays.asList("2024-02-04 00:00~2024-02-09 08:00", "2025-01-23 00:00~2025-01-28 08:00", "2026-02-11 " +
+                    "00:00~2026-02-16 08:00"));
+            put("立春", Arrays.asList("2024-02-02 00:00~2024-02-04 08:00", "2025-02-01 00:00~2025-02-03 08:00", "2026-02-02 " +
+                    "00:00~2026-02-04 08:00"));
+            put("小年", Arrays.asList("2024-01-29 00:00~2024-02-03 20:00", "2025-01-18 00:00~2025-01-23 08:00", "2026-02-06 " +
+                    "00:00~2026-02-11 08:00"));
+            put("大寒", Arrays.asList("2024-01-18 00:00~2024-01-20 08:00", "2025-01-18 00:00~2025-01-20 08:00", "2026-01-18 " +
+                    "00:00~2026-01-20 08:00"));
+            put("腊八节", Arrays.asList("2024-01-13 00:00~2024-01-18 08:00", "2025-01-02 00:00~2025-01-07 08:00", "2026-01-21 " +
+                    "00:00~2026-01-26 08:00"));
+            put("小寒", Arrays.asList("2024-01-04 00:00~2024-01-06 08:00", "2025-01-03 00:00~2025-01-05 08:00", "2026-01-03 " +
+                    "00:00~2026-01-05 08:00"));
+            put("元旦", Arrays.asList("2023-12-27 00:00~2024-01-01 08:00", "2024-12-27 00:00~2025-01-01 08:00", "2025-12-27 " +
+                    "00:00~2026-01-01 08:00"));
+        }
+    };
+
     public FestivalRecallScore(ScorerConfigInfo configInfo) {
         super(configInfo);
     }
+
     @Override
     public void loadModel() {
         doLoadModel(Model4RecallKeyValue.class);
@@ -24,13 +137,94 @@ public class FestivalRecallScore extends AbstractScorer4Recall {
     public List<Pair<Long, Double>> recall(Map<String, String> params){
         // 节假日、时效性,判断
         Model4RecallKeyValue model = (Model4RecallKeyValue) this.getModel();
-        String key = params.getOrDefault("region_province", "中国");
-        List<Pair<Long, Double>> lists = model.kv.getOrDefault(key, new ArrayList<>());
-        if (lists.isEmpty()){
-            lists = model.kv.getOrDefault("中国", new ArrayList<>());
+        if (model == null || model.kv == null) {
+            return new ArrayList<>();
+        }
+        List<Pair<Long, Double>> result = new ArrayList<>();
+        for (Map.Entry<String, List<String>> entry : FESTIVAL_TIME_MAP.entrySet()) {
+            String festival = entry.getKey();
+            List<String> timeRangeList = entry.getValue();
+            if (isFestivalTime(timeRangeList)) {
+                List<Pair<Long, Double>> festivalLists = model.kv.getOrDefault(festival, new ArrayList<>());
+                if (festivalLists.isEmpty()) {
+                    continue;
+                }
+                result.addAll(festivalLists);
+            }
         }
+        // 固定获取常规祝福类的小程序
+        List<Pair<Long, Double>> festivalLists = model.kv.getOrDefault("祝福", new ArrayList<>());
+        if (!festivalLists.isEmpty()) {
+            result.addAll(festivalLists);
+        }
+        return result.subList(0, Math.min(100, result.size()));
+    }
 
-        return lists.subList(0, Math.min(100, lists.size()));
+    public boolean isFestivalTime(List<String> timeRangeList) {
+        if (timeRangeList == null || timeRangeList.isEmpty()) {
+            return false;
+        }
+        for (String timeRange : timeRangeList) {
+            // 判断是否是 daily 开头
+            if (StringUtils.startsWith(timeRange, "daily")) {
+                // 判断是否是 daily 开头
+                String dailyTimeRange = StringUtils.substring(timeRange, 6);
+                String[] split = StringUtils.split(dailyTimeRange, "-");
+                if (split.length != 2) {
+                    continue;
+                }
+                String startTime = split[0];
+                String endTime = split[1];
+                // 获取当前时间
+                LocalDateTime now = LocalDateTime.now();
+                // 获取当前时间的小时和分钟
+                int hour = now.getHour();
+                int minute = now.getMinute();
+                // startTime: 21:00 endTime: 23:00
+                String[] startSplit = StringUtils.split(startTime, ":");
+                String[] endSplit = StringUtils.split(endTime, ":");
+                if (startSplit.length != 2 || endSplit.length != 2) {
+                    continue;
+                }
+                int startHour = Integer.parseInt(startSplit[0]);
+                int startMinute = Integer.parseInt(startSplit[1]);
+                int endHour = Integer.parseInt(endSplit[0]);
+                int endMinute = Integer.parseInt(endSplit[1]);
+                if (hour > startHour && hour < endHour) {
+                    return true;
+                } else if (hour == startHour && hour == endHour) {
+                    if (minute >= startMinute && minute <= endMinute) {
+                        return true;
+                    }
+                } else if (hour == startHour) {
+                    if (minute >= startMinute) {
+                        return true;
+                    }
+                } else if (hour == endHour) {
+                    if (minute <= endMinute) {
+                        return true;
+                    }
+                }
+                continue;
+            }
+            // 时间格式 2024-12-20 00:00~2024-12-25 08:00
+            String[] split = StringUtils.split(timeRange, "~");
+            if (split.length != 2) {
+                continue;
+            }
+            String startTime = split[0];
+            String endTime = split[1];
+            // 获取当前时间
+            LocalDateTime now = LocalDateTime.now();
+            // 解析 startTime endTime
+            DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
+            LocalDateTime startLocalDateTime = LocalDateTime.parse(startTime, dateTimeFormatter);
+            LocalDateTime endLocalDateTime = LocalDateTime.parse(endTime, dateTimeFormatter);
+            if (now.isAfter(startLocalDateTime) && now.isBefore(endLocalDateTime)) {
+                return true;
+            }
+        }
+        return false;
     }