Explorar el Código

Merge branch 'ocpm_bid_engine_scores'

gufengshou1 hace 1 año
padre
commit
a1ac710db3
Se han modificado 28 ficheros con 1251 adiciones y 43 borrados
  1. 2 2
      ad-engine-commons/pom.xml
  2. 20 0
      ad-engine-commons/src/main/java/com/tzld/piaoquan/ad/engine/commons/score/BaseCalibrationScorer.java
  3. 19 0
      ad-engine-commons/src/main/java/com/tzld/piaoquan/ad/engine/commons/score/BaseMergeScorer.java
  4. 20 0
      ad-engine-commons/src/main/java/com/tzld/piaoquan/ad/engine/commons/score/BaseThompsonSamplingScorer.java
  5. 5 0
      ad-engine-commons/src/main/java/com/tzld/piaoquan/ad/engine/commons/score/ScorerUtils.java
  6. 76 0
      ad-engine-commons/src/main/java/com/tzld/piaoquan/ad/engine/commons/score/model/CalibrationModel.java
  7. 107 0
      ad-engine-commons/src/main/java/com/tzld/piaoquan/ad/engine/commons/score/model/ThompsonSamplingModel.java
  8. 1 1
      ad-engine-server/pom.xml
  9. 14 0
      ad-engine-server/src/main/java/com/tzld/piaoquan/ad/engine/server/controller/AdRecommendController.java
  10. 2 2
      ad-engine-server/src/main/resources/application-dev.yml
  11. 11 1
      ad-engine-server/src/main/resources/feeds_score_config_baseline.conf
  12. 14 0
      ad-engine-server/src/main/resources/feeds_score_config_thompson.conf
  13. 4 2
      ad-engine-service/pom.xml
  14. 9 0
      ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/score/RankService.java
  15. 143 0
      ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/score/VlogAdCtrCalibrationScorer.java
  16. 5 11
      ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/score/VlogAdCtrLRScorer.java
  17. 143 0
      ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/score/VlogAdCvrCalibrationScorer.java
  18. 181 0
      ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/score/VlogAdCvrLRScorer.java
  19. 156 0
      ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/score/VlogAdThompsonScorer.java
  20. 68 0
      ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/score/VlogMergeEcpmScorer.java
  21. 5 5
      ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/score/convert/FeatureConvert.java
  22. 2 1
      ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/score/convert/RequestConvert.java
  23. 48 0
      ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/score/dto/AdPlatformBidCreativeDTO.java
  24. 105 14
      ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/score/impl/RankServiceImpl.java
  25. 65 0
      ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/score/impl/RankServiceThompsonImpl.java
  26. 13 0
      ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/score/param/BidRankRecommendRequestParam.java
  27. 1 4
      ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/score/param/RankRecommendRequestParam.java
  28. 12 0
      ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/score/param/RecommendRequestParam.java

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

@@ -10,7 +10,7 @@
     <modelVersion>4.0.0</modelVersion>
 
     <artifactId>ad-engine-commons</artifactId>
-    <version>1.0.2</version>
+    <version>1.0.3</version>
     <properties>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
         <maven.compiler.source>1.8</maven.compiler.source>
@@ -25,7 +25,7 @@
         <dependency>
             <groupId>com.tzld.piaoquan</groupId>
             <artifactId>recommend-feature-client</artifactId>
-            <version>1.0.2</version>
+            <version>1.0.3</version>
         </dependency>
         <dependency>
             <groupId>com.tzld.piaoquan</groupId>

+ 20 - 0
ad-engine-commons/src/main/java/com/tzld/piaoquan/ad/engine/commons/score/BaseCalibrationScorer.java

@@ -0,0 +1,20 @@
+package com.tzld.piaoquan.ad.engine.commons.score;
+
+import com.tzld.piaoquan.ad.engine.commons.score.model.CalibrationModel;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+public abstract class BaseCalibrationScorer extends AbstractScorer {
+
+    private static Logger LOGGER = LoggerFactory.getLogger(BaseCalibrationScorer.class);
+
+    public BaseCalibrationScorer(ScorerConfigInfo scorerConfigInfo) {
+        super(scorerConfigInfo);
+    }
+
+    @Override
+    public void loadModel() {
+        doLoadModel(CalibrationModel.class);
+    }
+}

+ 19 - 0
ad-engine-commons/src/main/java/com/tzld/piaoquan/ad/engine/commons/score/BaseMergeScorer.java

@@ -0,0 +1,19 @@
+package com.tzld.piaoquan.ad.engine.commons.score;
+
+import com.tzld.piaoquan.ad.engine.commons.score.model.LRModel;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+public abstract class BaseMergeScorer extends AbstractScorer {
+
+    private static Logger LOGGER = LoggerFactory.getLogger(BaseMergeScorer.class);
+
+    public BaseMergeScorer(ScorerConfigInfo scorerConfigInfo) {
+        super(scorerConfigInfo);
+    }
+
+    @Override
+    public void loadModel() {
+    }
+}

+ 20 - 0
ad-engine-commons/src/main/java/com/tzld/piaoquan/ad/engine/commons/score/BaseThompsonSamplingScorer.java

@@ -0,0 +1,20 @@
+package com.tzld.piaoquan.ad.engine.commons.score;
+
+import com.tzld.piaoquan.ad.engine.commons.score.model.ThompsonSamplingModel;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+public abstract class BaseThompsonSamplingScorer extends AbstractScorer {
+
+    private static Logger LOGGER = LoggerFactory.getLogger(BaseThompsonSamplingScorer.class);
+
+    public BaseThompsonSamplingScorer(ScorerConfigInfo scorerConfigInfo) {
+        super(scorerConfigInfo);
+    }
+
+    @Override
+    public void loadModel() {
+        doLoadModel(ThompsonSamplingModel.class);
+    }
+}

+ 5 - 0
ad-engine-commons/src/main/java/com/tzld/piaoquan/ad/engine/commons/score/ScorerUtils.java

