ad_recommend.py 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588
  1. import traceback
  2. import datetime
  3. from utils import RedisHelper
  4. from config import set_config
  5. from log import Log
  6. log_ = Log()
  7. config_ = set_config()
  8. redis_helper = RedisHelper()
  9. def get_params(ab_exp_info, ab_test_code):
  10. """
  11. 根据实验分组给定对应的参数
  12. :param ab_exp_info: AB实验组参数
  13. :param ab_test_code: 用户对应的ab组
  14. :return:
  15. """
  16. abtest_id, abtest_config_tag = None, None
  17. ad_abtest_id_list = [key.split('-')[0] for key in config_.AD_ABTEST_CONFIG]
  18. # 获取广告实验配置
  19. config_value_dict = {}
  20. if ab_exp_info:
  21. ab_exp_list = ab_exp_info.get('ab_test002', None)
  22. if ab_exp_list:
  23. for ab_item in ab_exp_list:
  24. ab_exp_code = ab_item.get('abExpCode', None)
  25. if not ab_exp_code:
  26. continue
  27. if ab_exp_code in ad_abtest_id_list:
  28. config_value = ab_item.get('configValue', None)
  29. if config_value:
  30. config_value_dict[str(ab_exp_code)] = eval(str(config_value))
  31. if len(config_value_dict) > 0:
  32. for ab_exp_code, config_value in config_value_dict.items():
  33. for tag, value in config_value.items():
  34. if ab_test_code in value:
  35. abtest_id = ab_exp_code
  36. abtest_config_tag = tag
  37. break
  38. return abtest_id, abtest_config_tag
  39. def get_threshold(abtest_id, abtest_config_tag, ab_test_code, mid_group, care_model_status, abtest_param):
  40. """获取对应的阈值"""
  41. # 判断是否是关怀模式实验
  42. care_model_status_param = abtest_param.get('care_model_status_param', None)
  43. care_model_ab_mid_group = abtest_param.get('care_model_ab_mid_group', [])
  44. if care_model_status_param is None:
  45. # 无关怀模式实验
  46. threshold_key_name_prefix = config_.KEY_NAME_PREFIX_AD_THRESHOLD
  47. else:
  48. # 关怀模式实验
  49. if care_model_status is None or len(care_model_ab_mid_group) == 0 or care_model_status == 'null':
  50. # 参数缺失,走默认
  51. threshold_key_name_prefix = config_.KEY_NAME_PREFIX_AD_THRESHOLD
  52. elif int(care_model_status) == int(care_model_status_param) and mid_group in care_model_ab_mid_group:
  53. # 实验匹配,获取对应的阈值
  54. threshold_key_name_prefix = config_.KEY_NAME_PREFIX_AD_THRESHOLD_CARE_MODEL
  55. else:
  56. threshold_key_name_prefix = config_.KEY_NAME_PREFIX_AD_THRESHOLD
  57. threshold_key_name = f"{threshold_key_name_prefix}{abtest_id}:{abtest_config_tag}:{ab_test_code}:{mid_group}"
  58. threshold = redis_helper.get_data_from_redis(key_name=threshold_key_name)
  59. if threshold is None:
  60. threshold = 0
  61. else:
  62. threshold = float(threshold)
  63. return threshold
  64. def predict_mid_video_res(now_date, mid, video_id, abtest_param, abtest_id, abtest_config_tag, ab_test_code, care_model_status):
  65. now_dt = datetime.datetime.strftime(now_date, '%Y%m%d')
  66. user_data_key = abtest_param['user'].get('data')
  67. user_rule_key = abtest_param['user'].get('rule')
  68. video_data_key = abtest_param['video'].get('data')
  69. group_class_key = abtest_param.get('group_class_key')
  70. no_ad_mid_group_list = abtest_param.get('no_ad_mid_group_list', [])
  71. # 判断mid所属分组
  72. mid_group_key_name = f"{config_.KEY_NAME_PREFIX_MID_GROUP}{group_class_key}:{mid}"
  73. mid_group = redis_helper.get_data_from_redis(key_name=mid_group_key_name)
  74. if mid_group is None:
  75. mid_group = 'mean_group'
  76. # 判断用户是否在免广告用户组列表中
  77. if mid_group in no_ad_mid_group_list:
  78. # 在免广告用户组列表中,则不出广告
  79. ad_predict = 1
  80. result = {
  81. 'mid_group': mid_group,
  82. 'ad_predict': ad_predict
  83. }
  84. else:
  85. # 获取用户组分享率
  86. group_share_rate_key = f"{config_.KEY_NAME_PREFIX_AD_GROUP}{user_data_key}:{user_rule_key}:{now_dt}"
  87. if not redis_helper.key_exists(group_share_rate_key):
  88. redis_dt = datetime.datetime.strftime(now_date - datetime.timedelta(days=1), '%Y%m%d')
  89. group_share_rate_key = f"{config_.KEY_NAME_PREFIX_AD_GROUP}{user_data_key}:{user_rule_key}:{redis_dt}"
  90. group_share_rate = redis_helper.get_score_with_value(key_name=group_share_rate_key, value=mid_group)
  91. # 获取视频分享率
  92. video_share_rate_key = f"{config_.KEY_NAME_PREFIX_AD_VIDEO}{video_data_key}:{now_dt}"
  93. if not redis_helper.key_exists(video_share_rate_key):
  94. redis_dt = datetime.datetime.strftime(now_date - datetime.timedelta(days=1), '%Y%m%d')
  95. video_share_rate_key = f"{config_.KEY_NAME_PREFIX_AD_VIDEO}{video_data_key}:{redis_dt}"
  96. video_share_rate = redis_helper.get_score_with_value(key_name=video_share_rate_key, value=int(video_id))
  97. if video_share_rate is None:
  98. video_share_rate = redis_helper.get_score_with_value(key_name=video_share_rate_key, value=-1)
  99. # 计算 mid-video 分享率
  100. if group_share_rate is None or video_share_rate is None:
  101. return None
  102. mid_video_predict_res = float(group_share_rate) * float(video_share_rate)
  103. # 获取对应的阈值
  104. threshold = get_threshold(
  105. abtest_id=abtest_id,
  106. abtest_config_tag=abtest_config_tag,
  107. ab_test_code=ab_test_code,
  108. mid_group=mid_group,
  109. care_model_status=care_model_status,
  110. abtest_param=abtest_param
  111. )
  112. # 阈值判断
  113. if mid_video_predict_res > threshold:
  114. # 大于阈值,出广告
  115. ad_predict = 2
  116. else:
  117. # 否则,不出广告
  118. ad_predict = 1
  119. result = {
  120. 'mid_group': mid_group,
  121. 'group_share_rate': group_share_rate,
  122. 'video_share_rate': video_share_rate,
  123. 'mid_video_predict_res': mid_video_predict_res,
  124. 'threshold': threshold,
  125. 'ad_predict': ad_predict}
  126. return result
  127. 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):
  128. now_dt = datetime.datetime.strftime(now_date, '%Y%m%d')
  129. # 判断mid所属分组
  130. group_class_key = abtest_param.get('group_class_key')
  131. mid_group_key_name = f"{config_.KEY_NAME_PREFIX_MID_GROUP}{group_class_key}:{mid}"
  132. mid_group = redis_helper.get_data_from_redis(key_name=mid_group_key_name)
  133. if mid_group is None:
  134. mid_group = 'mean_group'
  135. # 判断用户是否在免广告用户组列表中
  136. no_ad_mid_group_list = abtest_param.get('no_ad_mid_group_list', [])
  137. if mid_group in no_ad_mid_group_list:
  138. # 在免广告用户组列表中,则不出广告
  139. ad_predict = 1
  140. result = {
  141. 'mid_group': mid_group,
  142. 'ad_predict': ad_predict
  143. }
  144. else:
  145. # 获取用户组出广告后分享的概率
  146. share_user_data_key = abtest_param['share']['user'].get('data')
  147. share_user_rule_key = abtest_param['share']['user'].get('rule')
  148. group_share_rate_key = \
  149. f"{config_.KEY_NAME_PREFIX_AD_GROUP}{share_user_data_key}:{share_user_rule_key}:{now_dt}"
  150. if not redis_helper.key_exists(group_share_rate_key):
  151. redis_dt = datetime.datetime.strftime(now_date - datetime.timedelta(days=1), '%Y%m%d')
  152. group_share_rate_key = \
  153. f"{config_.KEY_NAME_PREFIX_AD_GROUP}{share_user_data_key}:{share_user_rule_key}:{redis_dt}"
  154. group_share_rate = redis_helper.get_score_with_value(key_name=group_share_rate_key, value=mid_group)
  155. # 获取视频出广告后分享的概率
  156. share_video_data_key = abtest_param['share']['video'].get('data')
  157. video_share_rate_key = f"{config_.KEY_NAME_PREFIX_AD_VIDEO}{share_video_data_key}:{now_dt}"
  158. if not redis_helper.key_exists(video_share_rate_key):
  159. redis_dt = datetime.datetime.strftime(now_date - datetime.timedelta(days=1), '%Y%m%d')
  160. video_share_rate_key = f"{config_.KEY_NAME_PREFIX_AD_VIDEO}{share_video_data_key}:{redis_dt}"
  161. video_share_rate = redis_helper.get_score_with_value(key_name=video_share_rate_key, value=int(video_id))
  162. if video_share_rate is None:
  163. video_share_rate = redis_helper.get_score_with_value(key_name=video_share_rate_key, value=-1)
  164. # 获取用户组出广告后不直接跳出的概率
  165. out_user_data_key = abtest_param['out']['user'].get('data')
  166. out_user_rule_key = abtest_param['out']['user'].get('rule')
  167. group_out_rate_key = \
  168. f"{config_.KEY_NAME_PREFIX_AD_GROUP}{out_user_data_key}:{out_user_rule_key}:{now_dt}"
  169. if not redis_helper.key_exists(group_out_rate_key):
  170. redis_dt = datetime.datetime.strftime(now_date - datetime.timedelta(days=1), '%Y%m%d')
  171. group_out_rate_key = \
  172. f"{config_.KEY_NAME_PREFIX_AD_GROUP}{out_user_data_key}:{out_user_rule_key}:{redis_dt}"
  173. group_out_rate = redis_helper.get_score_with_value(key_name=group_out_rate_key, value=mid_group)
  174. # 获取视频出广告后不直接跳出的概率
  175. out_video_data_key = abtest_param['out']['video'].get('data')
  176. video_out_rate_key = f"{config_.KEY_NAME_PREFIX_AD_VIDEO}{out_video_data_key}:{now_dt}"
  177. if not redis_helper.key_exists(video_out_rate_key):
  178. redis_dt = datetime.datetime.strftime(now_date - datetime.timedelta(days=1), '%Y%m%d')
  179. video_out_rate_key = f"{config_.KEY_NAME_PREFIX_AD_VIDEO}{out_video_data_key}:{redis_dt}"
  180. video_out_rate = redis_helper.get_score_with_value(key_name=video_out_rate_key, value=int(video_id))
  181. if video_out_rate is None:
  182. video_out_rate = redis_helper.get_score_with_value(key_name=video_out_rate_key, value=-1)
  183. # 计算 mid-video 预测值
  184. if group_share_rate is None or video_share_rate is None or group_out_rate is None or video_out_rate is None:
  185. return None
  186. # 加权融合
  187. share_weight = abtest_param['mix_param']['share_weight']
  188. out_weight = abtest_param['mix_param']['out_weight']
  189. group_rate = share_weight * float(group_share_rate) + out_weight * float(group_out_rate)
  190. video_rate = share_weight * float(video_share_rate) + out_weight * float(video_out_rate)
  191. mid_video_predict_res = group_rate * video_rate
  192. # 获取对应的阈值
  193. threshold = get_threshold(
  194. abtest_id=abtest_id,
  195. abtest_config_tag=abtest_config_tag,
  196. ab_test_code=ab_test_code,
  197. mid_group=mid_group,
  198. care_model_status=care_model_status,
  199. abtest_param=abtest_param
  200. )
  201. # 阈值判断
  202. if mid_video_predict_res > threshold:
  203. # 大于阈值,出广告
  204. ad_predict = 2
  205. else:
  206. # 否则,不出广告
  207. ad_predict = 1
  208. result = {
  209. 'mid_group': mid_group,
  210. 'group_share_rate': group_share_rate,
  211. 'video_share_rate': video_share_rate,
  212. 'group_out_rate': group_out_rate,
  213. 'video_out_rate': video_out_rate,
  214. 'group_rate': group_rate,
  215. 'video_rate': video_rate,
  216. 'mid_video_predict_res': mid_video_predict_res,
  217. 'threshold': threshold,
  218. 'ad_predict': ad_predict}
  219. return result
  220. 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):
  221. now_dt = datetime.datetime.strftime(now_date, '%Y%m%d')
  222. # 判断mid所属分组
  223. group_class_key = abtest_param.get('group_class_key')
  224. mid_group_key_name = f"{config_.KEY_NAME_PREFIX_MID_GROUP}{group_class_key}:{mid}"
  225. mid_group = redis_helper.get_data_from_redis(key_name=mid_group_key_name)
  226. if mid_group is None:
  227. mid_group = 'mean_group'
  228. # 判断用户是否在免广告用户组列表中
  229. no_ad_mid_group_list = abtest_param.get('no_ad_mid_group_list', [])
  230. if mid_group in no_ad_mid_group_list:
  231. # 在免广告用户组列表中,则不出广告
  232. ad_predict = 1
  233. result = {
  234. 'mid_group': mid_group,
  235. 'ad_predict': ad_predict
  236. }
  237. else:
  238. # 获取用户组出广告后分享的概率
  239. share_user_data_key = abtest_param['share']['user'].get('data')
  240. share_user_rule_key = abtest_param['share']['user'].get('rule')
  241. group_share_rate_key = \
  242. f"{config_.KEY_NAME_PREFIX_AD_GROUP}{share_user_data_key}:{share_user_rule_key}:{now_dt}"
  243. if not redis_helper.key_exists(group_share_rate_key):
  244. redis_dt = datetime.datetime.strftime(now_date - datetime.timedelta(days=1), '%Y%m%d')
  245. group_share_rate_key = \
  246. f"{config_.KEY_NAME_PREFIX_AD_GROUP}{share_user_data_key}:{share_user_rule_key}:{redis_dt}"
  247. group_share_rate = redis_helper.get_score_with_value(key_name=group_share_rate_key, value=mid_group)
  248. # 获取视频出广告后分享的概率
  249. share_video_data_key = abtest_param['share']['video'].get('data')
  250. video_share_rate_key = f"{config_.KEY_NAME_PREFIX_AD_VIDEO}{share_video_data_key}:{now_dt}"
  251. if not redis_helper.key_exists(video_share_rate_key):
  252. redis_dt = datetime.datetime.strftime(now_date - datetime.timedelta(days=1), '%Y%m%d')
  253. video_share_rate_key = f"{config_.KEY_NAME_PREFIX_AD_VIDEO}{share_video_data_key}:{redis_dt}"
  254. video_share_rate = redis_helper.get_score_with_value(key_name=video_share_rate_key, value=int(video_id))
  255. if video_share_rate is None:
  256. video_share_rate = redis_helper.get_score_with_value(key_name=video_share_rate_key, value=-1)
  257. # 获取用户组出广告后不直接跳出的概率
  258. out_user_data_key = abtest_param['out']['user'].get('data')
  259. out_user_rule_key = abtest_param['out']['user'].get('rule')
  260. group_out_rate_key = \
  261. f"{config_.KEY_NAME_PREFIX_AD_GROUP}{out_user_data_key}:{out_user_rule_key}:{now_dt}"
  262. if not redis_helper.key_exists(group_out_rate_key):
  263. redis_dt = datetime.datetime.strftime(now_date - datetime.timedelta(days=1), '%Y%m%d')
  264. group_out_rate_key = \
  265. f"{config_.KEY_NAME_PREFIX_AD_GROUP}{out_user_data_key}:{out_user_rule_key}:{redis_dt}"
  266. group_out_rate = redis_helper.get_score_with_value(key_name=group_out_rate_key, value=mid_group)
  267. # 获取视频出广告后不直接跳出的概率
  268. out_video_data_key = abtest_param['out']['video'].get('data')
  269. video_out_rate_key = f"{config_.KEY_NAME_PREFIX_AD_VIDEO}{out_video_data_key}:{now_dt}"
  270. if not redis_helper.key_exists(video_out_rate_key):
  271. redis_dt = datetime.datetime.strftime(now_date - datetime.timedelta(days=1), '%Y%m%d')
  272. video_out_rate_key = f"{config_.KEY_NAME_PREFIX_AD_VIDEO}{out_video_data_key}:{redis_dt}"
  273. video_out_rate = redis_helper.get_score_with_value(key_name=video_out_rate_key, value=int(video_id))
  274. if video_out_rate is None:
  275. video_out_rate = redis_helper.get_score_with_value(key_name=video_out_rate_key, value=-1)
  276. # 计算 mid-video 预测值
  277. if group_share_rate is None or video_share_rate is None or group_out_rate is None or video_out_rate is None:
  278. return None
  279. # 乘积融合
  280. group_rate = float(group_share_rate) * float(group_out_rate)
  281. video_rate = float(video_share_rate) * float(video_out_rate)
  282. mid_video_predict_res = group_rate * video_rate
  283. # 获取对应的阈值
  284. threshold = get_threshold(
  285. abtest_id=abtest_id,
  286. abtest_config_tag=abtest_config_tag,
  287. ab_test_code=ab_test_code,
  288. mid_group=mid_group,
  289. care_model_status=care_model_status,
  290. abtest_param=abtest_param
  291. )
  292. # 阈值判断
  293. if mid_video_predict_res > threshold:
  294. # 大于阈值,出广告
  295. ad_predict = 2
  296. else:
  297. # 否则,不出广告
  298. ad_predict = 1
  299. result = {
  300. 'mid_group': mid_group,
  301. 'group_share_rate': group_share_rate,
  302. 'video_share_rate': video_share_rate,
  303. 'group_out_rate': group_out_rate,
  304. 'video_out_rate': video_out_rate,
  305. 'group_rate': group_rate,
  306. 'video_rate': video_rate,
  307. 'mid_video_predict_res': mid_video_predict_res,
  308. 'threshold': threshold,
  309. 'ad_predict': ad_predict}
  310. return result
  311. def ad_recommend_predict(app_type, mid, video_id, ab_exp_info, ab_test_code, care_model_status):
  312. """
  313. 广告推荐预测
  314. :param app_type: app_type
  315. :param mid: mid
  316. :param video_id: video_id
  317. :param ab_exp_info: AB实验组参数
  318. :param ab_test_code: 用户对应的ab组
  319. :param care_model_status: 用户关怀模式状态 1-未开启,2-开启
  320. :return: ad_predict, type-int, 1-不发放广告,2-发放广告
  321. """
  322. try:
  323. now_date = datetime.datetime.today()
  324. # now_dt = datetime.datetime.strftime(now_date, '%Y%m%d')
  325. now_h = datetime.datetime.now().hour
  326. if 0 <= now_h < 8:
  327. # 00:00 - 08:00 不出广告
  328. ad_predict = 1
  329. result = {
  330. 'now_h': now_h,
  331. 'ad_predict': ad_predict
  332. }
  333. return result
  334. # 获取实验参数
  335. abtest_id, abtest_config_tag = get_params(ab_exp_info=ab_exp_info, ab_test_code=ab_test_code)
  336. if abtest_id is None or abtest_config_tag is None:
  337. return None
  338. abtest_param = config_.AD_ABTEST_CONFIG.get(f'{abtest_id}-{abtest_config_tag}')
  339. if abtest_param is None:
  340. return None
  341. threshold_mix_func = abtest_param.get('threshold_mix_func', None)
  342. if threshold_mix_func == 'add':
  343. result = predict_mid_video_res_with_add(
  344. now_date=now_date,
  345. mid=mid,
  346. video_id=video_id,
  347. abtest_param=abtest_param,
  348. abtest_id=abtest_id,
  349. abtest_config_tag=abtest_config_tag,
  350. ab_test_code=ab_test_code,
  351. care_model_status=care_model_status
  352. )
  353. elif threshold_mix_func == 'multiply':
  354. result = predict_mid_video_res_with_multiply(
  355. now_date=now_date,
  356. mid=mid,
  357. video_id=video_id,
  358. abtest_param=abtest_param,
  359. abtest_id=abtest_id,
  360. abtest_config_tag=abtest_config_tag,
  361. ab_test_code=ab_test_code,
  362. care_model_status=care_model_status
  363. )
  364. else:
  365. result = predict_mid_video_res(
  366. now_date=now_date,
  367. mid=mid,
  368. video_id=video_id,
  369. abtest_param=abtest_param,
  370. abtest_id=abtest_id,
  371. abtest_config_tag=abtest_config_tag,
  372. ab_test_code=ab_test_code,
  373. care_model_status=care_model_status
  374. )
  375. # user_data_key = abtest_param['user'].get('data')
  376. # user_rule_key = abtest_param['user'].get('rule')
  377. # video_data_key = abtest_param['video'].get('data')
  378. # group_class_key = abtest_param.get('group_class_key')
  379. # no_ad_mid_group_list = abtest_param.get('no_ad_mid_group_list', [])
  380. #
  381. # # 判断mid所属分组
  382. # mid_group_key_name = f"{config_.KEY_NAME_PREFIX_MID_GROUP}{group_class_key}:{mid}"
  383. # mid_group = redis_helper.get_data_from_redis(key_name=mid_group_key_name)
  384. # if mid_group is None:
  385. # mid_group = 'mean_group'
  386. #
  387. # # 判断用户是否在免广告用户组列表中
  388. # if mid_group in no_ad_mid_group_list:
  389. # # 在免广告用户组列表中,则不出广告
  390. # ad_predict = 1
  391. # result = {
  392. # 'mid_group': mid_group,
  393. # 'ad_predict': ad_predict
  394. # }
  395. # else:
  396. # # 获取用户组分享率
  397. # group_share_rate_key = f"{config_.KEY_NAME_PREFIX_AD_GROUP}{user_data_key}:{user_rule_key}:{now_dt}"
  398. # if not redis_helper.key_exists(group_share_rate_key):
  399. # redis_dt = datetime.datetime.strftime(now_date - datetime.timedelta(days=1), '%Y%m%d')
  400. # group_share_rate_key = f"{config_.KEY_NAME_PREFIX_AD_GROUP}{user_data_key}:{user_rule_key}:{redis_dt}"
  401. # group_share_rate = redis_helper.get_score_with_value(key_name=group_share_rate_key, value=mid_group)
  402. # # 获取视频分享率
  403. # video_share_rate_key = f"{config_.KEY_NAME_PREFIX_AD_VIDEO}{video_data_key}:{now_dt}"
  404. # if not redis_helper.key_exists(video_share_rate_key):
  405. # redis_dt = datetime.datetime.strftime(now_date - datetime.timedelta(days=1), '%Y%m%d')
  406. # video_share_rate_key = f"{config_.KEY_NAME_PREFIX_AD_VIDEO}{video_data_key}:{redis_dt}"
  407. # video_share_rate = redis_helper.get_score_with_value(key_name=video_share_rate_key, value=int(video_id))
  408. # if video_share_rate is None:
  409. # video_share_rate = redis_helper.get_score_with_value(key_name=video_share_rate_key, value=-1)
  410. #
  411. # # 计算 mid-video 分享率
  412. # if group_share_rate is None or video_share_rate is None:
  413. # return None
  414. # mid_video_share_rate = float(group_share_rate) * float(video_share_rate)
  415. #
  416. # # 获取对应的阈值
  417. # threshold = get_threshold(
  418. # abtest_id=abtest_id,
  419. # abtest_config_tag=abtest_config_tag,
  420. # ab_test_code=ab_test_code,
  421. # mid_group=mid_group,
  422. # care_model_status=care_model_status,
  423. # abtest_param=abtest_param
  424. # )
  425. # # 阈值判断
  426. # if mid_video_share_rate > threshold:
  427. # # 大于阈值,出广告
  428. # ad_predict = 2
  429. # else:
  430. # # 否则,不出广告
  431. # ad_predict = 1
  432. # result = {
  433. # 'mid_group': mid_group,
  434. # 'group_share_rate': group_share_rate,
  435. # 'video_share_rate': video_share_rate,
  436. # 'mid_video_share_rate': mid_video_share_rate,
  437. # 'threshold': threshold,
  438. # 'ad_predict': ad_predict}
  439. return result
  440. except Exception as e:
  441. log_.error(traceback.format_exc())
  442. return None
  443. def ad_recommend_predict_with_roi(app_type, mid, video_id, ads, arpu, roi_param):
  444. """
  445. 广告推荐预测
  446. :param app_type: app_type
  447. :param mid: mid
  448. :param video_id: video_id
  449. :param ads: 需要发放广告列表 list
  450. :param arpu: 上一周期arpu值
  451. :param roi_param: 计算roi使用参数
  452. :return: ad_predict, type-int, 1-不发放广告,2-发放广告
  453. """
  454. try:
  455. now_date = datetime.datetime.today()
  456. now_dt = datetime.datetime.strftime(now_date, '%Y%m%d')
  457. ad_info = ads[0]
  458. ad_id = ad_info['adId']
  459. ad_type = ad_info['adType']
  460. ecpm = float(ad_info['ecpm'])
  461. # 获取参数
  462. params = config_.PARAMS_NEW_STRATEGY[int(app_type)]
  463. # 判断mid所属分组
  464. group_class_key = params.get('group_class_key')
  465. mid_group_key_name = f"{config_.KEY_NAME_PREFIX_MID_GROUP}{group_class_key}:{mid}"
  466. mid_group = redis_helper.get_data_from_redis(key_name=mid_group_key_name)
  467. if mid_group is None:
  468. mid_group = 'mean_group'
  469. # 获取用户组出广告后分享的概率
  470. share_user_data_key = params['user'].get('data')
  471. share_user_rule_key = params['user'].get('rule')
  472. group_share_rate_key_with_ad = \
  473. f"{config_.KEY_NAME_PREFIX_GROUP_WITH_AD}{share_user_data_key}:{share_user_rule_key}:{now_dt}"
  474. if not redis_helper.key_exists(group_share_rate_key_with_ad):
  475. redis_dt = datetime.datetime.strftime(now_date - datetime.timedelta(days=1), '%Y%m%d')
  476. group_share_rate_key_with_ad = \
  477. f"{config_.KEY_NAME_PREFIX_GROUP_WITH_AD}{share_user_data_key}:{share_user_rule_key}:{redis_dt}"
  478. group_share_rate_with_ad = redis_helper.get_score_with_value(key_name=group_share_rate_key_with_ad,
  479. value=mid_group)
  480. # 获取视频出广告后分享的概率
  481. share_video_data_key = params['video'].get('data')
  482. video_share_rate_key_with_ad = f"{config_.KEY_NAME_PREFIX_VIDEO_WITH_AD}{share_video_data_key}:{now_dt}"
  483. if not redis_helper.key_exists(video_share_rate_key_with_ad):
  484. redis_dt = datetime.datetime.strftime(now_date - datetime.timedelta(days=1), '%Y%m%d')
  485. video_share_rate_key_with_ad = f"{config_.KEY_NAME_PREFIX_VIDEO_WITH_AD}{share_video_data_key}:{redis_dt}"
  486. video_share_rate_with_ad = redis_helper.get_score_with_value(key_name=video_share_rate_key_with_ad,
  487. value=int(video_id))
  488. if video_share_rate_with_ad is None:
  489. video_share_rate_with_ad = redis_helper.get_score_with_value(key_name=video_share_rate_key_with_ad,
  490. value=-1)
  491. # 获取用户组不出广告后分享的概率
  492. group_share_rate_key_no_ad = \
  493. f"{config_.KEY_NAME_PREFIX_GROUP_NO_AD}{share_user_data_key}:{share_user_rule_key}:{now_dt}"
  494. if not redis_helper.key_exists(group_share_rate_key_no_ad):
  495. redis_dt = datetime.datetime.strftime(now_date - datetime.timedelta(days=1), '%Y%m%d')
  496. group_share_rate_key_no_ad = \
  497. f"{config_.KEY_NAME_PREFIX_GROUP_NO_AD}{share_user_data_key}:{share_user_rule_key}:{redis_dt}"
  498. group_share_rate_no_ad = redis_helper.get_score_with_value(key_name=group_share_rate_key_no_ad, value=mid_group)
  499. # 获取视频不出广告后分享的概率
  500. video_share_rate_key_no_ad = f"{config_.KEY_NAME_PREFIX_VIDEO_NO_AD}{share_video_data_key}:{now_dt}"
  501. if not redis_helper.key_exists(video_share_rate_key_no_ad):
  502. redis_dt = datetime.datetime.strftime(now_date - datetime.timedelta(days=1), '%Y%m%d')
  503. video_share_rate_key_no_ad = f"{config_.KEY_NAME_PREFIX_VIDEO_NO_AD}{share_video_data_key}:{redis_dt}"
  504. video_share_rate_no_ad = redis_helper.get_score_with_value(key_name=video_share_rate_key_no_ad,
  505. value=int(video_id))
  506. if video_share_rate_no_ad is None:
  507. video_share_rate_no_ad = redis_helper.get_score_with_value(key_name=video_share_rate_key_no_ad, value=-1)
  508. if group_share_rate_with_ad is None or video_share_rate_with_ad is None \
  509. or group_share_rate_no_ad is None or video_share_rate_no_ad is None:
  510. return None
  511. # 计算此次请求出广告后分享的概率
  512. share_rate_with_ad = float(group_share_rate_with_ad) * float(video_share_rate_with_ad)
  513. # 计算此次请求不出广告分享的概率
  514. share_rate_no_ad = float(group_share_rate_no_ad) * float(video_share_rate_no_ad)
  515. # 计算此次请求出广告的收入增益
  516. roi_ad = ecpm / 1000 - float(roi_param) * float(arpu) * (share_rate_no_ad - share_rate_with_ad)
  517. # 收入增益判断
  518. if roi_ad > 0:
  519. # 大于0,出广告
  520. ad_predict = 2
  521. else:
  522. # 否则,不出广告
  523. ad_predict = 1
  524. result = {
  525. 'arpu': arpu,
  526. 'roi_param': roi_param,
  527. 'ad_id': ad_id,
  528. 'ad_type': ad_type,
  529. 'mid_group': mid_group,
  530. 'group_share_rate_with_ad': group_share_rate_with_ad,
  531. 'video_share_rate_with_ad': video_share_rate_with_ad,
  532. 'group_share_rate_no_ad': group_share_rate_no_ad,
  533. 'video_share_rate_no_ad': video_share_rate_no_ad,
  534. 'share_rate_with_ad': share_rate_with_ad,
  535. 'share_rate_no_ad': share_rate_no_ad,
  536. 'roi_ad': roi_ad,
  537. 'ad_predict': ad_predict
  538. }
  539. return result
  540. except Exception as e:
  541. log_.error(traceback.format_exc())
  542. return None