Browse Source

流量池已发布 降权修改

wangyunpeng 11 months ago
parent
commit
0dfeca35d9

+ 1 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/common/enums/RankStrategyEnum.java

@@ -8,6 +8,7 @@ import java.util.Objects;
 public enum RankStrategyEnum {
     ArticleRankV2("ArticleRankV2", "ArticleRankV2", "rankV2Strategy"),
     ArticleRankV3("ArticleRankV3", "ArticleRankV3", "rankV3Strategy"),
+    ArticleRankV4("ArticleRankV4", "ArticleRankV4", "rankV4Strategy"),
 
     default_strategy("ArticleRankV1", "默认策略", "defaultRankStrategy"),
     ;

+ 9 - 4
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/rank/strategy/RankV3Strategy.java

@@ -52,10 +52,12 @@ public class RankV3Strategy implements RankStrategy {
             if (contentPools[0].equals(item.getContent().getContentPoolType())) {
                 score = item.getScore(SimilarityStrategy.class.getSimpleName())
                         + item.getScore(CategoryStrategy.class.getSimpleName())
-                        + item.getScore(ViewCountRateStrategy.class.getSimpleName());
+                        + item.getScore(ViewCountRateStrategy.class.getSimpleName())
+                        + item.getScore(FlowCtlDecreaseStrategy.class.getSimpleName());
             } else if (contentPools[1].equals(item.getContent().getContentPoolType())) {
                 score = item.getScore(ViewCountStrategy.class.getSimpleName())
-                        + item.getScore(CategoryStrategy.class.getSimpleName());
+                        + item.getScore(CategoryStrategy.class.getSimpleName())
+                        + item.getScore(FlowCtlDecreaseStrategy.class.getSimpleName());
             } else {
                 score = item.getScore(SimilarityStrategy.class.getSimpleName())
                         + item.getScore(CategoryStrategy.class.getSimpleName())
@@ -108,12 +110,15 @@ public class RankV3Strategy implements RankStrategy {
                 }
             } else if (level == 2) {
                 if (CollectionUtils.isNotEmpty(pool)) {
-                    pool = pool.subList(0, Math.max(10, pool.size()));
-                    Collections.shuffle(pool);
                     result.add(pool.get(0));
                     if (pool.size() > 1) {
                         result.add(pool.get(1));
                     }
+                } else {
+                    pool = contentMap.get(ContentPoolEnum.autoArticlePoolLevel1.getContentPool());
+                    if (CollectionUtils.isNotEmpty(pool)) {
+                        result.add(pool.get(0));
+                    }
                 }
             }
         } else {

+ 188 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/rank/strategy/RankV4Strategy.java

@@ -0,0 +1,188 @@
+package com.tzld.longarticle.recommend.server.service.rank.strategy;
+
+
+import com.tzld.longarticle.recommend.server.common.enums.ContentPoolEnum;
+import com.tzld.longarticle.recommend.server.model.Content;
+import com.tzld.longarticle.recommend.server.service.AccountContentPoolConfigService;
+import com.tzld.longarticle.recommend.server.service.rank.RankItem;
+import com.tzld.longarticle.recommend.server.service.rank.RankParam;
+import com.tzld.longarticle.recommend.server.service.rank.RankResult;
+import com.tzld.longarticle.recommend.server.service.rank.RankStrategy;
+import com.tzld.longarticle.recommend.server.service.score.ScoreParam;
+import com.tzld.longarticle.recommend.server.service.score.ScoreResult;
+import com.tzld.longarticle.recommend.server.service.score.ScoreService;
+import com.tzld.longarticle.recommend.server.service.score.strategy.*;
+import com.tzld.longarticle.recommend.server.util.CommonCollectionUtils;
+import com.tzld.longarticle.recommend.server.util.JSONUtils;
+import com.tzld.longarticle.recommend.server.util.TitleSimilarCheckUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.*;
+
+/**
+ * @author dyp
+ */
+@Service
+@Slf4j
+public class RankV4Strategy implements RankStrategy {
+
+    @Autowired
+    private ScoreService scoreService;
+    @Autowired
+    private AccountContentPoolConfigService accountContentPoolConfigService;
+
+    public RankResult rank(RankParam param) {
+
+        log.info("RankParam {}", JSONUtils.toJson(param));
+        ScoreResult scoreResult = scoreService.score(convertToScoreParam(param));
+        log.info("ScoreResult {}", JSONUtils.toJson(scoreResult));
+
+        Map<String, Map<String, Double>> scoreMap = scoreResult.getScoreMap();
+
+        List<RankItem> items = CommonCollectionUtils.toList(param.getContents(), c -> {
+            RankItem item = new RankItem();
+            item.setContent(c);
+            item.setScoreMap(scoreMap.get(c.getId()));
+            String[] contentPools = accountContentPoolConfigService.getContentPools(param.getAccountName());
+            double score;
+            if (contentPools[0].equals(item.getContent().getContentPoolType())
+                    || contentPools[1].equals(item.getContent().getContentPoolType())) {
+                score = item.getScore(SimilarityStrategy.class.getSimpleName())
+                        + item.getScore(CategoryStrategy.class.getSimpleName())
+                        + item.getScore(ViewCountRateStrategy.class.getSimpleName())
+                        + item.getScore(FlowCtlDecreaseStrategy.class.getSimpleName());
+            } else {
+                score = item.getScore(SimilarityStrategy.class.getSimpleName())
+                        + item.getScore(CategoryStrategy.class.getSimpleName())
+                        + item.getScore(AccountPreDistributeStrategy.class.getSimpleName())
+                        + item.getScore(FlowCtlDecreaseStrategy.class.getSimpleName());
+            }
+            item.setScore(score);
+            return item;
+        });
+
+        // 1 排序
+        Collections.sort(items, (o1, o2) -> -Double.compare(o1.getScore(), o2.getScore()));
+        log.info("SortResult {}", JSONUtils.toJson(items));
+        // 2 相似去重
+        List<Content> contents = CommonCollectionUtils.toList(items, RankItem::getContent);
+        contents = deduplication(contents);
+        log.info("Deduplication {}", JSONUtils.toJson(contents));
+
+        // 3 文章按照内容池分组
+        Map<String, List<Content>> contentMap = new HashMap<>();
+        for (Content c : contents) {
+            List<Content> data = contentMap.computeIfAbsent(c.getContentPoolType(), k -> new ArrayList<>());
+            data.add(c);
+        }
+        log.info("ContentMap {}", JSONUtils.toJson(contentMap));
+        // 4 选文章
+        List<Content> result = new ArrayList<>();
+        String[] contentPools = accountContentPoolConfigService.getContentPools(param.getAccountName());
+
+
+        // 头、次
+        if (StringUtils.equals(contentPools[0], contentPools[1])) {
+            List<Content> pool = contentMap.get(contentPools[0]);
+            Integer level = accountContentPoolConfigService.getLevelByContentPool(contentPools[0]);
+            if (level == 1) {
+                if (CollectionUtils.isNotEmpty(pool)) {
+                    result.add(pool.get(0));
+                    if (pool.size() > 2) {
+                        result.add(pool.get(2));
+                    }
+                } else {
+                    // level2 兜底
+                    pool = contentMap.get(accountContentPoolConfigService.getContentPoolByLevel(2));
+                    if (CollectionUtils.isNotEmpty(pool)) {
+                        result.add(pool.get(0));
+                        if (pool.size() > 1) {
+                            result.add(pool.get(1));
+                        }
+                    }
+                }
+            } else if (level == 2) {
+                if (CollectionUtils.isNotEmpty(pool)) {
+                    result.add(pool.get(0));
+                    if (pool.size() > 1) {
+                        result.add(pool.get(1));
+                    }
+                } else {
+                    pool = contentMap.get(ContentPoolEnum.autoArticlePoolLevel1.getContentPool());
+                    if (CollectionUtils.isNotEmpty(pool)) {
+                        result.add(pool.get(0));
+                    }
+                }
+            }
+        } else {
+            // 配置错误 兜底
+            List<Content> pool1 = contentMap.get(contentPools[0]);
+            List<Content> pool2 = contentMap.get(contentPools[1]);
+            if (CollectionUtils.isNotEmpty(pool1)) {
+                result.add(pool1.get(0));
+                if (CollectionUtils.isNotEmpty(pool2)) {
+                    result.add(pool2.get(0));
+                }
+            } else if (CollectionUtils.isNotEmpty(pool2)) {
+                result.add(pool2.get(0));
+                if (pool2.size() > 1) {
+                    result.add(pool2.get(1));
+                }
+            }
+        }
+
+        // 3-8
+        List<Content> pool = contentMap.get(contentPools[2]);
+        if (CollectionUtils.isNotEmpty(pool)) {
+            result.addAll(pool.subList(0, Math.min(pool.size(), param.getSize() - result.size())));
+        }
+
+        if (result.size() < param.getSize()) {
+            // 兜底
+            pool = param.getBackup();
+            pool = deduplication(pool);
+            log.info("Backup Deduplication {}", JSONUtils.toJson(pool));
+            Collections.shuffle(pool);
+            result.addAll(pool.subList(0, Math.min(pool.size(), param.getSize() - result.size())));
+        }
+
+        return new RankResult(result);
+    }
+
+    private ScoreParam convertToScoreParam(RankParam param) {
+        ScoreParam scoreParam = new ScoreParam();
+        scoreParam.setGhId(param.getGhId());
+        scoreParam.setAccountName(param.getAccountName());
+        scoreParam.setContents(param.getContents());
+        scoreParam.setStrategy(param.getStrategy());
+        return scoreParam;
+    }
+
+    private List<Content> deduplication(List<Content> contents) {
+        List<String> titles = new ArrayList<>();
+        List<Content> result = new ArrayList<>();
+        // 遍历所有列表
+        for (String contentPool : ContentPoolEnum.getOrderContentPool()) {
+            for (Content c : contents) {
+                if (!contentPool.equals(c.getContentPoolType())) {
+                    continue;
+                }
+                if (!similarity(c.getTitle(), titles)) {
+                    result.add(c);
+                    titles.add(c.getTitle());
+                }
+            }
+        }
+
+        return result;
+    }
+
+    private boolean similarity(String title, List<String> titles) {
+        return TitleSimilarCheckUtil.isDuplicateContent(title, titles);
+    }
+
+}

+ 6 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/score/ScoreService.java

@@ -93,6 +93,12 @@ public class ScoreService implements ApplicationContextAware {
             strategies.add(strategyMap.get(FlowCtlDecreaseStrategy.class.getSimpleName()));
             strategies.add(strategyMap.get(ViewCountRateStrategy.class.getSimpleName()));
         }
+        if (StringUtils.equals(param.getStrategy(), RankStrategyEnum.ArticleRankV4.getStrategy())) {
+            strategies.add(strategyMap.get(CategoryStrategy.class.getSimpleName()));
+            strategies.add(strategyMap.get(AccountPreDistributeStrategy.class.getSimpleName()));
+            strategies.add(strategyMap.get(FlowCtlDecreaseStrategy.class.getSimpleName()));
+            strategies.add(strategyMap.get(ViewCountRateStrategy.class.getSimpleName()));
+        }
 
         return strategies;
     }

+ 1 - 2
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/score/strategy/FlowCtlDecreaseStrategy.java

@@ -79,8 +79,7 @@ public class FlowCtlDecreaseStrategy implements ScoreStrategy {
         }
         if (hisPublishedContentMap.containsKey(content.getTitle())) {
             List<PublishSortLog> publishContents = hisPublishedContentMap.get(content.getTitle());
-            int finalIndex = index;
-            double sumViewCount = publishContents.stream().filter(o -> (o.getIndex() / 3) == (finalIndex / 3)).mapToDouble(PublishSortLog::getIndexAvgCount).sum();
+            double sumViewCount = publishContents.stream().mapToDouble(PublishSortLog::getIndexAvgCount).sum();
             int hisViewCountSum = content.getHisPublishArticleList().stream().filter(ContentHisPublishArticle::isInnerAccount)
                     .mapToInt(ContentHisPublishArticle::getAvgViewCount).sum();
             if ((sumViewCount + hisViewCountSum) > indexTotalAvgReadCountBase.get(String.valueOf(index))) {

+ 29 - 27
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/score/strategy/ViewCountRateStrategy.java

@@ -12,8 +12,7 @@ import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
-import java.util.ArrayList;
-import java.util.List;
+import java.util.*;
 
 @Component
 @Slf4j
@@ -27,34 +26,37 @@ public class ViewCountRateStrategy implements ScoreStrategy {
     @Override
     public List<Score> score(ScoreParam param) {
         List<Score> scores = new ArrayList<>();
-        for (Content content: param.getContents()) {
+        for (Content content : param.getContents()) {
             String[] contentPools = accountContentPoolConfigService.getContentPools(param.getAccountName());
-            if (!contentPools[0].equals(content.getContentPoolType())) {
-                continue;
-            }
-            double firstAvgViewCount = accountIndexAvgViewCountService.getAvgReadCount(param.getGhId(), 1);
-            double showViewCountSum = 0D;
-            double avgViewCountSum = 0D;
-            for (ContentHisPublishArticle hisItem : content.getHisPublishArticleList()) {
-                if (hisItem.isInnerAccount() && hisItem.getShowViewCount() > 0 && hisItem.getAvgViewCount() > 0) {
-                    showViewCountSum += hisItem.getShowViewCount();
-                    avgViewCountSum += hisItem.getAvgViewCount();
+            for (int i = 0; i < contentPools.length; i++) {
+                if (!contentPools[i].equals(content.getContentPoolType())) {
+                    continue;
                 }
+                double firstAvgViewCount = accountIndexAvgViewCountService.getAvgReadCount(param.getGhId(), i + 1);
+                double showViewCountSum = 0D;
+                double avgViewCountSum = 0D;
+                for (ContentHisPublishArticle hisItem : content.getHisPublishArticleList()) {
+                    if (hisItem.isInnerAccount() && hisItem.getShowViewCount() > 0 && hisItem.getAvgViewCount() > 0) {
+                        showViewCountSum += hisItem.getShowViewCount();
+                        avgViewCountSum += hisItem.getAvgViewCount();
+                    }
+                }
+                double viewCountRate = 0D; // 设置默认值
+                if (avgViewCountSum > 0) {
+                    viewCountRate = showViewCountSum / avgViewCountSum;
+                }
+                double viewCountRateW = MathUtils.sigmoid(avgViewCountSum, 0.0005, firstAvgViewCount);
+                double viewCountRateScore = 0;
+                if (viewCountRate > 0) {
+                    viewCountRateScore = (Math.min(viewCountRate, 5) - 1D) * viewCountRateW;
+                }
+                Score score = new Score();
+                score.setStrategy(this);
+                score.setContentId(content.getId());
+                score.setScore(viewCountRateScore);
+                scores.add(score);
+                break;
             }
-            double viewCountRate = 0D; // 设置默认值
-            if (avgViewCountSum > 0) {
-                viewCountRate = showViewCountSum / avgViewCountSum;
-            }
-            double viewCountRateW = MathUtils.sigmoid(avgViewCountSum, 0.0005, firstAvgViewCount);
-            double viewCountRateScore = 0;
-            if (viewCountRate > 0) {
-                viewCountRateScore = (Math.min(viewCountRate, 5) - 1D) * viewCountRateW;
-            }
-            Score score = new Score();
-            score.setStrategy(this);
-            score.setContentId(content.getId());
-            score.setScore(viewCountRateScore);
-            scores.add(score);
         }
         return scores;
     }