Browse Source

Merge branch 'feature_gufengshou_20240125_pid' into pre-master

gufengshou1 1 year ago
parent
commit
d0c93c972c

+ 1 - 1
ad-engine-commons/pom.xml

@@ -25,7 +25,7 @@
         <dependency>
             <groupId>com.tzld.piaoquan</groupId>
             <artifactId>recommend-feature-client</artifactId>
-            <version>1.1.15</version>
+            <version>1.1.17</version>
         </dependency>
         <dependency>
             <groupId>com.tzld.piaoquan</groupId>

+ 1 - 1
ad-engine-server/src/main/java/com/tzld/piaoquan/ad/engine/server/controller/PredictController.java

@@ -44,7 +44,7 @@ public class PredictController {
 
     @RequestMapping("/test")
     public void test(Integer appType,String typeValue){
-        adTestConfigContainer.initMap(appType,typeValue);
+//        adTestConfigContainer.initMap(appType,typeValue);
     }
 
 }

+ 51 - 60
ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/predict/container/AbTestConfigContainer.java

@@ -28,64 +28,64 @@ public class AbTestConfigContainer {
     //List<Tuple<Integer>>
     Map<String,List<JSONObject>> adTimePlanMap=new HashMap<>();
 //    Map<Integer,Map<String,List<JSONObject>>> appAdTimePlanMap=new ConcurrentHashMap<>() ;
-    @PostConstruct
-    public void initContainer(){
-        Timer timer = new Timer();
-        timer.schedule(new TimerTask() {
-            @Override
-            public void run() {
-                try {
-//                    for (Integer appType:appAdTimePlanMap.keySet()){
-//                        initMap(appType,"ab_test002");
-//                    }
-                    initMap(3,"ab_test002");
-//                    log.info("svc=refresh_adTimePlanMap appAdTimePlanMap={}",JSONObject.toJSONString(appAdTimePlanMap));
-                    log.info("svc=refresh_adTimePlanMap adTimePlanMap={}",JSONObject.toJSONString(adTimePlanMap));
-                }catch (Exception e){
-                    e.printStackTrace();
-                }
-            }
-        }, 0, 1000*30);
-    }
+//    @PostConstruct
+//    public void initContainer(){
+//        Timer timer = new Timer();
+//        timer.schedule(new TimerTask() {
+//            @Override
+//            public void run() {
+//                try {
+////                    for (Integer appType:appAdTimePlanMap.keySet()){
+////                        initMap(appType,"ab_test002");
+////                    }
+//                    initMap(3,"ab_test002");
+////                    log.info("svc=refresh_adTimePlanMap appAdTimePlanMap={}",JSONObject.toJSONString(appAdTimePlanMap));
+//                    log.info("svc=refresh_adTimePlanMap adTimePlanMap={}",JSONObject.toJSONString(adTimePlanMap));
+//                }catch (Exception e){
+//                    e.printStackTrace();
+//                }
+//            }
+//        }, 0, 1000*30);
+//    }
 
-    public void initMap(Integer appType,String typeValue){
-        AbTestConfigRequest request=new  AbTestConfigRequest();
-        if(appType==null){
-            request.setAppType(0);
-        }else{
-            request.setAppType(appType);
-        }
-        request.setTypeValue(typeValue);
-        CommonResponse<JSONObject> response=longVideoFeign.getAbTestConfig(request);
-        log.info("svc=initAdTimePlanMap_getConfigFromLongVideoApi response={}",JSONObject.toJSONString(response));
-        JSONObject object=response.getData();
-        for(Map.Entry<String,Object> entry:object.getInnerMap().entrySet()){
-            for(Map<String,Object> map:(List<Map>)entry.getValue()){
-                if(adTestCode.equals(map.get("abExpCode").toString())){
-                    adTimePlanMap=JSONObject.parseObject(map.get("configValue").toString(),Map.class);
-                    break;
-                }
-            }
-        }
-    }
+//    public void initMap(Integer appType,String typeValue){
+//        AbTestConfigRequest request=new  AbTestConfigRequest();
+//        if(appType==null){
+//            request.setAppType(0);
+//        }else{
+//            request.setAppType(appType);
+//        }
+//        request.setTypeValue(typeValue);
+//        CommonResponse<JSONObject> response=longVideoFeign.getAbTestConfig(request);
+//        log.info("svc=initAdTimePlanMap_getConfigFromLongVideoApi response={}",JSONObject.toJSONString(response));
+//        JSONObject object=response.getData();
+//        for(Map.Entry<String,Object> entry:object.getInnerMap().entrySet()){
+//            for(Map<String,Object> map:(List<Map>)entry.getValue()){
+//                if(adTestCode.equals(map.get("abExpCode").toString())){
+//                    adTimePlanMap=JSONObject.parseObject(map.get("configValue").toString(),Map.class);
+//                    break;
+//                }
+//            }
+//        }
+//    }
 
-    public Boolean containsCode(String code){
-        return adTimePlanMap.keySet().contains(code);
-    }
+//    public Boolean containsCode(String code){
+//        return adTimePlanMap.keySet().contains(code);
+//    }
 
     public Boolean containsCode(Map<String,List<JSONObject>> configMap,String code){
         return configMap.keySet().contains(code);
     }
 
-    public Boolean inWithoutAdTime(String code,Integer hourOfDay){
-        Boolean flag=false;
-        for(JSONObject object:adTimePlanMap.getOrDefault(code,new ArrayList<>())){
-            if(object.getInteger("x")<=hourOfDay&&hourOfDay<object.getInteger("y")){
-                return true;
-            }
-        }
-        return flag;
-    }
+//    public Boolean inWithoutAdTime(String code,Integer hourOfDay){
+//        Boolean flag=false;
+//        for(JSONObject object:adTimePlanMap.getOrDefault(code,new ArrayList<>())){
+//            if(object.getInteger("x")<=hourOfDay&&hourOfDay<object.getInteger("y")){
+//                return true;
+//            }
+//        }
+//        return flag;
+//    }
 
     public Boolean inWithoutAdTime(Map<String,List<JSONObject>> abConfigMap,String code,Integer hourOfDay){
         Boolean flag=false;
@@ -110,13 +110,4 @@ public class AbTestConfigContainer {
         return false;
     }
 
-
-    public static void main(String[] args){
-        Map<String, Tuple<Integer>> map =new HashMap<>();
-        Tuple<Integer> t=new Tuple<>();
-        t.setX(1);
-        t.setY(2);
-        map.put("sk",t);
-        System.out.println(JSONObject.toJSONString(map));
-    }
 }

+ 4 - 4
ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/predict/model/threshold/ScoreV2ThresholdPredictModel.java

@@ -85,11 +85,11 @@ public class ScoreV2ThresholdPredictModel extends ThresholdPredictModel {
 
         int adPredict;
         if (maxItem != null && maxItem.getScore() < threshold) {
-            // If final score is below threshold, show the ad
-            adPredict = 2;
-        } else {
-            // Otherwise, do not show the ad
+            // If final score is below threshold, do not show the ad
             adPredict = 1;
+        } else {
+            // Otherwise, show the ad
+            adPredict = 2;
         }
         Map<String, Object> result = new HashMap<>();
         result.put("threshold", threshold);

+ 4 - 4
ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/score/VlogMergeBreakScorer.java

@@ -36,14 +36,14 @@ public class VlogMergeBreakScorer extends BaseLRModelScorer {
             double str = item.getStr();
             double ros = item.getRos();
 
-            double a = 0.7;
-            double b = 1;
-            double c = 0.3;
+            double a = 0.2;
+            double b = 1.0;
+            double c = 1.0;
 
             BigDecimal ctrCvr = new BigDecimal(Math.pow(70 * ctr * cvr, a));
             BigDecimal strRos = new BigDecimal(Math.pow(str * ros, b));
             BigDecimal breakRate = new BigDecimal(Math.pow(item.getBreakRate(), c));
-            BigDecimal score = ctrCvr.divide(strRos, 5, BigDecimal.ROUND_HALF_UP).multiply(breakRate);
+            BigDecimal score = ctrCvr.divide(strRos.multiply(breakRate), 5, BigDecimal.ROUND_HALF_UP);
 
             item.setScore(score.doubleValue());
         }

+ 7 - 2
ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/score/VlogMergeEcpmScorer.java

@@ -45,7 +45,7 @@ public class VlogMergeEcpmScorer extends BaseLRModelScorer {
 
         for (AdRankItem item : items) {
             try {
-                boolean isTfType=item.getItemFeature().getCreative_7day_cnt_features().getAdView()<1000;
+                boolean isTfType=item.getItemFeature().getCreative_7day_cnt_features().getAdView()<10000;
                 double cpa = item.getCpa();
                 double bid1 = item.getBid1();
                 double bid2 = item.getBid2();
@@ -53,7 +53,12 @@ public class VlogMergeEcpmScorer extends BaseLRModelScorer {
                 double pcvr = isTfType?item.getTf_cvr():item.getCvr();
                 item.setScore_type( isTfType?1:0);
                 //todo
-                double ecpm = cpa * bid1 * bid2 * pcvr * pctr * 1000d;
+                double ecpm;
+                if(isTfType){
+                    ecpm = cpa * bid1 * bid2 * pcvr * pctr * 1000d;
+                }else {
+                    ecpm = (cpa+item.getPidLambda()) * bid1 * bid2 * pcvr * pctr * 1000d;
+                }
 //                double ecpm = cpa * bid1 * bid2 * pcvr * pctr;
                 item.setEcpm1(ecpm/1000d);
                 item.setScore(ecpm/1000d);

+ 150 - 0
ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/score/container/PidLambdaContainer.java

@@ -0,0 +1,150 @@
+package com.tzld.piaoquan.ad.engine.service.score.container;
+
+import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson.TypeReference;
+import com.aliyun.oss.OSS;
+import com.aliyun.oss.OSSClientBuilder;
+import com.aliyun.oss.common.auth.CredentialsProvider;
+import com.aliyun.oss.common.auth.DefaultCredentialProvider;
+import com.aliyun.oss.model.CopyObjectResult;
+import com.aliyun.oss.model.OSSObject;
+import com.aliyun.oss.model.PutObjectResult;
+import com.tzld.piaoquan.ad.engine.service.predict.impl.PredictModelServiceImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.PostConstruct;
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+@Component
+public class PidLambdaContainer {
+    private final static Logger log = LoggerFactory.getLogger(PidLambdaContainer.class);
+
+    private static final int SCHEDULE_PERIOD = 1;
+    private static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
+    @Value("${model.oss.internal.endpoint:oss-cn-hangzhou.aliyuncs.com}")
+    String endpoint = "";
+    @Value("${model.oss.accessKeyId:LTAIP6x1l3DXfSxm}")
+    String accessKeyId = "";
+    @Value("${model.oss.accessKetSecret:KbTaM9ars4OX3PMS6Xm7rtxGr1FLon}")
+    String accessKetSecret = "";
+    @Value("${model.oss.bucketName:art-recommend}")
+    String bucketName = "";
+
+    @Value("${model.oss.pid.filename.lambda:pid/lambda}")
+    String lambdaFileName = "";
+
+    @Value("${model.oss.pid.filename.dCpa:pid/dCpa}")
+    String dCpaFileName = "";
+
+    @Value("${ad.model.pid.kp:0.5}")
+    Double kp = 0d;
+
+    @Value("${ad.model.pid.ki:0.05}")
+    Double ki = 0d;
+
+    @Value("${ad.model.pid.kd:0.005}")
+    Double kd = 0d;
+
+    OSS client;
+
+    private static ConcurrentHashMap<Long,Double>  lambdaCache=new ConcurrentHashMap<>();
+    private Date cacheDate;
+
+    @PostConstruct
+    private void init(){
+        instanceClient();
+        final Runnable task = new Runnable() {
+            public void run() {
+                try {
+                    loadAndCalIfNeed();
+                }catch (Exception e){
+                    e.printStackTrace();
+                }
+            }
+        };
+        scheduler.scheduleAtFixedRate(task, 0, SCHEDULE_PERIOD, TimeUnit.MINUTES); // 10分钟
+    }
+
+    private void instanceClient(){
+        CredentialsProvider credentialsProvider = new DefaultCredentialProvider(accessKeyId, accessKetSecret);
+        this.client = new OSSClientBuilder().build(endpoint, credentialsProvider);
+    }
+
+    private void loadAndCalIfNeed(){
+        loadLambdaFile();
+        OSSObject dCpaFileOjb=client.getObject(bucketName,dCpaFileName);
+        if(cacheDate==null||dCpaFileOjb.getObjectMetadata().getLastModified().after(cacheDate)){
+            calNewLambda(dCpaFileOjb);
+            writeLambdaFileToOss();
+        }
+    }
+
+    private void calNewLambda(OSSObject object) {
+        try {
+            InputStream is=object.getObjectContent();
+            InputStreamReader isr=new InputStreamReader(is);
+            BufferedReader bufferedReader = new BufferedReader(isr);
+            String line = null;
+            while ((line = bufferedReader.readLine()) != null){
+                try {
+                    String[] cols=line.split(",");
+                    Long creativeId=Long.parseLong(cols[0]);
+                    Double lambdaNew=lambdaCache.getOrDefault(creativeId,0d)+
+                            kp*Double.parseDouble(cols[1])+ki*Double.parseDouble(cols[2])+kd*Double.parseDouble(cols[3]);
+                    lambdaCache.put(creativeId,lambdaNew);
+                }catch (Exception e){
+                    e.printStackTrace();
+                }
+            }
+        }catch (Exception e){
+            log.error("svc=calNewLambda status=failed error={}", Arrays.toString(e.getStackTrace()));
+        }
+    }
+
+    private void writeLambdaFileToOss(){
+        //先不考虑各种更新失败及重复更新问题。
+        String tempFile=lambdaFileName+"_temp";
+        String content= JSONObject.toJSONString(lambdaCache);
+        PutObjectResult putObjectResult=client.putObject(bucketName,tempFile,new ByteArrayInputStream(content.getBytes()));
+        CopyObjectResult copyObjectResult=client.copyObject(bucketName, tempFile, bucketName, lambdaFileName);
+        this.cacheDate= copyObjectResult.getLastModified();
+        client.deleteObject(bucketName, tempFile);
+    }
+
+    private void loadLambdaFile(){
+        try {
+            OSSObject object=client.getObject(bucketName,lambdaFileName);
+            if(object==null) return;
+            if(cacheDate!=null&& !cacheDate.before(object.getObjectMetadata().getLastModified())) return;
+//            if(cacheDate!=null&& cacheDate.after(object.getObjectMetadata().getLastModified())) return;
+            StringBuilder builder=new StringBuilder();
+            InputStream is=object.getObjectContent();
+            InputStreamReader isr=new InputStreamReader(is);
+            BufferedReader bufferedReader = new BufferedReader(isr);
+            String line = null;
+            while ((line=bufferedReader.readLine())!=null){
+                builder.append(line);
+            }
+            lambdaCache=JSONObject.parseObject(builder.toString(),new TypeReference<ConcurrentHashMap<Long,Double>>(){});
+            this.cacheDate=object.getObjectMetadata().getLastModified();
+        }catch (Exception e){
+            e.printStackTrace();
+        }
+    }
+
+    public static Double getPidLambda(Long creativeId){
+        return lambdaCache.getOrDefault(creativeId,0d);
+    }
+}

+ 4 - 0
ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/score/impl/RankServiceImpl.java

@@ -1,6 +1,7 @@
 package com.tzld.piaoquan.ad.engine.service.score.impl;
 
 import com.alibaba.fastjson.JSONObject;
+import com.tzld.piaoquan.ad.engine.service.score.container.PidLambdaContainer;
 import com.tzld.piaoquan.ad.engine.service.score.dto.AdPlatformBidCreativeDTO;
 import com.tzld.piaoquan.ad.engine.service.score.param.BidRankRecommendRequestParam;
 import com.tzld.piaoquan.recommend.feature.domain.ad.base.AdItemFeature;
@@ -74,6 +75,7 @@ public class RankServiceImpl implements RankService {
             item.setBid1(1d);
             item.setBid2(1d);
             item.setCpa(75d);
+            item.setPidLambda(PidLambdaContainer.getPidLambda(item.getAdId()));
         }
 
         //兜底方案
@@ -131,6 +133,7 @@ public class RankServiceImpl implements RankService {
                 item.setBid1(dto.getBid1());
                 item.setBid2(dto.getBid2());
                 item.setCpa(dto.getCpa());
+                item.setPidLambda(PidLambdaContainer.getPidLambda(item.getAdId()));
             }catch (Exception e){
                 e.printStackTrace();
             }
@@ -145,6 +148,7 @@ public class RankServiceImpl implements RankService {
                 item.setCpa(dto.getCpa());
                 item.setAdId(dto.getCreativeId());
                 item.setItemFeature(new AdItemFeature());
+                item.setPidLambda(PidLambdaContainer.getPidLambda(item.getAdId()));
                 rankItems.add(item);
             }
             rankResult=rankServiceThompson.rank(param, userAdFeature, rankItems,null);