| 
					
				 | 
			
			
				@@ -1,16 +1,21 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 package com.tzld.piaoquan.ad.engine.service.predict.model.threshold; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.alibaba.fastjson.JSONObject; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import com.tzld.piaoquan.ad.engine.commons.redis.AlgorithmRedisHelper; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import com.tzld.piaoquan.ad.engine.service.predict.config.AdOutV1OnlineWeightConfig; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import com.tzld.piaoquan.ad.engine.service.predict.constant.RuleRedisKeyConst; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import com.tzld.piaoquan.ad.engine.service.predict.containner.ThresholdModelContainer; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import com.tzld.piaoquan.ad.engine.service.predict.param.RuleParamHelper; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import com.tzld.piaoquan.ad.engine.service.predict.param.ThresholdPredictModelParam; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import org.apache.commons.lang3.StringUtils; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import org.springframework.beans.factory.annotation.Autowired; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import org.springframework.stereotype.Component; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import javax.annotation.PostConstruct; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import java.text.SimpleDateFormat; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import java.util.*; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+@Component 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 public class ScoreThresholdPredictModel extends ThresholdPredictModel{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     @Autowired 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -19,6 +24,26 @@ public class ScoreThresholdPredictModel extends ThresholdPredictModel{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     @Autowired 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     AlgorithmRedisHelper redisHelper; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//    Map<String,Object> configMap=new HashMap<>(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//    @PostConstruct 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//    private void initParams(){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//        Timer timer = new Timer(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//        // 半小时更新一次 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//        timer.schedule(new TimerTask() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//            @Override 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//            public void run() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//                loadConfig(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//        }, 0, 1000*60*30); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//    public void loadConfig(){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//         configMap=new HashMap<>(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     @Override 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     String initName() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         return "model"; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -34,18 +59,67 @@ public class ScoreThresholdPredictModel extends ThresholdPredictModel{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         String userScore = redisHelper.get(userKeyName); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         String itemScore = redisHelper.get(itemKeyName); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if (userScore == null || itemScore == null) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //加载配置数据 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        String configKeyNamePrefix = RuleRedisKeyConst.KEY_NAME_PREFIX_AD_OUT_MODEL_CONFIG 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                + modelKey + ":" + modelParam.getAbtestId() + ":" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//                + modelParam.getAbTestConfigTag(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                + modelParam.getAbtestParam().get("abtest_config_tag"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        String configKey = configKeyNamePrefix + ":config"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        String configStr = redisHelper.get(configKey); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Map<String, Object> configMap = new HashMap<>(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        String hitStrategy="model"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (configStr != null) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                configMap= JSONObject.parseObject(configStr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } catch (Exception e) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // 处理 JSON 解析异常 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                e.printStackTrace(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                result = ThresholdModelContainer. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        getBasicPredictModel() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        .predict(modelParam); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                hitStrategy="error"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                result.put("hit_strategy",hitStrategy); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                return result; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        boolean useBackup = Boolean.valueOf((String)configMap.getOrDefault("use_backup_key","false")); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //有数据为空且开启兜底策略 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if ( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                (StringUtils.isBlank(userScore) || StringUtils.isBlank(itemScore)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                &&useBackup) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             // If offline scores are empty, fall back to baseline logic 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             result = ThresholdModelContainer. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     getBasicPredictModel() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     .predict(modelParam); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            hitStrategy="backup"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            result.put("hit_strategy",hitStrategy); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             return result; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        String configKeyPrefix = RuleRedisKeyConst.KEY_NAME_PREFIX_AD_OUT_MODEL_CONFIG 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                + modelKey + ":" + modelParam.getAbtestParam().get("abtest_id") + ":" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                + modelParam.getAbtestParam().get("abtest_config_tag"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        String thresholdKey = configKeyPrefix + ":threshold"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        double offlineScore = Double.parseDouble(userScore) + Double.parseDouble(itemScore); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        double offlineScore ; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //处理空值逻辑 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        double threshold=(double)configMap.getOrDefault("threshold",0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if(!StringUtils.isBlank(userScore)&&!StringUtils.isBlank(itemScore)){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        }else if(StringUtils.isBlank(userScore)&&StringUtils.isBlank(itemScore)){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            itemScore="0"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            threshold=(double)configMap.getOrDefault("item_threshold", 0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        }else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            boolean isUserScoreBlank=StringUtils.isBlank(userScore); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            userScore 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if(!StringUtils.isBlank(itemScore)){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            userScore="0"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            threshold=(double)configMap.getOrDefault("user_threshold", 0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            result.put("hit_strategy","error"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        offlineScore=Double.parseDouble(userScore) + Double.parseDouble(itemScore); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         SimpleDateFormat hourFormat = new SimpleDateFormat("HH"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         SimpleDateFormat weekDayFormat = new SimpleDateFormat("u"); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -56,14 +130,25 @@ public class ScoreThresholdPredictModel extends ThresholdPredictModel{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         onlineFeatures.put("ctx_week", weekDayFormat.format(modelParam.getDate())); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         onlineFeatures.put("ctx_hour", hourFormat.format(modelParam.getDate())); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //新模型更新权重计算 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        double rankScore = 0.0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if ((Boolean) configMap.getOrDefault("use_rank_score", false)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            String rankScoreKey = "rank:score1:" + modelParam.getVideoId(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            String rankScoreStr = redisHelper.get(rankScoreKey); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (rankScoreStr != null) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                rankScore = Double.parseDouble(rankScoreStr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         double onlineScore=getOlineScore(onlineFeatures); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        double rankScoreBias = (double)configMap.getOrDefault("rank_score_bias", 0.0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         double finalScore =getFinalScore(onlineScore,offlineScore); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        String thresholdValue = redisHelper.get(thresholdKey); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        double threshold = (thresholdValue != null) ? Double.parseDouble(thresholdValue) : 0.0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        double rankScoreW = (double)configMap.getOrDefault("rank_score_w", 1.0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        double finalScoreW = (double)configMap.getOrDefault("final_score_w", 1.0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        double mergeScore = finalScoreW * finalScore + rankScoreW * (rankScore + rankScoreBias); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         int adPredict; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if (finalScore < threshold) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (mergeScore < threshold) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             // If final score is below threshold, show the ad 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             adPredict = 2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } else { 
			 |