liqian 1 year ago
parent
commit
7af66ccf8a
1 changed files with 366 additions and 60 deletions
  1. 366 60
      ad_recommend.py

+ 366 - 60
ad_recommend.py

@@ -70,6 +70,277 @@ def get_threshold(abtest_id, abtest_config_tag, ab_test_code, mid_group, care_mo
     return threshold
 
 
+def predict_mid_video_res(now_date, mid, video_id, abtest_param, abtest_id, abtest_config_tag, ab_test_code, care_model_status):
+    now_dt = datetime.datetime.strftime(now_date, '%Y%m%d')
+    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_predict_res = 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_predict_res > 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_predict_res': mid_video_predict_res,
+            'threshold': threshold,
+            'ad_predict': ad_predict}
+    return result
+
+
+def predict_mid_video_res_with_add(now_date, mid, video_id, abtest_param, abtest_id, abtest_config_tag, ab_test_code, care_model_status):
+    now_dt = datetime.datetime.strftime(now_date, '%Y%m%d')
+
+    # 判断mid所属分组
+    group_class_key = abtest_param.get('group_class_key')
+    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'
+
+    # 判断用户是否在免广告用户组列表中
+    no_ad_mid_group_list = abtest_param.get('no_ad_mid_group_list', [])
+    if mid_group in no_ad_mid_group_list:
+        # 在免广告用户组列表中,则不出广告
+        ad_predict = 1
+        result = {
+            'mid_group': mid_group,
+            'ad_predict': ad_predict
+        }
+    else:
+        # 获取用户组出广告后分享的概率
+        share_user_data_key = abtest_param['share']['user'].get('data')
+        share_user_rule_key = abtest_param['share']['user'].get('rule')
+        group_share_rate_key = \
+            f"{config_.KEY_NAME_PREFIX_AD_GROUP}{share_user_data_key}:{share_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}{share_user_data_key}:{share_user_rule_key}:{redis_dt}"
+        group_share_rate = redis_helper.get_score_with_value(key_name=group_share_rate_key, value=mid_group)
+
+        # 获取视频出广告后分享的概率
+        share_video_data_key = abtest_param['share']['video'].get('data')
+        video_share_rate_key = f"{config_.KEY_NAME_PREFIX_AD_VIDEO}{share_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}{share_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)
+
+        # 获取用户组出广告后不直接跳出的概率
+        out_user_data_key = abtest_param['out']['user'].get('data')
+        out_user_rule_key = abtest_param['out']['user'].get('rule')
+        group_out_rate_key = \
+            f"{config_.KEY_NAME_PREFIX_AD_GROUP}{out_user_data_key}:{out_user_rule_key}:{now_dt}"
+        if not redis_helper.key_exists(group_out_rate_key):
+            redis_dt = datetime.datetime.strftime(now_date - datetime.timedelta(days=1), '%Y%m%d')
+            group_out_rate_key = \
+                f"{config_.KEY_NAME_PREFIX_AD_GROUP}{out_user_data_key}:{out_user_rule_key}:{redis_dt}"
+        group_out_rate = redis_helper.get_score_with_value(key_name=group_out_rate_key, value=mid_group)
+
+        # 获取视频出广告后不直接跳出的概率
+        out_video_data_key = abtest_param['out']['video'].get('data')
+        video_out_rate_key = f"{config_.KEY_NAME_PREFIX_AD_VIDEO}{out_video_data_key}:{now_dt}"
+        if not redis_helper.key_exists(video_out_rate_key):
+            redis_dt = datetime.datetime.strftime(now_date - datetime.timedelta(days=1), '%Y%m%d')
+            video_out_rate_key = f"{config_.KEY_NAME_PREFIX_AD_VIDEO}{out_video_data_key}:{redis_dt}"
+        video_out_rate = redis_helper.get_score_with_value(key_name=video_out_rate_key, value=int(video_id))
+        if video_out_rate is None:
+            video_out_rate = redis_helper.get_score_with_value(key_name=video_out_rate_key, value=-1)
+
+        # 计算 mid-video 预测值
+        if group_share_rate is None or video_share_rate is None or group_out_rate is None or video_out_rate is None:
+            return None
+        # 加权融合
+        share_weight = abtest_param['mix_param']['share_weight']
+        out_weight = abtest_param['mix_param']['out_weight']
+        group_rate = share_weight * float(group_share_rate) + out_weight * float(group_out_rate)
+        video_rate = share_weight * float(video_share_rate) + out_weight * float(video_out_rate)
+        mid_video_predict_res = group_rate * video_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_predict_res > 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,
+            'group_out_rate': group_out_rate,
+            'video_out_rate': video_out_rate,
+            'group_rate': group_rate,
+            'video_rate': video_rate,
+            'mid_video_predict_res': mid_video_predict_res,
+            'threshold': threshold,
+            'ad_predict': ad_predict}
+    return result
+
+
+def predict_mid_video_res_with_multiply(now_date, mid, video_id, abtest_param, abtest_id, abtest_config_tag, ab_test_code, care_model_status):
+    now_dt = datetime.datetime.strftime(now_date, '%Y%m%d')
+
+    # 判断mid所属分组
+    group_class_key = abtest_param.get('group_class_key')
+    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'
+
+    # 判断用户是否在免广告用户组列表中
+    no_ad_mid_group_list = abtest_param.get('no_ad_mid_group_list', [])
+    if mid_group in no_ad_mid_group_list:
+        # 在免广告用户组列表中,则不出广告
+        ad_predict = 1
+        result = {
+            'mid_group': mid_group,
+            'ad_predict': ad_predict
+        }
+    else:
+        # 获取用户组出广告后分享的概率
+        share_user_data_key = abtest_param['share']['user'].get('data')
+        share_user_rule_key = abtest_param['share']['user'].get('rule')
+        group_share_rate_key = \
+            f"{config_.KEY_NAME_PREFIX_AD_GROUP}{share_user_data_key}:{share_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}{share_user_data_key}:{share_user_rule_key}:{redis_dt}"
+        group_share_rate = redis_helper.get_score_with_value(key_name=group_share_rate_key, value=mid_group)
+
+        # 获取视频出广告后分享的概率
+        share_video_data_key = abtest_param['share']['video'].get('data')
+        video_share_rate_key = f"{config_.KEY_NAME_PREFIX_AD_VIDEO}{share_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}{share_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)
+
+        # 获取用户组出广告后不直接跳出的概率
+        out_user_data_key = abtest_param['out']['user'].get('data')
+        out_user_rule_key = abtest_param['out']['user'].get('rule')
+        group_out_rate_key = \
+            f"{config_.KEY_NAME_PREFIX_AD_GROUP}{out_user_data_key}:{out_user_rule_key}:{now_dt}"
+        if not redis_helper.key_exists(group_out_rate_key):
+            redis_dt = datetime.datetime.strftime(now_date - datetime.timedelta(days=1), '%Y%m%d')
+            group_out_rate_key = \
+                f"{config_.KEY_NAME_PREFIX_AD_GROUP}{out_user_data_key}:{out_user_rule_key}:{redis_dt}"
+        group_out_rate = redis_helper.get_score_with_value(key_name=group_out_rate_key, value=mid_group)
+
+        # 获取视频出广告后不直接跳出的概率
+        out_video_data_key = abtest_param['out']['video'].get('data')
+        video_out_rate_key = f"{config_.KEY_NAME_PREFIX_AD_VIDEO}{out_video_data_key}:{now_dt}"
+        if not redis_helper.key_exists(video_out_rate_key):
+            redis_dt = datetime.datetime.strftime(now_date - datetime.timedelta(days=1), '%Y%m%d')
+            video_out_rate_key = f"{config_.KEY_NAME_PREFIX_AD_VIDEO}{out_video_data_key}:{redis_dt}"
+        video_out_rate = redis_helper.get_score_with_value(key_name=video_out_rate_key, value=int(video_id))
+        if video_out_rate is None:
+            video_out_rate = redis_helper.get_score_with_value(key_name=video_out_rate_key, value=-1)
+
+        # 计算 mid-video 预测值
+        if group_share_rate is None or video_share_rate is None or group_out_rate is None or video_out_rate is None:
+            return None
+        # 乘积融合
+        group_rate = float(group_share_rate) * float(group_out_rate)
+        video_rate = float(video_share_rate) * float(video_out_rate)
+        mid_video_predict_res = group_rate * video_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_predict_res > 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,
+            'group_out_rate': group_out_rate,
+            'video_out_rate': video_out_rate,
+            'group_rate': group_rate,
+            'video_rate': video_rate,
+            'mid_video_predict_res': mid_video_predict_res,
+            'threshold': threshold,
+            'ad_predict': ad_predict}
+    return result
+
+
 def ad_recommend_predict(app_type, mid, video_id, ab_exp_info, ab_test_code, care_model_status):
     """
     广告推荐预测
@@ -83,7 +354,7 @@ def ad_recommend_predict(app_type, mid, video_id, ab_exp_info, ab_test_code, car
     """
     try:
         now_date = datetime.datetime.today()
