10 Commits 5eb61f123e ... 411e63d003

Autor SHA1 Mensaje Fecha
  yaodaoseng 411e63d003 Merge branch 'master' into 20250814_feature_fjy_crowdlayerenumadd hace 5 días
  zhaohaipeng f2c31a4be8 Merge branch 'feature_20250814_user_layer_4l' of algorithm/ad-engine into master hace 5 días
  zhaohaipeng 5ba6acd785 feat:修改获取用户分群逻辑 hace 5 días
  xueyiming 742e5560b6 Merge branch 'dev-xym-update-layer' of algorithm/ad-engine into master hace 5 días
  xueyiming fae9b6a229 切换人群 hace 5 días
  xueyiming 4ece1fff92 Merge branch 'refs/heads/master' into dev-xym-update-layer hace 5 días
  xueyiming b2c9d38076 切换人群 hace 5 días
  xueyiming 8ee229fda1 切换人群 hace 5 días
  zhaohaipeng ddcc77100b Merge branch 'feature_20250814_user_layer_4l' of algorithm/ad-engine into master hace 5 días
  zhaohaipeng 3033772d22 feat:修改获取用户分群逻辑 hace 5 días

+ 5 - 24
ad-engine-server/src/main/java/com/tzld/piaoquan/ad/engine/server/controller/AdRecommendController.java

@@ -10,6 +10,7 @@ import com.tzld.piaoquan.ad.engine.commons.param.RankRecommendRequestParam;
 import com.tzld.piaoquan.ad.engine.commons.redis.AlgorithmRedisHelper;
 import com.tzld.piaoquan.ad.engine.service.score.RankService;
 import com.tzld.piaoquan.ad.engine.service.score.deprecated.BidRankRecommendRequestParam;
+import com.tzld.piaoquan.ad.engine.service.user.UserService;
 import com.tzld.piaoquan.recommend.feature.domain.ad.base.AdRankItem;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
