如何实现个性化搜索,幻灯片如何实现个性化搜索功能
背景介绍
SlideLive是一款幻灯片在线播放和分享的网站,用户已上传的文档有10000+。为了方便用于快速找到自己想要的PPT文档,SlideLive需要提供一个优质的搜索方案。本文将简介SlideLive搜索方案的设计与实现。
SlideLive官网地址:https://www.slidelive
总体规划
SlideLive的搜索工程共包含两个阶段:
名称 | 主要特征 |
文本搜索 | (1)BM25 相关性算法 (2)特征建模 (3)IK分词器 (4)语义理解 |
个性化搜索 | (1)用户点击模型 (2)排名学习模型 (3)elasticsearch-learning-to-rank插件 |
第一阶段:文本搜索
特征建模
在项目之初,网站中的文档以及用户数量并不多,这时基于Elasticsearch的搜索技术即可满足业务需求。为了能够找到用户想要的幻灯片文档,我们需要抽取出对排序有影响的特征。在SlideLive网站的实践中我们了抽取出了如下特征:
特征字段 | 类别 | 含义 |
标题字段 | 文本相关性 | 幻灯片文档的标题,基于进行相关性评分 |
详情字段 | 文本相关性 | 幻灯片文档的详情字段,基于BM25进行相关性评分 |
主题名称字段 | 文本相关性 | 每个幻灯片文档都归属于一个特定的主题,基于MB25进行相关性评分 |
标签名称字段 | 文本相关性 | 每个幻灯片都对应于一组标签,基于BM25进行相关性评分 |
浏览数 | 静态分 | 幻灯片的浏览次数, |
点赞数 | 静态分 | 幻灯片的点赞次数 |
收藏数 | 静态分 | 幻灯片的收藏次数 |
分享数 | 静态分 | 幻灯片的分享次数 |
相关性模型:
score function = title*0.5 + desc + theme.name.keyword*5 + labels.name.keyword*3 + log(viewNum)*0.1 + log(colloctNum)*0.2 + log(shareNum)*0.3
Java代码:
private Query constructCriteriaQueryV2(SlideSearchCriteria criteria, Pageable pageable) {
QueryBuilder titleAndDescQuery;
QueryBuilder themeQuery;
QueryBuilder labelsQuery;
BoolQueryBuilder boolQuery = boolQuery();
if (criteria.getQuery() == null || criteria.getQuery().equals("")) {
titleAndDescQuery = QueryBuilders.matchAllQuery();
boolQuery.should(titleAndDescQuery);
} else {
// 匹配title和desc属性
titleAndDescQuery = QueryBuilders.multiMatchQuery(criteria.getQuery()).field("title", 0.5f).field("desc");
boolQuery.should(titleAndDescQuery);
// 匹配主题和用户自定标签
themeQuery = QueryBuilders.termQuery("slideTheme.name.keyword", criteria.getQuery());
labelsQuery = QueryBuilders.termQuery("slideLabels.name.keyword", criteria.getQuery()).boost(3);
boolQuery.should(themeQuery);
boolQuery.should(labelsQuery);
}
boolQuery.minimumShouldMatch(1);
ScoreFunctionBuilder starGradeFunction = ScoreFunctionBuilders.fieldValueFactorFunction("starGrade").factor(0.8f);
ScoreFunctionBuilder viewNumFunction = ScoreFunctionBuilders
.fieldValueFactorFunction("totalViewNum")
.factor(0.1f)
.modifier(FieldValueFactorFunction.Modifier.LN1P);
ScoreFunctionBuilder collectNumFunction = ScoreFunctionBuilders
.fieldValueFactorFunction("collectNum")
.factor(0.2f)
.modifier(FieldValueFactorFunction.Modifier.LN1P);
ScoreFunctionBuilder shareNumFunction = ScoreFunctionBuilders
.fieldValueFactorFunction("shareNum")
.factor(0.3f)
.modifier(FieldValueFactorFunction.Modifier.LN1P);
FunctionScoreQueryBuilder.FilterFunctionBuilder[] functions = new FunctionScoreQueryBuilder.FilterFunctionBuilder[4];
functions[0] = new FunctionScoreQueryBuilder.FilterFunctionBuilder(starGradeFunction);
functions[1] = new FunctionScoreQueryBuilder.FilterFunctionBuilder(viewNumFunction);
functions[2] = new FunctionScoreQueryBuilder.FilterFunctionBuilder(collectNumFunction);
functions[3] = new FunctionScoreQueryBuilder.FilterFunctionBuilder(shareNumFunction);
QueryBuilder functionScore = functionScoreQuery(boolQuery, functions).boostMode(CombineFunction.SUM).maxBoost(1.5f);
log.debug("slide Query DSL is {}", functionScore);
Query query = new NativeSearchQueryBuilder().withQuery(functionScore).withPageable(pageable).build();
return query;
}
相关性函数需要开发者在实际的开发过程中进行调试优化以找到最佳的排序结果。
语义理解
词语之间共包含如下几种关系:
(1)上位词或者下位词, 水果是苹果的上位词,同时苹果是水果的下位词
(2)同义词 Elasticsearch 是 es 的同义词
ES处理策略:
- 对于同义词,在索引时进行同义词过滤
- 对于下位词,在索引时进行下位词过滤
同义词和下位词的配置是为了扩大召回率
索引构建:
curl -XPUT "http://elasticsearch:9200/slide" -H 'Content-Type: application/json' -d'{ "settings": { "analysis": { "analyzer": { "index_analyzer": { "type": "custom", "tokenizer": "ik_smart", "filter": [ "lowercase", "remote_hypernym" ] }, "query_analyzer": { "type": "custom", "tokenizer": "ik_smart", "filter": [ "lowercase", "remote_synonym", "remote_hyponym" ] } }, "filter": { "remote_synonym": { "type": "dynamic_synonym", "synonyms_path": "http://example/download/synonyms.txt", "interval": 30 }, "remote_hypernym": { "type": "dynamic_synonym", "synonyms_path": "http://example/download/hypernyms.txt", "interval": 30 }, "remote_hyponym": { "type": "dynamic_synonym", "synonyms_path": "http://example/download/hyponyms.txt", "interval": 30 } } } }, "mappings": { "properties": { "id": { "type": "long" }, "title": { "type": "text", "analyzer": "index_analyzer", "search_analyzer": "query_analyzer" }, "desc": { "type": "text", "analyzer": "index_analyzer", "search_analyzer": "query_analyzer" }, "content": { "type": "text" }, "type": { "type": "keyword" }, "docUrl": { "type": "keyword" }, "firstImageUrl": { "type": "keyword" }, "starGrade": { "type": "integer" }, "createdAt": { "type": "date" }, "modifiedAt": { "type": "date" }, "downloadable": { "type": "boolean" }, "language": { "type": "keyword" } } }}'
第二阶段:个性化搜索
在第一阶段,通过手动调参的方式很难给出一个最佳的排名函数(rank model),而基于用户点击模型(Click Model)和 排名学习(Learning to Rank)算法,SlideLive可以实现自动化的参数调优。
自动化的LTR流程大体分为三步:
- 第 1 步 - 采集SlideLive网站中的用户行为数据(Singals),根据对用户行为信号的理解,将描述相关性的训练数据输入到 LTR 系统中(Logged Judgments)
- 第 2 步 - 基于RankLib提供的LamabdaMART算法训练模型:LTR 系统使用提供的训练数据重新训练 LTR 模型,并将模型数据保存于ES中
- 第 3 步 - 基于训练模型进行ES召回后精排
自动 LTR 不断重复步骤 1- 3 以自动优化相关性。
总结
SlideLive网站是一款PPT在线播放和分享的平台,目前已包含10000+的幻灯片。为了能够更好地为用户提供幻灯片服务,搜索功能就显得尤为重要。目前以实现搜索的第一阶段,正在开发搜索的第二阶段。真心希望SlideLive网站能够越来越好,并且能够为用户创造价值。如果您需要幻灯片模板、教育课件等,不妨去SlideLive官网上看一看。官网地址:https://www.slidelive