-        now_dt = datetime.datetime.strftime(now_date, '%Y%m%d')
+        # 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:
@@ -92,70 +363,105 @@ def ad_recommend_predict(app_type, mid, video_id, ab_exp_info, ab_test_code, car
         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
-            }
+        threshold_mix_func = abtest_param.get('threshold_mix_func', None)
+        if threshold_mix_func == 'add':
+            result = predict_mid_video_res_with_add(
+                now_date=now_date,
+                mid=mid,
+                video_id=video_id,
+                abtest_param=abtest_param,
+                abtest_id=abtest_id,
+                abtest_config_tag=abtest_config_tag,
+                ab_test_code=ab_test_code,
+                care_model_status=care_model_status
+            )
+        elif threshold_mix_func == 'multiply':
+            result = predict_mid_video_res_with_multiply(
+                now_date=now_date,
+                mid=mid,
+                video_id=video_id,
+                abtest_param=abtest_param,
+                abtest_id=abtest_id,
+                abtest_config_tag=abtest_config_tag,
+                ab_test_code=ab_test_code,
+                care_model_status=care_model_status
+            )
         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(
+            result = predict_mid_video_res(
+                now_date=now_date,
+                mid=mid,
+                video_id=video_id,
+                abtest_param=abtest_param,
                 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
+                care_model_status=care_model_status
             )
-            # 阈值判断
-            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}
+
+        # 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