|
@@ -1,16 +1,20 @@
|
|
|
package com.tzld.piaoquan.recommend.server.service.rank.strategy;
|
|
|
|
|
|
+import com.alibaba.fastjson.JSON;
|
|
|
import com.ctrip.framework.apollo.spring.annotation.ApolloJsonValue;
|
|
|
+import com.tzld.piaoquan.recommend.server.common.ThreadPoolFactory;
|
|
|
import com.tzld.piaoquan.recommend.server.common.base.RankItem;
|
|
|
+import com.tzld.piaoquan.recommend.server.model.MachineInfo;
|
|
|
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.UserSRBO;
|
|
|
+import com.tzld.piaoquan.recommend.server.service.rank.bo.UserShareReturnProfile;
|
|
|
import com.tzld.piaoquan.recommend.server.service.rank.extractor.ExtractVideoMergeCate;
|
|
|
+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.ExtractFeature20250218;
|
|
|
-import com.tzld.piaoquan.recommend.server.util.FeatureBucketUtils;
|
|
|
+import com.tzld.piaoquan.recommend.server.util.*;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
import org.apache.commons.collections4.MapUtils;
|
|
|
import org.apache.commons.lang3.StringUtils;
|
|
@@ -18,6 +22,8 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
|
import java.util.*;
|
|
|
+import java.util.concurrent.Future;
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
@Service
|
|
@@ -25,234 +31,137 @@ import java.util.stream.Collectors;
|
|
|
public class RankStrategy4RegionMergeModelV565 extends RankStrategy4RegionMergeModelBasic {
|
|
|
@ApolloJsonValue("${rank.score.merge.weightv565:}")
|
|
|
private Map<String, Double> mergeWeight;
|
|
|
-
|
|
|
@Autowired
|
|
|
private FeatureService featureService;
|
|
|
|
|
|
@Override
|
|
|
public List<Video> mergeAndRankRovRecall(RankParam param) {
|
|
|
-
|
|
|
- long startTime = System.currentTimeMillis();
|
|
|
-
|
|
|
Map<String, Double> mergeWeight = this.mergeWeight != null ? this.mergeWeight : new HashMap<>(0);
|
|
|
+
|
|
|
//-------------------融-------------------
|
|
|
//-------------------合-------------------
|
|
|
//-------------------逻-------------------
|
|
|
//-------------------辑-------------------
|
|
|
|
|
|
- List<Video> oldRovs = new ArrayList<>();
|
|
|
- oldRovs.addAll(extractAndSort(param, RegionHRecallStrategy.PUSH_FORM));
|
|
|
- oldRovs.addAll(extractAndSort(param, RegionHDupRecallStrategy.PUSH_FORM));
|
|
|
- oldRovs.addAll(extractAndSort(param, Region24HRecallStrategy.PUSH_FORM));
|
|
|
- oldRovs.addAll(extractAndSort(param, RegionRelative24HRecallStrategy.PUSH_FORM));
|
|
|
- oldRovs.addAll(extractAndSort(param, RegionRelative24HDupRecallStrategy.PUSH_FORM));
|
|
|
- removeDuplicate(oldRovs);
|
|
|
- int sizeReturn = param.getSize();
|
|
|
- List<Video> v0 = oldRovs.size() <= sizeReturn
|
|
|
- ? oldRovs
|
|
|
- : oldRovs.subList(0, sizeReturn);
|
|
|
+ long currentMs = System.currentTimeMillis();
|
|
|
Set<Long> setVideo = new HashSet<>();
|
|
|
- this.duplicate(setVideo, v0);
|
|
|
- setVideo.addAll(v0.stream().map(Video::getVideoId).collect(Collectors.toSet()));
|
|
|
- List<Video> rovRecallRank = new ArrayList<>(v0);
|
|
|
+ setVideo.add(param.getHeadVid());
|
|
|
+ List<Video> rovRecallRank = new ArrayList<>();
|
|
|
+ // -------------------5路特殊旧召回------------------
|
|
|
+ RecallUtils.extractOldSpecialRecall(param, setVideo, rovRecallRank);
|
|
|
//-------------------return相似召回------------------
|
|
|
- List<Video> v6 = extractAndSort(param, ReturnVideoRecallStrategy.PUSH_FORM);
|
|
|
- v6 = v6.stream().filter(r -> !setVideo.contains(r.getVideoId())).collect(Collectors.toList());
|
|
|
- v6 = v6.subList(0, Math.min(mergeWeight.getOrDefault("v6", 5.0).intValue(), v6.size()));
|
|
|
- rovRecallRank.addAll(v6);
|
|
|
- setVideo.addAll(v6.stream().map(Video::getVideoId).collect(Collectors.toSet()));
|
|
|
+ RecallUtils.extractRecall(mergeWeight.getOrDefault("v6", 5.0).intValue(), param, ReturnVideoRecallStrategy.PUSH_FORM, setVideo, rovRecallRank);
|
|
|
//-------------------新地域召回------------------
|
|
|
- List<Video> v1 = extractAndSort(param, RegionRealtimeRecallStrategyV1.PUSH_FORM);
|
|
|
- v1 = v1.stream().filter(r -> !setVideo.contains(r.getVideoId())).collect(Collectors.toList());
|
|
|
- v1 = v1.subList(0, Math.min(mergeWeight.getOrDefault("v1", 5.0).intValue(), v1.size()));
|
|
|
- rovRecallRank.addAll(v1);
|
|
|
- setVideo.addAll(v1.stream().map(Video::getVideoId).collect(Collectors.toSet()));
|
|
|
+ RecallUtils.extractRecall(mergeWeight.getOrDefault("v1", 5.0).intValue(), param, RegionRealtimeRecallStrategyV1.PUSH_FORM, setVideo, rovRecallRank);
|
|
|
//-------------------scene cf rovn------------------
|
|
|
- List<Video> sceneCFRovn = extractAndSort(param, SceneCFRovnRecallStrategy.PUSH_FORM);
|
|
|
- sceneCFRovn = sceneCFRovn.stream().filter(r -> !setVideo.contains(r.getVideoId())).collect(Collectors.toList());
|
|
|
- sceneCFRovn = sceneCFRovn.subList(0, Math.min(mergeWeight.getOrDefault("sceneCFRovn", 5.0).intValue(), sceneCFRovn.size()));
|
|
|
- rovRecallRank.addAll(sceneCFRovn);
|
|
|
- setVideo.addAll(sceneCFRovn.stream().map(Video::getVideoId).collect(Collectors.toSet()));
|
|
|
+ RecallUtils.extractRecall(mergeWeight.getOrDefault("sceneCFRovn", 5.0).intValue(), param, SceneCFRovnRecallStrategy.PUSH_FORM, setVideo, rovRecallRank);
|
|
|
//-------------------scene cf rosn------------------
|
|
|
- List<Video> sceneCFRosn = extractAndSort(param, SceneCFRosnRecallStrategy.PUSH_FORM);
|
|
|
- sceneCFRosn = sceneCFRosn.stream().filter(r -> !setVideo.contains(r.getVideoId())).collect(Collectors.toList());
|
|
|
- sceneCFRosn = sceneCFRosn.subList(0, Math.min(mergeWeight.getOrDefault("sceneCFRosn", 5.0).intValue(), sceneCFRosn.size()));
|
|
|
- rovRecallRank.addAll(sceneCFRosn);
|
|
|
- setVideo.addAll(sceneCFRosn.stream().map(Video::getVideoId).collect(Collectors.toSet()));
|
|
|
-
|
|
|
+ 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", 5.0).intValue(), param, PrioriProvinceRovnRecallStrategy.PUSH_FROM, setVideo, rovRecallRank);
|
|
|
|
|
|
//-------------------排-------------------
|
|
|
//-------------------序-------------------
|
|
|
//-------------------逻-------------------
|
|
|
//-------------------辑-------------------
|
|
|
+ Map<String, String> rtFeatureDumpsMap = dumpsRtFeature(param.getUserRTShareList());
|
|
|
|
|
|
- // 1 批量获取特征 省份参数要对齐 headvid 要传递过来!
|
|
|
- List<String> vids = CommonCollectionUtils.toListDistinct(rovRecallRank, v -> String.valueOf(v.getVideoId()));
|
|
|
-
|
|
|
+ // 1. 批量获取特征 省份参数要对齐 headvid 要传递过来!
|
|
|
// k1:视频、k2:表、k3:特征、v:特征值
|
|
|
- String provinceCn = param.getProvince().replaceAll("省$", "");
|
|
|
+ List<String> vids = CommonCollectionUtils.toListDistinct(rovRecallRank, v -> String.valueOf(v.getVideoId()));
|
|
|
String headVid = String.valueOf(param.getHeadVid());
|
|
|
- String sceneType = String.valueOf(param.getHotSceneType());
|
|
|
Map<String, Map<String, Map<String, String>>> videoBaseInfoMap = featureService.getVideoBaseInfo(headVid, vids);
|
|
|
- String appType = String.valueOf(param.getAppType());
|
|
|
- String brand = "";
|
|
|
- if (Objects.nonNull(param.getMachineInfo())) {
|
|
|
- brand = param.getMachineInfo().getBrand();
|
|
|
- }
|
|
|
-
|
|
|
- long ts = System.currentTimeMillis() / 1000;
|
|
|
-
|
|
|
- FeatureService.Feature feature = featureService.getFeatureByNewLabel(appType, sceneType, provinceCn, brand, param.getMid(), headVid, vids, videoBaseInfoMap);
|
|
|
+ FeatureService.Feature feature = featureService.getFeatureV3(param, videoBaseInfoMap, vids);
|
|
|
Map<String, Map<String, String>> featureOriginUser = feature.getUserFeature();
|
|
|
Map<String, Map<String, Map<String, String>>> featureOriginVideo = feature.getVideoFeature();
|
|
|
Map<String, String> headVideoInfo = videoBaseInfoMap.getOrDefault(headVid, new HashMap<>()).getOrDefault("alg_vid_feature_basic_info", new HashMap<>());
|
|
|
|
|
|
- // 2 特征处理
|
|
|
- Map<String, Double> userFeatureMapDouble = new HashMap<>();
|
|
|
-
|
|
|
- Map<String, String> c1 = featureOriginUser.getOrDefault("mid_global_feature_20250212", new HashMap<>());
|
|
|
- Map<String, String> c4 = featureOriginUser.getOrDefault("mid_u2u_friend_index_feature_20250212", new HashMap<>());
|
|
|
- Map<String, String> c5 = featureOriginUser.getOrDefault("alg_mid_feature_return_tags", new HashMap<>());
|
|
|
- Map<String, String> c6 = featureOriginUser.getOrDefault("alg_mid_feature_share_tags", new HashMap<>());
|
|
|
- Map<String, String> c7 = featureOriginUser.getOrDefault("alg_mid_feature_sharecf", new HashMap<>());
|
|
|
- Map<String, String> c8 = featureOriginUser.getOrDefault("alg_mid_feature_returncf", new HashMap<>());
|
|
|
-
|
|
|
- ExtractFeature20250218.handleC1(c1, userFeatureMapDouble);
|
|
|
- ExtractFeature20250218.handleC4(c4, userFeatureMapDouble);
|
|
|
- Map<String, Map<String, String[]>> c78FeatureMap = ExtractFeature20250218.handleC7ToC8(c7, c8);
|
|
|
+ // 2. 用户信息预处理
|
|
|
+ Map<String, Map<String, String[]>> newC7Map = FeatureV6.parseUCFScore(featureOriginUser.getOrDefault("alg_mid_feature_sharecf", new HashMap<>()));
|
|
|
+ Map<String, Map<String, String[]>> newC8Map = FeatureV6.parseUCFScore(featureOriginUser.getOrDefault("alg_mid_feature_returncf", new HashMap<>()));
|
|
|
+ UserShareReturnProfile userProfile = parseUserProfile(featureOriginUser);
|
|
|
+ Map<String, Map<String, String>> userBehaviorVideoMap = getUserBehaviorVideoMap(userProfile);
|
|
|
|
|
|
+ // 3. 特征处理
|
|
|
List<RankItem> rankItems = CommonCollectionUtils.toList(rovRecallRank, RankItem::new);
|
|
|
- for (RankItem item : rankItems) {
|
|
|
-
|
|
|
- String vidStr = String.valueOf(item.getVideoId());
|
|
|
-
|
|
|
- Map<String, Double> featureMap = new HashMap<>();
|
|
|
- Map<String, String> v1Feature = videoBaseInfoMap.getOrDefault(vidStr, new HashMap<>()).getOrDefault("alg_vid_feature_basic_info", new HashMap<>());
|
|
|
- Map<String, Map<String, String>> videoFeatureMap = featureOriginVideo.getOrDefault(vidStr, new HashMap<>());
|
|
|
- Map<String, String> b1 = videoFeatureMap.getOrDefault("alg_vid_global_feature_20250212", new HashMap<>());
|
|
|
- Map<String, String> b2 = videoFeatureMap.getOrDefault("alg_vid_recommend_exp_feature_20250212", new HashMap<>());
|
|
|
- Map<String, String> b3 = videoFeatureMap.getOrDefault("alg_vid_recommend_flowpool_exp_feature_20250212", new HashMap<>());
|
|
|
- Map<String, String> b4 = videoFeatureMap.getOrDefault("alg_vid_apptype_recommend_exp_feature_20250212", new HashMap<>());
|
|
|
- Map<String, String> b5 = videoFeatureMap.getOrDefault("alg_vid_province_recommend_exp_feature_20250212", new HashMap<>());
|
|
|
- Map<String, String> b6 = videoFeatureMap.getOrDefault("alg_vid_brand_recommend_exp_feature_20250212", new HashMap<>());
|
|
|
- Map<String, String> b7 = videoFeatureMap.getOrDefault("alg_vid_hotsencetype_recommend_exp_feature_20250212", new HashMap<>());
|
|
|
- Map<String, String> b8 = videoFeatureMap.getOrDefault("alg_merge_cate1_recommend_exp_feature_20250212", new HashMap<>());
|
|
|
- Map<String, String> b9 = videoFeatureMap.getOrDefault("alg_merge_cate2_recommend_exp_feature_20250212", new HashMap<>());
|
|
|
- Map<String, String> b10 = videoFeatureMap.getOrDefault("alg_channel_recommend_exp_feature_20250212", new HashMap<>());
|
|
|
- Map<String, String> b11 = videoFeatureMap.getOrDefault("alg_festive_recommend_exp_feature_20250212", new HashMap<>());
|
|
|
- Map<String, String> b12 = videoFeatureMap.getOrDefault("alg_vid_long_period_recommend_exp_feature_20250212", new HashMap<>());
|
|
|
- Map<String, String> b13 = videoFeatureMap.getOrDefault("alg_video_unionid_recommend_exp_feature_20250212", new HashMap<>());
|
|
|
-
|
|
|
- Map<String, String> c2 = videoFeatureMap.getOrDefault("mid_merge_cate1_feature_20250212", new HashMap<>());
|
|
|
- Map<String, String> c3 = videoFeatureMap.getOrDefault("mid_merge_cate2_feature_20250212", new HashMap<>());
|
|
|
-
|
|
|
- Map<String, String> d1 = videoFeatureMap.getOrDefault("scene_type_vid_cf_feature_20250212", new HashMap<>());
|
|
|
- Map<String, String> d2 = videoFeatureMap.getOrDefault("vid_click_cf_feature_20250212", new HashMap<>());
|
|
|
- Map<String, String> d3 = videoFeatureMap.getOrDefault("alg_recsys_feature_cf_i2i_v2", new HashMap<>());
|
|
|
-
|
|
|
- Map<String, Map<String, String>> b2ToB11AndB13Map = new HashMap<>();
|
|
|
- b2ToB11AndB13Map.put("b2", b2);
|
|
|
- b2ToB11AndB13Map.put("b3", b3);
|
|
|
- b2ToB11AndB13Map.put("b4", b4);
|
|
|
- b2ToB11AndB13Map.put("b5", b5);
|
|
|
- b2ToB11AndB13Map.put("b6", b6);
|
|
|
- b2ToB11AndB13Map.put("b7", b7);
|
|
|
- b2ToB11AndB13Map.put("b8", b8);
|
|
|
- b2ToB11AndB13Map.put("b9", b9);
|
|
|
- b2ToB11AndB13Map.put("b10", b10);
|
|
|
- b2ToB11AndB13Map.put("b11", b11);
|
|
|
- b2ToB11AndB13Map.put("b13", b13);
|
|
|
-
|
|
|
- ExtractFeature20250218.handleB1(b1, featureMap);
|
|
|
- ExtractFeature20250218.handleB12(b12, featureMap);
|
|
|
- ExtractFeature20250218.handleB2ToB11AndB13(b2ToB11AndB13Map, featureMap);
|
|
|
- ExtractFeature20250218.handleC2ToC3(c2, c3, featureMap);
|
|
|
- ExtractFeature20250218.useC7ToC8(c78FeatureMap, vidStr, featureMap);
|
|
|
- ExtractFeature20250218.handleC5ToC6(c5, c6, v1Feature, featureMap);
|
|
|
- ExtractFeature20250218.handleD1(d1, featureMap);
|
|
|
- ExtractFeature20250218.handleD2(d2, featureMap);
|
|
|
- ExtractFeature20250218.handleD3(d3, featureMap);
|
|
|
- ExtractFeature20250218.handleVideoBasicFeature(v1Feature, ts, featureMap);
|
|
|
- ExtractFeature20250218.handleVideoSimilarity(v1Feature, headVideoInfo, featureMap);
|
|
|
-
|
|
|
- item.featureMapDouble = featureMap;
|
|
|
- }
|
|
|
-
|
|
|
- // 3 连续值特征分桶
|
|
|
- Map<String, Float> userFeatureMap = FeatureBucketUtils.bucketFeatureV2("20250218_bucket_322.txt", userFeatureMapDouble);
|
|
|
- for (RankItem item : rankItems) {
|
|
|
- Map<String, Double> featureMapDouble = item.featureMapDouble;
|
|
|
- item.featureMap = FeatureBucketUtils.bucketFeatureV2("20250218_bucket_322.txt", featureMapDouble);
|
|
|
- }
|
|
|
+ Map<String, Float> userFeatureMap = getUserFeature(currentMs, param, headVideoInfo, userProfile, featureOriginUser);
|
|
|
+ batchGetVideoFeature(currentMs, userProfile, headVideoInfo, videoBaseInfoMap,
|
|
|
+ newC7Map, newC8Map, featureOriginUser, userBehaviorVideoMap, featureOriginVideo, rankItems);
|
|
|
|
|
|
-
|
|
|
- // 4.1 排序模型计算 - str
|
|
|
+ // 4. 排序模型计算
|
|
|
Map<String, Float> sceneFeatureMap = new HashMap<>(0);
|
|
|
- List<RankItem> items = ScorerUtils.getScorerPipeline("feeds_score_config_xgb_str_20250228.conf").scoring(sceneFeatureMap, userFeatureMap, rankItems);
|
|
|
- // 4.2 排序模型计算 - ros
|
|
|
- this.addRosScore(rankItems, userFeatureMapDouble, sceneFeatureMap);
|
|
|
-
|
|
|
- // 5 排序公式特征
|
|
|
- double xgbRovNegRate = mergeWeight.getOrDefault("xgbRovNegRate", 0.05);
|
|
|
-
|
|
|
- double calcVorMode = mergeWeight.getOrDefault("calcVorMode", 3d);
|
|
|
- double calcRosMode = mergeWeight.getOrDefault("calcRosMode", 0d);
|
|
|
- double calcStrMode = mergeWeight.getOrDefault("calcStrMode", 3d);
|
|
|
-
|
|
|
-
|
|
|
- double rosAdd = mergeWeight.getOrDefault("ros_add", 0d);
|
|
|
- double vorAdd = mergeWeight.getOrDefault("vor_add", 0d);
|
|
|
+ List<RankItem> items = ScorerUtils.getScorerPipeline("feeds_score_config_fm_xgb_20250317.conf").scoring(sceneFeatureMap, userFeatureMap, userFeatureMap, rankItems);
|
|
|
+
|
|
|
+ // 5. 排序公式特征
|
|
|
+ double xgbRovNegRate = mergeWeight.getOrDefault("xgbRovNegRate", 0.059);
|
|
|
+ double xgbNorPowerWeight = mergeWeight.getOrDefault("xgbNorPowerWeight", 1.22);
|
|
|
+ double xgbNorPowerExp = mergeWeight.getOrDefault("xgbNorPowerExp", 1.15);
|
|
|
+ Map<String, Map<String, String>> vid2MapFeature = this.getVideoRedisFeature(vids, "redis:vid_hasreturn_vor:");
|
|
|
+
|
|
|
+ // 获取权重
|
|
|
+ Map<String, Double> cate2Coefficient = new HashMap<>();
|
|
|
+ double cate2CoefficientFunc = mergeWeight.getOrDefault("cate2CoefficientFunc", 0d);
|
|
|
+ if (cate2CoefficientFunc == 1d) {
|
|
|
+ String headVidStr = String.valueOf(param.getHeadVid());
|
|
|
+ String mergeCate2 = this.findVideoMergeCate2(videoBaseInfoMap, headVidStr);
|
|
|
+ Double length = mergeWeight.getOrDefault("cate2CoefficientLength", 10000d);
|
|
|
+ Map<String, Double> simCateScore = this.findSimCateScore(mergeCate2, length.intValue());
|
|
|
+ cate2Coefficient.putAll(simCateScore);
|
|
|
+ }
|
|
|
+ Double cate2CoefficientDenominator = mergeWeight.getOrDefault("cate2CoefficientDenominator", 1d);
|
|
|
+ Map<String, String> regionMap = getUserRegion(param);
|
|
|
|
|
|
- Map<String, Map<String, String>> vid2MapFeature = this.getVideoRedisFeature(vids, "redis:vid_hasreturn_vor_4share:");
|
|
|
List<Video> result = new ArrayList<>();
|
|
|
for (RankItem item : items) {
|
|
|
+ String vidMergeCate2 = this.findVideoMergeCate2(videoBaseInfoMap, String.valueOf(item.getVideoId()));
|
|
|
+
|
|
|
+ double strPlusCalibrationCoefficient = this.calcStrPlusCalibrationCoefficientByMergeCate2(vidMergeCate2);
|
|
|
+
|
|
|
double score;
|
|
|
double fmRovOrigin = item.getScoreRov();
|
|
|
item.getScoresMap().put("fmRovOrigin", fmRovOrigin);
|
|
|
- double fmRov = restoreScore(fmRovOrigin, xgbRovNegRate);
|
|
|
- fmRov = this.handleStr(fmRov, calcStrMode, item, mergeWeight);
|
|
|
+ double fmRovCoefficientBefore = restoreScore(fmRovOrigin, xgbRovNegRate);
|
|
|
+ item.getScoresMap().put("fmRovCoefficientBefore", fmRovCoefficientBefore);
|
|
|
|
|
|
+ double fmRov = fmRovCoefficientBefore * strPlusCalibrationCoefficient;
|
|
|
item.getScoresMap().put("fmRov", fmRov);
|
|
|
- item.getScoresMap().put("xgbRovNegRate", xgbRovNegRate);
|
|
|
- item.getScoresMap().put("calcStrMode", calcStrMode);
|
|
|
-
|
|
|
- Map<String, String> vidFeatureMap = vid2MapFeature.getOrDefault(String.valueOf(item.getVideoId()), new HashMap<>());
|
|
|
-
|
|
|
-
|
|
|
- double originScoreRos = item.getScoreRos();
|
|
|
- double ros = this.handleRos(originScoreRos, calcRosMode, item, mergeWeight);
|
|
|
-
|
|
|
- item.getScoresMap().put("RosXGBScore", originScoreRos);
|
|
|
- item.getScoresMap().put("hasReturnRovScore", ros);
|
|
|
- item.getScoresMap().put("calcRosMode", calcRosMode);
|
|
|
-
|
|
|
-
|
|
|
- double vor24h = Double.parseDouble(vidFeatureMap.getOrDefault("vor_24h", "0"));
|
|
|
- double vor = this.handleVor(vor24h, calcVorMode, item, mergeWeight);
|
|
|
-
|
|
|
- item.getScoresMap().put("originVor", vor24h);
|
|
|
+ item.getScoresMap().put("strPlusCalibrationCoefficient", fmRov);
|
|
|
+ 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 vor = Double.parseDouble(vid2MapFeature.getOrDefault(item.getVideoId() + "", new HashMap<>()).getOrDefault("vor", "0"));
|
|
|
item.getScoresMap().put("vor", vor);
|
|
|
- item.getScoresMap().put("calcVorMode", calcVorMode);
|
|
|
|
|
|
+ Double scoreCoefficient = cate2Coefficient.getOrDefault(vidMergeCate2, 0d);
|
|
|
+ item.getScoresMap().put("scoreCoefficient", scoreCoefficient);
|
|
|
+ item.getScoresMap().put("cate2CoefficientDenominator", cate2CoefficientDenominator);
|
|
|
|
|
|
- item.getScoresMap().put("rosAdd", rosAdd);
|
|
|
- item.getScoresMap().put("vorAdd", vorAdd);
|
|
|
- score = fmRov * (rosAdd + ros) * (vorAdd + vor);
|
|
|
+ score = fmRov * (0.1 + newNorXGBScore) * (0.1 + vor) * (1 + scoreCoefficient / cate2CoefficientDenominator);
|
|
|
|
|
|
Video video = item.getVideo();
|
|
|
video.setScore(score);
|
|
|
video.setSortScore(score);
|
|
|
video.setScoresMap(item.getScoresMap());
|
|
|
+ // video.setAllFeatureMap(item.getAllFeatureMap());
|
|
|
|
|
|
- String mergeCate2 = ExtractVideoMergeCate.parseMergeCate2(String.valueOf(item.getVideoId()), featureOriginVideo);
|
|
|
+ String mergeCate2 = ExtractVideoMergeCate.parseMergeCate2(String.valueOf(item.getVideoId()), videoBaseInfoMap);
|
|
|
if (StringUtils.isNotBlank(mergeCate2)) {
|
|
|
video.getMergeCateList().add(mergeCate2);
|
|
|
}
|
|
|
|
|
|
- Map<String, String> allFeatureMap = new HashMap<>();
|
|
|
- item.getFeatureMapDouble().forEach((key, value) -> allFeatureMap.put(key, String.valueOf(value)));
|
|
|
- video.setAllFeatureMap(allFeatureMap);
|
|
|
-
|
|
|
if (MapUtils.isNotEmpty(feature.getVideoFeature()) && MapUtils.isNotEmpty(feature.getVideoFeature().get(item.getVideoId() + ""))) {
|
|
|
video.getMetaFeatureMap().putAll(feature.getVideoFeature().get(item.getVideoId() + ""));
|
|
|
}
|
|
@@ -265,45 +174,246 @@ public class RankStrategy4RegionMergeModelV565 extends RankStrategy4RegionMergeM
|
|
|
if (MapUtils.isNotEmpty(feature.getUserFeature())) {
|
|
|
video.getMetaFeatureMap().putAll(feature.getUserFeature());
|
|
|
}
|
|
|
-
|
|
|
+ if (null != rtFeatureDumpsMap && !rtFeatureDumpsMap.isEmpty()) {
|
|
|
+ video.getMetaFeatureMap().put("rt", rtFeatureDumpsMap);
|
|
|
+ }
|
|
|
+ if (MapUtils.isNotEmpty(param.getCreativeInfoFeature())) {
|
|
|
+ video.getMetaFeatureMap().put("creativeInfo", param.getCreativeInfoFeature());
|
|
|
+ }
|
|
|
+ if (MapUtils.isNotEmpty(regionMap)) {
|
|
|
+ video.getMetaFeatureMap().put("region", regionMap);
|
|
|
+ }
|
|
|
result.add(video);
|
|
|
}
|
|
|
ExtractVideoMergeCate.addOtherParam(result, videoBaseInfoMap);
|
|
|
result.sort(Comparator.comparingDouble(o -> -o.getSortScore()));
|
|
|
+ return result;
|
|
|
+ }
|
|
|
|
|
|
- log.info("565 run time: {}", (System.currentTimeMillis() - startTime));
|
|
|
+ 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;
|
|
|
+ }
|
|
|
|
|
|
- return result;
|
|
|
+ private Map<String, Map<String, String>> getUserBehaviorVideoMap(UserShareReturnProfile userProfile) {
|
|
|
+ Set<String> vidSet = new HashSet<>();
|
|
|
+ if (null != userProfile) {
|
|
|
+ for (List<UserSRBO> list : Arrays.asList(userProfile.getM_s_s(), userProfile.getM_r_s(), userProfile.getL_s_s(), userProfile.getL_r_s())) {
|
|
|
+ if (null != list) {
|
|
|
+ for (UserSRBO u : list) {
|
|
|
+ if (null != u) {
|
|
|
+ vidSet.add(u.getId() + "");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ Map<String, Map<String, String>> historyVideoMap = new HashMap<>();
|
|
|
+ if (!vidSet.isEmpty()) {
|
|
|
+ Map<String, Map<String, Map<String, String>>> videoMap = featureService.getVideoBaseInfo("", new ArrayList<>(vidSet));
|
|
|
+ if (null != videoMap && !videoMap.isEmpty()) {
|
|
|
+ for (Map.Entry<String, Map<String, Map<String, String>>> entry : videoMap.entrySet()) {
|
|
|
+ String vid = entry.getKey();
|
|
|
+ Map<String, Map<String, String>> map = entry.getValue();
|
|
|
+ if (null != map && map.containsKey("alg_vid_feature_basic_info")) {
|
|
|
+ historyVideoMap.put(vid, map.get("alg_vid_feature_basic_info"));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return historyVideoMap;
|
|
|
+ }
|
|
|
+
|
|
|
+ private Map<String, Float> getUserFeature(long currentMs, RankParam param, Map<String, String> headInfo, UserShareReturnProfile userProfile, Map<String, Map<String, String>> userOriginInfo) {
|
|
|
+ Map<String, Double> featMap = new HashMap<>();
|
|
|
+ // context feature
|
|
|
+ String appType = String.valueOf(param.getAppType());
|
|
|
+ String hotSceneType = String.valueOf(param.getHotSceneType());
|
|
|
+ FeatureV6.getContextFeature(currentMs, appType, hotSceneType, featMap);
|
|
|
+
|
|
|
+ // head video feature
|
|
|
+ FeatureV6.getVideoBaseFeature("h", currentMs, headInfo, featMap);
|
|
|
+
|
|
|
+ // user feature
|
|
|
+ Map<String, String> baseInfo = getUserBaseInfo(param);
|
|
|
+ FeatureV6.getUserFeature(userOriginInfo, featMap);
|
|
|
+ FeatureV6.getUserProfileFeature(userProfile, baseInfo, featMap);
|
|
|
+
|
|
|
+ return FeatureBucketUtils.noBucketFeature(featMap);
|
|
|
+ }
|
|
|
+
|
|
|
+ private Map<String, Float> getVideoFeature(long currentMs, String vid,
|
|
|
+ UserShareReturnProfile userProfile,
|
|
|
+ Map<String, String> headInfo, Map<String, String> rankInfo,
|
|
|
+ Map<String, Map<String, String[]>> c7Map,
|
|
|
+ Map<String, Map<String, String[]>> c8Map,
|
|
|
+ Map<String, Map<String, String>> userOriginInfo,
|
|
|
+ Map<String, Map<String, String>> historyVideoMap,
|
|
|
+ Map<String, Map<String, Map<String, String>>> videoOriginInfo) {
|
|
|
+ Map<String, Double> featMap = new HashMap<>();
|
|
|
+ // user & video feature
|
|
|
+ FeatureV6.getUserTagsCrossVideoFeature("c5", rankInfo, userOriginInfo.get("alg_mid_feature_return_tags"), featMap);
|
|
|
+ FeatureV6.getUserTagsCrossVideoFeature("c6", rankInfo, userOriginInfo.get("alg_mid_feature_share_tags"), featMap);
|
|
|
+ FeatureV6.getUserCFFeature("c7", vid, c7Map, featMap);
|
|
|
+ FeatureV6.getUserCFFeature("c8", vid, c8Map, featMap);
|
|
|
+
|
|
|
+ // rank video feature
|
|
|
+ FeatureV6.getVideoBaseFeature("r", currentMs, rankInfo, featMap);
|
|
|
+ FeatureV6.getVideoFeature(vid, videoOriginInfo, featMap);
|
|
|
+
|
|
|
+ // head&rank cross feature
|
|
|
+ FeatureV6.getHeadRankVideoCrossFeature(headInfo, rankInfo, featMap);
|
|
|
+
|
|
|
+ // user profile & rank cross
|
|
|
+ FeatureV6.getProfileVideoCrossFeature(currentMs, userProfile, rankInfo, historyVideoMap, featMap);
|
|
|
+
|
|
|
+ return FeatureBucketUtils.noBucketFeature(featMap);
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * ros模型打分
|
|
|
- */
|
|
|
- private void addRosScore(List<RankItem> rankItems, Map<String, Double> userFeatureMapDouble, Map<String, Float> sceneFeatureMap) {
|
|
|
- List<RankItem> rosRankItems = new ArrayList<>(rankItems.size());
|
|
|
- for (RankItem rankItem : rankItems) {
|
|
|
- RankItem rosRankItem = new RankItem(rankItem.getVideo());
|
|
|
- // 复用了str的二分类xgboost score,所以和str保持一致
|
|
|
- rosRankItem.featureMap = FeatureBucketUtils.bucketFeatureV2("20250306_ros_bucket_229.txt", rankItem.featureMapDouble);
|
|
|
- rosRankItems.add(rosRankItem);
|
|
|
+ private void batchGetVideoFeature(long currentMs,
|
|
|
+ UserShareReturnProfile userProfile,
|
|
|
+ Map<String, String> headInfo,
|
|
|
+ Map<String, Map<String, Map<String, String>>> videoBaseInfoMap,
|
|
|
+ Map<String, Map<String, String[]>> c7Map,
|
|
|
+ Map<String, Map<String, String[]>> c8Map,
|
|
|
+ Map<String, Map<String, String>> userOriginInfo,
|
|
|
+ Map<String, Map<String, String>> historyVideoMap,
|
|
|
+ Map<String, Map<String, Map<String, String>>> videoOriginInfo,
|
|
|
+ List<RankItem> rankItems) {
|
|
|
+ if (null != rankItems && !rankItems.isEmpty()) {
|
|
|
+ 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, headInfo, rankInfo, c7Map, c8Map, userOriginInfo, historyVideoMap, videoOriginInfo);
|
|
|
+ item.norFeatureMap = item.featureMap;
|
|
|
+ return 1;
|
|
|
+ });
|
|
|
+ futures.add(future);
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ for (Future<Integer> future : futures) {
|
|
|
+ future.get(1000, TimeUnit.MILLISECONDS);
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("get feature error", e);
|
|
|
+ }
|
|
|
+ // 超时后取消
|
|
|
+ for (Future<Integer> future : futures) {
|
|
|
+ try {
|
|
|
+ if (!future.isDone()) {
|
|
|
+ future.cancel(true);
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("cancel feature error", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
- Map<String, Float> userFeatureMap = FeatureBucketUtils.bucketFeatureV2("20250306_ros_bucket_229.txt", userFeatureMapDouble);
|
|
|
- ScorerUtils.getScorerPipeline("feeds_score_config_xgb_ros_binary_20250319.conf").scoring(sceneFeatureMap, userFeatureMap, rosRankItems);
|
|
|
+ }
|
|
|
|
|
|
- // 将ros分数补充到之前的列表中
|
|
|
- Map<Long, RankItem> vidRosMap = new HashMap<>(rosRankItems.size());
|
|
|
- for (RankItem rosRankItem : rosRankItems) {
|
|
|
- vidRosMap.put(rosRankItem.getVideoId(), rosRankItem);
|
|
|
+ private Map<String, String> getUserBaseInfo(RankParam param) {
|
|
|
+ Map<String, String> baseInfo = new HashMap<>();
|
|
|
+ String province = param.getProvince();
|
|
|
+ if (null != province && !province.isEmpty()) {
|
|
|
+ baseInfo.put("province", province.replaceAll("省$", ""));
|
|
|
}
|
|
|
|
|
|
- for (RankItem rankItem : rankItems) {
|
|
|
- if (vidRosMap.containsKey(rankItem.getVideoId())) {
|
|
|
- RankItem rosRankItem = vidRosMap.get(rankItem.getVideoId());
|
|
|
+ String city = param.getCity();
|
|
|
+ if (null != city && !city.isEmpty()) {
|
|
|
+ baseInfo.put("city", city.replaceAll("市$", ""));
|
|
|
+ }
|
|
|
|
|
|
- // 复用了rov的xgboost model类,所以取scoreRov的值
|
|
|
- rankItem.setScoreRos(rosRankItem.getScoreRov());
|
|
|
- rankItem.getScoresMap().put("RosXGBScore", rosRankItem.getScoreRov());
|
|
|
+ MachineInfo machineInfo = param.getMachineInfo();
|
|
|
+ if (null != machineInfo) {
|
|
|
+ String model = machineInfo.getModel();
|
|
|
+ if (null != model && !model.isEmpty()) {
|
|
|
+ baseInfo.put("model", model);
|
|
|
+ }
|
|
|
+ String brand = machineInfo.getBrand();
|
|
|
+ if (null != brand && !brand.isEmpty()) {
|
|
|
+ baseInfo.put("brand", brand);
|
|
|
+ }
|
|
|
+ String system = machineInfo.getSystem();
|
|
|
+ if (null != system && !system.isEmpty()) {
|
|
|
+ baseInfo.put("system", system);
|
|
|
}
|
|
|
}
|
|
|
+ String userChannel = param.getChannelName();
|
|
|
+ if (null != userChannel && !userChannel.isEmpty()) {
|
|
|
+ baseInfo.put("user_channel", userChannel);
|
|
|
+ }
|
|
|
+ if (FeatureUtils.firstLevel(param.getUserShareDepth())) {
|
|
|
+ baseInfo.put("user_level", "1st");
|
|
|
+ }
|
|
|
+ return baseInfo;
|
|
|
+ }
|
|
|
+
|
|
|
+ private double norPowerCalibration(double weight, double exp, double score) {
|
|
|
+ double newScore = weight * Math.pow(score, exp);
|
|
|
+ if (newScore > 100) {
|
|
|
+ newScore = 100;
|
|
|
+ } else if (newScore < score) {
|
|
|
+ newScore = score;
|
|
|
+ }
|
|
|
+ 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()));
|
|
|
+ }
|
|
|
+
|
|
|
+ return resultMap;
|
|
|
+ }
|
|
|
+
|
|
|
+ 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");
|
|
|
}
|
|
|
}
|