import traceback
import datetime
from utils import RedisHelper
from config import set_config
from log import Log
log_ = Log()
config_ = set_config()
redis_helper = RedisHelper()
def get_params(ab_exp_info, ab_test_code):
"""
根据实验分组给定对应的参数
:param ab_exp_info: AB实验组参数
:param ab_test_code: 用户对应的ab组
:return:
"""
abtest_id, abtest_config_tag = None, None
ad_abtest_id_list = [key.split('-')[0] for key in config_.AD_ABTEST_CONFIG]
# 获取广告实验配置
config_value_dict = {}
if ab_exp_info:
ab_exp_list = ab_exp_info.get('ab_test002', None)
if ab_exp_list:
for ab_item in ab_exp_list:
ab_exp_code = ab_item.get('abExpCode', None)
if not ab_exp_code:
continue
if ab_exp_code in ad_abtest_id_list:
config_value = ab_item.get('configValue', None)
if config_value:
config_value_dict[str(ab_exp_code)] = eval(str(config_value))
if len(config_value_dict) > 0:
for ab_exp_code, config_value in config_value_dict.items():
for tag, value in config_value.items():
if ab_test_code in value:
abtest_id = ab_exp_code
abtest_config_tag = tag
break
return abtest_id, abtest_config_tag
def get_threshold(abtest_id, abtest_config_tag, ab_test_code, mid_group, care_model_status, abtest_param):
"""获取对应的阈值"""
# 判断是否是关怀模式实验
care_model_status_param = abtest_param.get('care_model_status_param', None)
care_model_ab_mid_group = abtest_param.get('care_model_ab_mid_group', None)
if care_model_status_param is None:
# 无关怀模式实验
threshold_key_name_prefix = config_.KEY_NAME_PREFIX_AD_THRESHOLD
else:
# 关怀模式实验
if care_model_status is None or care_model_ab_mid_group is None or care_model_status == 'null':
# 参数缺失,走默认
threshold_key_name_prefix = config_.KEY_NAME_PREFIX_AD_THRESHOLD
elif int(care_model_status) == int(care_model_status_param) and mid_group == care_model_ab_mid_group:
# 实验匹配,获取对应的阈值
threshold_key_name_prefix = config_.KEY_NAME_PREFIX_AD_THRESHOLD_CARE_MODEL
else:
threshold_key_name_prefix = config_.KEY_NAME_PREFIX_AD_THRESHOLD
threshold_key_name = f"{threshold_key_name_prefix}{abtest_id}:{abtest_config_tag}:{ab_test_code}:{mid_group}"
threshold = redis_helper.get_data_from_redis(key_name=threshold_key_name)
if threshold is None:
threshold = 0
else:
threshold = float(threshold)
return threshold
def ad_recommend_predict(app_type, mid, video_id, ab_exp_info, ab_test_code, care_model_status):
"""
广告推荐预测
:param app_type: app_type
:param mid: mid
:param video_id: video_id
:param ab_exp_info: AB实验组参数
:param ab_test_code: 用户对应的ab组
:param care_model_status: 用户关怀模式状态 1-未开启,2-开启
:return: ad_predict, type-int, 1-不发放广告,2-发放广告
"""
try:
now_date = datetime.datetime.today()
now_dt = datetime.datetime.strftime(now_date, '%Y%m%d')
# 获取实验参数
abtest_id, abtest_config_tag = get_params(ab_exp_info=ab_exp_info, ab_test_code=ab_test_code)
if abtest_id is None or abtest_config_tag is None:
return None
abtest_param = config_.AD_ABTEST_CONFIG.get(f'{abtest_id}-{abtest_config_tag}')
if abtest_param is None:
return None
user_data_key = abtest_param['user'].get('data')
user_rule_key = abtest_param['user'].get('rule')
video_data_key = abtest_param['video'].get('data')
group_class_key = abtest_param.get('group_class_key')
no_ad_mid_group_list = abtest_param.get('no_ad_mid_group_list', [])
# 判断mid所属分组
mid_group_key_name = f"{config_.KEY_NAME_PREFIX_MID_GROUP}{group_class_key}:{mid}"
mid_group = redis_helper.get_data_from_redis(key_name=mid_group_key_name)
if mid_group is None:
mid_group = 'mean_group'
# 判断用户是否在免广告用户组列表中
if mid_group in no_ad_mid_group_list:
# 在免广告用户组列表中,则不出广告
ad_predict = 1
result = {
'mid_group': mid_group,
'ad_predict': ad_predict
}
else:
# 获取用户组分享率
group_share_rate_key = f"{config_.KEY_NAME_PREFIX_AD_GROUP}{user_data_key}:{user_rule_key}:{now_dt}"
if not redis_helper.key_exists(group_share_rate_key):
redis_dt = datetime.datetime.strftime(now_date - datetime.timedelta(days=1), '%Y%m%d')
group_share_rate_key = f"{config_.KEY_NAME_PREFIX_AD_GROUP}{user_data_key}:{user_rule_key}:{redis_dt}"
group_share_rate = redis_helper.get_score_with_value(key_name=group_share_rate_key, value=mid_group)
# 获取视频分享率
video_share_rate_key = f"{config_.KEY_NAME_PREFIX_AD_VIDEO}{video_data_key}:{now_dt}"
if not redis_helper.key_exists(video_share_rate_key):
redis_dt = datetime.datetime.strftime(now_date - datetime.timedelta(days=1), '%Y%m%d')
video_share_rate_key = f"{config_.KEY_NAME_PREFIX_AD_VIDEO}{video_data_key}:{redis_dt}"
video_share_rate = redis_helper.get_score_with_value(key_name=video_share_rate_key, value=int(video_id))
if video_share_rate is None:
video_share_rate = redis_helper.get_score_with_value(key_name=video_share_rate_key, value=-1)
# 计算 mid-video 分享率
if group_share_rate is None or video_share_rate is None:
return None
mid_video_share_rate = float(group_share_rate) * float(video_share_rate)
# 获取对应的阈值
threshold = get_threshold(
abtest_id=abtest_id,
abtest_config_tag=abtest_config_tag,
ab_test_code=ab_test_code,
mid_group=mid_group,
care_model_status=care_model_status,
abtest_param=abtest_param
)
# 阈值判断
if mid_video_share_rate > threshold:
# 大于阈值,出广告
ad_predict = 2
else:
# 否则,不出广告
ad_predict = 1
result = {
'mid_group': mid_group,
'group_share_rate': group_share_rate,
'video_share_rate': video_share_rate,
'mid_video_share_rate': mid_video_share_rate,
'threshold': threshold,
'ad_predict': ad_predict}
return result
except Exception as e:
log_.error(traceback.format_exc())
return None