Parcourir la source

feat:添加dnn模型

zhaohaipeng il y a 1 mois
Parent
commit
de2d7ebf2d
17 fichiers modifiés avec 589 ajouts et 814 suppressions
  1. 1 0
      recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/common/base/RankItem.java
  2. 15 0
      recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/model/Tuple4.java
  3. 0 56
      recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/RecommendService.java
  4. 0 10
      recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/rank/RankService.java
  5. 265 167
      recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/rank/strategy/RankStrategy4RegionMergeModelDNNDemo.java
  6. 1 1
      recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/rank/strategy/RankStrategy4RegionMergeModelV536.java
  7. 51 48
      recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/rank/strategy/RankStrategy4RegionMergeModelV562.java
  8. 1 1
      recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/rank/strategy/RankStrategy4RegionMergeModelV566.java
  9. 2 2
      recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/rank/strategy/RankStrategy4RegionMergeModelV568.java
  10. 5 1
      recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/rank/tansform/FeatureFGEncoder.java
  11. 14 0
      recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/rank/tansform/FeatureV6.java
  12. 0 1
      recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/recall/RecallParam.java
  13. 0 4
      recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/recall/RecallService.java
  14. 0 77
      recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/recall/strategy/AppTypeSpecialRecallStrategy.java
  15. 93 0
      recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/score/PAIScorer.java
  16. 138 0
      recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/score/model/PAIModel.java
  17. 3 446
      recommend-server-service/src/main/resources/feeds_score_config_xgb_ros_20250311.conf

+ 1 - 0
recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/common/base/RankItem.java

