Browse Source

MOD: rov池强插视频标签的功能

sunxy 1 year ago
parent
commit
aa0bdbb96b

+ 34 - 11
recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/rank/processor/RankProcessorInsert.java

@@ -3,9 +3,11 @@ package com.tzld.piaoquan.recommend.server.service.rank.processor;
 import com.tzld.piaoquan.recommend.server.model.Video;
 import com.tzld.piaoquan.recommend.server.service.rank.RankParam;
 import com.tzld.piaoquan.recommend.server.util.MathUtil;
+import com.tzld.piaoquan.recommend.server.util.WeightRandom;
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
@@ -44,9 +46,15 @@ public class RankProcessorInsert {
         }
 
         // 获取需要插入的视频
-        Video insertTagVideo = rovList.stream()
-                .filter(video -> video.getTags().contains(finalTagName))
-                .findFirst().orElse(null);
+        Video insertTagVideo = null;
+        int tagVideoIndex = -1;
+        for (int i = 0; i < rovList.size(); i++) {
+            if (rovList.get(i).getTags().contains(finalTagName)) {
+                insertTagVideo = rovList.get(i);
+                tagVideoIndex = i;
+                break;
+            }
+        }
         if (insertTagVideo == null) {
             return;
         }
@@ -56,15 +64,30 @@ public class RankProcessorInsert {
         List<Double> insertWeightList = Arrays.stream(insertWeight)
                 .map(Double::valueOf).collect(Collectors.toList());
 
-        // 遍历权重,随机插入
-        for (int i = 0; i < insertWeightList.size(); i++) {
-            double probability = insertWeightList.get(i);
-            double randomDouble = MathUtil.nextDouble(0, 1);
-            if (randomDouble <= probability) {
-                rovList.add(i, insertTagVideo);
-                break;
-            }
+        if (CollectionUtils.size(insertWeightList) != 5) {
+            return;
+        }
+        Double showProbability = insertWeightList.get(0);
+        double randomDouble = MathUtil.nextDouble(0, 1);
+        if (randomDouble > showProbability) {
+            // 没有命中强插规则
+            return;
+        }
+        // 遍历权重,获取插入位置
+        List<WeightRandom.ItemWithWeight<Integer>> items = new ArrayList<>(insertWeightList.size());
+        for (int i = 1; i < insertWeightList.size(); i++) {
+            WeightRandom.ItemWithWeight<Integer> itemWithWeight = new WeightRandom.ItemWithWeight<>(i, insertWeightList.get(i));
+            items.add(itemWithWeight);
+        }
+        WeightRandom<Integer> integerWeightRandom = new WeightRandom<>(items);
+        Integer insertIndex = integerWeightRandom.choose();
+        if (insertIndex == null) {
+            return;
         }
+        // 删除原视频
+        rovList.remove(tagVideoIndex);
+        // 插入该视频到指定位置
+        rovList.add(insertIndex - 1, insertTagVideo);
 
     }
 

+ 6 - 3
recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/rank/strategy/FestivalStrategy4RankModel.java

@@ -34,7 +34,11 @@ public class FestivalStrategy4RankModel extends RankService {
         List<Video> rovRecallRank = new ArrayList<>();
         rovRecallRank.addAll(extractAndSort(param, SimHotVideoRecallStrategy.PUSH_FORM));
         rovRecallRank.addAll(extractAndSort(param, ReturnVideoRecallStrategy.PUSH_FORM));
-        rovRecallRank.addAll(extractAndSort(param, FestivalRecallStrategyV1.PUSH_FORM));
+        List<Video> festivalRecallVideoList = extractAndSort(param, FestivalRecallStrategyV1.PUSH_FORM);
+        // 截断
+        if (CollectionUtils.isNotEmpty(festivalRecallVideoList)) {
+            rovRecallRank.addAll(festivalRecallVideoList.stream().limit(30).collect(Collectors.toList()));
+        }
         removeDuplicate(rovRecallRank);
         // 融合排序
         List<String> videoIdKeys = rovRecallRank.stream()
@@ -48,9 +52,8 @@ public class FestivalStrategy4RankModel extends RankService {
             for (int i = 0; i < videoScores.size(); i++) {
                 rovRecallRank.get(i).setSortScore(NumberUtils.toDouble(videoScores.get(i), 0.0));
             }
-            // TODO 提权
             Collections.sort(rovRecallRank,
-                    Comparator.comparingDouble(o -> -(o.getSortScore() * 0.4 * (o.getRovScore() / 100))));
+                    Comparator.comparingDouble(o -> -(o.getSortScore() * 0.1 * (o.getRovScore() / 100))));
         }
 
         return rovRecallRank;

+ 119 - 0
recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/util/WeightRandom.java

@@ -0,0 +1,119 @@
+package com.tzld.piaoquan.recommend.server.util;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.ThreadLocalRandom;
+
+/**
+ * 基于权重随机算法选择
+ *
+ * @author sunxy
+ */
+public class WeightRandom<T> {
+
+    private final List<T> items = new ArrayList<>();
+    private double[] weights;
+
+    public WeightRandom(List<ItemWithWeight<T>> itemsWithWeight) {
+        this.calWeights(itemsWithWeight);
+    }
+
+    /**
+     * 计算权重,初始化或者重新定义权重时使用
+     */
+    private void calWeights(List<ItemWithWeight<T>> itemsWithWeight) {
+        items.clear();
+
+        // 计算权重总和
+        double originWeightSum = 0;
+        for (ItemWithWeight<T> itemWithWeight : itemsWithWeight) {
+            double weight = itemWithWeight.getWeight();
+            if (weight <= 0) {
+                continue;
+            }
+
+            items.add(itemWithWeight.getItem());
+            if (Double.isInfinite(weight)) {
+                weight = 10000.0D;
+            }
+            if (Double.isNaN(weight)) {
+                weight = 1.0D;
+            }
+            originWeightSum += weight;
+        }
+
+        // 计算每个item的实际权重比例
+        double[] actualWeightRatios = new double[items.size()];
+        int index = 0;
+        for (ItemWithWeight<T> itemWithWeight : itemsWithWeight) {
+            double weight = itemWithWeight.getWeight();
+            if (weight <= 0) {
+                continue;
+            }
+            actualWeightRatios[index++] = weight / originWeightSum;
+        }
+
+        // 计算每个item的权重范围
+        // 权重范围起始位置
+        weights = new double[items.size()];
+        double weightRangeStartPos = 0;
+        for (int i = 0; i < index; i++) {
+            weights[i] = weightRangeStartPos + actualWeightRatios[i];
+            weightRangeStartPos += actualWeightRatios[i];
+        }
+    }
+
+    /**
+     * 基于权重随机算法选择
+     */
+    public T choose() {
+        if (items.isEmpty()) {
+            return null;
+        }
+        double random = ThreadLocalRandom.current().nextDouble();
+        int index = Arrays.binarySearch(weights, random);
+        if (index < 0) {
+            index = -index - 1;
+        } else {
+            return items.get(index);
+        }
+
+        if (index < weights.length && random < weights[index]) {
+            return items.get(index);
+        }
+
+        // 通常不会走到这里,为了保证能得到正确的返回,这里随便返回一个
+        return items.get(0);
+    }
+
+    public static class ItemWithWeight<T> {
+        T item;
+        double weight;
+
+        public ItemWithWeight() {
+        }
+
+        public ItemWithWeight(T item, double weight) {
+            this.item = item;
+            this.weight = weight;
+        }
+
+        public T getItem() {
+            return item;
+        }
+
+        public void setItem(T item) {
+            this.item = item;
+        }
+
+        public double getWeight() {
+            return weight;
+        }
+
+        public void setWeight(double weight) {
+            this.weight = weight;
+        }
+    }
+
+}