|
@@ -10,7 +10,7 @@ import config
|
|
|
from log import Log
|
|
|
from config import set_config
|
|
|
from video_recall import PoolRecall
|
|
|
-from video_rank import video_rank, bottom_strategy, video_rank_by_w_h_rate, video_rank_with_old_video, bottom_strategy2
|
|
|
+from video_rank import video_new_rank,video_rank,refactor_video_rank, bottom_strategy, video_rank_by_w_h_rate, video_rank_with_old_video, bottom_strategy2
|
|
|
from db_helper import RedisHelper
|
|
|
import gevent
|
|
|
from utils import FilterVideos, get_user_has30day_return
|
|
@@ -180,7 +180,7 @@ def video_recommend(request_id, mid, uid, size, top_K, flow_pool_P, app_type, al
|
|
|
pool_recall = PoolRecall(request_id=request_id,
|
|
|
app_type=app_type, mid=mid, uid=uid, ab_code=ab_code,
|
|
|
client_info=client_info, rule_key=rule_key, data_key=data_key, no_op_flag=no_op_flag,
|
|
|
- params=params, rule_key_30day=rule_key_30day, shield_config=shield_config)
|
|
|
+ params=params, rule_key_30day=rule_key_30day, shield_config=shield_config, video_id= video_id)
|
|
|
|
|
|
|
|
|
|
|
@@ -281,6 +281,9 @@ def video_recommend(request_id, mid, uid, size, top_K, flow_pool_P, app_type, al
|
|
|
'rov_pool_recall': recall_result_list[0],
|
|
|
'flow_pool_recall': recall_result_list[2]
|
|
|
}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
rank_result = video_rank(data=data, size=size, top_K=top_K, flow_pool_P=float(flow_pool_P))
|
|
|
|
|
|
|
|
@@ -298,6 +301,7 @@ def video_recommend(request_id, mid, uid, size, top_K, flow_pool_P, app_type, al
|
|
|
|
|
|
|
|
|
|
|
|
+
|
|
|
result['rankResult'] = rank_result
|
|
|
result['rankTime'] = (time.time() - start_rank) * 1000
|
|
|
|
|
@@ -335,6 +339,179 @@ def video_recommend(request_id, mid, uid, size, top_K, flow_pool_P, app_type, al
|
|
|
return result
|
|
|
|
|
|
|
|
|
+def new_video_recommend(request_id, mid, uid, size, top_K, flow_pool_P, app_type, algo_type, client_info,
|
|
|
+ expire_time=24*3600, ab_code=config_.AB_CODE['initial'], rule_key='', data_key='',
|
|
|
+ no_op_flag=False, old_video_index=-1, video_id=None, params=None, rule_key_30day=None,
|
|
|
+ shield_config=None):
|
|
|
+ """
|
|
|
+ 首页线上推荐逻辑
|
|
|
+ :param request_id: request_id
|
|
|
+ :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": "城市"}
|
|
|
+ :param expire_time: 末位视频记录redis过期时间
|
|
|
+ :param ab_code: AB实验code
|
|
|
+ :param video_id: 相关推荐头部视频id
|
|
|
+ :param params:
|
|
|
+ :return:
|
|
|
+ """
|
|
|
+
|
|
|
+ result = {}
|
|
|
+ result['rankResult'] = []
|
|
|
+
|
|
|
+ start_recall = time.time()
|
|
|
+
|
|
|
+
|
|
|
+ city_code_list = [code for _, code in config_.CITY_CODE.items()]
|
|
|
+
|
|
|
+ province_code = client_info.get('provinceCode', '-1')
|
|
|
+
|
|
|
+ city_code = client_info.get('cityCode', '-1')
|
|
|
+
|
|
|
+ if city_code in city_code_list:
|
|
|
+
|
|
|
+ region_code = city_code
|
|
|
+ else:
|
|
|
+ region_code = province_code
|
|
|
+ if region_code == '':
|
|
|
+ region_code = '-1'
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ pool_recall = PoolRecall(request_id=request_id,
|
|
|
+ app_type=app_type, mid=mid, uid=uid, ab_code=ab_code,
|
|
|
+ client_info=client_info, rule_key=rule_key, data_key=data_key, no_op_flag=no_op_flag,
|
|
|
+ params=params, rule_key_30day=rule_key_30day, shield_config=shield_config, video_id= video_id)
|
|
|
+ if app_type in [config_.APP_TYPE['LAO_HAO_KAN_VIDEO'], config_.APP_TYPE['ZUI_JING_QI']]:
|
|
|
+ t = [gevent.spawn(pool_recall.get_region_hour_recall, size, region_code),
|
|
|
+ gevent.spawn(pool_recall.get_region_day_recall, size, region_code),
|
|
|
+ gevent.spawn(pool_recall.get_selected_recall, size, region_code),
|
|
|
+ gevent.spawn(pool_recall.get_no_selected_recall, size, region_code)
|
|
|
+ ]
|
|
|
+ else:
|
|
|
+ t = [
|
|
|
+ gevent.spawn(pool_recall.get_region_hour_recall, size, region_code),
|
|
|
+ gevent.spawn(pool_recall.get_region_day_recall, size, region_code),
|
|
|
+ gevent.spawn(pool_recall.get_selected_recall, size, region_code),
|
|
|
+ gevent.spawn(pool_recall.get_no_selected_recall, size, region_code),
|
|
|
+ gevent.spawn(pool_recall.flow_pool_recall, size, config_.QUICK_FLOW_POOL_ID),
|
|
|
+ gevent.spawn(pool_recall.flow_pool_recall, size)]
|
|
|
+
|
|
|
+ if ab_code ==60049:
|
|
|
+ t.append(gevent.spawn(pool_recall.get_sim_hot_item_reall))
|
|
|
+ gevent.joinall(t)
|
|
|
+
|
|
|
+ all_recall_result_list = [i.get() for i in t]
|
|
|
+ all_recall_result = []
|
|
|
+
|
|
|
+ result['recallTime'] = (time.time() - start_recall) * 1000
|
|
|
+
|
|
|
+ if not all_recall_result_list or len(all_recall_result_list)==0:
|
|
|
+ return result
|
|
|
+ for recall_item in all_recall_result_list:
|
|
|
+ if not recall_item or len(recall_item)==0:
|
|
|
+ continue
|
|
|
+ for per_item in recall_item:
|
|
|
+ all_recall_result.append(per_item)
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ recall_dict = {}
|
|
|
+ fast_flow_set = set('')
|
|
|
+ flow_flow_set = set('')
|
|
|
+ region_h_recall = []
|
|
|
+ region_day_recall = []
|
|
|
+ select_day_recall = []
|
|
|
+ no_selected_recall = []
|
|
|
+ sim_hot_recall = []
|
|
|
+ flow_recall = []
|
|
|
+ flowFlag_dict = {}
|
|
|
+ for per_item in all_recall_result:
|
|
|
+
|
|
|
+ vId = int(per_item.get("videoId",0))
|
|
|
+ if vId==0:
|
|
|
+ continue
|
|
|
+ recall_name = per_item.get("pushFrom",'')
|
|
|
+ flow_pool = per_item.get("flowPool", '')
|
|
|
+ if flow_pool != '':
|
|
|
+ flow_pool_id = int(flow_pool.split('#')[0])
|
|
|
+ if flow_pool_id == config_.QUICK_FLOW_POOL_ID:
|
|
|
+ fast_flow_set.add(vId)
|
|
|
+ else:
|
|
|
+ flow_flow_set.add(vId)
|
|
|
+ flowFlag_dict[vId] = flow_pool
|
|
|
+
|
|
|
+
|
|
|
+ if vId not in recall_dict:
|
|
|
+ if recall_name == config_.PUSH_FROM['rov_recall_region_h']:
|
|
|
+ region_h_recall.append(per_item)
|
|
|
+ elif recall_name == config_.PUSH_FROM['rov_recall_region_24h']:
|
|
|
+ region_day_recall.append(per_item)
|
|
|
+ elif recall_name == config_.PUSH_FROM['rov_recall_24h']:
|
|
|
+ select_day_recall.append(per_item)
|
|
|
+ elif recall_name == config_.PUSH_FROM['rov_recall_24h_dup']:
|
|
|
+ no_selected_recall.append(per_item)
|
|
|
+ elif recall_name == config_.PUSH_FROM['sim_hot_vid_recall']:
|
|
|
+ sim_hot_recall.append(per_item)
|
|
|
+ elif recall_name == config_.PUSH_FROM['flow_recall']:
|
|
|
+ flow_recall.append(per_item)
|
|
|
+ if vId not in recall_dict:
|
|
|
+ recall_dict[vId] = recall_name
|
|
|
+ else:
|
|
|
+ recall_name = recall_dict[vId] + "," + recall_name
|
|
|
+ recall_dict[vId] = recall_name
|
|
|
+
|
|
|
+
|
|
|
+ filter_ = FilterVideos(request_id=request_id,
|
|
|
+ app_type=app_type, mid=mid, uid=uid, video_ids=list(recall_dict.keys()))
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ all_recall_list = filter_.filter_videos_new(pool_type='rov', region_code=region_code, shield_config=shield_config)
|
|
|
+
|
|
|
+
|
|
|
+ start_rank = time.time()
|
|
|
+
|
|
|
+ redis_helper = RedisHelper()
|
|
|
+ quick_flow_pool_P = redis_helper.get_data_from_redis(
|
|
|
+ key_name=f"{config_.QUICK_FLOWPOOL_DISTRIBUTE_RATE_KEY_NAME_PREFIX}{config_.QUICK_FLOW_POOL_ID}"
|
|
|
+ )
|
|
|
+ if quick_flow_pool_P:
|
|
|
+ flow_pool_P = quick_flow_pool_P
|
|
|
+
|
|
|
+ rank_result= []
|
|
|
+ if ab_code==60048 or ab_code==60049:
|
|
|
+ rank_ids, add_flow_set = video_new_rank(videoIds=all_recall_list,fast_flow_set=fast_flow_set, flow_set=flow_flow_set,size=size, top_K=top_K, flow_pool_P=float(flow_pool_P))
|
|
|
+
|
|
|
+ for rank_item in rank_ids:
|
|
|
+ rank_id = rank_item[0]
|
|
|
+ rank_score = rank_item[1]
|
|
|
+ pushFrom = recall_dict.get(rank_id, '')
|
|
|
+
|
|
|
+ flowPoolFlag = ''
|
|
|
+ if rank_id in add_flow_set:
|
|
|
+ flowPoolFlag = flowFlag_dict.get(rank_id,'')
|
|
|
+ rank_result.append({'videoId': rank_id, 'flowPool': flowPoolFlag,
|
|
|
+ 'rovScore': rank_score, 'pushFrom': pushFrom,
|
|
|
+ 'abCode': ab_code})
|
|
|
+
|
|
|
+
|
|
|
+ else:
|
|
|
+ all_dup_recall_result = region_h_recall+region_day_recall+select_day_recall+no_selected_recall+flow_recall
|
|
|
+ rank_result = refactor_video_rank(rov_recall_rank=all_dup_recall_result,fast_flow_set=fast_flow_set, flow_set=flow_flow_set, size=size, top_K=top_K, flow_pool_P=float(flow_pool_P))
|
|
|
+
|
|
|
+ result['rankResult'] = rank_result
|
|
|
+ result['rankTime'] = (time.time() - start_rank) * 1000
|
|
|
+ return result
|
|
|
+
|
|
|
+
|
|
|
|
|
|
def ab_test_op(rank_result, ab_code_list, app_type, mid, uid, **kwargs):
|
|
|
"""
|
|
@@ -498,6 +675,66 @@ def update_redis_data(result, app_type, mid, top_K, expire_time=24*3600):
|
|
|
log_.error(traceback.format_exc())
|
|
|
|
|
|
|
|
|
+def update_flow_redis_data(result, app_type, mid, top_K, expire_time=24*3600):
|
|
|
+ """
|
|
|
+ 根据最终的排序结果更新相关redis数据
|
|
|
+ :param result: 排序结果
|
|
|
+ :param app_type: 产品标识
|
|
|
+ :param mid: mid
|
|
|
+ :param top_K: 保证topK为召回池视频 type-int
|
|
|
+ :param expire_time: 末位视频记录redis过期时间
|
|
|
+ :return: None
|
|
|
+ """
|
|
|
+
|
|
|
+ try:
|
|
|
+ redis_helper = RedisHelper()
|
|
|
+
|
|
|
+ if mid and mid != 'null':
|
|
|
+
|
|
|
+
|
|
|
+ preview_key_name = f"{config_.PREVIEW_KEY_PREFIX}{app_type}:{mid}"
|
|
|
+ preview_video_ids = [int(item['videoId']) for item in result]
|
|
|
+ if preview_video_ids:
|
|
|
+
|
|
|
+ redis_helper.add_data_with_set(key_name=preview_key_name, values=tuple(preview_video_ids), expire_time=30 * 60)
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ if app_type not in [config_.APP_TYPE['LAO_HAO_KAN_VIDEO'], config_.APP_TYPE['ZUI_JING_QI']]:
|
|
|
+
|
|
|
+ switch = redis_helper.get_data_from_redis(key_name=config_.IN_FLOW_POOL_COUNT_SWITCH_KEY_NAME)
|
|
|
+ if switch is not None:
|
|
|
+ if int(switch) == 1:
|
|
|
+ flow_recall_video = [item for item in result if item.get('flowPool', None) is not None]
|
|
|
+ else:
|
|
|
+ flow_recall_video = [item for item in result if
|
|
|
+ item['pushFrom'] == config_.PUSH_FROM['flow_recall']]
|
|
|
+ else:
|
|
|
+ flow_recall_video = [item for item in result if item['pushFrom'] == config_.PUSH_FROM['flow_recall']]
|
|
|
+ if flow_recall_video:
|
|
|
+ update_local_distribute_count(flow_recall_video)
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ if app_type == config_.APP_TYPE['APP']:
|
|
|
+
|
|
|
+ return
|
|
|
+ limit_video_id_list = redis_helper.get_data_from_set(
|
|
|
+ key_name=f"{config_.KEY_NAME_PREFIX_LIMIT_VIDEO_SET}{datetime.today().strftime('%Y%m%d')}"
|
|
|
+ )
|
|
|
+ if limit_video_id_list is not None:
|
|
|
+ limit_video_id_list = [int(item) for item in limit_video_id_list]
|
|
|
+ for item in result:
|
|
|
+ video_id = item['videoId']
|
|
|
+ if video_id in limit_video_id_list:
|
|
|
+ key_name = f"{config_.KEY_NAME_PREFIX_LIMIT_VIDEO_DISTRIBUTE_COUNT}{video_id}"
|
|
|
+ redis_helper.setnx_key(key_name=key_name, value=0, expire_time=24*2600)
|
|
|
+ redis_helper.incr_key(key_name=key_name, amount=1, expire_time=24*3600)
|
|
|
+
|
|
|
+ except Exception as e:
|
|
|
+ log_.error("update redis data fail!")
|
|
|
+ log_.error(traceback.format_exc())
|
|
|
+
|
|
|
def update_local_distribute_count(videos):
|
|
|
"""
|
|
|
更新本地分发数
|
|
@@ -1087,7 +1324,18 @@ def video_homepage_recommend(request_id, mid, uid, size, app_type, algo_type,
|
|
|
|
|
|
|
|
|
get_result_st = time.time()
|
|
|
- result = video_recommend(request_id=request_id,
|
|
|
+ print("ab_code:", ab_code)
|
|
|
+ if ab_code == 60047 or ab_code == 60048 or ab_code == 60049:
|
|
|
+ result = new_video_recommend(request_id=request_id,
|
|
|
+ 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_code=ab_code, expire_time=expire_time,
|
|
|
+ rule_key=rule_key, data_key=data_key,
|
|
|
+ no_op_flag=no_op_flag, old_video_index=old_video_index,
|
|
|
+ params=params, rule_key_30day=rule_key_30day, shield_config=shield_config)
|
|
|
+ else:
|
|
|
+ result = video_recommend(request_id=request_id,
|
|
|
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,
|
|
@@ -1115,7 +1363,10 @@ def video_homepage_recommend(request_id, mid, uid, size, app_type, algo_type,
|
|
|
|
|
|
|
|
|
update_redis_st = time.time()
|
|
|
- update_redis_data(result=rank_result, app_type=app_type, mid=mid, top_K=top_K)
|
|
|
+ if ab_code == 60047 or ab_code == 60048 or ab_code == 60049:
|
|
|
+ update_flow_redis_data(result=rank_result, app_type=app_type, mid=mid, top_K=top_K)
|
|
|
+ else:
|
|
|
+ update_redis_data(result=rank_result, app_type=app_type, mid=mid, top_K=top_K)
|
|
|
|
|
|
|
|
|
|
|
@@ -1176,7 +1427,19 @@ def video_relevant_recommend(request_id, video_id, mid, uid, size, app_type, ab_
|
|
|
|
|
|
|
|
|
get_result_st = time.time()
|
|
|
- result = video_recommend(request_id=request_id,
|
|
|
+
|
|
|
+ if ab_code == 60047 or ab_code == 60048 or ab_code == 60049:
|
|
|
+ result = new_video_recommend(request_id=request_id,
|
|
|
+ mid=mid, uid=uid, app_type=app_type,
|
|
|
+ size=size, top_K=top_K, flow_pool_P=flow_pool_P,
|
|
|
+ algo_type='', client_info=client_info,
|
|
|
+ ab_code=ab_code, expire_time=expire_time,
|
|
|
+ rule_key=rule_key, data_key=data_key, no_op_flag=no_op_flag,
|
|
|
+ old_video_index=old_video_index, video_id=video_id,
|
|
|
+ params=params, rule_key_30day=rule_key_30day, shield_config=shield_config)
|
|
|
+
|
|
|
+ else:
|
|
|
+ result = video_recommend(request_id=request_id,
|
|
|
mid=mid, uid=uid, app_type=app_type,
|
|
|
size=size, top_K=top_K, flow_pool_P=flow_pool_P,
|
|
|
algo_type='', client_info=client_info,
|
|
@@ -1205,7 +1468,10 @@ def video_relevant_recommend(request_id, video_id, mid, uid, size, app_type, ab_
|
|
|
|
|
|
|
|
|
update_redis_st = time.time()
|
|
|
- update_redis_data(result=rank_result, app_type=app_type, mid=mid, top_K=top_K)
|
|
|
+ if ab_code == 60047 or ab_code == 60048 or ab_code == 60049:
|
|
|
+ update_flow_redis_data(result=rank_result, app_type=app_type, mid=mid, top_K=top_K)
|
|
|
+ else:
|
|
|
+ update_redis_data(result=rank_result, app_type=app_type, mid=mid, top_K=top_K)
|
|
|
|
|
|
|
|
|
|