@@ -23,9 +23,14 @@ public final class ScorerUtils {
 
     public static String BASE_CONF = "feeds_score_config_baseline.conf";
 
+    public static String THOMPSON_CONF = "feeds_score_config_thompson.conf";
+
+
     public static void warmUp() {
         log.info("scorer warm up ");
         ScorerUtils.init(BASE_CONF);
+        ScorerUtils.init(THOMPSON_CONF);
+
     }
 
     private ScorerUtils() {

+ 76 - 0
ad-engine-commons/src/main/java/com/tzld/piaoquan/ad/engine/commons/score/model/CalibrationModel.java

@@ -0,0 +1,76 @@
+package com.tzld.piaoquan.ad.engine.commons.score.model;
+
+import com.tzld.piaoquan.recommend.feature.domain.ad.base.AdActionFeature;
+import com.tzld.piaoquan.recommend.feature.domain.ad.base.AdRankItem;
+import org.apache.commons.math3.distribution.BetaDistribution;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.math.BigInteger;
+import java.util.HashMap;
+import java.util.TreeMap;
+
+
+public class CalibrationModel extends Model {
+    protected static final int MODEL_FIRST_LOAD_COUNT = 1 << 25;  // 32M
+    private static final Logger LOGGER = LoggerFactory.getLogger(CalibrationModel.class);
+
+    private TreeMap<Double, Double> calibrationModel;
+
+    public CalibrationModel() {
+        //配置不同环境的hdfs conf
+        this.calibrationModel = new TreeMap<>();
+    }
+
+    public TreeMap<Double, Double> getCalibrationModel() {
+        return this.calibrationModel;
+    }
+
+
+    @Override
+    public boolean loadFromStream(InputStreamReader in) throws IOException {
+        TreeMap<Double, Double> bins = new TreeMap<>();
+        BufferedReader input = new BufferedReader(in);
+        String line = null;
+        int cnt = 0;
+        while ((line = input.readLine()) != null) {
+            String[] items = line.split("\t");
+            if (items.length < 2) {
+                continue;
+            }
+            bins.put(Double.parseDouble(items[0]), Double.parseDouble(items[1]));
+        }
+
+        this.calibrationModel = bins;
+        LOGGER.info("[MODELLOAD] calibration model load over and size " + cnt);
+        input.close();
+        in.close();
+        return true;
+    }
+
+
+    @Override
+    public int getModelSize() {
+        if (this.calibrationModel == null)
+            return 0;
+        int sum = this.calibrationModel.size();
+        return sum;
+    }
+
+    public double score(AdRankItem adRankItem, String ctrOrCVR) {
+        double score = 0.0f;
+        if (ctrOrCVR.equals("ctr")) {
+            double upperBound = this.calibrationModel.floorKey(adRankItem.getCtr());
+            score = this.calibrationModel.get(upperBound);
+        }
+        if (ctrOrCVR.equals("cvr")) {
+            double upperBound = this.calibrationModel.floorKey(adRankItem.getCvr());
+            score = this.calibrationModel.get(upperBound);
+        }
+        return score;
+    }
+
+}

+ 107 - 0
ad-engine-commons/src/main/java/com/tzld/piaoquan/ad/engine/commons/score/model/ThompsonSamplingModel.java

@@ -0,0 +1,107 @@
+package com.tzld.piaoquan.ad.engine.commons.score.model;
+
+import com.tzld.piaoquan.recommend.feature.domain.ad.base.AdActionFeature;
+import com.tzld.piaoquan.recommend.feature.domain.ad.base.AdRankItem;
+import com.tzld.piaoquan.recommend.feature.model.sample.BaseFeature;
+import com.tzld.piaoquan.recommend.feature.model.sample.GroupedFeature;
+import com.tzld.piaoquan.recommend.feature.model.sample.LRSamples;
+import it.unimi.dsi.fastutil.longs.Long2FloatMap;
+import it.unimi.dsi.fastutil.longs.Long2FloatOpenHashMap;
+import org.apache.commons.math3.distribution.BetaDistribution;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+
+public class ThompsonSamplingModel extends Model {
+    protected static final int MODEL_FIRST_LOAD_COUNT = 1 << 25;  // 32M
+    private static final Logger LOGGER = LoggerFactory.getLogger(ThompsonSamplingModel.class);
+
+    // key = adid, value = <exp, click, conversation>
+    private Map<Long, AdActionFeature> thompsonSamplingModel;
+
+    private static final int alpha = 6;
+    private static final int beta_click = 100;
+    private static final int beta_conversion = 1000;
+
+    public ThompsonSamplingModel() {
+        //配置不同环境的hdfs conf
+        this.thompsonSamplingModel = new HashMap<>();
+    }
+
+    public Map<Long, AdActionFeature> getLrModel() {
+        return this.thompsonSamplingModel;
+    }
+
+
+    public void putFeature(Map<Long, AdActionFeature> model, Long key, Double expose, Double click, Double conversation) {
+        AdActionFeature adActionFeature = new AdActionFeature();
+        adActionFeature.setOriginAdView(expose);
+        adActionFeature.setOriginAdClick(click);
+        adActionFeature.setOriginAdConversion(conversation);
+        model.put(key, adActionFeature);
+    }
+
+
+    @Override
+    public boolean loadFromStream(InputStreamReader in) throws IOException {
+        Map<Long, AdActionFeature> initModel = new HashMap<>();
+        BufferedReader input = new BufferedReader(in);
+        String line = null;
+        int cnt = 0;
+        while ((line = input.readLine()) != null) {
+            String[] items = line.split("\t");
+            if (items.length < 3) {
+                continue;
+            }
+            putFeature(initModel, new BigInteger(items[0].trim()).longValue(), Double.valueOf(items[1].trim()).doubleValue(), Double.valueOf(items[2].trim()).doubleValue(), Double.valueOf(items[3].trim()).doubleValue());
+        }
+
+        this.thompsonSamplingModel = initModel;
+        LOGGER.info("[MODELLOAD] model load over and size " + cnt);
+        input.close();
+        in.close();
+        return true;
+    }
+
+
+    @Override
+    public int getModelSize() {
+        if (this.thompsonSamplingModel == null)
+            return 0;
+        int sum = this.thompsonSamplingModel.size();
+        return sum;
+    }
+
+    public double score(AdRankItem adRankItem, String ctrOrCVR) {
+        double score = 0.0f;
+        AdActionFeature adActionFeature = this.thompsonSamplingModel.getOrDefault(adRankItem.getAdId(),new AdActionFeature());
+
+        if (ctrOrCVR.equals("ctr")){
+            int alpha_ctr = (int) adActionFeature.getAdClick() + this.alpha ;
+            int beta_ctr = this.beta_click + (int)adActionFeature.getAdView() - (int)adActionFeature.getAdClick();
+            score = this.betaSampler(alpha_ctr, beta_ctr);
+        }
+        if (ctrOrCVR.equals("cvr")){
+            int alpha_cvr = (int) adActionFeature.getAdClick() + this.alpha ;
+            int beta_cvr = this.beta_conversion + (int)adActionFeature.getAdView() - (int)adActionFeature.getAdConversion();
+            score = this.betaSampler(alpha_cvr, beta_cvr);
+        }
+        return score;
+    }
+
+    public double betaSampler(double alpha, double beta) {
+        BetaDistribution betaSample = new BetaDistribution(alpha, beta);
+        return betaSample.sample();
+    }
+
+
+}

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

@@ -15,7 +15,7 @@
         <dependency>
             <groupId>com.tzld.piaoquan</groupId>
             <artifactId>ad-engine-service</artifactId>
-            <version>1.0.0</version>
+            <version>1.0.3</version>
         </dependency>
 
     </dependencies>

+ 14 - 0
ad-engine-server/src/main/java/com/tzld/piaoquan/ad/engine/server/controller/AdRecommendController.java

@@ -1,11 +1,14 @@
 package com.tzld.piaoquan.ad.engine.server.controller;
 
 import com.tzld.piaoquan.ad.engine.service.score.RankService;
+import com.tzld.piaoquan.ad.engine.service.score.dto.AdPlatformBidCreativeDTO;
+import com.tzld.piaoquan.ad.engine.service.score.param.BidRankRecommendRequestParam;
 import com.tzld.piaoquan.ad.engine.service.score.param.RankRecommendRequestParam;
 import com.tzld.piaoquan.recommend.feature.domain.ad.base.AdRankItem;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
@@ -19,6 +22,7 @@ public class AdRecommendController {
 
     private final static Logger log = LoggerFactory.getLogger(AdRecommendController.class);
     @Autowired
+    @Qualifier("rankServiceImpl")
     RankService rankService;
 
     @RequestMapping("/top1/basic")
@@ -34,4 +38,14 @@ public class AdRecommendController {
         return map;
     }
 
+    @RequestMapping("/top1/bid/basic")
+    public Map<String,Object> adRecommendTop1BidBasic(@RequestBody BidRankRecommendRequestParam request){
+        AdPlatformBidCreativeDTO rankResult = rankService.adBidRank(request);
+        HashMap map =new HashMap();
+        map.put("code","0");
+        map.put("msg","success");
+        map.put("content",rankResult);
+        return map;
+    }
+
 }

+ 2 - 2
ad-engine-server/src/main/resources/application-dev.yml

@@ -43,8 +43,8 @@ spring:
     password: Wqsd@2019
     timeout: 1000
   redis-algorithm:
-    hostName: r-bp1ps6my7lzg8rdhwx682.redis.rds.aliyuncs.com
-#    hostName: r-bp1fogs2mflr1ybfot.redis.rds.aliyuncs.com
+#    hostName: r-bp1ps6my7lzg8rdhwx682.redis.rds.aliyuncs.com
+    hostName: r-bp1fogs2mflr1ybfot.redis.rds.aliyuncs.com
     port: 6379
     password: Wqsd@2019
     timeout: 1000

+ 11 - 1
ad-engine-server/src/main/resources/feeds_score_config_baseline.conf

@@ -1,7 +1,17 @@
 scorer-config = {
-  related-score-config = {
+  lr-ctr-score-config = {
     scorer-name = "com.tzld.piaoquan.ad.engine.service.score.VlogAdCtrLRScorer"
     scorer-priority = 99
     model-path = "ad_ctr_model/model_ad_ctr.txt"
   }
+  lr-cvr-score-config = {
+      scorer-name = "com.tzld.piaoquan.ad.engine.service.score.VlogAdCvrLRScorer"
+      scorer-priority = 98
+      model-path = "ad_cvr_model/model_ad_cvr.txt"
+  }
+  lr-ecpm-merge-config = {
+      scorer-name = "com.tzld.piaoquan.ad.engine.service.score.VlogMergeEcpmScorer"
+      scorer-priority = 97
+  }
+
 }

+ 14 - 0
ad-engine-server/src/main/resources/feeds_score_config_thompson.conf

@@ -0,0 +1,14 @@
+scorer-config = {
+  tf-ctr-score-config = {
+    scorer-name = "com.tzld.piaoquan.ad.engine.service.score.VlogAdThompsonScorer"
+    scorer-priority = 99
+    model-path = "ad_thompson_model/model_ad_thompson.txt"
+  }
+
+  tf-ecpm-merge-config = {
+        scorer-name = "com.tzld.piaoquan.ad.engine.service.score.VlogMergeEcpmScorer"
+        scorer-priority = 98
+  }
+
+
+}

+ 4 - 2
ad-engine-service/pom.xml

@@ -10,6 +10,8 @@
     </parent>
 
     <artifactId>ad-engine-service</artifactId>
+    <version>1.0.3</version>
+
 
     <properties>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
@@ -21,13 +23,13 @@
         <dependency>
             <groupId>com.tzld.piaoquan</groupId>
             <artifactId>ad-engine-commons</artifactId>
-            <version>1.0.2</version>
+            <version>1.0.3</version>
         </dependency>
 
         <dependency>
             <groupId>com.tzld.piaoquan</groupId>
             <artifactId>recommend-feature-client</artifactId>
-            <version>1.0.2</version>
+            <version>1.0.6</version>
         </dependency>
 
     </dependencies>

+ 9 - 0
ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/score/RankService.java

@@ -1,11 +1,20 @@
 package com.tzld.piaoquan.ad.engine.service.score;
 
+import com.tzld.piaoquan.ad.engine.commons.score.ScoreParam;
+import com.tzld.piaoquan.ad.engine.commons.score.ScorerUtils;
+import com.tzld.piaoquan.ad.engine.service.score.dto.AdPlatformBidCreativeDTO;
+import com.tzld.piaoquan.ad.engine.service.score.param.BidRankRecommendRequestParam;
 import com.tzld.piaoquan.ad.engine.service.score.param.RankRecommendRequestParam;
 import com.tzld.piaoquan.recommend.feature.domain.ad.base.AdRankItem;
+import com.tzld.piaoquan.recommend.feature.domain.ad.base.UserAdFeature;
 
+import java.util.List;
 import java.util.Map;
 
 public interface RankService {
 
     AdRankItem adItemRank(RankRecommendRequestParam request);
+    AdPlatformBidCreativeDTO adBidRank(BidRankRecommendRequestParam request);
+
+    List<AdRankItem> rank (ScoreParam param, UserAdFeature userAdFeature, List<AdRankItem> rankItems, String configFile);
 }

+ 143 - 0
ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/score/VlogAdCtrCalibrationScorer.java

@@ -0,0 +1,143 @@
+package com.tzld.piaoquan.ad.engine.service.score;
+
+
+import com.tzld.piaoquan.ad.engine.commons.score.BaseCalibrationScorer;
+import com.tzld.piaoquan.ad.engine.commons.score.ScoreParam;
+import com.tzld.piaoquan.ad.engine.commons.score.ScorerConfigInfo;
+import com.tzld.piaoquan.ad.engine.commons.score.model.CalibrationModel;
+import com.tzld.piaoquan.recommend.feature.domain.ad.base.AdRankItem;
+import com.tzld.piaoquan.recommend.feature.domain.ad.base.AdRequestContext;
+import com.tzld.piaoquan.recommend.feature.domain.ad.base.UserAdFeature;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang.exception.ExceptionUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.*;
+
+
+//@Service
+public class VlogAdCtrCalibrationScorer extends BaseCalibrationScorer {
+
+    private static final int LOCAL_TIME_OUT = 150;
+    private final static Logger LOGGER = LoggerFactory.getLogger(VlogAdCtrCalibrationScorer.class);
+    private static final ExecutorService executorService = Executors.newFixedThreadPool(128);
+
+    public VlogAdCtrCalibrationScorer(ScorerConfigInfo configInfo) {
+        super(configInfo);
+    }
+
+    @Override
+    public List<AdRankItem> scoring(final ScoreParam param,
+                                    final UserAdFeature userFeature,
+                                    final List<AdRankItem> rankItems) {
+
+        if (userFeature == null || CollectionUtils.isEmpty(rankItems)) {
+            return rankItems;
+        }
+
+        long startTime = System.currentTimeMillis();
+        CalibrationModel model = (CalibrationModel) this.getModel();
+        LOGGER.debug("model size: [{}]", model.getModelSize());
+
+        List<AdRankItem> result = rankItems;
+        result = rankByJava(rankItems, param.getRequestContext(), userFeature);
+
+        LOGGER.debug("calibration ctr ranker time java items size={}, time={} ", result != null ? result.size() : 0,
+                System.currentTimeMillis() - startTime);
+
+        return result;
+    }
+
+    private List<AdRankItem> rankByJava(final List<AdRankItem> items,
+                                        final AdRequestContext requestContext,
+                                        final UserAdFeature user) {
+        long startTime = System.currentTimeMillis();
+        CalibrationModel model = (CalibrationModel) this.getModel();
+        LOGGER.debug("model size: [{}]", model.getModelSize());
+
+        // 所有都参与打分,按照ctr排序
+        multipleCtrScore(items, model);
+
+        // debug log
+        if (LOGGER.isDebugEnabled()) {
+            for (int i = 0; i < items.size(); i++) {
+                LOGGER.debug("after enter feeds model predict ctr score [{}] [{}]", items.get(i), items.get(i).getScore());
+            }
+        }
+
+        LOGGER.debug("calibration ranker java execute time: [{}]", System.currentTimeMillis() - startTime);
+        return items;
+    }
+
+
+    /**
+     * 计算 predict ecpm
+     */
+    public double calcScore(final CalibrationModel model,
+                            final AdRankItem item) {
+        double pctr = 0.0;
+        try {
+            pctr = model.score(item, "ctr");
+        } catch (Exception e) {
+            LOGGER.error("score error for doc={} exception={}", new Object[]{
+                    item.getAdId(), ExceptionUtils.getFullStackTrace(e)});
+        }
+        item.setCtr(pctr);
+        return pctr;
+    }
+
+
+    /**
+     * 并行打分 ecpm
+     *
+     * @param items
+     * @param model
+     */
+    private void multipleCtrScore(final List<AdRankItem> items,
+                                  final CalibrationModel model) {
+
+        List<Callable<Object>> calls = new ArrayList<Callable<Object>>();
+        for (int index = 0; index < items.size(); index++) {
+            final int fIndex = index;
+            items.get(fIndex).setScore(0.0);   //设置为原始值为0
+            calls.add(new Callable<Object>() {
+                @Override
+                public Object call() throws Exception {
+                    try {
+                        calcScore(model, items.get(fIndex));
+                    } catch (Exception e) {
+                        LOGGER.error("calibration exception: [{}] [{}]", items.get(fIndex).adId, ExceptionUtils.getFullStackTrace(e));
+                    }
+                    return new Object();
+                }
+            });
+        }
+
+        List<Future<Object>> futures = null;
+        try {
+            futures = executorService.invokeAll(calls, LOCAL_TIME_OUT, TimeUnit.MILLISECONDS);
+        } catch (InterruptedException e) {
+            LOGGER.error("execute invoke fail: {}", ExceptionUtils.getFullStackTrace(e));
+        }
+
+        //等待所有请求的结果返回, 超时也返回
+        int cancel = 0;
+        if (futures != null) {
+            for (Future<Object> future : futures) {
+                try {
+                    if (!future.isDone() || future.isCancelled() || future.get() == null) {
+                        cancel++;
+                    }
+                } catch (InterruptedException e) {
+                    LOGGER.error("InterruptedException {},{}", ExceptionUtils.getFullStackTrace(e));
+                } catch (ExecutionException e) {
+                    LOGGER.error("ExecutionException {},{}", ExceptionUtils.getFullStackTrace(e));
+                }
+            }
+        }
+        LOGGER.debug("ecpm Score {}, Total: {}, Cancel: {}", new Object[]{items.size(), cancel});
+    }
+}

+ 5 - 11
ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/score/VlogAdCtrLRScorer.java

@@ -26,7 +26,7 @@ public class VlogAdCtrLRScorer extends BaseLRModelScorer {
 
     private final static int CORE_POOL_SIZE = 64;
 
-    private static final int LOCAL_TIME_OUT = 150;
+    private static final int LOCAL_TIME_OUT = 150000;
     private final static Logger LOGGER = LoggerFactory.getLogger(VlogAdCtrLRScorer.class);
     private static final ExecutorService executorService = Executors.newFixedThreadPool(128);
     private static final double defaultUserCtrGroupNumber = 10.0;
@@ -82,9 +82,6 @@ public class VlogAdCtrLRScorer extends BaseLRModelScorer {
             }
         }
 
-        Collections.sort(items);
-
-
         LOGGER.debug("ctr ranker java execute time: [{}]", System.currentTimeMillis() - startTime);
         LOGGER.debug("[ctr ranker time java] items size={}, cost={} ", items != null ? items.size() : 0,
                 System.currentTimeMillis() - startTime);
@@ -122,14 +119,11 @@ public class VlogAdCtrLRScorer extends BaseLRModelScorer {
                 LOGGER.error("score error for doc={} exception={}", new Object[]{
                         item.getAdId(), ExceptionUtils.getFullStackTrace(e)});
             }
-            // 增加实时特征后打开在线存储日志逻辑
-            //
-            // CtrSamples.Builder samples =  com.tzld.piaoquan.recommend.server.gen.recommend.CtrSamples.newBuilder();
-            // samples.setLr_samples(lrSamples);
-            // item.setSamples(samples);
-            //
         }
-        item.setScore(pro);
+        lrSamples.toBuilder().setPredictCtr(pro);
+        //
+//        System.out.println("svc=lrSamplePrint  lrSamples="+lrSamples.toString());
+        item.setCtr(pro);
         return pro;
     }
 

+ 143 - 0
ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/score/VlogAdCvrCalibrationScorer.java

@@ -0,0 +1,143 @@
+package com.tzld.piaoquan.ad.engine.service.score;
+
+
+import com.tzld.piaoquan.ad.engine.commons.score.BaseCalibrationScorer;
+import com.tzld.piaoquan.ad.engine.commons.score.ScoreParam;
+import com.tzld.piaoquan.ad.engine.commons.score.ScorerConfigInfo;
+import com.tzld.piaoquan.ad.engine.commons.score.model.CalibrationModel;
+import com.tzld.piaoquan.recommend.feature.domain.ad.base.AdRankItem;
+import com.tzld.piaoquan.recommend.feature.domain.ad.base.AdRequestContext;
+import com.tzld.piaoquan.recommend.feature.domain.ad.base.UserAdFeature;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang.exception.ExceptionUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.*;
+
+
+//@Service
+public class VlogAdCvrCalibrationScorer extends BaseCalibrationScorer {
+
+    private static final int LOCAL_TIME_OUT = 150;
+    private final static Logger LOGGER = LoggerFactory.getLogger(VlogAdCvrCalibrationScorer.class);
+    private static final ExecutorService executorService = Executors.newFixedThreadPool(128);
+
+    public VlogAdCvrCalibrationScorer(ScorerConfigInfo configInfo) {
+        super(configInfo);
+    }
+
+    @Override
+    public List<AdRankItem> scoring(final ScoreParam param,
+                                    final UserAdFeature userFeature,
+                                    final List<AdRankItem> rankItems) {
+
+        if (userFeature == null || CollectionUtils.isEmpty(rankItems)) {
+            return rankItems;
+        }
+
+        long startTime = System.currentTimeMillis();
+        CalibrationModel model = (CalibrationModel) this.getModel();
+        LOGGER.debug("model size: [{}]", model.getModelSize());
+
+        List<AdRankItem> result = rankItems;
+        result = rankByJava(rankItems, param.getRequestContext(), userFeature);
+
+        LOGGER.debug("calibration ctr ranker time java items size={}, time={} ", result != null ? result.size() : 0,
+                System.currentTimeMillis() - startTime);
+
+        return result;
+    }
+
+    private List<AdRankItem> rankByJava(final List<AdRankItem> items,
+                                        final AdRequestContext requestContext,
+                                        final UserAdFeature user) {
+        long startTime = System.currentTimeMillis();
+        CalibrationModel model = (CalibrationModel) this.getModel();
+        LOGGER.debug("model size: [{}]", model.getModelSize());
+
+        // 所有都参与打分,按照ctr排序
+        multipleCtrScore(items, model);
+
+        // debug log
+        if (LOGGER.isDebugEnabled()) {
+            for (int i = 0; i < items.size(); i++) {
+                LOGGER.debug("after enter feeds model predict ctr score [{}] [{}]", items.get(i), items.get(i).getScore());
+            }
+        }
+
+        LOGGER.debug("calibration ranker java execute time: [{}]", System.currentTimeMillis() - startTime);
+        return items;
+    }
+
+
+    /**
+     * 计算 predict ecpm
+     */
+    public double calcScore(final CalibrationModel model,
+                            final AdRankItem item) {
+        double pcvr = 0.0;
+        try {
+            pcvr = model.score(item, "cvr");
+        } catch (Exception e) {
+            LOGGER.error("score error for doc={} exception={}", new Object[]{
+                    item.getAdId(), ExceptionUtils.getFullStackTrace(e)});
+        }
+        item.setCvr(pcvr);
+        return pcvr;
+    }
+
+
+    /**
+     * 并行打分 ecpm
+     *
+     * @param items
+     * @param model
+     */
+    private void multipleCtrScore(final List<AdRankItem> items,
+                                  final CalibrationModel model) {
+
+        List<Callable<Object>> calls = new ArrayList<Callable<Object>>();
+        for (int index = 0; index < items.size(); index++) {
+            final int fIndex = index;
+            items.get(fIndex).setScore(0.0);   //设置为原始值为0
+            calls.add(new Callable<Object>() {
+                @Override
+                public Object call() throws Exception {
+                    try {
+                        calcScore(model, items.get(fIndex));
+                    } catch (Exception e) {
+                        LOGGER.error("calibration exception: [{}] [{}]", items.get(fIndex).adId, ExceptionUtils.getFullStackTrace(e));
+                    }
+                    return new Object();
+                }
+            });
+        }
+
+        List<Future<Object>> futures = null;
+        try {
+            futures = executorService.invokeAll(calls, LOCAL_TIME_OUT, TimeUnit.MILLISECONDS);
+        } catch (InterruptedException e) {
+            LOGGER.error("execute invoke fail: {}", ExceptionUtils.getFullStackTrace(e));
+        }
+
+        //等待所有请求的结果返回, 超时也返回
+        int cancel = 0;
+        if (futures != null) {
+            for (Future<Object> future : futures) {
+                try {
+                    if (!future.isDone() || future.isCancelled() || future.get() == null) {
+                        cancel++;
+                    }
+                } catch (InterruptedException e) {
+                    LOGGER.error("InterruptedException {},{}", ExceptionUtils.getFullStackTrace(e));
+                } catch (ExecutionException e) {
+                    LOGGER.error("ExecutionException {},{}", ExceptionUtils.getFullStackTrace(e));
+                }
+            }
+        }
+        LOGGER.debug("ecpm Score {}, Total: {}, Cancel: {}", new Object[]{items.size(), cancel});
+    }
+}

+ 181 - 0
ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/score/VlogAdCvrLRScorer.java

@@ -0,0 +1,181 @@
+package com.tzld.piaoquan.ad.engine.service.score;
+
+
+import com.tzld.piaoquan.ad.engine.commons.score.BaseLRModelScorer;
+import com.tzld.piaoquan.ad.engine.commons.score.ScoreParam;
+import com.tzld.piaoquan.ad.engine.commons.score.ScorerConfigInfo;
+import com.tzld.piaoquan.ad.engine.commons.score.model.LRModel;
+import com.tzld.piaoquan.recommend.feature.domain.ad.base.*;
+import com.tzld.piaoquan.recommend.feature.domain.ad.feature.VlogAdCtrLRFeatureExtractor;
+import com.tzld.piaoquan.recommend.feature.model.sample.LRSamples;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang.exception.ExceptionUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.*;
+
+
+//@Service
+public class VlogAdCvrLRScorer extends BaseLRModelScorer {
+
+    private final static int CORE_POOL_SIZE = 64;
+
+    private static final int LOCAL_TIME_OUT = 150;
+    private final static Logger LOGGER = LoggerFactory.getLogger(VlogAdCvrLRScorer.class);
+    private static final ExecutorService executorService = Executors.newFixedThreadPool(128);
+    private static final double defaultUserCtrGroupNumber = 10.0;
+    private static final int enterFeedsScoreRatio = 10;
+    private static final int enterFeedsScoreNum = 20;
+
+
+    public VlogAdCvrLRScorer(ScorerConfigInfo configInfo) {
+        super(configInfo);
+    }
+
+
+    @Override
+    public List<AdRankItem> scoring(final ScoreParam param,
+                                    final UserAdFeature userFeature,
+                                    final List<AdRankItem> rankItems) {
+
+        if (userFeature == null || CollectionUtils.isEmpty(rankItems)) {
+            return rankItems;
+        }
+
+        long startTime = System.currentTimeMillis();
+        LRModel model = (LRModel) this.getModel();
+        LOGGER.debug("model size: [{}]", model.getModelSize());
+
+        List<AdRankItem> result = rankItems;
+        result = rankByJava(rankItems, param.getRequestContext(), userFeature);
+
+        LOGGER.debug("ctr ranker time java items size={}, time={} ", result != null ? result.size() : 0,
+                System.currentTimeMillis() - startTime);
+
+        return result;
+    }
+
+    private List<AdRankItem> rankByJava(final List<AdRankItem> items,
+                                        final AdRequestContext requestContext,
+                                        final UserAdFeature user) {
+        long startTime = System.currentTimeMillis();
+        LRModel model = (LRModel) this.getModel();
+        LOGGER.debug("model size: [{}]", model.getModelSize());
+
+        // userAdBytes
+        UserAdBytesFeature userInfoBytes = null;
+        userInfoBytes = new UserAdBytesFeature(user);
+
+        // 所有都参与打分,按照cvr排序
+        multipleScore(items, userInfoBytes, requestContext, model);
+
+        // debug log
+        if (LOGGER.isDebugEnabled()) {
+            for (int i = 0; i < items.size(); i++) {
+                LOGGER.debug("after enter feeds model predict ctr score [{}] [{}]", items.get(i), items.get(i).getScore());
+            }
+        }
+
+        LOGGER.debug("ctr ranker java execute time: [{}]", System.currentTimeMillis() - startTime);
+        LOGGER.debug("[ctr ranker time java] items size={}, cost={} ", items != null ? items.size() : 0,
+                System.currentTimeMillis() - startTime);
+        return items;
+    }
+
+
+    /**
+     * 计算 predict cvr
+     */
+    public double calcScore(final LRModel lrModel,
+                            final AdRankItem item,
+                            final UserAdBytesFeature userInfoBytes,
+                            final AdRequestContext requestContext) {
+
+        LRSamples lrSamples = null;
+        VlogAdCtrLRFeatureExtractor bytesFeatureExtractor;
+        bytesFeatureExtractor = new VlogAdCtrLRFeatureExtractor();
+
+        try {
+            AdItemBytesFeature newsInfoBytes = new AdItemBytesFeature(item.getItemFeature());
+            lrSamples = bytesFeatureExtractor.single(userInfoBytes, newsInfoBytes,
+                    new AdRequestContextBytesFeature(requestContext));
+        } catch (Exception e) {
+            LOGGER.error("extract feature error for imei={}, doc={}, [{}]", new Object[]{new String(userInfoBytes.getMid()), item.getAdId(),
+                    ExceptionUtils.getFullStackTrace(e)});
+        }
+
+
+        double pro = 0.0;
+        if (lrSamples != null && lrSamples.getFeaturesList() != null) {
+            try {
+                pro = lrModel.score(lrSamples);
+            } catch (Exception e) {
+                LOGGER.error("score error for doc={} exception={}", new Object[]{
+                        item.getAdId(), ExceptionUtils.getFullStackTrace(e)});
+            }
+        }
+        item.setCvr(pro);
+        return pro;
+    }
+
+
+    /**
+     * 并行打分
+     *
+     * @param items
+     * @param userInfoBytes
+     * @param requestContext
+     * @param model
+     */
+    private void multipleScore(final List<AdRankItem> items,
+                                  final UserAdBytesFeature userInfoBytes,
+                                  final AdRequestContext requestContext,
+                                  final LRModel model) {
+
+        List<Callable<Object>> calls = new ArrayList<Callable<Object>>();
+        for (int index = 0; index < items.size(); index++) {
+            final int fIndex = index;
+            items.get(fIndex).setScore(0.0);   //原始分为 cube中的粗打分,如果超时,为原始值存在问题, 需要置0
+            calls.add(new Callable<Object>() {
+                @Override
+                public Object call() throws Exception {
+                    try {
+                        calcScore(model, items.get(fIndex), userInfoBytes, requestContext);
+                    } catch (Exception e) {
+                        LOGGER.error("ctr exception: [{}] [{}]", items.get(fIndex).adId, ExceptionUtils.getFullStackTrace(e));
+                    }
+                    return new Object();
+                }
+            });
+        }
+
+        List<Future<Object>> futures = null;
+        try {
+            futures = executorService.invokeAll(calls, LOCAL_TIME_OUT, TimeUnit.MILLISECONDS);
+        } catch (InterruptedException e) {
+            LOGGER.error("execute invoke fail: {}", ExceptionUtils.getFullStackTrace(e));
+        }
+
+        //等待所有请求的结果返回, 超时也返回
+        int cancel = 0;
+        if (futures != null) {
+            for (Future<Object> future : futures) {
+                try {
+                    if (!future.isDone() || future.isCancelled() || future.get() == null) {
+                        cancel++;
+                    }
+                } catch (InterruptedException e) {
+                    LOGGER.error("InterruptedException {},{}", ExceptionUtils.getFullStackTrace(e));
+                } catch (ExecutionException e) {
+                    LOGGER.error("ExecutionException {},{}", requestContext.getApptype(),
+                            ExceptionUtils.getFullStackTrace(e));
+                }
+            }
+        }
+        LOGGER.debug("Ctr Score {}, Total: {}, Cancel: {}", new Object[]{requestContext.getApptype(), items.size(), cancel});
+    }
+}

+ 156 - 0
ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/score/VlogAdThompsonScorer.java

@@ -0,0 +1,156 @@
+package com.tzld.piaoquan.ad.engine.service.score;
+
+
+import com.tzld.piaoquan.ad.engine.commons.score.BaseThompsonSamplingScorer;
+import com.tzld.piaoquan.ad.engine.commons.score.ScoreParam;
+import com.tzld.piaoquan.ad.engine.commons.score.ScorerConfigInfo;
+import com.tzld.piaoquan.ad.engine.commons.score.model.LRModel;
+import com.tzld.piaoquan.ad.engine.commons.score.model.ThompsonSamplingModel;
+import com.tzld.piaoquan.recommend.feature.domain.ad.base.*;
+import com.tzld.piaoquan.recommend.feature.domain.ad.feature.VlogAdCtrLRFeatureExtractor;
+import com.tzld.piaoquan.recommend.feature.model.sample.LRSamples;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang.exception.ExceptionUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.*;
+
+
+//@Service
+public class VlogAdThompsonScorer extends BaseThompsonSamplingScorer {
+
+    private static final int LOCAL_TIME_OUT = 150;
+    private final static Logger LOGGER = LoggerFactory.getLogger(VlogAdThompsonScorer.class);
+    private static final ExecutorService executorService = Executors.newFixedThreadPool(128);
+
+    public VlogAdThompsonScorer(ScorerConfigInfo configInfo) {
+        super(configInfo);
+    }
+
+    @Override
+    public List<AdRankItem> scoring(final ScoreParam param,
+                                    final UserAdFeature userFeature,
+                                    final List<AdRankItem> rankItems) {
+
+        if (userFeature == null || CollectionUtils.isEmpty(rankItems)) {
+            return rankItems;
+        }
+
+        long startTime = System.currentTimeMillis();
+        ThompsonSamplingModel model = (ThompsonSamplingModel) this.getModel();
+        LOGGER.debug("model size: [{}]", model.getModelSize());
+
+        List<AdRankItem> result = rankItems;
+        result = rankByJava(rankItems, param.getRequestContext(), userFeature);
+
+        LOGGER.debug("thompson sampling ctr ranker time java items size={}, time={} ", result != null ? result.size() : 0,
+                System.currentTimeMillis() - startTime);
+
+        return result;
+    }
+
+    private List<AdRankItem> rankByJava(final List<AdRankItem> items,
+                                        final AdRequestContext requestContext,
+                                        final UserAdFeature user) {
+        long startTime = System.currentTimeMillis();
+        ThompsonSamplingModel model = (ThompsonSamplingModel) this.getModel();
+        LOGGER.debug("model size: [{}]", model.getModelSize());
+
+        // 所有都参与打分,按照ctr排序
+        multipleCtrScore(items, model);
+
+        // debug log
+        if (LOGGER.isDebugEnabled()) {
+            for (int i = 0; i < items.size(); i++) {
+                LOGGER.debug("after enter feeds model predict ctr score [{}] [{}]", items.get(i), items.get(i).getScore());
+            }
+        }
+
+        LOGGER.debug("thompson ranker java execute time: [{}]", System.currentTimeMillis() - startTime);
+        LOGGER.debug("[thompson ranker time java] items size={}, cost={} ", items != null ? items.size() : 0,
+                System.currentTimeMillis() - startTime);
+        return items;
+    }
+
+
+    /**
+     * 计算 predict ecpm
+     */
+    public double calcScore(final ThompsonSamplingModel model,
+                            final AdRankItem item) {
+
+
+        double pctr = 0.0;
+        double pcvr = 0.0;
+        double ecpm = 0.0;
+
+        try {
+            pctr = model.score(item, "ctr");
+            pcvr = model.score(item, "cvr");
+            ecpm = item.getCpa() * item.getBid1() * item.getBid2() * pctr * pcvr;
+        } catch (Exception e) {
+            LOGGER.error("score error for doc={} exception={}", new Object[]{
+                    item.getAdId(), ExceptionUtils.getFullStackTrace(e)});
+        }
+        item.setCtr(pctr);
+        item.setCvr(pcvr);
+        item.setEcpm1(ecpm);
+        item.setScore(ecpm);
+        return ecpm;
+    }
+
+
+    /**
+     * 并行打分 ecpm
+     * @param items
+     * @param model
+     */
+    private void multipleCtrScore(final List<AdRankItem> items,
+                                  final ThompsonSamplingModel model) {
+
+        List<Callable<Object>> calls = new ArrayList<Callable<Object>>();
+        for (int index = 0; index < items.size(); index++) {
+            final int fIndex = index;
+            items.get(fIndex).setScore(0.0);   //设置为原始值为0
+            calls.add(new Callable<Object>() {
+                @Override
+                public Object call() throws Exception {
+                    try {
+                        calcScore(model, items.get(fIndex));
+                    } catch (Exception e) {
+                        LOGGER.error("thompson exception: [{}] [{}]", items.get(fIndex).adId, ExceptionUtils.getFullStackTrace(e));
+                    }
+                    return new Object();
+                }
+            });
+        }
+
+        List<Future<Object>> futures = null;
+        try {
+            futures = executorService.invokeAll(calls, LOCAL_TIME_OUT, TimeUnit.MILLISECONDS);
+        } catch (InterruptedException e) {
+            LOGGER.error("execute invoke fail: {}", ExceptionUtils.getFullStackTrace(e));
+        }
+
+        //等待所有请求的结果返回, 超时也返回
+        int cancel = 0;
+        if (futures != null) {
+            for (Future<Object> future : futures) {
+                try {
+                    if (!future.isDone() || future.isCancelled() || future.get() == null) {
+                        cancel++;
+                    }
+                } catch (InterruptedException e) {
+                    LOGGER.error("InterruptedException {},{}", ExceptionUtils.getFullStackTrace(e));
+                } catch (ExecutionException e) {
+                    LOGGER.error("ExecutionException {},{}", ExceptionUtils.getFullStackTrace(e));
+                }
+            }
+        }
+        LOGGER.debug("ecpm Score {}, Total: {}, Cancel: {}", new Object[]{ items.size(), cancel});
+    }
+}

+ 68 - 0
ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/score/VlogMergeEcpmScorer.java

@@ -0,0 +1,68 @@
+package com.tzld.piaoquan.ad.engine.service.score;
+
+
+import com.tzld.piaoquan.ad.engine.commons.score.BaseLRModelScorer;
+import com.tzld.piaoquan.ad.engine.commons.score.ScoreParam;
+import com.tzld.piaoquan.ad.engine.commons.score.ScorerConfigInfo;
+import com.tzld.piaoquan.ad.engine.commons.score.model.LRModel;
+import com.tzld.piaoquan.recommend.feature.domain.ad.base.AdRankItem;
+import com.tzld.piaoquan.recommend.feature.domain.ad.base.UserAdFeature;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Collections;
+import java.util.List;
+
+
+//@Service
+public class VlogMergeEcpmScorer extends BaseLRModelScorer {
+
+    private final static Logger LOGGER = LoggerFactory.getLogger(VlogMergeEcpmScorer.class);
+
+
+    public VlogMergeEcpmScorer(ScorerConfigInfo configInfo) {
+        super(configInfo);
+    }
+
+
+    @Override
+    public List<AdRankItem> scoring(final ScoreParam param,
+                                    final UserAdFeature userFeature,
+                                    final List<AdRankItem> rankItems) {
+
+
+        long startTime = System.currentTimeMillis();
+        List<AdRankItem> result = mergetEcpm(rankItems);
+        LOGGER.debug("ctr ranker time java items size={}, time={} ", result != null ? result.size() : 0,
+                System.currentTimeMillis() - startTime);
+
+        return result;
+    }
+
+
+    public List<AdRankItem> mergetEcpm(List<AdRankItem> items) {
+        long startTime = System.currentTimeMillis();
+
+        for (AdRankItem item : items) {
+            try {
+                double cpa = item.getCpa();
+                double bid1 = item.getBid1();
+                double bid2 = item.getBid2();
+                double pctr = item.getCtr();
+                double pcvr = item.getCvr();
+                //todo
+                double ecpm = cpa * bid1 * bid2 * pcvr * pctr * 1000d;
+//                double ecpm = cpa * bid1 * bid2 * pcvr * pctr;
+                item.setEcpm1(ecpm/1000d);
+                item.setScore(ecpm/1000d);
+            } catch (Exception e) {
+                LOGGER.error("merge Ecpm Score: {} error", "");
+                item.setCtr(0.0);
+            }
+            LOGGER.debug("merge Ecpm ranker , score: {}->{}", "");
+        }
+        Collections.sort(items);
+        return items;
+    }
+
+}

+ 5 - 5
ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/score/convert/FeatureConvert.java

@@ -48,11 +48,11 @@ public class FeatureConvert {
 
     public static AdActionFeature convertToJava(AdActionFeatureProto adActionFeatureProto) {
         AdActionFeature adActionFeature = new AdActionFeature();
-        adActionFeature.setAdView(adActionFeatureProto.getAdView());
-        adActionFeature.setAdClick(adActionFeatureProto.getAdClick());
-        adActionFeature.setAdConversion(adActionFeatureProto.getAdConversion());
-        adActionFeature.setCtr(adActionFeatureProto.getCtr());
-        adActionFeature.setCvr(adActionFeatureProto.getCvr());
+        adActionFeature.setOriginAdView(adActionFeatureProto.getAdView());
+        adActionFeature.setOriginAdClick(adActionFeatureProto.getAdClick());
+        adActionFeature.setOriginAdConversion(adActionFeatureProto.getAdConversion());
+        adActionFeature.setOriginCtr(adActionFeatureProto.getCtr());
+        adActionFeature.setOriginCvr(adActionFeatureProto.getCvr());
         return adActionFeature;
     }
 

+ 2 - 1
ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/score/convert/RequestConvert.java

@@ -1,5 +1,6 @@
 package com.tzld.piaoquan.ad.engine.service.score.convert;
 
+import com.tzld.piaoquan.ad.engine.service.score.param.RecommendRequestParam;
 import com.tzld.piaoquan.recommend.feature.domain.ad.base.AdRequestContext;
 import com.tzld.piaoquan.ad.engine.commons.score.ScoreParam;
 import com.tzld.piaoquan.ad.engine.service.score.param.RankRecommendRequestParam;
@@ -9,7 +10,7 @@ import java.time.format.DateTimeFormatter;
 
 public class RequestConvert {
 
-    public static ScoreParam requestConvert(RankRecommendRequestParam request){
+    public static ScoreParam requestConvert(RecommendRequestParam request){
         AdRequestContext context=new AdRequestContext();
         context.setApptype(request.getAppType().toString());
         context.setMachineinfoBrand(request.getMachineInfo().getBrand());

+ 48 - 0
ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/score/dto/AdPlatformBidCreativeDTO.java

@@ -0,0 +1,48 @@
+package com.tzld.piaoquan.ad.engine.service.score.dto;
+
+import com.alibaba.fastjson.JSON;
+import lombok.Builder;
+import lombok.Data;
+import lombok.ToString;
+
+@Builder
+@Data
+@ToString
+public class AdPlatformBidCreativeDTO {
+
+    private Long creativeId;
+
+    private String creativeCode;
+
+    private Integer bidType;
+
+    private Double pctr;
+
+    private Double pcvr;
+
+    private Double cpa;
+
+    private Double bid1;
+
+    private Double bid2;
+
+    private Double ecpm1;
+
+    private Double ecpm2;
+
+    public static void main(String[] args) {
+        System.out.println(JSON.toJSONString(AdPlatformBidCreativeDTO.builder()
+                .creativeId(3366L)
+                .creativeCode("CREATIVE_17036704789851370")
+                .bidType(2)
+                .pctr(3.2)
+                .pcvr(1.2)
+                .cpa(40.1)
+                .bid1(1.3)
+                .bid2(2.1)
+                .ecpm1(0.1)
+                .ecpm2(0.2)
+                .build()));
+    }
+
+}

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

@@ -1,5 +1,10 @@
 package com.tzld.piaoquan.ad.engine.service.score.impl;
 
+import com.alibaba.fastjson.JSONObject;
+import com.google.gson.JsonObject;
+import com.tzld.piaoquan.ad.engine.commons.util.DateUtils;
+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;
 import com.tzld.piaoquan.recommend.feature.domain.ad.base.AdRankItem;
 import com.tzld.piaoquan.recommend.feature.domain.ad.base.UserAdFeature;
@@ -10,13 +15,19 @@ import com.tzld.piaoquan.ad.engine.service.score.FeatureRemoteService;
 import com.tzld.piaoquan.ad.engine.service.score.RankService;
 import com.tzld.piaoquan.ad.engine.service.score.convert.RequestConvert;
 import com.tzld.piaoquan.ad.engine.service.score.param.RankRecommendRequestParam;
+import org.joda.time.LocalTime;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.util.CollectionUtils;
 
+import java.time.DayOfWeek;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
 import java.util.*;
+import java.util.stream.Collectors;
 
 @Service
 public class RankServiceImpl implements RankService {
@@ -26,9 +37,18 @@ public class RankServiceImpl implements RankService {
     @Autowired
     FeatureRemoteService featureRemoteService;
 
+    @Autowired
+    RankServiceThompsonImpl rankServiceThompson;
+
     public AdRankItem adItemRank(RankRecommendRequestParam request){
 
         ScoreParam param= RequestConvert.requestConvert(request);
+        LocalDateTime currentTime = LocalDateTime.now();
+        int currentHour = currentTime.getHour();
+        int dayOfWeek = currentTime.getDayOfWeek().getValue();
+        param.getRequestContext().setHour(currentHour+"");
+        param.getRequestContext().setWeek(dayOfWeek+"");
+
         UserAdFeature userAdFeature=featureRemoteService.getUserAdFeature(request.getMid());
         if(userAdFeature==null){
             userAdFeature=new UserAdFeature();
@@ -38,25 +58,96 @@ public class RankServiceImpl implements RankService {
                         CommonCollectionUtils.toList(request.getAdIdList(),id->id.toString())
                 );
         //兜底方案
+        List<AdRankItem> rankResult;
         if(rankItems==null|| rankItems.size()==0){
-            AdItemFeature feature=new AdItemFeature();
-            feature.setAdId(request.getAdIdList().get(0).toString());
-            AdRankItem adRankItem=new AdRankItem();
-            adRankItem.setAdId(request.getAdIdList().get(0));
-            adRankItem.setItemFeature(feature);
-            rankItems=new ArrayList<>();
-            rankItems.add(adRankItem);
+            rankResult=rankServiceThompson.rank(param, userAdFeature, rankItems,null);
+        }else {
+            rankResult=rank(param, userAdFeature, rankItems,ScorerUtils.BASE_CONF);
         }
-        List<AdRankItem> rankResult = ScorerUtils
-                .getScorerPipeline(
-                        ScorerUtils.BASE_CONF)
-                .scoring(param, userAdFeature, rankItems);
+        log.info("svc=adItemRank rankResult={}", JSONObject.toJSONString(rankResult));
+        if (!CollectionUtils.isEmpty(rankResult)) {
+            return rankResult.get(0);
+        }else {
+            //空返回值
+            return new AdRankItem();
+        }
+    }
 
+    @Override
+    public AdPlatformBidCreativeDTO adBidRank(BidRankRecommendRequestParam request) {
 
-        if (!CollectionUtils.isEmpty(rankResult)) {
-           return rankResult.get(0);
+        ScoreParam param= RequestConvert.requestConvert(request);
+        UserAdFeature userAdFeature=featureRemoteService.getUserAdFeature(request.getMid());
+        if(userAdFeature==null){
+            userAdFeature=new UserAdFeature();
+        }
+        Map<String,List<AdPlatformBidCreativeDTO>> groupMap=request
+                .getCreativeList()
+                .stream()
+                .                                  collect(Collectors.groupingBy(creativeDTO -> creativeDTO.getCreativeId()+""));
+
+        List<AdRankItem> rankItems=featureRemoteService.
+                getAllAdFeatureList(
+                        new ArrayList<>(groupMap.keySet())
+                );
+
+        for(AdRankItem item:rankItems){
+            try {
+                AdPlatformBidCreativeDTO dto=groupMap.get(item.getAdId()+"").get(0);
+                item.setBid1(dto.getBid1());
+                item.setBid2(dto.getBid2());
+                item.setCpa(dto.getCpa());
+            }catch (Exception e){
+                e.printStackTrace();
+            }
+        }
+        log.info("svc=adItemRank  param={}  userAdFeature={}  rankItems={}",
+                JSONObject.toJSONString(param),JSONObject.toJSONString(userAdFeature),JSONObject.toJSONString(rankItems));
+        List<AdRankItem> rankResult;
+        if(rankItems==null|| rankItems.size()==0){
+            rankItems=new LinkedList<>();
+            for(AdPlatformBidCreativeDTO dto:request.getCreativeList()){
+                AdRankItem item=new AdRankItem();
+                item.setBid1(dto.getBid1());
+                item.setBid2(dto.getBid2());
+                item.setCpa(dto.getCpa());
+                item.setAdId(dto.getCreativeId());
+                item.setItemFeature(new AdItemFeature());
+                rankItems.add(item);
+            }
+            rankResult=rankServiceThompson.rank(param, userAdFeature, rankItems,null);
+        }else {
+            rankResult=rank(param, userAdFeature, rankItems,ScorerUtils.BASE_CONF);
+        }
+        log.info("svc=adBidRank rankResult={}", JSONObject.toJSONString(rankResult));
+
+        AdRankItem topItem=rankResult.get(0);
+
+        AdPlatformBidCreativeDTO result=AdPlatformBidCreativeDTO
+                .builder()
+                .build();
+        BeanUtils.copyProperties(topItem,result);
+        result.setCreativeId(topItem.getAdId());
+        result.setPctr(topItem.getCtr());
+        result.setPcvr(topItem.getCvr());
+        result.setCreativeCode(groupMap.get(topItem.getAdId()+"").get(0).getCreativeCode());
+        if(rankResult.size()<=1){
+            //经验值 待定
+            result.setEcpm2(topItem.getEcpm1()*0.9);
         }else {
-            return null;
+            result.setEcpm2(rankResult.get(1).getEcpm1());
         }
+        return result;
     }
+
+
+
+    public List<AdRankItem> rank (ScoreParam param, UserAdFeature userAdFeature, List<AdRankItem> rankItems,String configFile){
+        List<AdRankItem> rankResult = ScorerUtils
+                .getScorerPipeline(configFile)
+                .scoring(param, userAdFeature, rankItems);
+        return rankResult;
+    }
+
+
 }

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

@@ -0,0 +1,65 @@
+package com.tzld.piaoquan.ad.engine.service.score.impl;
+
+import com.tzld.piaoquan.ad.engine.commons.score.ScoreParam;
+import com.tzld.piaoquan.ad.engine.commons.score.ScorerUtils;
+import com.tzld.piaoquan.ad.engine.commons.util.CommonCollectionUtils;
+import com.tzld.piaoquan.ad.engine.service.score.FeatureRemoteService;
+import com.tzld.piaoquan.ad.engine.service.score.RankService;
+import com.tzld.piaoquan.ad.engine.service.score.convert.RequestConvert;
+import com.tzld.piaoquan.ad.engine.service.score.dto.AdPlatformBidCreativeDTO;
+import com.tzld.piaoquan.ad.engine.service.score.param.BidRankRecommendRequestParam;
+import com.tzld.piaoquan.ad.engine.service.score.param.RankRecommendRequestParam;
+import com.tzld.piaoquan.recommend.feature.domain.ad.base.AdItemFeature;
+import com.tzld.piaoquan.recommend.feature.domain.ad.base.AdRankItem;
+import com.tzld.piaoquan.recommend.feature.domain.ad.base.UserAdFeature;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Service
+public class RankServiceThompsonImpl implements RankService {
+
+    private final static Logger log = LoggerFactory.getLogger(RankServiceThompsonImpl.class);
+
+    @Autowired
+    FeatureRemoteService featureRemoteService;
+
+    public AdRankItem adItemRank(RankRecommendRequestParam request) {
+
+        ScoreParam param = RequestConvert.requestConvert(request);
+        UserAdFeature userAdFeature = new UserAdFeature();
+        List<AdRankItem> rankItems = featureRemoteService.getAllAdFeatureList(
+                CommonCollectionUtils.toList(request.getAdIdList(), id -> id.toString())
+        );
+        List<AdRankItem> rankResult = ScorerUtils
+                .getScorerPipeline(ScorerUtils.THOMPSON_CONF)
+                .scoring(param, userAdFeature, rankItems);
+
+        if (!CollectionUtils.isEmpty(rankResult)) {
+            return rankResult.get(0);
+        } else {
+            return null;
+        }
+    }
+
+    @Override
+    public AdPlatformBidCreativeDTO adBidRank(BidRankRecommendRequestParam request) {
+        return null;
+    }
+
+    public List<AdRankItem> rank (ScoreParam param, UserAdFeature userAdFeature, List<AdRankItem> rankItems,String configFile){
+        if(configFile==null){
+            configFile=ScorerUtils.THOMPSON_CONF;
+        }
+        List<AdRankItem> rankResult = ScorerUtils
+                .getScorerPipeline(configFile)
+                .scoring(param, userAdFeature, rankItems);
+        return rankResult;
+    }
+
+}

+ 13 - 0
ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/score/param/BidRankRecommendRequestParam.java

@@ -0,0 +1,13 @@
+package com.tzld.piaoquan.ad.engine.service.score.param;
+
+import com.tzld.piaoquan.ad.engine.service.score.dto.AdPlatformBidCreativeDTO;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class BidRankRecommendRequestParam extends RecommendRequestParam{
+
+     List<AdPlatformBidCreativeDTO> creativeList;
+
+}

+ 1 - 4
ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/score/param/RankRecommendRequestParam.java

@@ -5,10 +5,7 @@ import lombok.Data;
 import java.util.List;
 
 @Data
-public class RankRecommendRequestParam {
-     MachineInfoParam machineInfo;
-     Long appType;
-     String mid;
+public class RankRecommendRequestParam extends RecommendRequestParam{
      List<Long> adIdList;
 
 }

+ 12 - 0
ad-engine-service/src/main/java/com/tzld/piaoquan/ad/engine/service/score/param/RecommendRequestParam.java

@@ -0,0 +1,12 @@
+package com.tzld.piaoquan.ad.engine.service.score.param;
+
+import lombok.Data;
+import lombok.ToString;
+
+@Data
+@ToString
+public class RecommendRequestParam {
+    MachineInfoParam machineInfo;
+    Long appType;
+    String mid;
+}