|
@@ -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");
|