|
@@ -135,13 +135,15 @@ def positon_duplicate(pos1_vids, pos2_vids, videos):
|
|
|
return l
|
|
|
|
|
|
|
|
|
-def video_recommend(mid, uid, size, app_type, algo_type, client_info, expire_time=24*3600,
|
|
|
+def video_recommend(mid, uid, size, top_K, flow_pool_P, app_type, algo_type, client_info, expire_time=24*3600,
|
|
|
ab_code=config_.AB_CODE['initial']):
|
|
|
"""
|
|
|
首页线上推荐逻辑
|
|
|
:param mid: mid type-string
|
|
|
:param uid: uid type-string
|
|
|
:param size: 请求视频数量 type-int
|
|
|
+ :param top_K: 保证topK为召回池视频 type-int
|
|
|
+ :param flow_pool_P: size-top_K视频为流量池视频的概率 type-float
|
|
|
:param app_type: 产品标识 type-int
|
|
|
:param algo_type: 算法类型 type-string
|
|
|
:param client_info: 用户位置信息 {"country": "国家", "province": "省份", "city": "城市"}
|
|
@@ -186,7 +188,7 @@ def video_recommend(mid, uid, size, app_type, algo_type, client_info, expire_tim
|
|
|
'rov_pool_recall': recall_result_list[0],
|
|
|
'flow_pool_recall': recall_result_list[1]
|
|
|
}
|
|
|
- rank_result = video_rank(data=data, size=size)
|
|
|
+ rank_result = video_rank(data=data, size=size, top_K=top_K, flow_pool_P=flow_pool_P)
|
|
|
end_rank = time.time()
|
|
|
log_.info('mid: {}, uid: {}, rank_result: {}, execute time = {}ms'.format(
|
|
|
mid, uid, rank_result, (end_rank - start_rank) * 1000))
|
|
@@ -216,10 +218,10 @@ def ab_test_op(rank_result, ab_code_list, app_type, mid, uid, **kwargs):
|
|
|
"""
|
|
|
# ####### 视频宽高比AB实验
|
|
|
# 对内容精选进行 视频宽高比分发实验
|
|
|
- if config_.AB_CODE['w_h_rate'] in ab_code_list and app_type in config_.AB_TEST.get('w_h_rate', []):
|
|
|
- rank_result = video_rank_by_w_h_rate(videos=rank_result)
|
|
|
- log_.info('app_type: {}, mid: {}, uid: {}, rank_by_w_h_rate_result: {}'.format(
|
|
|
- app_type, mid, uid, rank_result))
|
|
|
+ # if config_.AB_CODE['w_h_rate'] in ab_code_list and app_type in config_.AB_TEST.get('w_h_rate', []):
|
|
|
+ # rank_result = video_rank_by_w_h_rate(videos=rank_result)
|
|
|
+ # log_.info('app_type: {}, mid: {}, uid: {}, rank_by_w_h_rate_result: {}'.format(
|
|
|
+ # app_type, mid, uid, rank_result))
|
|
|
|
|
|
# 按position位置排序
|
|
|
if config_.AB_CODE['position_insert'] in ab_code_list and app_type in config_.AB_TEST.get('position_insert', []):
|
|
@@ -230,26 +232,27 @@ def ab_test_op(rank_result, ab_code_list, app_type, mid, uid, **kwargs):
|
|
|
app_type, mid, uid, rank_result))
|
|
|
|
|
|
# 相关推荐强插
|
|
|
- if config_.AB_CODE['relevant_video_op'] in ab_code_list \
|
|
|
- and app_type in config_.AB_TEST.get('relevant_video_op', []):
|
|
|
- head_vid = kwargs['head_vid']
|
|
|
- size = kwargs['size']
|
|
|
- rank_result = relevant_video_top_recommend(
|
|
|
- app_type=app_type, mid=mid, uid=uid, head_vid=head_vid, videos=rank_result, size=size
|
|
|
- )
|
|
|
- log_.info('app_type: {}, mid: {}, uid: {}, head_vid: {}, rank_by_relevant_video_op_result: {}'.format(
|
|
|
- app_type, mid, uid, head_vid, rank_result))
|
|
|
+ # if config_.AB_CODE['relevant_video_op'] in ab_code_list \
|
|
|
+ # and app_type in config_.AB_TEST.get('relevant_video_op', []):
|
|
|
+ # head_vid = kwargs['head_vid']
|
|
|
+ # size = kwargs['size']
|
|
|
+ # rank_result = relevant_video_top_recommend(
|
|
|
+ # app_type=app_type, mid=mid, uid=uid, head_vid=head_vid, videos=rank_result, size=size
|
|
|
+ # )
|
|
|
+ # log_.info('app_type: {}, mid: {}, uid: {}, head_vid: {}, rank_by_relevant_video_op_result: {}'.format(
|
|
|
+ # app_type, mid, uid, head_vid, rank_result))
|
|
|
|
|
|
return rank_result
|
|
|
|
|
|
|
|
|
-def update_redis_data(result, app_type, mid, last_rov_recall_key, expire_time=24*3600):
|
|
|
+def update_redis_data(result, app_type, mid, last_rov_recall_key, top_K, expire_time=24*3600):
|
|
|
"""
|
|
|
根据最终的排序结果更新相关redis数据
|
|
|
:param result: 排序结果
|
|
|
:param app_type: 产品标识
|
|
|
:param mid: mid
|
|
|
:param last_rov_recall_key: 用户上一次在rov召回池对应的位置 redis key
|
|
|
+ :param top_K: 保证topK为召回池视频 type-int
|
|
|
:param expire_time: 末位视频记录redis过期时间
|
|
|
:return: None
|
|
|
"""
|
|
@@ -265,8 +268,8 @@ def update_redis_data(result, app_type, mid, last_rov_recall_key, expire_time=24
|
|
|
redis_helper.add_data_with_set(key_name=preview_key_name, values=tuple(preview_video_ids), expire_time=30 * 60)
|
|
|
log_.info('preview redis update success!')
|
|
|
|
|
|
- # 将此次获取的ROV召回池config_.K末位视频id同步刷新到Redis中,方便下次快速定位到召回位置,过期时间为1天
|
|
|
- rov_recall_video = [item['videoId'] for item in result[:config_.K]
|
|
|
+ # 将此次获取的ROV召回池top_K末位视频id同步刷新到Redis中,方便下次快速定位到召回位置,过期时间为1天
|
|
|
+ rov_recall_video = [item['videoId'] for item in result[:top_K]
|
|
|
if item['pushFrom'] == config_.PUSH_FROM['rov_recall']]
|
|
|
if len(rov_recall_video) > 0:
|
|
|
if app_type == config_.APP_TYPE['APP']:
|
|
@@ -315,7 +318,7 @@ def update_local_distribute_count(videos):
|
|
|
log_.error(traceback.format_exc())
|
|
|
|
|
|
|
|
|
-def video_homepage_recommend(mid, uid, size, app_type, algo_type, client_info):
|
|
|
+def video_homepage_recommend(mid, uid, size, app_type, algo_type, client_info, ab_exp_info):
|
|
|
"""
|
|
|
首页线上推荐逻辑
|
|
|
:param mid: mid type-string
|
|
@@ -324,8 +327,10 @@ def video_homepage_recommend(mid, uid, size, app_type, algo_type, client_info):
|
|
|
:param app_type: 产品标识 type-int
|
|
|
:param algo_type: 算法类型 type-string
|
|
|
:param client_info: 用户位置信息 {"country": "国家", "province": "省份", "city": "城市"}
|
|
|
+ :param ab_exp_info: ab实验分组参数 [{"expItemId":1, "configValue":{"size":4, "K":3, ...}}, ...]
|
|
|
:return:
|
|
|
"""
|
|
|
+
|
|
|
# 对 vlog 切换10%的流量做实验
|
|
|
# 对mid进行哈希
|
|
|
# hash_mid = hashlib.md5(mid.encode('utf-8')).hexdigest()
|
|
@@ -345,8 +350,11 @@ def video_homepage_recommend(mid, uid, size, app_type, algo_type, client_info):
|
|
|
|
|
|
if app_type == config_.APP_TYPE['APP']:
|
|
|
# 票圈视频APP
|
|
|
+ top_K = config_.K
|
|
|
+ flow_pool_P = config_.P
|
|
|
# 简单召回 - 排序 - 兜底
|
|
|
- rank_result, last_rov_recall_key = video_recommend(mid=mid, uid=uid, size=size, app_type=app_type,
|
|
|
+ rank_result, last_rov_recall_key = video_recommend(mid=mid, uid=uid, app_type=app_type,
|
|
|
+ size=size, top_K=top_K, flow_pool_P=flow_pool_P,
|
|
|
algo_type=algo_type, client_info=client_info,
|
|
|
expire_time=12 * 3600)
|
|
|
# ab-test
|
|
@@ -355,22 +363,42 @@ def video_homepage_recommend(mid, uid, size, app_type, algo_type, client_info):
|
|
|
app_type=app_type, mid=mid, uid=uid)
|
|
|
# redis数据刷新
|
|
|
update_redis_data(result=result, app_type=app_type, mid=mid, last_rov_recall_key=last_rov_recall_key,
|
|
|
- expire_time=12 * 3600)
|
|
|
+ top_K=top_K, expire_time=12 * 3600)
|
|
|
+
|
|
|
else:
|
|
|
+
|
|
|
+ if ab_exp_info is None:
|
|
|
+ size = size
|
|
|
+ top_K = config_.K
|
|
|
+ flow_pool_P = config_.P
|
|
|
+ else:
|
|
|
+ exp_item_id_list = [item.get('expItemId') for item in ab_exp_info]
|
|
|
+ if config_.EXP_ITEM_ID['rec_size'] in exp_item_id_list:
|
|
|
+ config_value = ab_exp_info[exp_item_id_list.index(config_.EXP_ITEM_ID['rec_size'])].get('configValue')
|
|
|
+ size = config_value.get('size', 4)
|
|
|
+ top_K = config_value.get('K', 3)
|
|
|
+ flow_pool_P = config_value.get('P', 0.3)
|
|
|
+ else:
|
|
|
+ size = size
|
|
|
+ top_K = config_.K
|
|
|
+ flow_pool_P = config_.P
|
|
|
+
|
|
|
# 简单召回 - 排序 - 兜底
|
|
|
- rank_result, last_rov_recall_key = video_recommend(mid=mid, uid=uid, size=size, app_type=app_type,
|
|
|
+ rank_result, last_rov_recall_key = video_recommend(mid=mid, uid=uid, app_type=app_type,
|
|
|
+ size=size, top_K=top_K, flow_pool_P=flow_pool_P,
|
|
|
algo_type=algo_type, client_info=client_info)
|
|
|
# ab-test
|
|
|
result = ab_test_op(rank_result=rank_result,
|
|
|
ab_code_list=[config_.AB_CODE['position_insert']],
|
|
|
app_type=app_type, mid=mid, uid=uid)
|
|
|
# redis数据刷新
|
|
|
- update_redis_data(result=result, app_type=app_type, mid=mid, last_rov_recall_key=last_rov_recall_key)
|
|
|
+ update_redis_data(result=result, app_type=app_type, mid=mid, last_rov_recall_key=last_rov_recall_key,
|
|
|
+ top_K=top_K)
|
|
|
|
|
|
return result
|
|
|
|
|
|
|
|
|
-def video_relevant_recommend(video_id, mid, uid, size, app_type):
|
|
|
+def video_relevant_recommend(video_id, mid, uid, size, app_type, ab_exp_info):
|
|
|
"""
|
|
|
相关推荐逻辑
|
|
|
:param video_id: 相关推荐的头部视频id
|
|
@@ -378,21 +406,37 @@ def video_relevant_recommend(video_id, mid, uid, size, app_type):
|
|
|
:param uid: uid type-string
|
|
|
:param size: 请求视频数量 type-int
|
|
|
:param app_type: 产品标识 type-int
|
|
|
+ :param ab_exp_info: ab实验分组参数 [{"expItemId":1, "configValue":{"size":4, "K":3, ...}}, ...]
|
|
|
:return: videos type-list
|
|
|
"""
|
|
|
- # videos = video_recommend(mid=mid, uid=uid, size=size, app_type=app_type, algo_type='', client_info=None)
|
|
|
+
|
|
|
+ if ab_exp_info is None:
|
|
|
+ size = size
|
|
|
+ top_K = config_.K
|
|
|
+ flow_pool_P = config_.P
|
|
|
+ else:
|
|
|
+ exp_item_id_list = [item.get('expItemId') for item in ab_exp_info]
|
|
|
+ if config_.EXP_ITEM_ID['rec_size'] in exp_item_id_list:
|
|
|
+ config_value = ab_exp_info[exp_item_id_list.index(config_.EXP_ITEM_ID['rec_size'])].get('configValue')
|
|
|
+ size = config_value.get('size', 4)
|
|
|
+ top_K = config_value.get('K', 3)
|
|
|
+ flow_pool_P = config_value.get('P', 0.3)
|
|
|
+ else:
|
|
|
+ size = size
|
|
|
+ top_K = config_.K
|
|
|
+ flow_pool_P = config_.P
|
|
|
+
|
|
|
# 简单召回 - 排序 - 兜底
|
|
|
- rank_result, last_rov_recall_key = video_recommend(mid=mid, uid=uid, size=size, app_type=app_type,
|
|
|
+ rank_result, last_rov_recall_key = video_recommend(mid=mid, uid=uid, app_type=app_type,
|
|
|
+ size=size, top_K=top_K, flow_pool_P=flow_pool_P,
|
|
|
algo_type='', client_info=None)
|
|
|
# ab-test
|
|
|
result = ab_test_op(rank_result=rank_result,
|
|
|
- ab_code_list=[
|
|
|
- config_.AB_CODE['position_insert'],
|
|
|
- config_.AB_CODE['relevant_video_op']
|
|
|
- ],
|
|
|
+ ab_code_list=[config_.AB_CODE['position_insert'], config_.AB_CODE['relevant_video_op']],
|
|
|
app_type=app_type, mid=mid, uid=uid, head_vid=video_id, size=size)
|
|
|
# redis数据刷新
|
|
|
- update_redis_data(result=result, app_type=app_type, mid=mid, last_rov_recall_key=last_rov_recall_key)
|
|
|
+ update_redis_data(result=result, app_type=app_type, mid=mid, last_rov_recall_key=last_rov_recall_key,
|
|
|
+ top_K=top_K)
|
|
|
|
|
|
return result
|
|
|
|