package com.iplatform.recvideo.support; import com.iplatform.model.po.Rc_video_t1; import com.iplatform.model.po.Rc_video_t2; import com.iplatform.model.po.Rc_video_user; import com.iplatform.recvideo.Constants; import com.iplatform.recvideo.SimilarExecutor; import com.iplatform.recvideo.SimilarVideoInfo; import com.iplatform.recvideo.SimilarVideoOrder; import com.iplatform.recvideo.SimilarVideoUser; import com.iplatform.recvideo.SimilarVideoUserOrder; import com.iplatform.recvideo.VideoFolderInfo; import com.iplatform.recvideo.service.VideoExecutorServiceImpl; import com.iplatform.recvideo.util.PythonInvokeUtils; import com.walker.infrastructure.utils.DateUtils; import com.walker.infrastructure.utils.NumberGenerator; import com.walker.infrastructure.utils.StringUtils; import org.springframework.web.client.RestTemplate; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; public class DefaultSimilarExecutor extends SimilarExecutor { private RestTemplate restTemplate; // python AI 服务地址前缀 private String remoteUrl; private VideoExecutorServiceImpl videoExecutorService = null; public void setVideoExecutorService(VideoExecutorServiceImpl videoExecutorService) { this.videoExecutorService = videoExecutorService; } public void setRemoteUrl(String remoteUrl) { this.remoteUrl = remoteUrl; } public void setRestTemplate(RestTemplate restTemplate) { this.restTemplate = restTemplate; } @Override protected boolean pythonLoadVideoDone(String batchId, String batchFolder) { return this.videoExecutorService.queryLoadVideoDone(batchFolder); } @Override protected String requestStartPythonLoadVideo(String batchId) throws Exception { logger.info("开始请求python服务:" + Constants.AI_SERVICE_VIDEO_LOAD); return null; } @Override protected List acquirePythonSearchSimilarOnce(String srcVideoId, String imagePath, String topN) throws Exception { String url = this.remoteUrl + Constants.AI_SERVICE_VIDEO_SEARCH; return PythonInvokeUtils.acquireImageSearchResult(srcVideoId, imagePath, topN, url, this.restTemplate); } @Override protected void writeRcVideoT1(List list, String srcImageId) { // 删除 distance == 0 的,这个是自身视频信息(推荐的要排除自己) Rc_video_t1 e = null; for(Iterator it = list.iterator(); it.hasNext();){ e = it.next(); if(e.getDistance().doubleValue() == 0){ it.remove(); } } this.videoExecutorService.execBatchInsertVideoT1(list, srcImageId); logger.debug("成功写入集合'Rc_video_t1':" + list.size()); } @Override protected void writeRcVideoT2(VideoFolderInfo videoFolderInfo, String batchId) { logger.debug("正在写入'Rc_video_t2',原始视频:" + videoFolderInfo.getVideoId()); List list = this.videoExecutorService.queryVideoT_1List(videoFolderInfo.getVideoId()); if(StringUtils.isEmptyList(list)){ logger.warn("writeRcVideoT2: Rc_video_t1检索结果为空,无法继续写入'Rc_video_t2'"); return; } SimilarVideoOrder similarVideoOrder = new SimilarVideoOrder(list); List similarVideoInfoList = similarVideoOrder.calculateOrder(); List video2List = this.toRcVideoT2List(videoFolderInfo.getVideoId(), similarVideoInfoList, batchId); if(video2List == null){ logger.warn("writeRcVideoT2(): similarVideoInfoList为空,不能执行, srcVideoId = " + videoFolderInfo.getVideoId()); return; } this.videoExecutorService.execBatchInsertVideoT2(video2List, videoFolderInfo.getVideoId()); } @Override protected void writeRcVideoUser(String batchId, List recVideoIdList) { logger.info("正在写入一次用户推荐视频数据, batchId = " + batchId); List> batchUserVideoList = this.videoExecutorService.queryBatchUserVideoList(batchId); if(StringUtils.isEmptyList(batchUserVideoList)){ logger.error("未找到批次用户视频记录,无法更新用户推荐视频数据,batchId = " + batchId); return; } List video2List = this.videoExecutorService.queryVideoT_2List(batchId); if(StringUtils.isEmptyList(video2List)){ logger.warn("从表'rc_video_t2'未加载到批次视频结果记录,无法继续写入用户推荐视频'rc_video_user'"); return; } // 原始视频ID与用户关系 Map srcVideoIdUserCache = new HashMap<>(); for(Map m : batchUserVideoList){ srcVideoIdUserCache.put(m.get("src_video_id").toString(), Long.parseLong(m.get("user_id").toString())); } // 推荐视频ID与用户关系 Map videoIdUserCache = new HashMap<>(); Long userId = null; for(Rc_video_t2 e : video2List){ userId = srcVideoIdUserCache.get(e.getSrc_video_id()); if(userId == null){ throw new IllegalArgumentException("推荐视频的原始视频未找到对应用户,src_video = " + e.getSrc_video_id() + ", rec_video = " + e.getSim_video_id()); } videoIdUserCache.put(e.getSim_video_id(), userId); } SimilarVideoUserOrder similarVideoUserOrder = new SimilarVideoUserOrder(videoIdUserCache, video2List); List similarVideoUserList = similarVideoUserOrder.calculateOrder(); List videoUserList = this.toRcVideoUserList(similarVideoUserList); if(videoUserList == null){ logger.warn("writeRcVideoUser(): similarVideoUserList,不能执行, batchId = " + batchId); return; } // 用户推荐视频记录,需要更新,如果不存在才写入。 // 注意:这里暂时不更新,全部写入,这样用户推荐表中会存在较多重复数据,后续要添加定时任务清除重复数据即可。 this.videoExecutorService.execBatchInsertVideoUser(videoUserList, batchId); logger.debug("批次任务状态已更新成功! " + batchId); } private List toRcVideoUserList(List similarVideoUserList){ if(StringUtils.isEmptyList(similarVideoUserList)){ return null; } List resultList = new ArrayList<>(similarVideoUserList.size()); Rc_video_user rc_video_t2 = null; for(SimilarVideoUser e : similarVideoUserList){ rc_video_t2 = new Rc_video_user(NumberGenerator.getLongSequenceNumber()); rc_video_t2.setCreate_time(Long.parseLong(DateUtils.getDateTimeSecondForShow())); rc_video_t2.setUser_id(e.getUserId()); rc_video_t2.setVideo_id(e.getRecommendVideoId()); rc_video_t2.setScore(e.getScore()); resultList.add(rc_video_t2); } return resultList; } private List toRcVideoT2List(String srcVideoId , List similarVideoInfoList, String batchId){ if(StringUtils.isEmptyList(similarVideoInfoList)){ return null; } List resultList = new ArrayList<>(similarVideoInfoList.size()); Rc_video_t2 rc_video_t2 = null; for(SimilarVideoInfo e : similarVideoInfoList){ rc_video_t2 = new Rc_video_t2(NumberGenerator.getLongSequenceId()); rc_video_t2.setSrc_video_id(srcVideoId); rc_video_t2.setSim_video_id(e.getId()); rc_video_t2.setScore(e.getScore()); rc_video_t2.setBatch_id(batchId); resultList.add(rc_video_t2); } return resultList; } }