Authored by hugufei

向量代码兼容

... ... @@ -28,7 +28,7 @@ public class RecommendBrandAggregation extends AbstractAggregation {
this.simpleFieldAggs = new ArrayList<SimpleFieldAgg>();
simpleFieldAggs.add(new SimpleFieldAgg(aggName(), ProductIndexEsField.brandId, 300));
// 构造TopHitOrder
if (personalVectorFeatureSearch.getPersonalizedSearch(paramMap) != null) {
if (personalVectorFeatureSearch.queryPersonalizedSearch(paramMap) != null) {
topHitOrder = "_score:desc";
}
}
... ...
... ... @@ -36,7 +36,7 @@ public class RecommendShopAggregation extends AbstractAggregation {
this.simpleFieldAggs = new ArrayList<SimpleFieldAgg>();
simpleFieldAggs.add(new SimpleFieldAgg(aggName(), ProductIndexEsField.shopId, shopCount));
// 构造topHit排序规则
if (personalVectorFeatureSearch.getPersonalizedSearch(paramMap) != null) {
if (personalVectorFeatureSearch.queryPersonalizedSearch(paramMap) != null) {
topHitOrder = "_score:desc";
}
}
... ...
... ... @@ -6,7 +6,9 @@ import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import com.yoho.search.base.utils.ConvertUtils;
import com.yoho.search.service.recall.config.SpecialShopConstants;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.common.lucene.search.function.CombineFunction;
... ... @@ -74,7 +76,7 @@ public class FunctionScoreSearchHelper {
// 3、构造functionScoreQueryBuilder
YohoFilterFunctionBuilders yohoFilterFunctionBuilders = new YohoFilterFunctionBuilders();
for (IScorer iScorer : scorers) {
if(iScorer!=null){
if (iScorer != null) {
iScorer.addScorer(yohoFilterFunctionBuilders);
}
}
... ... @@ -148,7 +150,7 @@ public class FunctionScoreSearchHelper {
scorers.add(searchScorerFactory.getOfflineSaleOnlyScorer());
// 6、添加关键词完全匹配的打分器
String query = MapUtils.getString(paramMap, SearchRequestParams.PARAM_SEARCH_QUERY);
if(StringUtils.isNotBlank(query)){
if (StringUtils.isNotBlank(query)) {
scorers.add(searchScorerFactory.getCsBrandKeyWordScorer(query));
}
// 7、添加特殊店铺的打分器
... ... @@ -217,13 +219,13 @@ public class FunctionScoreSearchHelper {
return null;
}
// 2、获取PersonalizedSearch
PersonalizedSearch personalizedSearch = personalVectorFeatureSearch.getPersonalizedSearch(paramMap);
PersonalizedSearch personalizedSearch = personalVectorFeatureSearch.queryPersonalizedSearch(paramMap);
if (personalizedSearch == null) {
return null;
}
// 3、为个性化打分添加filter条件
BoolQueryBuilder scoreFilter = productCountService.genScoreFilter(persionalFilter);
return searchScorerFactory.getFeatureFactorScorer(scoreFilter, personalizedSearch.getUserVectorFeature(), personalizedSearch.getVectorFeatureVersion());
return searchScorerFactory.getFeatureFactorScorer(scoreFilter, personalizedSearch.getVectorVersion(), personalizedSearch.getVectorFeatures());
}
/**
... ... @@ -243,12 +245,17 @@ public class FunctionScoreSearchHelper {
if (productVectorFeatures.length != 2) {
return queryBuilder;
}
IScorer scorer = searchScorerFactory.getFeatureFactorScorer(queryBuilder, productVectorFeatures[1], productVectorFeatures[0]);
// 3、参数检测
String featureVersion = productVectorFeatures[0];
List<Double> featureFactors = ConvertUtils.stringToDoubleList(productVectorFeatures[1], ",");
if (StringUtils.isBlank(featureVersion) || CollectionUtils.isEmpty(featureFactors)) {
return queryBuilder;
}
//4、构造scorer
IScorer scorer = searchScorerFactory.getFeatureFactorScorer(queryBuilder, featureVersion, featureFactors);
YohoFilterFunctionBuilders yohoFilterFunctionBuilders = new YohoFilterFunctionBuilders();
if(scorer!=null){
scorer.addScorer(yohoFilterFunctionBuilders);
}
FunctionScoreQueryBuilder functionScoreQueryBuilder = new FunctionScoreQueryBuilder(queryBuilder,yohoFilterFunctionBuilders.getFilterFunctionBuilders());
FunctionScoreQueryBuilder functionScoreQueryBuilder = new FunctionScoreQueryBuilder(queryBuilder, yohoFilterFunctionBuilders.getFilterFunctionBuilders());
return functionScoreQueryBuilder;
}
... ...
... ... @@ -182,7 +182,7 @@ public class UserRecallResponseBuilder {
//1、获取用户向量
Map<String, String> paramMap = new HashMap<>();
paramMap.put("uid", "" + uid);
PersonalizedSearch personalizedSearch = personalVectorFeatureSearch.getPersonalizedSearch(paramMap);
PersonalizedSearch personalizedSearch = personalVectorFeatureSearch.queryPersonalizedSearch(paramMap);
UserFeatureFactor userFeatureFactor = new UserFeatureFactor(personalizedSearch);
//2、计算相关性
int recommendSknIndex = 10000;
... ...
package com.yoho.search.service.recall.beans.persional;
import com.yoho.search.base.helper.Word2VectorCalculator;
import com.yoho.search.base.utils.ConvertUtils;
import com.yoho.search.core.personalized.models.PersonalizedSearch;
import com.yoho.search.service.recall.models.personal.UserFeatureFactor;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
@Component
... ... @@ -21,23 +22,28 @@ public class ProductFeatureFactorComponent {
public double calProductFeatureFactor(UserFeatureFactor userFeatureFactor, String productFeatureFactor) {
try {
//商品向量不存在,则返回
if (StringUtils.isBlank(productFeatureFactor)) {
return 0;
}
//用户向量不存在,则返回0
if (userFeatureFactor == null || StringUtils.isBlank(userFeatureFactor.getVectorFeatureVersion())) {
if (userFeatureFactor == null || StringUtils.isBlank(userFeatureFactor.getVectorVersion())) {
return 0;
}
if (StringUtils.isBlank(productFeatureFactor)) {
if (CollectionUtils.isEmpty(userFeatureFactor.getVectorFeatureList())) {
return 0;
}
String versionPrefix = userFeatureFactor.getVectorFeatureVersion() + "|";
//版本不匹配,则返回0
String versionPrefix = userFeatureFactor.getVectorVersion() + "|";
if (!productFeatureFactor.trim().startsWith(versionPrefix)) {
return 0;
}
String[] productFeatureFactorArr = productFeatureFactor.trim().substring(versionPrefix.length()).split(",");
List<Double> productFeatureVectors = this.arrayToList(productFeatureFactorArr);
if (productFeatureVectors == null || productFeatureVectors.size() != userFeatureFactor.getUserFeatureVectorList().size()) {
//执行计算
List<Double> productFeatureVectors = ConvertUtils.stringToDoubleList(productFeatureFactor.trim().substring(versionPrefix.length()), ",");
if (productFeatureVectors == null || productFeatureVectors.size() != userFeatureFactor.getVectorFeatureList().size()) {
return 0;
}
double score = Word2VectorCalculator.calScore(userFeatureFactor.getUserFeatureVectorList(), userFeatureFactor.getUserFeatureVectorNorm(), productFeatureVectors);
double score = Word2VectorCalculator.calScore(userFeatureFactor.getVectorFeatureList(), userFeatureFactor.getUserFeatureVectorNorm(), productFeatureVectors);
double finalScore = baseConstant + factorConstant * score;
return finalScore;
} catch (Exception e) {
... ... @@ -46,22 +52,12 @@ public class ProductFeatureFactorComponent {
}
}
private List<Double> arrayToList(String[] productFeatureFactorStrArr) {
List<Double> results = new ArrayList<>();
if (productFeatureFactorStrArr == null) {
return results;
}
for (String productFeatureFactor : productFeatureFactorStrArr) {
results.add(Double.parseDouble(productFeatureFactor));
}
return results;
}
public static void main(String[] args) {
PersonalizedSearch personalizedSearch = new PersonalizedSearch("1", "20180408", "0.342045,-0.547933,0.291732,-0.056515,-0.182701,0.31113,0.151578,0.087678,-0.045536,-0.525699,-0.394715,-0.103153,-0.05575,-0.540641,0.028046,-0.193109,-0.003591,0.180923,0.290261,0.532309,-0.202463,-0.047271,-0.246197,0.324561,0.188814,0.36475,0.079007,0.455753,-0.11848,-0.135874,-0.187155,-0.055342,-0.12525,0.210669,-0.388331,-0.197123,0.132309,-0.4231,0.217752,-0.203266,0.190836,0.373428,-0.0102,-0.038654,0.2379,0.044424,0.071826,-0.201054,0.257434,0.141901,-0.390064,0.437099,0.559701,-0.040162,-0.193089,0.442338,-0.141678,-0.049696,0.315545,-0.028972,0.278694,-0.064345,-0.327943,0.103025,-0.40344,-0.34269,-0.237931,0.287046,0.139693,-0.38454,0.019959,-0.156907,0.374996,-0.074558,-0.019391,0.050522,0.315171,0.211605,-0.15418,0.502362,0.10184,0.153274,0.592659,-0.010284,0.28029,0.319741,-0.164559,0.286884,0.420483,-0.628866,-0.172259,0.027954,-0.411674,0.376585,0.322832,0.352039,0.078705,0.045152,0.139083,-0.164182");
List<Double> array = ConvertUtils.stringToDoubleList("0.342045,-0.547933,0.291732,-0.056515,-0.182701,0.31113,0.151578,0.087678,-0.045536,-0.525699,-0.394715,-0.103153,-0.05575,-0.540641,0.028046,-0.193109,-0.003591,0.180923,0.290261,0.532309,-0.202463,-0.047271,-0.246197,0.324561,0.188814,0.36475,0.079007,0.455753,-0.11848,-0.135874,-0.187155,-0.055342,-0.12525,0.210669,-0.388331,-0.197123,0.132309,-0.4231,0.217752,-0.203266,0.190836,0.373428,-0.0102,-0.038654,0.2379,0.044424,0.071826,-0.201054,0.257434,0.141901,-0.390064,0.437099,0.559701,-0.040162,-0.193089,0.442338,-0.141678,-0.049696,0.315545,-0.028972,0.278694,-0.064345,-0.327943,0.103025,-0.40344,-0.34269,-0.237931,0.287046,0.139693,-0.38454,0.019959,-0.156907,0.374996,-0.074558,-0.019391,0.050522,0.315171,0.211605,-0.15418,0.502362,0.10184,0.153274,0.592659,-0.010284,0.28029,0.319741,-0.164559,0.286884,0.420483,-0.628866,-0.172259,0.027954,-0.411674,0.376585,0.322832,0.352039,0.078705,0.045152,0.139083,-0.164182", ",");
PersonalizedSearch personalizedSearch = new PersonalizedSearch("1", "20180408", array);
UserFeatureFactor userFeatureFactor = new UserFeatureFactor(personalizedSearch);
String productFeatureFactor = "20180408|0.342045,-0.547933,0.291732,-0.056515,-0.182701,0.31113,0.151578,0.087678,-0.045536,-0.525699,-0.394715,-0.103153,-0.05575,-0.540641,0.028046,-0.193109,-0.003591,0.180923,0.290261,0.532309,-0.202463,-0.047271,-0.246197,0.324561,0.188814,0.36475,0.079007,0.455753,-0.11848,-0.135874,-0.187155,-0.055342,-0.12525,0.210669,-0.388331,-0.197123,0.132309,-0.4231,0.217752,-0.203266,0.190836,0.373428,-0.0102,-0.038654,0.2379,0.044424,0.071826,-0.201054,0.257434,0.141901,-0.390064,0.437099,0.559701,-0.040162,-0.193089,0.442338,-0.141678,-0.049696,0.315545,-0.028972,0.278694,-0.064345,-0.327943,0.103025,-0.40344,-0.34269,-0.237931,0.287046,0.139693,-0.38454,0.019959,-0.156907,0.374996,-0.074558,-0.019391,0.050522,0.315171,0.211605,-0.15418,0.502362,0.10184,0.153274,0.592659,-0.010284,0.28029,0.319741,-0.164559,0.286884,0.420483,-0.628866,-0.172259,0.027954,-0.411674,0.376585,0.322832,0.352039,0.078705,0.045152,0.139083,-0.164182";
System.out.println(new ProductFeatureFactorComponent().calProductFeatureFactor(userFeatureFactor,productFeatureFactor));
String productFeatureFactor = "20180408|1.342045,-0.547933,0.291732,-0.056515,-0.182701,0.31113,0.151578,0.087678,-0.045536,-0.525699,-0.394715,-0.103153,-0.05575,-0.540641,0.028046,-0.193109,-0.003591,0.180923,0.290261,0.532309,-0.202463,-0.047271,-0.246197,0.324561,0.188814,0.36475,0.079007,0.455753,-0.11848,-0.135874,-0.187155,-0.055342,-0.12525,0.210669,-0.388331,-0.197123,0.132309,-0.4231,0.217752,-0.203266,0.190836,0.373428,-0.0102,-0.038654,0.2379,0.044424,0.071826,-0.201054,0.257434,0.141901,-0.390064,0.437099,0.559701,-0.040162,-0.193089,0.442338,-0.141678,-0.049696,0.315545,-0.028972,0.278694,-0.064345,-0.327943,0.103025,-0.40344,-0.34269,-0.237931,0.287046,0.139693,-0.38454,0.019959,-0.156907,0.374996,-0.074558,-0.019391,0.050522,0.315171,0.211605,-0.15418,0.502362,0.10184,0.153274,0.592659,-0.010284,0.28029,0.319741,-0.164559,0.286884,0.420483,-0.628866,-0.172259,0.027954,-0.411674,0.376585,0.322832,0.352039,0.078705,0.045152,0.139083,-0.164182";
System.out.println(new ProductFeatureFactorComponent().calProductFeatureFactor(userFeatureFactor, productFeatureFactor));
}
}
... ...
package com.yoho.search.service.recall.models.personal;
import com.yoho.search.core.personalized.models.PersonalizedSearch;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
public class UserFeatureFactor {
private static final Logger logger = LoggerFactory.getLogger(UserFeatureFactor.class);
private List<Double> userFeatureVectorList = null;
private String vectorVersion;
private List<Double> vectorFeatureList = null;
private double userFeatureVectorNorm = 0.0D;
private String vectorFeatureVersion;
public UserFeatureFactor(PersonalizedSearch personalizedSearch) {
try {
if (personalizedSearch == null) {
return;
}
this.vectorFeatureVersion = personalizedSearch.getVectorFeatureVersion();
String userVectorFeature = personalizedSearch.getUserVectorFeature();
if(StringUtils.isBlank(userVectorFeature)){
this.vectorVersion = personalizedSearch.getVectorVersion();
this.vectorFeatureList = personalizedSearch.getVectorFeatures();
if (CollectionUtils.isEmpty(vectorFeatureList)) {
return;
}
String[] userFeatureFactorStrArr = userVectorFeature.split(",");
if(userFeatureFactorStrArr.length==0){
return;
}
userFeatureVectorList = new ArrayList<>(userFeatureFactorStrArr.length);
for (String userFeatureFactorStr : userFeatureFactorStrArr) {
double userFeatureVector = Double.parseDouble(userFeatureFactorStr.trim());
userFeatureVectorList.add(userFeatureVector);
userFeatureVectorNorm += userFeatureVector * userFeatureVector;
for (Double vectorFeature : vectorFeatureList) {
userFeatureVectorNorm += vectorFeature * vectorFeature;
}
}catch (Exception e){
} catch (Exception e) {
logger.error(e.getMessage());
}
}
public List<Double> getUserFeatureVectorList() {
return userFeatureVectorList;
public String getVectorVersion() {
return vectorVersion;
}
public List<Double> getVectorFeatureList() {
return vectorFeatureList;
}
public double getUserFeatureVectorNorm() {
return userFeatureVectorNorm;
}
public String getVectorFeatureVersion() {
return vectorFeatureVersion;
}
}
... ...
... ... @@ -102,8 +102,8 @@ public class SearchScorerFactory {
}
// 获取【向量余弦夹角】的打分器
public IScorer getFeatureFactorScorer(QueryBuilder scoreFilter, String featureFactors, String featureVersion) {
return new FeatureFactorScorer(scoreFilter, featureFactors, featureVersion);
public IScorer getFeatureFactorScorer(QueryBuilder scoreFilter,String featureVersion, List<Double> featureFactors) {
return new FeatureFactorScorer(scoreFilter,featureVersion,featureFactors);
}
public IScorer getOfflineSaleOnlyScorer() {
... ...
package com.yoho.search.service.scorer.impl;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders;
import org.elasticsearch.script.Script;
... ... @@ -21,22 +24,22 @@ public class FeatureFactorScorer implements IScorer {
private static final Double FACTOR_CONSTANT = 0.4D;
private QueryBuilder scoreFilter;
private String featureFactors;
private String featureVersion;
private String featureFactorString;
public FeatureFactorScorer(QueryBuilder scoreFilter, String featureFactors, String featureVersion) {
public FeatureFactorScorer(QueryBuilder scoreFilter, String featureVersion,List<Double> featureFactors) {
super();
this.scoreFilter = scoreFilter;
this.featureFactors = featureFactors;
this.featureVersion = featureVersion;
this.featureFactorString = StringUtils.join(featureFactors,",");
}
@Override
public void addScorer(YohoFilterFunctionBuilders yohoFilterFunctionBuilders) {
Map<String, Object> scriptParams = new HashMap<>();
scriptParams.put("field", "productFeatureFactor");
scriptParams.put("userFeatureFactors", featureFactors);
scriptParams.put("vectorFeatureVersion", featureVersion);
scriptParams.put("userFeatureFactors", featureFactorString);
scriptParams.put("baseConstant", BASE_CONSTANT);
scriptParams.put("factorConstant", FACTOR_CONSTANT);
Script script = new Script(ScriptType.INLINE, "native", "feature_factor_vector_score", scriptParams);
... ...
package com.yoho.search.service.scorer.personal;
import com.yoho.search.aop.cache.SearchCacheAble;
import com.yoho.search.base.utils.ConvertUtils;
import com.yoho.search.cache.CacheType;
import com.yoho.search.core.personalized.models.PersonalizedSearch;
import com.yoho.search.core.personalized.service.BidataServiceCaller;
import com.yoho.search.core.personalized.service.PersonalVersionManager;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
@Service
... ... @@ -23,8 +26,8 @@ public class PersonalVectorFeatureSearch {
@Autowired
private BidataServiceCaller bidataServiceCaller;
@SearchCacheAble(cacheInMinute = 30, cacheName = "PERSIONAL_VECTOR", returnClass = PersonalizedSearch.class, cacheType = CacheType.SEARCH_REDIS, includeParams = { "uid" })
public PersonalizedSearch getPersonalizedSearch(Map<String, String> paramMap) {
@SearchCacheAble(cacheInMinute = 30, cacheName = "USER_PERSIONAL_VECTOR", returnClass = PersonalizedSearch.class, cacheType = CacheType.SEARCH_REDIS, includeParams = { "uid" })
public PersonalizedSearch queryPersonalizedSearch(Map<String, String> paramMap) {
try {
// 1、参数校验
String uid = paramMap.get("uid");
... ... @@ -41,7 +44,11 @@ public class PersonalVectorFeatureSearch {
if (StringUtils.isEmpty(userVectorFeature)) {
return null;
}
return new PersonalizedSearch(uid, vectorFeatureVersion, userVectorFeature);
List<Double> doubleList = ConvertUtils.stringToDoubleList(userVectorFeature,",");
if(CollectionUtils.isEmpty(doubleList)){
return null;
}
return new PersonalizedSearch(uid, vectorFeatureVersion, doubleList);
} catch (Exception e) {
logger.error(e.getMessage(),e);
return null;
... ...