@@ -33,7 +34,7 @@ public class AdRecommendController {
     RankService rankService;
 
     @Autowired
-    protected AlgorithmRedisHelper algRedisHelper;
+    private UserService userService;
 
     @RequestMapping("/top1/basic")
     public Map<String, Object> adRecommendTop1Basic(@RequestBody RankRecommendRequestParam request) {
@@ -136,29 +137,9 @@ public class AdRecommendController {
         }
         map.put("code", "0");
         map.put("msg", "success");
-        Map<String, Object> result = new HashMap<>();
-        map.put("content", result);
-        String key = String.format("ad:engine:mid:layer:%s", request.getMid());
-        String value = algRedisHelper.get(key);
-        if (StringUtils.isEmpty(value)) {
-            result.put("layer", "无曝光");
-            return map;
-        }
-        try {
-            Map<String, String> layerMap = JSON.parseObject(value, new TypeReference<Map<String, String>>() {
-            });
-            String layer = layerMap.getOrDefault("layer", "无曝光");
-            if (Objects.equals(layer, "已转化")) {
-                layer = "有转化";
-            }
-            result.put("layer", layer);
-            return map;
-        } catch (Exception e) {
-            log.error("getMidWithLayer error. mid: {}, \n", request.getMid(), e);
-            map.put("code", "1");
-            map.put("msg", "get mid layer error");
-            return map;
-        }
+        Map<String, String> userLayer = userService.getUserLayer(request.getMid());
+        map.put("content", userLayer);
+        return map;
     }
 
 

+ 1 - 1
ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/predict/impl/PredictModelServiceImpl.java

@@ -275,7 +275,7 @@ public class PredictModelServiceImpl implements PredictModelService {
             setExtraParam(modelParam);
 
             requestParam.setShareType(shareType);
-            String userLayer = userService.getUserLayerByMid(requestParam.getMid());
+            String userLayer = userService.getUserLayer4Level(requestParam.getMid());
             requestParam.setUserLayer(userLayer);
 
             // 先走rootSessionId 实验

+ 89 - 75
ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/score/strategy/RankStrategyBasic.java

@@ -82,8 +82,6 @@ public abstract class RankStrategyBasic implements RankStrategy {
     @Value("${target.crowd.exclude.exp:785}")
     protected String targetCrowdExcludeExp;
 
-    @Value("${calibration.coefficient.exp:786}")
-    protected String calibrationCoefficientExp;
 
     @Value("${calibration.view:2000}")
     protected Integer calibrationView;
@@ -110,6 +108,9 @@ public abstract class RankStrategyBasic implements RankStrategy {
     @Value("${calibration.profession.exp:792}")
     protected String calibrationProfessionExp;
 
+    @Value("${checkout.layer:false}")
+    protected Boolean checkoutLayer;
+
     @Autowired
     private FeatureService featureService;
     @Autowired
@@ -121,14 +122,16 @@ public abstract class RankStrategyBasic implements RankStrategy {
 
     String realLayerCtcvrKey = "ad:platform:real:ctcvr:{model}:{layer}:{class}";
 
+    String realLayerCtcvrV2Key = "ad:platform:real:ctcvr:v2:{model}:{layer}:{class}";
+
     String adLayerHourKey = "ad:platform:ad:hour:{layer}:{clazz}:{adId}";
 
     String adLayerDayKey = "ad:platform:ad:day:{layer}:{clazz}:{adId}";
 
-    String cidLayerKey = "ad:engine:cid:layer:info:{cid}:{userLayer}";
-
     String userLayerDataKey = "ad:platform:{layer}:{class}:{model}:{type}:{value}";
 
+    String userLayerDataV2Key = "ad:platform:v2:{layer}:{class}:{model}:{type}:{value}";
+
 
     private static final double DEFAULT_CORRECTION = 1.0;
 
@@ -214,16 +217,19 @@ public abstract class RankStrategyBasic implements RankStrategy {
                 map.put("root_source_channel", rootSourceChannel);
             }
         }
+
         Map<String, String> userLayer = getUserLayer(request.getMid());
         String layer = userLayer.getOrDefault("layer", "无曝光");
         String clazz = userLayer.getOrDefault("class", "近期未出现");
         if (request.getIsFilterUser()) {
             layer = layer + "-炸";
         }
-        String userLayerClass = layer + "-" + clazz;
-        map.put("user_layer_class", userLayerClass);
         map.put("layer", layer);
         map.put("clazz", clazz);
+        String layerL4 = userLayer.getOrDefault("layer_l4", "无曝光");
+        String clazzL4 = userLayer.getOrDefault("class_l4", "近期未出现");
+        map.put("layer_l4", layerL4);
+        map.put("clazz_l4", clazzL4);
         return map;
     }
 
@@ -278,8 +284,16 @@ public abstract class RankStrategyBasic implements RankStrategy {
 
     protected void filterRequestAdList(RankRecommendRequestParam request, ScoreParam scoreParam) {
         Map<String, String> userLayer = this.getUserLayer(request.getMid());
-        String layer = userLayer.getOrDefault("layer", "无曝光");
-        String clazz = userLayer.getOrDefault("class", "近期未出现");
+        String layer;
+        String clazz;
+        if (!checkoutLayer) {
+            layer = userLayer.getOrDefault("layer", "无曝光");
+            clazz = userLayer.getOrDefault("class", "近期未出现");
+        } else {
+            layer = userLayer.getOrDefault("layer_l4", "无曝光");
+            clazz = userLayer.getOrDefault("class_l4", "近期未出现");
+        }
+
         //有转化中医层,中医和兴趣教育同时存在过滤兴趣教育行业
         if (Objects.equals(layer, "有转化") && Objects.equals(clazz, "中医") && scoreParam.getExpCodeSet().contains(excludeExp)) {
             List<AdPlatformCreativeDTO> adIdList = request.getAdIdList();
@@ -293,14 +307,26 @@ public abstract class RankStrategyBasic implements RankStrategy {
             log.info("excludeExp filtered request={}", JSONObject.toJSONString(request));
         }
 
-        // 有曝光无转化-其他 过滤德瑞骅客户 客户id 26
-        if (Objects.equals(layer, "有曝光无转化") && Objects.equals(clazz, "其他") && scoreParam.getExpCodeSet().contains(targetCrowdExcludeExp)) {
-            List<AdPlatformCreativeDTO> adIdList = request.getAdIdList();
-            List<AdPlatformCreativeDTO> filteredAdList = adIdList.stream().filter(e -> e.getCustomerId() == null || e.getCustomerId() != 26L).collect(Collectors.toList());
-            if (CollectionUtils.isNotEmpty(filteredAdList)) {
-                request.setAdIdList(filteredAdList);
+        if (!checkoutLayer) {
+            // 有曝光无转化-其他 过滤德瑞骅客户 客户id 26
+            if (Objects.equals(layer, "有曝光无转化") && Objects.equals(clazz, "其他") && scoreParam.getExpCodeSet().contains(targetCrowdExcludeExp)) {
+                List<AdPlatformCreativeDTO> adIdList = request.getAdIdList();
+                List<AdPlatformCreativeDTO> filteredAdList = adIdList.stream().filter(e -> e.getCustomerId() == null || e.getCustomerId() != 26L).collect(Collectors.toList());
+                if (CollectionUtils.isNotEmpty(filteredAdList)) {
+                    request.setAdIdList(filteredAdList);
+                }
+                log.info("targetCrowdExcludeExp filtered request={}", JSONObject.toJSONString(request));
+            }
+        } else {
+            // 有曝光无点击-其他 过滤德瑞骅客户 客户id 26
+            if (Objects.equals(layer, "有曝光无点击") && Objects.equals(clazz, "其他") && scoreParam.getExpCodeSet().contains(targetCrowdExcludeExp)) {
+                List<AdPlatformCreativeDTO> adIdList = request.getAdIdList();
+                List<AdPlatformCreativeDTO> filteredAdList = adIdList.stream().filter(e -> e.getCustomerId() == null || e.getCustomerId() != 26L).collect(Collectors.toList());
+                if (CollectionUtils.isNotEmpty(filteredAdList)) {
+                    request.setAdIdList(filteredAdList);
+                }
+                log.info("targetCrowdExcludeExp filtered request={}", JSONObject.toJSONString(request));
             }
-            log.info("targetCrowdExcludeExp filtered request={}", JSONObject.toJSONString(request));
         }
     }
 
@@ -503,8 +529,17 @@ public abstract class RankStrategyBasic implements RankStrategy {
     }
 
     protected Map<Long, CorrectCpaParam> getCorrectCpaParamMap(RankRecommendRequestParam request, ScoreParam scoreParam, Map<String, String> reqFeature) {
-        String layer = reqFeature.get("layer");
-        String clazz = reqFeature.get("clazz");
+        String layer;
+        String clazz;
+        if (!checkoutLayer) {
+            layer = reqFeature.get("layer");
+            clazz = reqFeature.get("clazz");
+        } else {
+            layer = reqFeature.get("layer_l4");
+            clazz = reqFeature.get("clazz_l4");
+        }
+
+
         Map<Long, CorrectCpaParam> resultMap = new HashMap<>();
         try {
             if (CollectionUtils.isEmpty(request.getAdIdList())) {
@@ -644,14 +679,6 @@ public abstract class RankStrategyBasic implements RankStrategy {
             }
         }
 
-        if (scoreParam.getExpCodeSet().contains(calibrationCoefficientExp)) {
-            try {
-                calibrationCtcvrScore(items, request, reqFeature);
-            } catch (Exception e) {
-                log.error("calibrationCtcvrScore error", e);
-            }
-        }
-
         if (scoreParam.getExpCodeSet().contains(calibrationProfessionExp)) {
             try {
                 calibrationProfessionCtcvrScore(items, modelName, reqFeature);
@@ -665,12 +692,22 @@ public abstract class RankStrategyBasic implements RankStrategy {
         if (StringUtils.isEmpty(modelName)) {
             return;
         }
-        // 构建Key模板
-        String layerKeyTemplate = userLayerDataKey
-                .replace("{model}", modelName)
-                .replace("{layer}", reqFeature.get("layer"))
-                .replace("{class}", reqFeature.get("clazz"))
-                .replace("{type}", "profession");
+        String layerKeyTemplate;
+        if (!checkoutLayer) {
+            // 构建Key模板
+            layerKeyTemplate = userLayerDataKey
+                    .replace("{model}", modelName)
+                    .replace("{layer}", reqFeature.get("layer"))
+                    .replace("{class}", reqFeature.get("clazz"))
+                    .replace("{type}", "profession");
+        } else {
+            // 构建Key模板
+            layerKeyTemplate = userLayerDataV2Key
+                    .replace("{model}", modelName)
+                    .replace("{layer}", reqFeature.get("layer_l4"))
+                    .replace("{class}", reqFeature.get("clazz_l4"))
+                    .replace("{type}", "profession");
+        }
         List<String> professions = items.stream().map(AdRankItem::getProfession).filter(StringUtils::isNotEmpty).distinct().collect(Collectors.toList());
         List<String> professionRedisKeys = professions.stream().map(e -> layerKeyTemplate.replace("{value}", e)).collect(Collectors.toList());
         List<String> redisValues = adRedisHelper.mget(professionRedisKeys);
@@ -710,22 +747,6 @@ public abstract class RankStrategyBasic implements RankStrategy {
         }
     }
 
-    protected void calibrationCtcvrScore(List<AdRankItem> items, RankRecommendRequestParam request, Map<String, String> reqFeature) {
-        String userLayerClass = reqFeature.get("layer") + "-" + reqFeature.get("clazz");
-        String cidLayerClassKey = cidLayerKey.replace("{userLayer}", userLayerClass);
-
-        // 3. 批量查询Redis
-        List<Long> cidList = items.stream().map(AdRankItem::getAdId).collect(Collectors.toList());
-        List<String> redisKeys = cidList.stream()
-                .map(cid -> cidLayerClassKey.replace("{cid}", cid.toString()))
-                .collect(Collectors.toList());
-
-        List<String> redisValues = algRedisHelper.mget(redisKeys);
-        Map<Long, CorrectCtcvrScoreParam> calibrationMap = parseRedisValues(cidList, redisValues);
-
-        // 4. 应用校准逻辑
-        applyCalibration(items, calibrationMap);
-    }
 
     // 解析Redis返回值到Map
     private Map<Long, CorrectCtcvrScoreParam> parseRedisValues(List<Long> cidList, List<String> values) {
@@ -751,23 +772,6 @@ public abstract class RankStrategyBasic implements RankStrategy {
         return map;
     }
 
-    // 应用校准到广告项
-    private void applyCalibration(List<AdRankItem> items, Map<Long, CorrectCtcvrScoreParam> calibrationMap) {
-        for (AdRankItem item : items) {
-            CorrectCtcvrScoreParam param = calibrationMap.get(item.getAdId());
-            if (param == null || param.getView() == null || param.getView() < calibrationView) {
-                continue; // 跳过无效数据
-            }
-
-            double realCtcvr = Optional.ofNullable(param.getRealCtcvr()).orElse(0.0);
-            double calibratedScore = item.getLrScore() * calibrationAlpha + (1 - calibrationAlpha) * realCtcvr;
-            item.getExt().put("correctCtcvrScoreParam", JSONObject.toJSONString(param));
-            item.getScoreMap().put("cidCorrectCtcvrScore", calibratedScore);
-            item.getScoreMap().put("ctcvrScore", calibratedScore);
-            item.setLrScore(calibratedScore);
-        }
-    }
-
 
     protected AdRankItem creativeCovertRankItem(AdPlatformCreativeDTO dto, RankRecommendRequestParam request, Set<String> noApiAdVerIds) {
         AdRankItem adRankItem = new AdRankItem();
@@ -858,10 +862,13 @@ public abstract class RankStrategyBasic implements RankStrategy {
             return new HashMap<>();
         }
         try {
-            Map<String, String> map = JSON.parseObject(value, new TypeReference<Map<String, String>>() {
-            });
-            if (map.containsKey("layer") && Objects.equals(map.get("layer"), "已转化")) {
-                map.put("layer", "有转化");
+            Map<String, String> map = new HashMap<>();
+            JSONObject jsonObject = JSONObject.parseObject(value);
+            map.put("layer", jsonObject.getString("layer"));
+            map.put("class", jsonObject.getString("class"));
+            if (jsonObject.containsKey("basic_l4")) {
+                map.put("layer_l4", jsonObject.getJSONObject("basic_l4").getString("level"));
+                map.put("class_l4", jsonObject.getJSONObject("basic_l4").getString("class"));
             }
             return map;
         } catch (Exception e) {
@@ -874,13 +881,20 @@ public abstract class RankStrategyBasic implements RankStrategy {
         if (StringUtils.isEmpty(modelName)) {
             return;
         }
-        // 构建Key模板
-        String layerKeyTemplate = realLayerCtcvrKey
-                .replace("{model}", modelName)
-                .replace("{layer}", reqFeature.get("layer"))
-                .replace("{class}", reqFeature.get("clazz"));
-
-
+        String layerKeyTemplate;
+        if (!checkoutLayer) {
+            // 构建Key模板
+            layerKeyTemplate = realLayerCtcvrKey
+                    .replace("{model}", modelName)
+                    .replace("{layer}", reqFeature.get("layer"))
+                    .replace("{class}", reqFeature.get("clazz"));
+        } else {
+            // 构建Key模板
+            layerKeyTemplate = realLayerCtcvrV2Key
+                    .replace("{model}", modelName)
+                    .replace("{layer}", reqFeature.get("layer_l4"))
+                    .replace("{class}", reqFeature.get("clazz_l4"));
+        }
         String value = adRedisHelper.get(layerKeyTemplate);
         JSONObject json = JSONObject.parseObject(value);
         Integer view = json.getInteger("view");

+ 5 - 1
ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/user/UserService.java

@@ -1,5 +1,9 @@
 package com.tzld.piaoquan.ad.engine.service.user;
 
+import java.util.Map;
+
 public interface UserService {
-    String getUserLayerByMid(String mid);
+    String getUserLayer4Level(String mid);
+
+    Map<String, String> getUserLayer(String mid);
 }

+ 39 - 8
ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/user/impl/UserServiceImpl.java

@@ -5,10 +5,12 @@ import com.alibaba.fastjson.TypeReference;
 import com.tzld.piaoquan.ad.engine.commons.redis.AlgorithmRedisHelper;
 import com.tzld.piaoquan.ad.engine.service.user.UserService;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections4.MapUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import java.util.HashMap;
 import java.util.Map;
 
 @Slf4j
@@ -19,24 +21,53 @@ public class UserServiceImpl implements UserService {
     protected AlgorithmRedisHelper algRedisHelper;
 
     @Override
-    public String getUserLayerByMid(String mid) {
+    public String getUserLayer4Level(String mid) {
+
+        Map<String, String> userLayer = this.getUserLayer(mid);
+        if (MapUtils.isEmpty(userLayer)) {
+            return "无曝光";
+        }
+
+        return userLayer.getOrDefault("layer_l4", "无曝光");
+    }
+
+    @Override
+    public Map<String, String> getUserLayer(String mid) {
+
+        Map<String, String> resultMap = new HashMap<>();
+        resultMap.put("layer", "无曝光");
+        resultMap.put("layer_l4", "无曝光");
+
+        if (StringUtils.isEmpty(mid)) {
+            return resultMap;
+        }
+
         String key = String.format("ad:engine:mid:layer:%s", mid);
         String value = algRedisHelper.get(key);
         if (StringUtils.isEmpty(value)) {
-            return "无曝光";
+            return resultMap;
         }
+
         try {
             Map<String, String> layerMap = JSON.parseObject(value, new TypeReference<Map<String, String>>() {
             });
-            String layer = layerMap.getOrDefault("layer", "无曝光");
-            if (StringUtils.equals(layer, "已转化")) {
-                layer = "有转化";
+            String layer3L = layerMap.getOrDefault("layer", "无曝光");
+            if (StringUtils.equals(layer3L, "已转化")) {
+                layer3L = "有转化";
             }
-            return layer;
+
+            Map<String, String> basic4lMap = JSON.parseObject(layerMap.getOrDefault("basic_l4", "{}"), new TypeReference<Map<String, String>>() {
+            });
+
+            String layer4L = basic4lMap.getOrDefault("level", "无曝光");
+
+            resultMap.put("layer", layer3L);
+            resultMap.put("layer_l4", layer4L);
+            return resultMap;
         } catch (Exception e) {
-            log.error("UserServiceImpl getUserLayerByMi error: ", e);
+            log.error("UserServiceImpl getUserLayer error: ", e);
         }
 
-        return "无曝光";
+        return resultMap;
     }
 }