|
@@ -107,6 +107,9 @@ public abstract class RankStrategyBasic implements RankStrategy {
|
|
|
@Value("${filter.ecpm:60}")
|
|
|
protected String filterEcpm;
|
|
|
|
|
|
+ @Value("${calibration.profession.exp:792}")
|
|
|
+ protected String calibrationProfessionExp;
|
|
|
+
|
|
|
@Autowired
|
|
|
private FeatureService featureService;
|
|
|
@Autowired
|
|
@@ -124,7 +127,7 @@ public abstract class RankStrategyBasic implements RankStrategy {
|
|
|
|
|
|
String cidLayerKey = "ad:engine:cid:layer:info:{cid}:{userLayer}";
|
|
|
|
|
|
- String userLayerDataKey = "ad:platform:{layer}:{class}:{type}:{value}";
|
|
|
+ String userLayerDataKey = "ad:platform:{layer}:{class}:{model}:{type}:{value}";
|
|
|
|
|
|
|
|
|
private static final double DEFAULT_CORRECTION = 1.0;
|
|
@@ -364,7 +367,7 @@ public abstract class RankStrategyBasic implements RankStrategy {
|
|
|
* 根据人群信息计算保量权重系数(新版本)
|
|
|
*
|
|
|
* @param guaranteeView 保量视图对象
|
|
|
- * @param reqFeature 请求特征信息,包含用户人群layer信息
|
|
|
+ * @param reqFeature 请求特征信息,包含用户人群layer信息
|
|
|
* @return 保量权重系数
|
|
|
*/
|
|
|
protected double calculateGuaranteeWeightWithCrowd(GuaranteeView guaranteeView, Map<String, String> reqFeature) {
|
|
@@ -407,7 +410,7 @@ public abstract class RankStrategyBasic implements RankStrategy {
|
|
|
// 对勾选了保量人群,且不是勾选了全部的保量人群的广告进行额外加权
|
|
|
double finalWeight = baseWeight * guaranteeCrowdWeightCoefficient;
|
|
|
log.debug("RankStrategyBasic 保量人群加权: userLayer={}, guaranteeCrowdCode={}, baseWeight={}, coefficient={}, finalWeight={}",
|
|
|
- userLayer, guaranteeCrowdCode, baseWeight, guaranteeCrowdWeightCoefficient, finalWeight);
|
|
|
+ userLayer, guaranteeCrowdCode, baseWeight, guaranteeCrowdWeightCoefficient, finalWeight);
|
|
|
return finalWeight;
|
|
|
} else {
|
|
|
// 用户不在保量人群范围内,权重设为1
|
|
@@ -422,18 +425,18 @@ public abstract class RankStrategyBasic implements RankStrategy {
|
|
|
|
|
|
/**
|
|
|
* 计算保量权重系数(原有逻辑)
|
|
|
- *
|
|
|
+ * <p>
|
|
|
* 保量逻辑说明:
|
|
|
* 1. 根据广告主的保量配置(保量比例、保量上限)和实际曝光情况计算权重
|
|
|
* 2. 权重用于调整广告排序分数,帮助未达到保量目标的广告主获得更多曝光
|
|
|
* 3. 已达到保量上限的广告主权重为0,避免过度曝光
|
|
|
*
|
|
|
* @param guaranteeView 保量视图对象,包含广告主保量相关数据
|
|
|
- * - adrId: 广告主ID
|
|
|
- * - adrAlgoViewNum: 广告主当天算法曝光数
|
|
|
- * - allAlgoViewNum: 全平台当天算法曝光数
|
|
|
- * - guaranteeNum: 保量上限(广告主最大允许曝光数)
|
|
|
- * - guaranteeRate: 保量比例(广告主期望占全平台曝光的百分比)
|
|
|
+ * - adrId: 广告主ID
|
|
|
+ * - adrAlgoViewNum: 广告主当天算法曝光数
|
|
|
+ * - allAlgoViewNum: 全平台当天算法曝光数
|
|
|
+ * - guaranteeNum: 保量上限(广告主最大允许曝光数)
|
|
|
+ * - guaranteeRate: 保量比例(广告主期望占全平台曝光的百分比)
|
|
|
* @return 保量权重系数,范围[0.0, 2.0],默认1.0
|
|
|
*/
|
|
|
protected double calculateGuaranteedWeight(GuaranteeView guaranteeView) {
|
|
@@ -648,6 +651,62 @@ public abstract class RankStrategyBasic implements RankStrategy {
|
|
|
log.error("calibrationCtcvrScore error", e);
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ if (scoreParam.getExpCodeSet().contains(calibrationProfessionExp)) {
|
|
|
+ try {
|
|
|
+ calibrationProfessionCtcvrScore(items, modelName, reqFeature);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("calibrationProfessionCtcvrScore error", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void calibrationProfessionCtcvrScore(List<AdRankItem> items, String modelName, Map<String, String> reqFeature) {
|
|
|
+ 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");
|
|
|
+ List<String> professions = items.stream().map(AdRankItem::getProfession).distinct().collect(Collectors.toList());
|
|
|
+ List<String> professionRedisKeys = professions.stream().map(e -> layerKeyTemplate.replace("{value}", e)).collect(Collectors.toList());
|
|
|
+ List<String> redisValues = adRedisHelper.mget(professionRedisKeys);
|
|
|
+ Map<String, CalibrationModelCtcvrData> map = new HashMap<>();
|
|
|
+ for (int i = 0; i < professions.size(); i++) {
|
|
|
+ String value = redisValues.get(i);
|
|
|
+ if (StringUtils.isEmpty(value)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ JSONObject json = JSONObject.parseObject(value);
|
|
|
+ CalibrationModelCtcvrData calibrationModelCtcvrData = new CalibrationModelCtcvrData();
|
|
|
+ calibrationModelCtcvrData.setRealCtcvr(json.getDouble("ctcvr"));
|
|
|
+ calibrationModelCtcvrData.setView(json.getInteger("view"));
|
|
|
+ calibrationModelCtcvrData.setPCtcvr(json.getDouble("pCtcvr"));
|
|
|
+ map.put(professions.get(i), calibrationModelCtcvrData);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ for (AdRankItem item : items) {
|
|
|
+ CalibrationModelCtcvrData calibrationModelCtcvrData = map.get(item.getProfession());
|
|
|
+ item.getExt().put("calibrationModelProfessionCtcvrData", JSONObject.toJSONString(calibrationModelCtcvrData));
|
|
|
+ if (calibrationModelCtcvrData.getPCtcvr() == null
|
|
|
+ || calibrationModelCtcvrData.getPCtcvr() == 0.0
|
|
|
+ || calibrationModelCtcvrData.getRealCtcvr() == null
|
|
|
+ || calibrationModelCtcvrData.getRealCtcvr() == 0.0) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ double diff = calibrationModelCtcvrData.getRealCtcvr() / calibrationModelCtcvrData.getPCtcvr();
|
|
|
+ if (Math.abs(diff - 1) < 0.1) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ double calibratedCtcvrScore = item.getLrScore() * diff;
|
|
|
+ item.getScoreMap().put("layerModelProfessionCtcvrScore", calibratedCtcvrScore);
|
|
|
+ item.getScoreMap().put("ctcvrScore", calibratedCtcvrScore);
|
|
|
+ item.setLrScore(calibratedCtcvrScore);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
protected void calibrationCtcvrScore(List<AdRankItem> items, RankRecommendRequestParam request, Map<String, String> reqFeature) {
|
|
@@ -883,7 +942,7 @@ public abstract class RankStrategyBasic implements RankStrategy {
|
|
|
* 判断用户人群是否在保量人群范围内
|
|
|
*
|
|
|
* @param guaranteeCrowdCode 保量人群代码字符串,格式如"1,2,3"
|
|
|
- * @param userCrowdCode 用户人群代码
|
|
|
+ * @param userCrowdCode 用户人群代码
|
|
|
* @return true表示用户在保量人群范围内
|
|
|
*/
|
|
|
private boolean isUserInGuaranteeCrowd(String guaranteeCrowdCode, Integer userCrowdCode) {
|
|
@@ -908,6 +967,7 @@ public abstract class RankStrategyBasic implements RankStrategy {
|
|
|
|
|
|
/**
|
|
|
* 判断是否全部保量人群
|
|
|
+ *
|
|
|
* @param guaranteeCrowdCode 保量人群代码字符串
|
|
|
* @return true表示是全部保量人群
|
|
|
*/
|
|
@@ -936,7 +996,7 @@ public abstract class RankStrategyBasic implements RankStrategy {
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
log.error("判断保量人群加权失败: guaranteeCrowdCode={}",
|
|
|
- guaranteeCrowdCode, e);
|
|
|
+ guaranteeCrowdCode, e);
|
|
|
return false;
|
|
|
}
|
|
|
}
|