|
@@ -94,20 +94,20 @@ public class PredictStrategyByRorCopy extends BasicPredict {
|
|
|
String appType = ctx.getAppType();
|
|
String appType = ctx.getAppType();
|
|
|
|
|
|
|
|
// 获取默认概率阈值(基于 rootSessionId 尾号和 appType 匹配配置)
|
|
// 获取默认概率阈值(基于 rootSessionId 尾号和 appType 匹配配置)
|
|
|
- Boolean matchResult = getDefaultProbability(rootSessionId, appType);
|
|
|
|
|
|
|
+ Double defaultProbability = getDefaultProbability(rootSessionId, appType);
|
|
|
|
|
|
|
|
// 用户不在实验分桶内,跳过该策略
|
|
// 用户不在实验分桶内,跳过该策略
|
|
|
- if (!matchResult) {
|
|
|
|
|
|
|
+ if (defaultProbability == null) {
|
|
|
return null;
|
|
return null;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
Map<String, Object> rtnMap = new HashMap<>();
|
|
Map<String, Object> rtnMap = new HashMap<>();
|
|
|
|
|
|
|
|
// 用户行为特征变量(来自离线特征表 alg_mid_history_behavior_1month)
|
|
// 用户行为特征变量(来自离线特征表 alg_mid_history_behavior_1month)
|
|
|
- String launchs = null; // 启动次数分桶(如 "0-5", "5-10" 等)
|
|
|
|
|
- String ror = null; // 留存率分桶
|
|
|
|
|
- String adLevel = null; // 广告等级(用户对广告的敏感度分层)
|
|
|
|
|
- String return30day = null; // 用户回流率分桶
|
|
|
|
|
|
|
+ String launchs = "-999"; // 启动次数分桶(如 "0-5", "5-10" 等)
|
|
|
|
|
+ String ror = "-999"; // 留存率分桶
|
|
|
|
|
+ String adLevel = "无转化"; // 广告等级(用户对广告的敏感度分层)
|
|
|
|
|
+ String return30day = "r_0_8"; // 用户回流率分桶
|
|
|
|
|
|
|
|
// 根据 mid 获取用户近一个月的历史行为特征
|
|
// 根据 mid 获取用户近一个月的历史行为特征
|
|
|
Feature feature = featureService.getMidBehaviorFeature(TABLE_NAME, ctx.getMid());
|
|
Feature feature = featureService.getMidBehaviorFeature(TABLE_NAME, ctx.getMid());
|
|
@@ -117,15 +117,15 @@ public class PredictStrategyByRorCopy extends BasicPredict {
|
|
|
// 安全地提取特征值(多层 null 检查)
|
|
// 安全地提取特征值(多层 null 检查)
|
|
|
if (feature != null && feature.getUserFeature() != null && feature.getUserFeature().get(TABLE_NAME) != null) {
|
|
if (feature != null && feature.getUserFeature() != null && feature.getUserFeature().get(TABLE_NAME) != null) {
|
|
|
Map<String, String> algMidHistoryBehavior1month = feature.getUserFeature().get(TABLE_NAME);
|
|
Map<String, String> algMidHistoryBehavior1month = feature.getUserFeature().get(TABLE_NAME);
|
|
|
- launchs = algMidHistoryBehavior1month.get("launchs");
|
|
|
|
|
- ror = algMidHistoryBehavior1month.get("ror");
|
|
|
|
|
- adLevel = algMidHistoryBehavior1month.get("ad_level");
|
|
|
|
|
- return30day = algMidHistoryBehavior1month.get("return_30day");
|
|
|
|
|
|
|
+ launchs = StringUtils.isBlank(algMidHistoryBehavior1month.get("launchs")) ? launchs : algMidHistoryBehavior1month.get("launchs");
|
|
|
|
|
+ ror = StringUtils.isBlank(algMidHistoryBehavior1month.get("ror")) ? ror : algMidHistoryBehavior1month.get("ror");
|
|
|
|
|
+ adLevel = StringUtils.isBlank(algMidHistoryBehavior1month.get("ad_level")) ? adLevel : algMidHistoryBehavior1month.get("ad_level");
|
|
|
|
|
+ return30day = StringUtils.isBlank(algMidHistoryBehavior1month.get("return_30day")) ? return30day : algMidHistoryBehavior1month.get("return_30day");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 计算最终的广告展示概率阈值
|
|
// 计算最终的广告展示概率阈值
|
|
|
// 优先使用 Redis 中基于用户特征的精细化阈值,否则使用默认阈值
|
|
// 优先使用 Redis 中基于用户特征的精细化阈值,否则使用默认阈值
|
|
|
- Double showAdProbability = getShowAdProbability(launchs, ror, adLevel,return30day);
|
|
|
|
|
|
|
+ Double showAdProbability = getShowAdProbability(launchs, ror, adLevel,return30day,defaultProbability);
|
|
|
|
|
|
|
|
if (showAdProbability == null) {
|
|
if (showAdProbability == null) {
|
|
|
return null;
|
|
return null;
|
|
@@ -172,10 +172,10 @@ public class PredictStrategyByRorCopy extends BasicPredict {
|
|
|
*
|
|
*
|
|
|
* @return 广告展示概率阈值 [0, 1]
|
|
* @return 广告展示概率阈值 [0, 1]
|
|
|
*/
|
|
*/
|
|
|
- private Double getShowAdProbability(String launchs, String ror, String ad_level,String return30day) {
|
|
|
|
|
|
|
+ private Double getShowAdProbability(String launchs, String ror, String ad_level,String return30day, Double defaultProbability) {
|
|
|
// 任一特征为空,使用默认概率
|
|
// 任一特征为空,使用默认概率
|
|
|
if (StringUtils.isAnyBlank(launchs, ror, ad_level,return30day)) {
|
|
if (StringUtils.isAnyBlank(launchs, ror, ad_level,return30day)) {
|
|
|
- return null;
|
|
|
|
|
|
|
+ return defaultProbability;
|
|
|
}
|
|
}
|
|
|
try {
|
|
try {
|
|
|
// 构建 Redis key:格式为 "ad_level:launchs:ror",例如 "有转化:10:000"
|
|
// 构建 Redis key:格式为 "ad_level:launchs:ror",例如 "有转化:10:000"
|
|
@@ -186,11 +186,11 @@ public class PredictStrategyByRorCopy extends BasicPredict {
|
|
|
String probability = adRedisHelper.get(key);
|
|
String probability = adRedisHelper.get(key);
|
|
|
|
|
|
|
|
// 解析概率值,如果为 null 则使用默认值
|
|
// 解析概率值,如果为 null 则使用默认值
|
|
|
- return StringUtils.isBlank(probability) ? null : Double.parseDouble(probability);
|
|
|
|
|
|
|
+ return StringUtils.isBlank(probability) ? defaultProbability : Double.parseDouble(probability);
|
|
|
} catch (Exception e) {
|
|
} catch (Exception e) {
|
|
|
// 解析失败(如非数字字符串)或 Redis 异常,记录错误并使用默认值
|
|
// 解析失败(如非数字字符串)或 Redis 异常,记录错误并使用默认值
|
|
|
log.error("getShowAdProbability error, launchs: {}, ror: {}, ad_level: {}, e = ", launchs, ror, ad_level, e);
|
|
log.error("getShowAdProbability error, launchs: {}, ror: {}, ad_level: {}, e = ", launchs, ror, ad_level, e);
|
|
|
- return null;
|
|
|
|
|
|
|
+ return defaultProbability;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -203,10 +203,10 @@ public class PredictStrategyByRorCopy extends BasicPredict {
|
|
|
* @param appType 应用类型
|
|
* @param appType 应用类型
|
|
|
* @return 默认概率,如果不匹配任何配置则返回 null
|
|
* @return 默认概率,如果不匹配任何配置则返回 null
|
|
|
*/
|
|
*/
|
|
|
- private Boolean getDefaultProbability(String rootSessionId, String appType) {
|
|
|
|
|
|
|
+ private Double getDefaultProbability(String rootSessionId, String appType) {
|
|
|
// 前置校验
|
|
// 前置校验
|
|
|
if (CollectionUtils.isEmpty(configItems) || StringUtils.isAnyBlank(rootSessionId) || appType == null) {
|
|
if (CollectionUtils.isEmpty(configItems) || StringUtils.isAnyBlank(rootSessionId) || appType == null) {
|
|
|
- return false;
|
|
|
|
|
|
|
+ return null;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 提取 rootSessionId 的最后一个字符作为尾号,用于流量分桶
|
|
// 提取 rootSessionId 的最后一个字符作为尾号,用于流量分桶
|
|
@@ -216,15 +216,14 @@ public class PredictStrategyByRorCopy extends BasicPredict {
|
|
|
for (RootSessionIdTailConfigItem item : configItems) {
|
|
for (RootSessionIdTailConfigItem item : configItems) {
|
|
|
if (item.getAppType() != null && item.getTail() != null) {
|
|
if (item.getAppType() != null && item.getTail() != null) {
|
|
|
if (item.getAppType().contains(appType) && item.getTail().contains(tail)) {
|
|
if (item.getAppType().contains(appType) && item.getTail().contains(tail)) {
|
|
|
-// return item.getConfig().get("default_probability");
|
|
|
|
|
- return true;
|
|
|
|
|
|
|
+ return item.getConfig().get("default_probability");
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 未匹配到任何配置
|
|
// 未匹配到任何配置
|
|
|
- return false;
|
|
|
|
|
|
|
+ return null;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
}
|
|
}
|