@@ -19,6 +19,7 @@ public class RankItem implements Comparable<RankItem> {
     // 所有特征,包括视频、用户等等
     public Map<String, Float> allFeatureMap = new HashMap<>();
     public Map<String, Double> featureMapDouble = new HashMap<>();
+    public Map<String, String> featureMapString = new HashMap<>();
     public String id;
     public Map<String, Double> scoresMap = new HashMap<>();
     public Map<String, String> itemBasicFeature = new HashMap<>();

+ 15 - 0
recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/model/Tuple4.java

@@ -0,0 +1,15 @@
+package com.tzld.piaoquan.recommend.server.model;
+
+import lombok.Data;
+
+@Data
+public class Tuple4<T1, T2, T3, T4> {
+
+    private T1 v1;
+
+    private T2 v2;
+
+    private T3 v3;
+
+    private T4 v4;
+}

+ 0 - 56
recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/RecommendService.java

@@ -103,9 +103,6 @@ public class RecommendService {
     @ApolloJsonValue("${log.upload.field.switch:{}}")
     private Map<String, String> logUploadFieldSwitch;
 
-    @ApolloJsonValue("${special.apptype.set:[]}")
-    private Set<Integer> specialAppTypeSet;
-
     public static final String channelGroupPrefix = "alg_recsys_user_channel_group";
     /**
      * wx_user_info 表信息
@@ -176,9 +173,6 @@ public class RecommendService {
                 return specialMidRecommend(request);
             }
             Stopwatch stopwatch = Stopwatch.createStarted();
-            if (CollectionUtils.isNotEmpty(specialAppTypeSet) && specialAppTypeSet.contains(request.getAppType())) {
-                return specialAppTypeRecommend(request);
-            }
 
             if (StringUtils.isNotBlank(request.getMid())
                     && redisTemplate.opsForSet().isMember("special:mid", request.getMid())) {
@@ -371,56 +365,6 @@ public class RecommendService {
                 .build();
     }
 
-    public RecommendResponse specialAppTypeRecommend(RecommendRequest request) {
-        log.info("hit special apptype recommend request={}", JSONUtils.toJson(request));
-        if (request == null) {
-            return RecommendResponse.newBuilder()
-                    .setResult(Result.newBuilder().setCode(1).setMessage("success"))
-                    .build();
-        }
-
-        RecallParam recallParam = new RecallParam();
-        recallParam.setAppType(request.getAppType());
-        recallParam.setMid(request.getMid());
-        recallParam.setAppTypeSpecialRecommend(true);
-        recallParam.setProvince(request.getProvince());
-        recallParam.setCityCode(request.getCityCode());
-        recallParam.setSize(request.getSize());
-
-        RecallResult recallResult = recallService.recall(recallParam);
-
-        RankParam rankParam = new RankParam();
-        rankParam.setRecallResult(recallResult);
-        rankParam.setSize(request.getSize());
-        rankParam.setAppTypeSpecialRecommend(true);
-
-        RankResult rankResult = rankRouter.rank(rankParam);
-
-        if (Objects.isNull(rankResult) || CollectionUtils.isEmpty(rankResult.getVideos())) {
-            return RecommendResponse.newBuilder()
-                    .setResult(Result.newBuilder().setCode(1).setMessage("success"))
-                    .build();
-        }
-
-        // 只返回size条数据
-        List<Video> videos= rankResult.getVideos().subList(0, Math.min(recallParam.getSize(), rankResult.getVideos().size()));
-
-        if (CollectionUtils.isNotEmpty(videos)) {
-            Video lastVideo = videos.get(videos.size() - 1);
-            redisTemplate.opsForValue().set(lastVideo.getLastVideoKey(), String.valueOf(lastVideo.getVideoId()),
-                    1, TimeUnit.DAYS);
-        }
-
-        return RecommendResponse.newBuilder()
-                .setResult(Result.newBuilder().setCode(1).setMessage("success"))
-                .addAllVideo(CommonCollectionUtils.toList(videos, v -> VideoProto.newBuilder()
-                        .setPushFrom(Strings.nullToEmpty(v.getPushFrom()))
-                        .setVideoId(v.getVideoId())
-                        .setRovScore(v.getRovScore())
-                        .build()))
-                .build();
-    }
-
     public RecommendParam genRecommendParam(RecommendRequest request, int recommendType) {
         RecommendParam param = new RecommendParam();
         param.setTopK(3);

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

@@ -38,16 +38,6 @@ public abstract class RankService {
             return null;
         }
 
-        if (param.isAppTypeSpecialRecommend()) {
-            Optional<RecallResult.RecallData> data = param.getRecallResult().getData().stream()
-                    .filter(d -> d.getPushFrom().equals(AppTypeSpecialRecallStrategy.PUSH_FROM))
-                    .findFirst();
-            if (data.isPresent() && CollectionUtils.isNotEmpty(data.get().getVideos())) {
-                return new RankResult(data.get().getVideos());
-            }
-            return null;
-        }
-
         if (2 == param.getRecommendType()) {
             tagDuplicateVideos(param);
             List<Video> rovRecallRank = mergeAndRankRovRecall(param);

+ 265 - 167
recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/rank/strategy/RankStrategy4RegionMergeModelDNNDemo.java

@@ -1,167 +1,265 @@
-package com.tzld.piaoquan.recommend.server.service.rank.strategy;
-
-import com.tzld.piaoquan.recommend.server.common.base.RankItem;
-import com.tzld.piaoquan.recommend.server.model.Video;
-import com.tzld.piaoquan.recommend.server.service.FeatureService;
-import com.tzld.piaoquan.recommend.server.service.rank.RankParam;
-import com.tzld.piaoquan.recommend.server.service.rank.bo.UserShareReturnProfile;
-import com.tzld.piaoquan.recommend.server.service.rank.tansform.FeatureFGEncoder;
-import com.tzld.piaoquan.recommend.server.service.rank.tansform.FeatureV6;
-import com.tzld.piaoquan.recommend.server.util.CommonCollectionUtils;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-
-import javax.annotation.PostConstruct;
-import java.util.*;
-
-/**
- * DNN 模型排序 Demo
- *
- * 流程:
- *   1. 特征提取: 复用 FeatureV6(跟 FM/XGB 完全一样)
- *   2. FG 编码: FeatureFGEncoder 按 fg_config.json 顺序编码为 chr(2) 字符串
- *   3. 模型打分: 调用 EAS 服务(TODO: 接入 EAS SDK)
- *
- * 特征配置: resources/fg/fg_config.json(975 特征,跟离线训练一致)
- */
-@Service
-@Slf4j
-public class RankStrategy4RegionMergeModelDNNDemo extends RankStrategy4RegionMergeModelBasic {
-
-    @Autowired
-    private FeatureService featureService;
-
-    private FeatureFGEncoder fgEncoder;
-
-    @PostConstruct
-    public void init() {
-        fgEncoder = new FeatureFGEncoder("fg/fg_config.json");
-        log.info("DNN Demo 初始化完成: {} 个特征", fgEncoder.getFeatureCount());
-    }
-
-    @Override
-    public List<Video> mergeAndRankRovRecall(RankParam param) {
-        long currentMs = System.currentTimeMillis();
-
-        // ============ 召回(跟 V569 一样,省略)============
-        // TODO: 复制 V569 的召回逻辑
-        List<Video> rovRecallRank = new ArrayList<>();
-
-        // ============ 特征提取 ============
-        Map<String, String> headVideoInfo = param.getHeadInfo();
-        List<String> vids = CommonCollectionUtils.toListDistinct(rovRecallRank, v -> String.valueOf(v.getVideoId()));
-        Map<String, Map<String, Map<String, String>>> videoBaseInfoMap = featureService.getVideoBaseInfo("", vids);
-
-        FeatureService.Feature feature = featureService.getFeatureV4(param, headVideoInfo, videoBaseInfoMap, vids);
-        Map<String, Map<String, String>> featureOriginUser = feature.getUserFeature();
-        Map<String, Map<String, Map<String, String>>> featureOriginVideo = feature.getVideoFeature();
-
-        Map<String, Map<String, String[]>> c7Map = FeatureV6.parseUCFScore(featureOriginUser.getOrDefault("alg_mid_feature_sharecf", new HashMap<>()));
-        Map<String, Map<String, String[]>> c8Map = FeatureV6.parseUCFScore(featureOriginUser.getOrDefault("alg_mid_feature_returncf", new HashMap<>()));
-        UserShareReturnProfile userProfile = parseUserProfile(featureOriginUser);
-        Map<String, String> creativeInfo = param.getCreativeInfoFeature();
-        Map<String, Map<String, String>> historyVideoMap = param.getBehaviorVideos();
-        Map<String, String> baseInfo = featureOriginUser.getOrDefault("mid_base_info", new HashMap<>());
-
-        // ============ 用户级特征(所有视频共享)============
-        Map<String, Double> userNumericFeatures = new HashMap<>();
-        Map<String, String> userStringFeatures = new HashMap<>();
-
-        // 上下文特征
-        String appType = Optional.ofNullable(param.getAppType()).map(String::valueOf).orElse("0");
-        String hotSceneType = Optional.ofNullable(param.getHotSceneType()).map(String::valueOf).orElse("other");
-        FeatureV6.getContextFeature(currentMs, appType, hotSceneType, userNumericFeatures);
-        userStringFeatures.put("ctx_app", appType);
-        userStringFeatures.put("ctx_hot", hotSceneType);
-        userStringFeatures.put("ctx_week", String.valueOf(Calendar.getInstance().get(Calendar.DAY_OF_WEEK)));
-        userStringFeatures.put("ctx_hour", String.valueOf(Calendar.getInstance().get(Calendar.HOUR_OF_DAY)));
-
-        // 用户特征
-        FeatureV6.getUserFeature(featureOriginUser, userNumericFeatures);
-        FeatureV6.getUserProfileFeature(userProfile, baseInfo, userNumericFeatures);
-        userStringFeatures.put("mid", param.getMid());
-        userStringFeatures.put("user_province", baseInfo.getOrDefault("province", ""));
-        userStringFeatures.put("user_city", baseInfo.getOrDefault("city", ""));
-        userStringFeatures.put("user_brand", baseInfo.getOrDefault("brand", ""));
-        userStringFeatures.put("user_model", baseInfo.getOrDefault("model", ""));
-        userStringFeatures.put("user_system", baseInfo.getOrDefault("system", ""));
-        userStringFeatures.put("user_channel", baseInfo.getOrDefault("user_channel", ""));
-        userStringFeatures.put("user_level", baseInfo.getOrDefault("user_level", ""));
-
-        // 创意特征
-        FeatureV6.getCreativeBaseFeature("e1", creativeInfo, userNumericFeatures);
-        userStringFeatures.put("e1_ghid", creativeInfo.getOrDefault("ghid", ""));
-        userStringFeatures.put("e1_name", creativeInfo.getOrDefault("name", ""));
-
-        // 头部视频特征
-        FeatureV6.getVideoBaseFeature("h", currentMs, headVideoInfo, userNumericFeatures);
-        putVideoStringFeatures("h", headVideoInfo, userStringFeatures);
-
-        // ============ 逐视频特征 + FG 编码 + 打分 ============
-        // 批量收集 FG 字符串,后续可批量调 EAS
-        List<String> fgFeaturesList = new ArrayList<>(rovRecallRank.size());
-
-        for (Video video : rovRecallRank) {
-            String vid = String.valueOf(video.getVideoId());
-            Map<String, String> rankInfo = videoBaseInfoMap
-                    .getOrDefault(vid, new HashMap<>())
-                    .getOrDefault("alg_vid_feature_basic_info", new HashMap<>());
-
-            // 复制用户级特征
-            Map<String, Double> numericFeatures = new HashMap<>(userNumericFeatures);
-            Map<String, String> stringFeatures = new HashMap<>(userStringFeatures);
-
-            // 当前视频特征
-            FeatureV6.getVideoBaseFeature("r", currentMs, rankInfo, numericFeatures);
-            FeatureV6.getVideoFeature(vid, featureOriginVideo, numericFeatures);
-            putVideoStringFeatures("r", rankInfo, stringFeatures);
-            stringFeatures.put("r_vid_source", rankInfo.getOrDefault("vid_source", ""));
-
-            // CF 特征
-            FeatureV6.getUserTagsCrossVideoFeature("c5", rankInfo, featureOriginUser.get("alg_mid_feature_return_tags"), numericFeatures);
-            FeatureV6.getUserTagsCrossVideoFeature("c6", rankInfo, featureOriginUser.get("alg_mid_feature_share_tags"), numericFeatures);
-            FeatureV6.getUserCFFeature("c7", vid, c7Map, numericFeatures);
-            FeatureV6.getUserCFFeature("c8", vid, c8Map, numericFeatures);
-
-            // 交叉特征
-            FeatureV6.getHeadRankVideoCrossFeature(headVideoInfo, rankInfo, numericFeatures);
-            FeatureV6.getCreativeCrossFeature("e1", creativeInfo, rankInfo, numericFeatures);
-            FeatureV6.getProfileVideoCrossFeature(currentMs, userProfile, rankInfo, historyVideoMap, numericFeatures);
-
-            // FG 编码
-            String fgFeatures = fgEncoder.encode(numericFeatures, stringFeatures);
-            fgFeaturesList.add(fgFeatures);
-        }
-
-        // ============ 调用 EAS 打分(TODO)============
-        // List<Double> scores = easClient.predict(fgFeaturesList);
-        // 临时: 用随机分数
-        for (int i = 0; i < rovRecallRank.size(); i++) {
-            Video video = rovRecallRank.get(i);
-            double score = Math.random();  // TODO: 替换为 EAS 返回的分数
-            video.setScore(score);
-            video.setSortScore(score);
-        }
-
-        rovRecallRank.sort((a, b) -> Double.compare(b.getSortScore(), a.getSortScore()));
-        return rovRecallRank;
-    }
-
-    /**
-     * 视频 ID 类特征放入 stringFeatures
-     */
-    private void putVideoStringFeatures(String prefix, Map<String, String> videoInfo, Map<String, String> stringFeatures) {
-        stringFeatures.put(prefix + "_resolution", videoInfo.getOrDefault("resolution", ""));
-        stringFeatures.put(prefix + "_time_type", videoInfo.getOrDefault("time_type", ""));
-        stringFeatures.put(prefix + "_cate2", videoInfo.getOrDefault("merge_second_level_cate", ""));
-        stringFeatures.put(prefix + "_cate1_list", videoInfo.getOrDefault("merge_first_level_cate", ""));
-        stringFeatures.put(prefix + "_festive_label1", videoInfo.getOrDefault("festive_label1", ""));
-        stringFeatures.put(prefix + "_channel", videoInfo.getOrDefault("channel", ""));
-        stringFeatures.put(prefix + "_vid_source", videoInfo.getOrDefault("vid_source", ""));
-        stringFeatures.put(prefix + "_uid", videoInfo.getOrDefault("uid", ""));
-        stringFeatures.put(prefix + "_keywords", videoInfo.getOrDefault("keywords", ""));
-        stringFeatures.put(prefix + "_merge_first_level_cate", videoInfo.getOrDefault("merge_first_level_cate", ""));
-        stringFeatures.put(prefix + "_merge_second_level_cate", videoInfo.getOrDefault("merge_second_level_cate", ""));
-    }
-}
+// package com.tzld.piaoquan.recommend.server.service.rank.strategy;
+//
+// import com.alibaba.fastjson.JSON;
+// import com.aliyun.openservices.eas.predict.http.HttpConfig;
+// import com.aliyun.openservices.eas.predict.http.PredictClient;
+// import com.aliyun.openservices.eas.predict.request.TFRequest;
+// import com.aliyun.openservices.eas.predict.response.TFResponse;
+// import com.ctrip.framework.apollo.spring.annotation.ApolloJsonValue;
+// import com.tzld.piaoquan.recommend.server.common.base.RankItem;
+// import com.tzld.piaoquan.recommend.server.model.Video;
+// import com.tzld.piaoquan.recommend.server.service.FeatureService;
+// import com.tzld.piaoquan.recommend.server.service.rank.RankParam;
+// import com.tzld.piaoquan.recommend.server.service.rank.bo.UserShareReturnProfile;
+// import com.tzld.piaoquan.recommend.server.service.rank.tansform.FeatureFGEncoder;
+// import com.tzld.piaoquan.recommend.server.service.rank.tansform.FeatureV6;
+// 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.JSONUtils;
+// import com.tzld.piaoquan.recommend.server.util.RecallUtils;
+// import lombok.extern.slf4j.Slf4j;
+// import org.springframework.beans.factory.annotation.Autowired;
+// import org.springframework.stereotype.Service;
+//
+// import javax.annotation.PostConstruct;
+// import java.util.*;
+//
+// /**
+//  * DNN 模型排序 Demo
+//  *
+//  * 流程:
+//  *   1. 特征提取: 复用 FeatureV6(跟 FM/XGB 完全一样)
+//  *   2. FG 编码: FeatureFGEncoder 按 fg_config.json 顺序编码为 chr(2) 字符串
+//  *   3. 模型打分: 调用 EAS 服务(TODO: 接入 EAS SDK)
+//  *
+//  * 特征配置: resources/fg/fg_config.json(975 特征,跟离线训练一致)
+//  */
+// @Service
+// @Slf4j
+// public class RankStrategy4RegionMergeModelDNNDemo extends RankStrategy4RegionMergeModelBasic {
+//
+//     @ApolloJsonValue("${rank.score.merge.weightv569:}")
+//     private Map<String, Double> mergeWeight;
+//
+//     @Autowired
+//     private FeatureService featureService;
+//
+//     private FeatureFGEncoder fgEncoder;
+//
+//     private PredictClient predictClient;
+//
+//     @PostConstruct
+//     public void init() {
+//         fgEncoder = new FeatureFGEncoder("fg/fg_config.json");
+//         log.info("DNN Demo 初始化完成: {} 个特征", fgEncoder.getFeatureCount());
+//
+//         predictClient = new PredictClient(new HttpConfig());
+//         predictClient.setModelName("recsys_dnn_v1_20260327");
+//         predictClient.setToken("MmEwYzVlZGFiOTM4YWM3ZTE5ZDMzNTgzY2Q5YjZlYjVjODE5ZjIzYQ==");
+//         predictClient.setEndpoint("1894469520484605.cn-hangzhou.pai-eas.aliyuncs.com");
+//
+//     }
+//
+//     @Override
+//     public List<Video> mergeAndRankRovRecall(RankParam param) {
+//         Map<String, Double> mergeWeight = this.mergeWeight != null ? this.mergeWeight : new HashMap<>(0);
+//
+//         //-------------------融-------------------
+//         //-------------------合-------------------
+//         //-------------------逻-------------------
+//         //-------------------辑-------------------
+//
+//         long currentMs = System.currentTimeMillis();
+//         Set<Long> setVideo = new HashSet<>();
+//         setVideo.add(param.getHeadVid());
+//         List<Video> rovRecallRank = new ArrayList<>();
+//         // -------------------5路特殊旧召回------------------
+//         RecallUtils.extractOldSpecialRecall(mergeWeight.getOrDefault("oldSpecialN", (double) param.getSize()).intValue(), param, setVideo, rovRecallRank);
+//         //-------------------return相似召回------------------
+//         RecallUtils.extractRecall(mergeWeight.getOrDefault("v6", 5.0).intValue(), param, ReturnVideoRecallStrategy.PUSH_FORM, setVideo, rovRecallRank);
+//         //-------------------新地域召回------------------
+//         RecallUtils.extractRecall(mergeWeight.getOrDefault("v1", 5.0).intValue(), param, RegionRealtimeRecallStrategyV1.PUSH_FORM, setVideo, rovRecallRank);
+//         //-------------------scene cf rovn------------------
+//         RecallUtils.extractRecall(mergeWeight.getOrDefault("sceneCFRovn", 5.0).intValue(), param, SceneCFRovnRecallStrategy.PUSH_FORM, setVideo, rovRecallRank);
+//         //-------------------scene cf rosn------------------
+//         RecallUtils.extractRecall(mergeWeight.getOrDefault("sceneCFRosn", 5.0).intValue(), param, SceneCFRosnRecallStrategy.PUSH_FORM, setVideo, rovRecallRank);
+//         // -------------------user cate1------------------
+//         RecallUtils.extractRecall(mergeWeight.getOrDefault("cate1RecallN", 5.0).intValue(), param, UserCate1RecallStrategy.PUSH_FORM, setVideo, rovRecallRank);
+//         // -------------------user cate2------------------
+//         RecallUtils.extractRecall(mergeWeight.getOrDefault("cate2RecallN", 5.0).intValue(), param, UserCate2RecallStrategy.PUSH_FORM, setVideo, rovRecallRank);
+//         // -------------------head province cate1------------------
+//         RecallUtils.extractRecall(mergeWeight.getOrDefault("headCate1RecallN", 3.0).intValue(), param, HeadProvinceCate1RecallStrategy.PUSH_FORM, setVideo, rovRecallRank);
+//         // -------------------head province cate2------------------
+//         RecallUtils.extractRecall(mergeWeight.getOrDefault("headCate2RecallN", 3.0).intValue(), param, HeadProvinceCate2RecallStrategy.PUSH_FORM, setVideo, rovRecallRank);
+//         //-------------------head cate2 of rovn------------------
+//         RecallUtils.extractRecall(mergeWeight.getOrDefault("headCate2Rov", 5.0).intValue(), param, HeadCate2RovRecallStrategy.PUSH_FROM, setVideo, rovRecallRank);
+//         //-------------------city rovn------------------
+//         RecallUtils.extractRecall(mergeWeight.getOrDefault("cityRov", 5.0).intValue(), param, CityRovnRecallStrategy.PUSH_FROM, setVideo, rovRecallRank);
+//         //-------------------priori province rovn------------------
+//         RecallUtils.extractRecall(mergeWeight.getOrDefault("prioriProvinceRov", 3.0).intValue(), param, PrioriProvinceRovnRecallStrategy.PUSH_FROM, setVideo, rovRecallRank);
+//         //-------------------priori province str------------------
+//         RecallUtils.extractRecall(mergeWeight.getOrDefault("prioriProvinceStr", 1.0).intValue(), param, PrioriProvinceStrRecallStrategy.PUSH_FROM, setVideo, rovRecallRank);
+//         //-------------------priori province ros------------------
+//         RecallUtils.extractRecall(mergeWeight.getOrDefault("prioriProvinceRos", 1.0).intValue(), param, PrioriProvinceRosRecallStrategy.PUSH_FROM, setVideo, rovRecallRank);
+//         //-------------------return1 cate2 ros------------------
+//         RecallUtils.extractRecall(mergeWeight.getOrDefault("return1Cate2Ros", 5.0).intValue(), param, Return1Cate2RosRecallStrategy.PUSH_FORM, setVideo, rovRecallRank);
+//         //-------------------return1 cate2 str------------------
+//         RecallUtils.extractRecall(mergeWeight.getOrDefault("return1Cate2Str", 5.0).intValue(), param, Return1Cate2StrRecallStrategy.PUSH_FORM, setVideo, rovRecallRank);
+//
+//         // 记录召回源中的视频
+//         this.rankBeforePostProcessor(rovRecallRank);
+//
+//         // ============ 特征提取 ============
+//         Map<String, String> headVideoInfo = param.getHeadInfo();
+//         List<String> vids = CommonCollectionUtils.toListDistinct(rovRecallRank, v -> String.valueOf(v.getVideoId()));
+//         Map<String, Map<String, Map<String, String>>> videoBaseInfoMap = featureService.getVideoBaseInfo("", vids);
+//
+//         FeatureService.Feature feature = featureService.getFeatureV4(param, headVideoInfo, videoBaseInfoMap, vids);
+//         Map<String, Map<String, String>> featureOriginUser = feature.getUserFeature();
+//         Map<String, Map<String, Map<String, String>>> featureOriginVideo = feature.getVideoFeature();
+//
+//         Map<String, Map<String, String[]>> c7Map = FeatureV6.parseUCFScore(featureOriginUser.getOrDefault("alg_mid_feature_sharecf", new HashMap<>()));
+//         Map<String, Map<String, String[]>> c8Map = FeatureV6.parseUCFScore(featureOriginUser.getOrDefault("alg_mid_feature_returncf", new HashMap<>()));
+//         UserShareReturnProfile userProfile = parseUserProfile(featureOriginUser);
+//         Map<String, String> creativeInfo = param.getCreativeInfoFeature();
+//         Map<String, Map<String, String>> historyVideoMap = param.getBehaviorVideos();
+//         Map<String, String> baseInfo = featureOriginUser.getOrDefault("mid_base_info", new HashMap<>());
+//
+//         // ============ 用户级特征(所有视频共享)============
+//         Map<String, Double> userNumericFeatures = new HashMap<>();
+//         Map<String, String> userStringFeatures = new HashMap<>();
+//
+//         // 上下文特征
+//         String appType = Optional.of(param.getAppType()).map(String::valueOf).orElse("0");
+//         String hotSceneType = Optional.ofNullable(param.getHotSceneType()).map(String::valueOf).orElse("other");
+//         FeatureV6.getContextFeature(currentMs, appType, hotSceneType, userNumericFeatures);
+//         userStringFeatures.put("ctx_app", appType);
+//         userStringFeatures.put("ctx_hot", hotSceneType);
+//         userStringFeatures.put("ctx_week", String.valueOf(Calendar.getInstance().get(Calendar.DAY_OF_WEEK)));
+//         userStringFeatures.put("ctx_hour", String.valueOf(Calendar.getInstance().get(Calendar.HOUR_OF_DAY)));
+//
+//         // 用户特征
+//         FeatureV6.getUserFeature(featureOriginUser, userNumericFeatures);
+//         FeatureV6.getUserProfileFeature(userProfile, baseInfo, userNumericFeatures);
+//         userStringFeatures.put("mid", param.getMid());
+//         userStringFeatures.put("user_province", baseInfo.getOrDefault("province", ""));
+//         userStringFeatures.put("user_city", baseInfo.getOrDefault("city", ""));
+//         userStringFeatures.put("user_brand", baseInfo.getOrDefault("brand", ""));
+//         userStringFeatures.put("user_model", baseInfo.getOrDefault("model", ""));
+//         userStringFeatures.put("user_system", baseInfo.getOrDefault("system", ""));
+//         userStringFeatures.put("user_channel", baseInfo.getOrDefault("user_channel", ""));
+//         userStringFeatures.put("user_level", baseInfo.getOrDefault("user_level", ""));
+//
+//         // 创意特征
+//         FeatureV6.getCreativeBaseFeature("e1", creativeInfo, userNumericFeatures);
+//         userStringFeatures.put("e1_ghid", creativeInfo.getOrDefault("ghid", ""));
+//         userStringFeatures.put("e1_name", creativeInfo.getOrDefault("name", ""));
+//
+//         // 头部视频特征
+//         FeatureV6.getVideoBaseFeature("h", currentMs, headVideoInfo, userNumericFeatures);
+//         putVideoStringFeatures("h", headVideoInfo, userStringFeatures);
+//
+//         // ============ 逐视频特征 + FG 编码 + 打分 ============
+//         // 批量收集 FG 字符串,后续可批量调 EAS
+//         List<TFRequest> tfRequests= new ArrayList<>(rovRecallRank.size());
+//         List<String> fgEncodes = new ArrayList<>(rovRecallRank.size());
+//
+//         List<RankItem> rankItems = CommonCollectionUtils.toList(rovRecallRank, RankItem::new);
+//
+//         for (RankItem rankItem : rankItems) {
+//             Video video = rankItem.getVideo();
+//
+//             String vid = String.valueOf(video.getVideoId());
+//             Map<String, String> rankInfo = videoBaseInfoMap
+//                     .getOrDefault(vid, new HashMap<>())
+//                     .getOrDefault("alg_vid_feature_basic_info", new HashMap<>());
+//
+//             // 复制用户级特征
+//             Map<String, Double> numericFeatures = new HashMap<>(userNumericFeatures);
+//             Map<String, String> stringFeatures = new HashMap<>(userStringFeatures);
+//
+//             // 当前视频特征
+//             FeatureV6.getVideoBaseFeature("r", currentMs, rankInfo, numericFeatures);
+//             FeatureV6.getVideoFeature(vid, featureOriginVideo, numericFeatures);
+//             putVideoStringFeatures("r", rankInfo, stringFeatures);
+//             stringFeatures.put("r_vid_source", rankInfo.getOrDefault("vid_source", ""));
+//
+//             // CF 特征
+//             FeatureV6.getUserTagsCrossVideoFeature("c5", rankInfo, featureOriginUser.get("alg_mid_feature_return_tags"), numericFeatures);
+//             FeatureV6.getUserTagsCrossVideoFeature("c6", rankInfo, featureOriginUser.get("alg_mid_feature_share_tags"), numericFeatures);
+//             FeatureV6.getUserCFFeature("c7", vid, c7Map, numericFeatures);
+//             FeatureV6.getUserCFFeature("c8", vid, c8Map, numericFeatures);
+//
+//             // 交叉特征
+//             FeatureV6.getHeadRankVideoCrossFeature(headVideoInfo, rankInfo, numericFeatures);
+//             FeatureV6.getCreativeCrossFeature("e1", creativeInfo, rankInfo, numericFeatures);
+//             FeatureV6.getProfileVideoCrossFeature(currentMs, userProfile, rankInfo, historyVideoMap, numericFeatures);
+//
+//             rankItem.setFeatureMapDouble(numericFeatures);
+//             rankItem.setFeatureMapString(stringFeatures);
+//
+//             tfRequests.add(fgEncoder.tfRequests(numericFeatures, stringFeatures));
+//         }
+//
+//         // ============ 调用 EAS 打分(TODO)============
+//         // List<Double> scores = easClient.predict(fgFeaturesList);
+//         // 临时: 用随机分数
+//
+//         for (int i = 0; i < rovRecallRank.size(); i++) {
+//             Video video = rovRecallRank.get(i);
+//
+//             try {
+//                 TFRequest tfRequest = tfRequests.get(i);
+//                 TFResponse tfPredict = predictClient.predict(tfRequest);
+//                 System.out.println(tfPredict);
+//             } catch (Exception e) {
+//                 log.error("dnn predict error videoId: {}", video.getVideoId(), e);
+//             }
+//         }
+//
+//         for (int i = 0; i < rovRecallRank.size(); i++) {
+//             Video video = rovRecallRank.get(i);
+//             double score = Math.random();  // TODO: 替换为 EAS 返回的分数
+//             video.setScore(score);
+//             video.setSortScore(score);
+//         }
+//
+//         rovRecallRank.sort((a, b) -> Double.compare(b.getSortScore(), a.getSortScore()));
+//         return rovRecallRank;
+//     }
+//
+//     /**
+//      * 视频 ID 类特征放入 stringFeatures
+//      */
+//     private void putVideoStringFeatures(String prefix, Map<String, String> videoInfo, Map<String, String> stringFeatures) {
+//         stringFeatures.put(prefix + "_resolution", videoInfo.getOrDefault("resolution", ""));
+//         stringFeatures.put(prefix + "_time_type", videoInfo.getOrDefault("time_type", ""));
+//         stringFeatures.put(prefix + "_cate2", videoInfo.getOrDefault("merge_second_level_cate", ""));
+//         stringFeatures.put(prefix + "_cate1_list", videoInfo.getOrDefault("merge_first_level_cate", ""));
+//         stringFeatures.put(prefix + "_festive_label1", videoInfo.getOrDefault("festive_label1", ""));
+//         stringFeatures.put(prefix + "_channel", videoInfo.getOrDefault("channel", ""));
+//         stringFeatures.put(prefix + "_vid_source", videoInfo.getOrDefault("vid_source", ""));
+//         stringFeatures.put(prefix + "_uid", videoInfo.getOrDefault("uid", ""));
+//         stringFeatures.put(prefix + "_keywords", videoInfo.getOrDefault("keywords", ""));
+//         stringFeatures.put(prefix + "_merge_first_level_cate", videoInfo.getOrDefault("merge_first_level_cate", ""));
+//         stringFeatures.put(prefix + "_merge_second_level_cate", videoInfo.getOrDefault("merge_second_level_cate", ""));
+//     }
+//
+//     private UserShareReturnProfile parseUserProfile(Map<String, Map<String, String>> userOriginInfo) {
+//         if (null != userOriginInfo) {
+//             Map<String, String> c9 = userOriginInfo.get("alg_recsys_feature_user_share_return_stat");
+//             if (null != c9 && !c9.isEmpty()) {
+//                 String c9Str = JSONUtils.toJson(c9);
+//                 if (!c9Str.isEmpty()) {
+//                     try {
+//                         return JSON.parseObject(c9Str, UserShareReturnProfile.class);
+//                     } catch (Exception e) {
+//                         log.error("parseObject user profile error! value=[{}]", c9Str, e);
+//                     }
+//                 }
+//             }
+//         }
+//         return null;
+//     }
+// }

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

@@ -217,7 +217,7 @@ public class RankStrategy4RegionMergeModelV536 extends RankStrategy4RegionMergeM
             item.getScoresMap().put("dnRovn24hW", dnRovn24hW);
             item.getScoresMap().put("dnRovn24h", dnRovn24h);
 
-            score = fmRov * (rosAdd + rosW * newNorXGBScore) * (vorAdd + vorW * vor) + c1RovnScore + b0StrScore + b0RorScore + cnRovnScore * dnRovnScore;
+            score = fmRov * (rosAdd + rosW * newNorXGBScore) * (vorAdd + vorW * vor) + c1RovnScore + b0StrScore + b0RorScore + cnRovnScore + dnRovnScore;
 
             Video video = item.getVideo();
             video.setScore(score);

+ 51 - 48
recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/rank/strategy/RankStrategy4RegionMergeModelV562.java

@@ -15,6 +15,7 @@ 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.*;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.collections4.MapUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -106,15 +107,21 @@ public class RankStrategy4RegionMergeModelV562 extends RankStrategy4RegionMergeM
         Map<String, Map<String, String>> userBehaviorVideoMap = param.getBehaviorVideos();
         Map<String, String> creativeInfo = param.getCreativeInfoFeature();
 
+
+        Map<String, String> featureMapToString = new HashMap<>();
+        this.parseStringFeatureMap(featureMapToString, param);
+        FeatureV6.putVideoStringFeatures("h", headVideoInfo, featureMapToString);
+
         // 3. 特征处理
         List<RankItem> rankItems = CommonCollectionUtils.toList(rovRecallRank, RankItem::new);
         Map<String, Float> userFeatureMap = getUserFeature(currentMs, param, creativeInfo, headVideoInfo, userProfile, featureOriginUser);
         batchGetVideoFeature(currentMs, userProfile, creativeInfo, headVideoInfo, videoBaseInfoMap,
-                newC7Map, newC8Map, featureOriginUser, userBehaviorVideoMap, featureOriginVideo, rankItems);
+                newC7Map, newC8Map, featureOriginUser, userBehaviorVideoMap, featureOriginVideo, featureMapToString, userFeatureMap, rankItems);
+
 
         // 4. 排序模型计算
         Map<String, Float> sceneFeatureMap = new HashMap<>(0);
-        List<RankItem> items = ScorerUtils.getScorerPipeline("feeds_score_config_xgb_ros_20250311.conf").scoring(sceneFeatureMap, userFeatureMap, userFeatureMap, rankItems);
+        List<RankItem> items = ScorerUtils.getScorerPipeline("feeds_score_config_xgb_ros_20250311.conf").scoring(sceneFeatureMap, userFeatureMap, rankItems);
 
         // 5. 排序公式特征
         double xgbRovNegRate = mergeWeight.getOrDefault("xgbRovNegRate", 0.059);
@@ -158,8 +165,8 @@ public class RankStrategy4RegionMergeModelV562 extends RankStrategy4RegionMergeM
             double hasReturnRovScore = Double.parseDouble(vid2MapFeature.getOrDefault(item.getVideoId() + "", new HashMap<>()).getOrDefault("rov", "0"));
             item.getScoresMap().put("hasReturnRovScore", hasReturnRovScore);
 
-            double norXGBScore = item.getScoresMap().getOrDefault("NorXGBScore", 0d);
-            double newNorXGBScore = norPowerCalibration(xgbNorPowerWeight, xgbNorPowerExp, norXGBScore);
+            double norDNNScore = item.getScoresMap().getOrDefault("NorDNNScore", 0d);
+            // double newNorXGBScore = norPowerCalibration(xgbNorPowerWeight, xgbNorPowerExp, norDNNScore);
             item.getScoresMap().put("rosAdd", rosAdd);
             item.getScoresMap().put("rosW", rosW);
 
@@ -217,7 +224,7 @@ public class RankStrategy4RegionMergeModelV562 extends RankStrategy4RegionMergeM
             item.getScoresMap().put("dnRovn24hW", dnRovn24hW);
             item.getScoresMap().put("dnRovn24h", dnRovn24h);
 
-            score = fmRov * (rosAdd + rosW * newNorXGBScore) * (vorAdd + vorW * vor) + c1RovnScore + b0StrScore + b0RorScore + cnRovnScore * dnRovnScore;
+            score = fmRov * (rosAdd + rosW * norDNNScore) * (vorAdd + vorW * vor) + c1RovnScore + b0StrScore + b0RorScore + cnRovnScore + dnRovnScore;
 
             Video video = item.getVideo();
             video.setScore(score);
@@ -251,7 +258,7 @@ public class RankStrategy4RegionMergeModelV562 extends RankStrategy4RegionMergeM
             if (MapUtils.isNotEmpty(contextInfo)) {
                 video.getMetaFeatureMap().put("context", contextInfo);
             }
-            if (Objects.nonNull(video.getRankVideoInfoMap()) && video.getRankVideoInfoMap().containsKey(video.getVideoId())){
+            if (Objects.nonNull(video.getRankVideoInfoMap()) && video.getRankVideoInfoMap().containsKey(video.getVideoId())) {
                 video.getRankVideoInfoMap().get(video.getVideoId()).setScore(score);
                 video.getRankVideoInfoMap().get(video.getVideoId()).setScoresMap(video.getScoresMap());
             }
@@ -338,15 +345,23 @@ public class RankStrategy4RegionMergeModelV562 extends RankStrategy4RegionMergeM
                                       Map<String, Map<String, String>> userOriginInfo,
                                       Map<String, Map<String, String>> historyVideoMap,
                                       Map<String, Map<String, Map<String, String>>> videoOriginInfo,
+                                      Map<String, String> featureMapToString,
+                                      Map<String, Float> userFeatureMap,
                                       List<RankItem> rankItems) {
-        if (null != rankItems && !rankItems.isEmpty()) {
+        if (CollectionUtils.isNotEmpty(rankItems)) {
             List<Future<Integer>> futures = new ArrayList<>();
             for (RankItem item : rankItems) {
                 String vid = item.getVideoId() + "";
                 Map<String, String> rankInfo = videoBaseInfoMap.getOrDefault(vid, new HashMap<>()).getOrDefault("alg_vid_feature_basic_info", new HashMap<>());
                 Future<Integer> future = ThreadPoolFactory.defaultPool().submit(() -> {
-                    item.featureMap = getVideoFeature(currentMs, vid, userProfile, creativeInfo, headInfo, rankInfo, c7Map, c8Map, userOriginInfo, historyVideoMap, videoOriginInfo);
-                    item.norFeatureMap = item.featureMap;
+                    Map<String, Float> featureMap = new HashMap<>(userFeatureMap);
+                    Map<String, Float> videoFeature = getVideoFeature(currentMs, vid, userProfile, creativeInfo, headInfo, rankInfo, c7Map, c8Map, userOriginInfo, historyVideoMap, videoOriginInfo);
+                    featureMap.putAll(videoFeature);
+                    item.featureMap = featureMap;
+
+                    Map<String, String> featureMapString = new HashMap<>(featureMapToString);
+                    FeatureV6.putVideoStringFeatures("r", rankInfo, featureMapString);
+                    item.featureMapString = featureMapString;
                     return 1;
                 });
                 futures.add(future);
@@ -419,47 +434,35 @@ public class RankStrategy4RegionMergeModelV562 extends RankStrategy4RegionMergeM
         return newScore;
     }
 
-    private Map<String, Double> findSimCateScore(String headCate2, int length) {
-        if (StringUtils.isBlank(headCate2)) {
-            return new HashMap<>();
-        }
-
-        String redisKey = String.format("alg_recsys_good_cate_pair_list:%s", headCate2);
-        String cate2Value = redisTemplate.opsForValue().get(redisKey);
-        if (StringUtils.isEmpty(cate2Value)) {
-            return new HashMap<>();
-        }
-
-        return this.parsePair(cate2Value, length);
-    }
-
-    private Map<String, Double> parsePair(String value, int length) {
-        if (StringUtils.isBlank(value)) {
-            return new HashMap<>();
-        }
-
-        String[] split = value.split("\t");
-        if (split.length != 2) {
-            return new HashMap<>();
-        }
-
-        String[] valueList = split[0].trim().split(",");
-        String[] scoreList = split[1].trim().split(",");
-        if (valueList.length != scoreList.length) {
-            return new HashMap<>();
-        }
-
-        int minLength = Math.min(length, valueList.length);
-        Map<String, Double> resultMap = new HashMap<>();
-        for (int i = 0; i < minLength; i++) {
-            resultMap.put(valueList[i].trim(), Double.parseDouble(scoreList[i].trim()));
+    private void parseStringFeatureMap(Map<String, String> featureMapToString, RankParam param) {
+        String hotSceneType = Optional.ofNullable(param.getHotSceneType()).map(String::valueOf).orElse("other");
+        String province = Optional.ofNullable(param.getProvince()).orElse("");
+        String city = Optional.ofNullable(param.getCity()).orElse("");
+        String brand = Optional.ofNullable(param.getMachineInfo()).map(MachineInfo::getBrand).orElse("");
+        String model = Optional.ofNullable(param.getMachineInfo()).map(MachineInfo::getModel).orElse("");
+        String system = Optional.ofNullable(param.getMachineInfo()).map(MachineInfo::getSystem).orElse("");
+        String channel = Optional.ofNullable(param.getChannelName()).orElse("");
+        String userLevel = "";
+        if (FeatureUtils.firstLevel(param.getUserShareDepth())) {
+            userLevel = "1st";
         }
 
-        return resultMap;
-    }
+        Map<String, String> creativeInfo = param.getCreativeInfoFeature();
+        featureMapToString.put("ctx_app", String.valueOf(param.getAppType()));
+        featureMapToString.put("ctx_hot", hotSceneType);
+        featureMapToString.put("ctx_week", String.valueOf(Calendar.getInstance().get(Calendar.DAY_OF_WEEK)));
+        featureMapToString.put("ctx_hour", String.valueOf(Calendar.getInstance().get(Calendar.HOUR_OF_DAY)));
+        featureMapToString.put("mid", param.getMid());
+        featureMapToString.put("user_province", province);
+        featureMapToString.put("user_city", city);
+        featureMapToString.put("user_brand", brand);
+        featureMapToString.put("user_model", model);
+        featureMapToString.put("user_system", system);
+        featureMapToString.put("user_channel", channel);
+        featureMapToString.put("user_level", userLevel);
+
+        featureMapToString.put("e1_ghid", creativeInfo.getOrDefault("ghid", ""));
+        featureMapToString.put("e1_name", creativeInfo.getOrDefault("name", ""));
 
-    private String findVideoMergeCate2(Map<String, Map<String, Map<String, String>>> featureOriginVideo, String vid) {
-        Map<String, String> videoInfo = featureOriginVideo.getOrDefault(vid, new HashMap<>()).getOrDefault("alg_vid_feature_basic_info", new HashMap<>());
-        return videoInfo.get("merge_second_level_cate");
     }
 }

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

@@ -217,7 +217,7 @@ public class RankStrategy4RegionMergeModelV566 extends RankStrategy4RegionMergeM
             item.getScoresMap().put("dnRovn24hW", dnRovn24hW);
             item.getScoresMap().put("dnRovn24h", dnRovn24h);
 
-            score = fmRov * (rosAdd + rosW * newNorXGBScore) * (vorAdd + vorW * vor) + c1RovnScore + b0StrScore + b0RorScore + cnRovnScore * dnRovnScore;
+            score = fmRov * (rosAdd + rosW * newNorXGBScore) * (vorAdd + vorW * vor) + c1RovnScore + b0StrScore + b0RorScore + cnRovnScore + dnRovnScore;
 
             Video video = item.getVideo();
             video.setScore(score);

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

@@ -220,7 +220,7 @@ public class RankStrategy4RegionMergeModelV568 extends RankStrategy4RegionMergeM
             item.getScoresMap().put("dnRovn24hW", dnRovn24hW);
             item.getScoresMap().put("dnRovn24h", dnRovn24h);
 
-            score = fmRov * (rosAdd + rosW * newNorXGBScore) * (vorAdd + vorW * vor) + c1RovnScore + b0StrScore + b0RorScore + cnRovnScore * dnRovnScore;
+            score = fmRov * (rosAdd + rosW * newNorXGBScore) * (vorAdd + vorW * vor) + c1RovnScore + b0StrScore + b0RorScore + cnRovnScore + dnRovnScore;
 
             Video video = item.getVideo();
             video.setScore(score);
@@ -255,7 +255,7 @@ public class RankStrategy4RegionMergeModelV568 extends RankStrategy4RegionMergeM
             if (MapUtils.isNotEmpty(contextInfo)) {
                 video.getMetaFeatureMap().put("context", contextInfo);
             }
-            if (Objects.nonNull(video.getRankVideoInfoMap()) && video.getRankVideoInfoMap().containsKey(video.getVideoId())){
+            if (Objects.nonNull(video.getRankVideoInfoMap()) && video.getRankVideoInfoMap().containsKey(video.getVideoId())) {
                 video.getRankVideoInfoMap().get(video.getVideoId()).setScore(score);
                 video.getRankVideoInfoMap().get(video.getVideoId()).setScoresMap(video.getScoresMap());
             }

+ 5 - 1
recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/rank/tansform/FeatureFGEncoder.java

@@ -119,7 +119,7 @@ public class FeatureFGEncoder {
      *   ctx_app           → null (不走 Map,从 stringFeatures 取)
      *   h_total_time      → null (不走 Map,从 stringFeatures 取)
      */
-    static String fgNameToV6Key(String fgName) {
+    public String fgNameToV6Key(String fgName) {
         // 统计特征前缀列表
         Set<String> statPrefixes = new HashSet<>(Arrays.asList(
                 "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8", "b9",
@@ -247,4 +247,8 @@ public class FeatureFGEncoder {
         }
         return names;
     }
+
+    public List<FeatureDef> getFeatureDefs() {
+        return featureDefs;
+    }
 }

+ 14 - 0
recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/rank/tansform/FeatureV6.java

@@ -600,4 +600,18 @@ public class FeatureV6 {
             }
         }
     }
+
+    public static void putVideoStringFeatures(String prefix, Map<String, String> videoInfo, Map<String, String> featureMapToString) {
+        featureMapToString.put(prefix + "_resolution", videoInfo.getOrDefault("resolution", ""));
+        featureMapToString.put(prefix + "_time_type", videoInfo.getOrDefault("time_type", ""));
+        featureMapToString.put(prefix + "_cate2", videoInfo.getOrDefault("merge_second_level_cate", ""));
+        featureMapToString.put(prefix + "_cate1_list", videoInfo.getOrDefault("merge_first_level_cate", ""));
+        featureMapToString.put(prefix + "_festive_label1", videoInfo.getOrDefault("festive_label1", ""));
+        featureMapToString.put(prefix + "_channel", videoInfo.getOrDefault("channel", ""));
+        featureMapToString.put(prefix + "_vid_source", videoInfo.getOrDefault("vid_source", ""));
+        featureMapToString.put(prefix + "_uid", videoInfo.getOrDefault("uid", ""));
+        featureMapToString.put(prefix + "_keywords", videoInfo.getOrDefault("keywords", ""));
+        featureMapToString.put(prefix + "_merge_first_level_cate", videoInfo.getOrDefault("merge_first_level_cate", ""));
+        featureMapToString.put(prefix + "_merge_second_level_cate", videoInfo.getOrDefault("merge_second_level_cate", ""));
+    }
 }

+ 0 - 1
recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/recall/RecallParam.java

@@ -26,7 +26,6 @@ public class RecallParam {
     private Long videoId;
     private String uid;
     private boolean specialRecommend;
-    private boolean appTypeSpecialRecommend;
     private Set<String> abExpCodes;
     private Integer categoryId;
 

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

@@ -89,10 +89,6 @@ public class RecallService implements ApplicationContextAware {
 
     private List<RecallStrategy> getRecallStrategy(RecallParam param) {
         List<RecallStrategy> strategies = new ArrayList<>();
-        if (param.isAppTypeSpecialRecommend()){
-            strategies.add(strategyMap.get(AppTypeSpecialRecallStrategy.class.getSimpleName()));
-            return strategies;
-        }
 
         if (2 == param.getRecommendType()) {
             strategies.add(strategyMap.get(HotReturnUvRecallStrategy.class.getSimpleName()));

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

@@ -1,77 +0,0 @@
-package com.tzld.piaoquan.recommend.server.service.recall.strategy;
-
-import com.tzld.piaoquan.recommend.server.model.Video;
-import com.tzld.piaoquan.recommend.server.service.recall.RecallParam;
-import com.tzld.piaoquan.recommend.server.service.recall.RecallStrategy;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang.math.NumberUtils;
-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.data.redis.core.ZSetOperations;
-import org.springframework.stereotype.Service;
-import org.springframework.util.CollectionUtils;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-
-
-@Slf4j
-@Service
-public class AppTypeSpecialRecallStrategy implements RecallStrategy {
-    @Autowired
-    @Qualifier("redisTemplate")
-    private RedisTemplate<String, String> redisTemplate;
-
-    public static final String LAST_VIDEO_KEY_FORMAT = "recall:apptype:last:special:%s:%s";
-    public static final String PUSH_FROM = "special_videos";
-    public static final String RECALL_KEY_FORMAT = "recall:apptype:specil:items:%s";
-
-    @Override
-    public List<Video> recall(RecallParam param) {
-
-        String lastVideoRedisKey = String.format(LAST_VIDEO_KEY_FORMAT, param.getAppType(), param.getVideoId());
-        String recallKey = String.format(RECALL_KEY_FORMAT, param.getAppType());
-        String value = redisTemplate.opsForValue().get(lastVideoRedisKey);
-        Long idx = 0L;
-        if (StringUtils.isNotBlank(value)) {
-            idx = redisTemplate.opsForZSet().reverseRank(recallKey, value);
-            if (idx == null) {
-                idx = 0L;
-            } else {
-                idx += 1;
-            }
-        }
-
-        int getSize = param.getSize() * 5;
-        int freq = 0;
-        List<Video> results = new ArrayList<>();
-        while (results.size() < param.getSize()) {
-            freq += 1;
-            if (freq > 2) {
-                break;
-            }
-            Set<ZSetOperations.TypedTuple<String>> data = redisTemplate.opsForZSet().reverseRangeWithScores(recallKey, idx, idx + getSize - 1);
-            if (CollectionUtils.isEmpty(data)) {
-                break;
-            }
-            idx += getSize;
-            data.forEach(t -> {
-                Video video = new Video();
-                video.setVideoId(NumberUtils.toLong(t.getValue(), 0L));
-                video.setRovScore(t.getScore());
-                video.setPushFrom(PUSH_FROM);
-                video.setLastVideoKey(lastVideoRedisKey);
-                results.add(video);
-            });
-        }
-        return results;
-    }
-
-    @Override
-    public String pushFrom() {
-        return PUSH_FROM;
-    }
-}

+ 93 - 0
recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/score/PAIScorer.java

@@ -0,0 +1,93 @@
+package com.tzld.piaoquan.recommend.server.service.score;
+
+import com.google.common.collect.Lists;
+import com.tzld.piaoquan.recommend.feature.domain.video.base.UserFeature;
+import com.tzld.piaoquan.recommend.server.common.base.RankItem;
+import com.tzld.piaoquan.recommend.server.service.score.model.PAIModel;
+import org.apache.commons.collections4.CollectionUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+public class PAIScorer extends AbstractScorer {
+
+    private static final int LOCAL_TIME_OUT = 300;
+    private final static Logger LOGGER = LoggerFactory.getLogger(PAIScorer.class);
+    private static final ExecutorService executorService = Executors.newFixedThreadPool(128);
+    private static final int BATCH_SIZE = 300;
+
+
+    public PAIScorer(ScorerConfigInfo scorerConfigInfo) {
+        super(scorerConfigInfo);
+    }
+
+    @Override
+    public List<RankItem> scoring(ScoreParam param, UserFeature userFeature, List<RankItem> rankItems) {
+        throw new NoSuchMethodError();
+    }
+
+    @Override
+    public List<RankItem> scoring(Map<String, Float> sceneFeatureMap, Map<String, Float> userFeatureMap, List<RankItem> rankItems) {
+        if (CollectionUtils.isEmpty(rankItems)) {
+            return rankItems;
+        }
+        long startTime = System.currentTimeMillis();
+        List<RankItem> result = rankByJava(sceneFeatureMap, userFeatureMap, rankItems);
+
+        LOGGER.debug("pai ranker time java items size={}, time={} ",
+                result.size(), System.currentTimeMillis() - startTime);
+
+        return result;
+    }
+
+    private List<RankItem> rankByJava(Map<String, Float> sceneFeatureMap, Map<String, Float> userFeatureMap, List<RankItem> rankItems) {
+        List<List<RankItem>> partition = Lists.partition(rankItems, BATCH_SIZE);
+        List<Future<List<RankItem>>> futures = new ArrayList<>();
+        for (List<RankItem> items : partition) {
+            futures.add(executorService.submit(() -> {
+                try {
+                    batchCallScore(PAIModel.getModelInstance(), items);
+                } catch (Exception e) {
+                    LOGGER.error("batchCallScore error ", e);
+                }
+                return items;
+            }));
+        }
+
+        List<RankItem> result = new ArrayList<>(rankItems.size());
+        for (Future<List<RankItem>> future : futures) {
+            try {
+                result.addAll(future.get(LOCAL_TIME_OUT, TimeUnit.MILLISECONDS));
+            } catch (Exception e) {
+                LOGGER.info("executorService.submit error ", e);
+            }
+        }
+        Collections.sort(result);
+        return result;
+    }
+
+    public void batchCallScore(final PAIModel model, final List<RankItem> rankItems) {
+        try {
+            Map<String, List<Float>> scoreMap = model.score(rankItems);
+            List<Float> returnNUvScoreList = scoreMap.get("y_return_n_uv");
+            List<Float> isShareScoreList = scoreMap.get("probs_is_share");
+            for (int i = 0; i < rankItems.size(); i++) {
+                RankItem rankItem = rankItems.get(i);
+                Float ros = returnNUvScoreList.get(i);
+                Float str = isShareScoreList.get(i);
+                rankItem.setScoreRov(Double.valueOf(str));
+                rankItem.getScoresMap().put("NorDNNScore", Double.valueOf(ros));
+            }
+        } catch (Exception e) {
+            LOGGER.error("pai scorer batch call score error ", e);
+        }
+    }
+}

+ 138 - 0
recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/score/model/PAIModel.java

@@ -1,4 +1,142 @@
 package com.tzld.piaoquan.recommend.server.service.score.model;
 
+import com.aliyun.openservices.eas.predict.http.HttpConfig;
+import com.aliyun.openservices.eas.predict.http.PredictClient;
+import com.aliyun.openservices.eas.predict.proto.PredictProtos;
+import com.aliyun.openservices.eas.predict.request.TFDataType;
+import com.aliyun.openservices.eas.predict.request.TFRequest;
+import com.aliyun.openservices.eas.predict.response.TFResponse;
+import com.tzld.piaoquan.recommend.server.common.base.RankItem;
+import com.tzld.piaoquan.recommend.server.model.Tuple4;
+import com.tzld.piaoquan.recommend.server.service.rank.tansform.FeatureFGEncoder;
+import org.apache.commons.lang3.math.NumberUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.*;
+
 public class PAIModel {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(PAIModel.class);
+
+    private final String fgConfigFilePath;
+    private final String easToken;
+    private final String easEndpoint;
+    private final String modelName;
+
+    private PredictClient predictClient;
+    private List<Tuple4<String, String, String, TFDataType>> featureKeys = new ArrayList<>();
+
+    private static final PAIModel MODEL = new PAIModel();
+
+    private PAIModel() {
+        this.fgConfigFilePath = "fg/fg_config.json";
+        this.easToken = "MmEwYzVlZGFiOTM4YWM3ZTE5ZDMzNTgzY2Q5YjZlYjVjODE5ZjIzYQ==";
+        this.easEndpoint = "1894469520484605.cn-hangzhou.pai-eas.aliyuncs.com";
+        this.modelName = "recsys_dnn_v1_20260327";
+
+        this.parseFeatureKey();
+        this.initPredictClient();
+    }
+
+
+    public static PAIModel getModelInstance() {
+        return MODEL;
+    }
+
+    private void parseFeatureKey() {
+        // 初始化fg key与特征生产时的key的映射
+        FeatureFGEncoder fgEncoder = new FeatureFGEncoder(this.fgConfigFilePath);
+        for (FeatureFGEncoder.FeatureDef featureDef : fgEncoder.getFeatureDefs()) {
+            Tuple4<String, String, String, TFDataType> featureKey = new Tuple4<>();
+            String key = Optional.ofNullable(fgEncoder.fgNameToV6Key(featureDef.feature_name))
+                    .orElse(featureDef.feature_name);
+            featureKey.setV1(key);
+            featureKey.setV2(featureDef.feature_name);
+            featureKey.setV3(featureDef.default_value);
+            featureKey.setV4(featureDef.isRaw() ? TFDataType.DT_DOUBLE : TFDataType.DT_STRING);
+            featureKeys.add(featureKey);
+        }
+    }
+
+    private void initPredictClient() {
+        predictClient = new PredictClient(new HttpConfig());
+        predictClient.setModelName(this.modelName);
+        predictClient.setToken(this.easToken);
+        predictClient.setEndpoint(this.easEndpoint);
+    }
+
+    public Map<String, List<Float>> score(List<RankItem> rankItems) {
+
+        List<String> scoreKeys = Arrays.asList("y_return_n_uv", "probs_is_share");
+        int size = rankItems.size();
+
+        try {
+
+            List<Map<String, Float>> featureMapList = new ArrayList<>(rankItems.size());
+            List<Map<String, String>> featureMapStringList = new ArrayList<>(rankItems.size());
+
+            for (RankItem rankItem : rankItems) {
+                featureMapList.add(Optional.ofNullable(rankItem.featureMap).orElse(new HashMap<>()));
+                featureMapStringList.add(Optional.ofNullable(rankItem.featureMapString).orElse(new HashMap<>()));
+            }
+
+            // 生成特征名与特征值数组的映射
+            Map<String, double[]> doubleFeatureArr = new HashMap<>();
+            Map<String, String[]> stringFeatureArr = new HashMap<>();
+            for (Tuple4<String, String, String, TFDataType> featureKey : featureKeys) {
+                TFDataType dataType = featureKey.getV4();
+                String featureName = featureKey.getV2();
+                String key = featureKey.getV1();
+                String defaultValue = featureKey.getV3();
+
+                if (TFDataType.DT_STRING.equals(dataType)) {
+                    for (int i = 0; i < size; i++) {
+                        Map<String, String> featureMapString = featureMapStringList.get(i);
+                        String[] strArr = stringFeatureArr.computeIfAbsent(featureName, s -> new String[size]);
+                        String value = featureMapString.getOrDefault(key, defaultValue);
+                        strArr[i] = value;
+                    }
+                } else {
+                    for (int i = 0; i < size; i++) {
+                        Map<String, Float> featureMap = featureMapList.get(i);
+                        double[] doubleArr = doubleFeatureArr.computeIfAbsent(featureName, s -> new double[size]);
+                        double value = NumberUtils.toDouble(defaultValue, 0d);
+                        if (featureMap.containsKey(key)) {
+                            value = featureMap.getOrDefault(key, 0f);
+                        }
+                        doubleArr[i] = value;
+                    }
+                }
+            }
+
+            TFRequest request = new TFRequest();
+            long[] shape = new long[]{size};
+            for (Tuple4<String, String, String, TFDataType> featureKey : featureKeys) {
+                String featureName = featureKey.getV2();
+                TFDataType dataType = featureKey.getV4();
+                if (TFDataType.DT_STRING.equals(dataType)) {
+                    request.addFeed(featureName, TFDataType.DT_STRING, shape, stringFeatureArr.get(featureName));
+                } else {
+                    request.addFeed(featureName, TFDataType.DT_DOUBLE, shape, doubleFeatureArr.get(featureName));
+                }
+            }
+            TFResponse response = predictClient.predict(request);
+            Map<String, PredictProtos.ArrayProto> outputsMap = response.getOutputsMap();
+            LOGGER.info("response keys: {}", outputsMap.keySet());
+            Map<String, List<Float>> resultMap = new HashMap<>();
+            for (String scoreKey : scoreKeys) {
+                resultMap.put(scoreKey, response.getFloatVals(scoreKey));
+            }
+            return resultMap;
+        } catch (Exception e) {
+            LOGGER.error("pai eas error ", e);
+            Map<String, List<Float>> resultMap = new HashMap<>();
+            for (String scoreKey : scoreKeys) {
+                resultMap.put(scoreKey, Collections.nCopies(size, 0.0f));
+            }
+            return resultMap;
+        }
+    }
+
 }

+ 3 - 446
recommend-server-service/src/main/resources/feeds_score_config_xgb_ros_20250311.conf

@@ -1,449 +1,6 @@
 scorer-config = {
-  rov-score-config = {
-     scorer-name = "com.tzld.piaoquan.recommend.server.service.score.VlogRovFMScorer"
-     scorer-priority = 96
-     model-path = "zhangbo/model_fm_for_recsys_v1_str.txt"
-  }
-  nor-score-config = {
-    scorer-name = "com.tzld.piaoquan.recommend.server.service.score.NorXGBRegressionScorer"
-    scorer-priority = 97
-    model-path = "zhangbo/model_xgb_for_recsys_v9_nor.tar.gz"
-    param = {
-      localDir = "xgboost/recsys_v9_nor"
-      features = [
-      "b0_12h@return_1_uv",
-      "b0_12h@ros1_#",
-      "b0_12h@ros_#",
-      "b0_12h@ros_minus1_#",
-      "b0_12h@ros_minus_#",
-      "b0_12h@ros_n1_#",
-      "b0_12h@ros_n_#",
-      "b0_12h@ros_one",
-      "b0_12h@rovn1_#",
-      "b0_12h@rovn_#",
-      "b0_1h@return_1_uv",
-      "b0_1h@ros1_#",
-      "b0_1h@ros_#",
-      "b0_1h@ros_minus1_#",
-      "b0_1h@ros_minus_#",
-      "b0_1h@ros_n1_#",
-      "b0_1h@ros_n_#",
-      "b0_1h@ros_one",
-      "b0_1h@rovn1_#",
-      "b0_1h@rovn_#",
-      "b0_3h@return_1_uv",
-      "b0_3h@ros1_#",
-      "b0_3h@ros_#",
-      "b0_3h@ros_minus1_#",
-      "b0_3h@ros_minus_#",
-      "b0_3h@ros_n1_#",
-      "b0_3h@ros_n_#",
-      "b0_3h@ros_one",
-      "b0_3h@rovn1_#",
-      "b0_3h@rovn_#",
-      "b0_6h@return_1_uv",
-      "b0_6h@ros1_#",
-      "b0_6h@ros_#",
-      "b0_6h@ros_minus1_#",
-      "b0_6h@ros_minus_#",
-      "b0_6h@ros_n1_#",
-      "b0_6h@ros_n_#",
-      "b0_6h@ros_one",
-      "b0_6h@rovn1_#",
-      "b0_6h@rovn_#",
-      "b10_12h@is_share",
-      "b10_12h@return_n_uv",
-      "b10_12h@ros_#",
-      "b10_12h@ros_minus_#",
-      "b10_12h@rovn_#",
-      "b10_12h@str",
-      "b10_12h@str_plus",
-      "b10_1h@is_share",
-      "b10_1h@return_n_uv",
-      "b10_1h@ros_#",
-      "b10_1h@ros_minus_#",
-      "b10_1h@rovn_#",
-      "b10_1h@str",
-      "b10_1h@str_plus",
-      "b11_12h@is_share",
-      "b11_12h@return_n_uv",
-      "b11_12h@ros_#",
-      "b11_12h@ros_minus_#",
-      "b11_12h@rovn_#",
-      "b11_12h@str",
-      "b11_12h@str_plus",
-      "b13_1h@exp",
-      "b13_1h@is_share",
-      "b13_1h@ros_#",
-      "b13_1h@ros_minus_#",
-      "b13_1h@ros_n_#",
-      "b13_1h@ros_one",
-      "b13_1h@rovn_#",
-      "b13_1h@share_cnt",
-      "b13_1h@str",
-      "b13_1h@str_plus",
-      "b13_24h@exp",
-      "b13_24h@is_share",
-      "b13_24h@ros_#",
-      "b13_24h@ros_minus_#",
-      "b13_24h@ros_n_#",
-      "b13_24h@ros_one",
-      "b13_24h@rovn_#",
-      "b13_24h@share_cnt",
-      "b13_24h@str",
-      "b13_24h@str_plus",
-      "b13_3h@exp",
-      "b13_3h@is_share",
-      "b13_3h@ros_#",
-      "b13_3h@ros_minus_#",
-      "b13_3h@ros_n_#",
-      "b13_3h@ros_one",
-      "b13_3h@rovn_#",
-      "b13_3h@share_cnt",
-      "b13_3h@str",
-      "b13_3h@str_plus",
-      "b13_72h@exp",
-      "b13_72h@is_share",
-      "b13_72h@ros_#",
-      "b13_72h@ros_minus_#",
-      "b13_72h@ros_n_#",
-      "b13_72h@ros_one",
-      "b13_72h@rovn_#",
-      "b13_72h@share_cnt",
-      "b13_72h@str",
-      "b13_72h@str_plus",
-      "b1_1h@ros_#",
-      "b1_1h@ros_minus_#",
-      "b1_1h@ros_n_#",
-      "b1_1h@ros_one",
-      "b1_1h@rovn_#",
-      "b1_24h@ros_#",
-      "b1_24h@ros_minus_#",
-      "b1_24h@ros_n_#",
-      "b1_24h@ros_one",
-      "b1_24h@rovn_#",
-      "b1_3h@ros_#",
-      "b1_3h@ros_minus_#",
-      "b1_3h@ros_n_#",
-      "b1_3h@ros_one",
-      "b1_3h@rovn_#",
-      "b1_72h@ros_#",
-      "b1_72h@ros_minus_#",
-      "b1_72h@ros_n_#",
-      "b1_72h@ros_one",
-      "b1_72h@rovn_#",
-      "b2_24h@return_n_uv",
-      "b2_24h@ros_#",
-      "b2_24h@ros_minus_#",
-      "b2_24h@ros_n_#",
-      "b2_24h@ros_one",
-      "b2_24h@rovn_#",
-      "b2_3h@return_n_uv",
-      "b2_3h@ros_#",
-      "b2_3h@ros_minus_#",
-      "b2_3h@ros_n_#",
-      "b2_3h@ros_one",
-      "b2_3h@rovn_#",
-      "b3_24h@is_share",
-      "b3_24h@return_n_uv",
-      "b3_24h@ros_#",
-      "b3_24h@ros_minus_#",
-      "b3_24h@ros_n_#",
-      "b3_24h@ros_one",
-      "b3_24h@rovn_#",
-      "b3_24h@str",
-      "b3_24h@str_plus",
-      "b3_72h@is_share",
-      "b3_72h@return_n_uv",
-      "b3_72h@ros_#",
-      "b3_72h@ros_minus_#",
-      "b3_72h@ros_n_#",
-      "b3_72h@ros_one",
-      "b3_72h@rovn_#",
-      "b3_72h@str",
-      "b3_72h@str_plus",
-      "b4_12h@is_share",
-      "b4_12h@return_n_uv",
-      "b4_12h@ros_#",
-      "b4_12h@ros_minus_#",
-      "b4_12h@ros_n_#",
-      "b4_12h@ros_one",
-      "b4_12h@rovn_#",
-      "b4_3h@is_share",
-      "b4_3h@return_n_uv",
-      "b4_3h@ros_#",
-      "b4_3h@ros_minus_#",
-      "b4_3h@ros_n_#",
-      "b4_3h@ros_one",
-      "b4_3h@rovn_#",
-      "b5_12h@exp",
-      "b5_12h@is_share",
-      "b5_12h@return_n_uv",
-      "b5_12h@ros_#",
-      "b5_12h@ros_minus_#",
-      "b5_12h@ros_n_#",
-      "b5_12h@ros_one",
-      "b5_12h@rovn_#",
-      "b5_12h@share_cnt",
-      "b5_12h@str",
-      "b5_12h@str_plus",
-      "b5_1h@exp",
-      "b5_1h@is_share",
-      "b5_1h@return_n_uv",
-      "b5_1h@ros_#",
-      "b5_1h@ros_minus_#",
-      "b5_1h@ros_n_#",
-      "b5_1h@ros_one",
-      "b5_1h@rovn_#",
-      "b5_1h@share_cnt",
-      "b5_1h@str",
-      "b5_1h@str_plus",
-      "b5_24h@exp",
-      "b5_24h@is_share",
-      "b5_24h@return_n_uv",
-      "b5_24h@ros_#",
-      "b5_24h@ros_minus_#",
-      "b5_24h@ros_n_#",
-      "b5_24h@ros_one",
-      "b5_24h@rovn_#",
-      "b5_24h@share_cnt",
-      "b5_24h@str",
-      "b5_24h@str_plus",
-      "b5_3h@exp",
-      "b5_3h@is_share",
-      "b5_3h@return_n_uv",
-      "b5_3h@ros_#",
-      "b5_3h@ros_minus_#",
-      "b5_3h@ros_n_#",
-      "b5_3h@ros_one",
-      "b5_3h@rovn_#",
-      "b5_3h@share_cnt",
-      "b5_3h@str",
-      "b5_3h@str_plus",
-      "b5_6h@exp",
-      "b5_6h@is_share",
-      "b5_6h@return_n_uv",
-      "b5_6h@ros_#",
-      "b5_6h@ros_minus_#",
-      "b5_6h@ros_n_#",
-      "b5_6h@ros_one",
-      "b5_6h@rovn_#",
-      "b5_6h@share_cnt",
-      "b5_6h@str",
-      "b5_6h@str_plus",
-      "b5_72h@exp",
-      "b5_72h@is_share",
-      "b5_72h@return_n_uv",
-      "b5_72h@ros_#",
-      "b5_72h@ros_minus_#",
-      "b5_72h@ros_n_#",
-      "b5_72h@ros_one",
-      "b5_72h@rovn_#",
-      "b5_72h@share_cnt",
-      "b5_72h@str",
-      "b5_72h@str_plus",
-      "b6_1h@is_share",
-      "b6_1h@return_n_uv",
-      "b6_1h@ros_#",
-      "b6_1h@ros_minus_#",
-      "b6_1h@ros_n_#",
-      "b6_1h@ros_one",
-      "b6_1h@rovn_#",
-      "b6_1h@str",
-      "b6_1h@str_plus",
-      "b6_24h@is_share",
-      "b6_24h@return_n_uv",
-      "b6_24h@ros_#",
-      "b6_24h@ros_minus_#",
-      "b6_24h@ros_n_#",
-      "b6_24h@ros_one",
-      "b6_24h@rovn_#",
-      "b6_24h@str",
-      "b6_24h@str_plus",
-      "b7_1h@is_share",
-      "b7_1h@return_n_uv",
-      "b7_1h@ros_#",
-      "b7_1h@ros_minus_#",
-      "b7_1h@ros_n_#",
-      "b7_1h@ros_one",
-      "b7_1h@rovn_#",
-      "b7_1h@str",
-      "b7_1h@str_plus",
-      "b7_24h@is_share",
-      "b7_24h@return_n_uv",
-      "b7_24h@ros_#",
-      "b7_24h@ros_minus_#",
-      "b7_24h@ros_n_#",
-      "b7_24h@ros_one",
-      "b7_24h@rovn_#",
-      "b7_24h@str",
-      "b7_24h@str_plus",
-      "b7_3h@is_share",
-      "b7_3h@return_n_uv",
-      "b7_3h@ros_#",
-      "b7_3h@ros_minus_#",
-      "b7_3h@ros_n_#",
-      "b7_3h@ros_one",
-      "b7_3h@rovn_#",
-      "b7_3h@str",
-      "b7_3h@str_plus",
-      "b7_72h@is_share",
-      "b7_72h@return_n_uv",
-      "b7_72h@ros_#",
-      "b7_72h@ros_minus_#",
-      "b7_72h@ros_n_#",
-      "b7_72h@ros_one",
-      "b7_72h@rovn_#",
-      "b7_72h@str",
-      "b7_72h@str_plus",
-      "b8_1h@is_share",
-      "b8_1h@return_n_uv",
-      "b8_1h@ros_#",
-      "b8_1h@ros_minus_#",
-      "b8_1h@rovn_#",
-      "b8_1h@str",
-      "b8_1h@str_plus",
-      "b8_24h@is_share",
-      "b8_24h@return_n_uv",
-      "b8_24h@ros_#",
-      "b8_24h@ros_minus_#",
-      "b8_24h@rovn_#",
-      "b8_24h@str",
-      "b8_24h@str_plus",
-      "b8_3h@is_share",
-      "b8_3h@return_n_uv",
-      "b8_3h@ros_#",
-      "b8_3h@ros_minus_#",
-      "b8_3h@rovn_#",
-      "b8_3h@str",
-      "b8_3h@str_plus",
-      "b9_1h@is_share",
-      "b9_1h@return_n_uv",
-      "b9_1h@ros_#",
-      "b9_1h@ros_minus_#",
-      "b9_1h@rovn_#",
-      "b9_1h@str",
-      "b9_1h@str_plus",
-      "b9_24h@is_share",
-      "b9_24h@return_n_uv",
-      "b9_24h@ros_#",
-      "b9_24h@ros_minus_#",
-      "b9_24h@rovn_#",
-      "b9_24h@str",
-      "b9_24h@str_plus",
-      "b9_3h@is_share",
-      "b9_3h@return_n_uv",
-      "b9_3h@ros_#",
-      "b9_3h@ros_minus_#",
-      "b9_3h@rovn_#",
-      "b9_3h@str",
-      "b9_3h@str_plus",
-      "c1_168h@is_share",
-      "c1_168h@return_n_uv",
-      "c1_168h@ros_#",
-      "c1_168h@ros_minus_#",
-      "c1_168h@ros_n_#",
-      "c1_168h@ros_one",
-      "c1_168h@rovn_#",
-      "c1_168h@str",
-      "c1_168h@str_plus",
-      "c1_72h@is_share",
-      "c1_72h@return_n_uv",
-      "c1_72h@ros_#",
-      "c1_72h@ros_minus_#",
-      "c1_72h@ros_n_#",
-      "c1_72h@ros_one",
-      "c1_72h@rovn_#",
-      "c1_72h@str",
-      "c1_72h@str_plus",
-      "c5_tags_1d@avgscore",
-      "c5_tags_1d@maxscore",
-      "c5_tags_3d@avgscore",
-      "c5_tags_3d@maxscore",
-      "c5_tags_7d@avgscore",
-      "c5_tags_7d@maxscore",
-      "c6_tags_1d@avgscore",
-      "c6_tags_1d@maxscore",
-      "c6_tags_3d@avgscore",
-      "c6_tags_3d@maxscore",
-      "c6_tags_7d@avgscore",
-      "c6_tags_7d@maxscore",
-      "c9@m_r_uv",
-      "c9@m_s_cnt",
-      "c9@r_pv",
-      "c9@r_uv",
-      "c9@ros",
-      "c9@ros_minus",
-      "c9@ros_one",
-      "c9@s_cnt",
-      "c9@s_pv",
-      "c9_c1s@mu",
-      "c9_c1s@ros",
-      "c9_c1s@ros_minus",
-      "c9_c1s@ros_one",
-      "c9_c1s@rp",
-      "c9_c1s@ru",
-      "c9_c1s@sp",
-      "c9_c2s@mu",
-      "c9_c2s@ros",
-      "c9_c2s@ros_minus",
-      "c9_c2s@ros_one",
-      "c9_c2s@rp",
-      "c9_c2s@ru",
-      "c9_c2s@sp",
-      "c9_l1s@mu",
-      "c9_l1s@ros",
-      "c9_l1s@ros_minus",
-      "c9_l1s@sp",
-      "c9_l2s@mu",
-      "c9_l2s@ros",
-      "c9_l2s@ros_minus",
-      "c9_l2s@sp",
-      "c9_lrs@1@title",
-      "c9_lrs@1@ts",
-      "c9_lrs@1@uv",
-      "c9_lrs@2@title",
-      "c9_lrs@2@ts",
-      "c9_lrs@2@uv",
-      "c9_lss@1@cnt",
-      "c9_lss@1@title",
-      "c9_lss@1@ts",
-      "c9_lss@2@cnt",
-      "c9_lss@2@title",
-      "c9_lss@2@ts",
-      "c9_mrs@1@title",
-      "c9_mrs@1@ts",
-      "c9_mrs@1@uv",
-      "c9_mrs@2@title",
-      "c9_mrs@2@ts",
-      "c9_mrs@2@uv",
-      "c9_mss@1@cnt",
-      "c9_mss@1@title",
-      "c9_mss@1@ts",
-      "c9_mss@2@cnt",
-      "c9_mss@2@title",
-      "c9_mss@2@ts",
-      "d1@ros_cf_rank",
-      "d1@ros_cf_score",
-      "d1@rov_cf_rank",
-      "d1@rov_cf_score",
-      "d2@rank",
-      "d2@score",
-      "d3@exp",
-      "d3@return_n",
-      "d3@rovn",
-      "h@bit_rate",
-      "h@total_time",
-      "h@ts",
-      "hour",
-      "hr_sim@cate2",
-      "hr_sim@cate2_list",
-      "hr_sim@keywords",
-      "hr_sim@title",
-      "r@bit_rate",
-      "r@total_time",
-      "r@ts"
-      ]
-    }
+  pai-eas-score-config = {
+     scorer-name = "com.tzld.piaoquan.recommend.server.service.score.PAIScorer"
+     scorer-priority = 100
   }
 }