背景
OpenSearch是一个以云服务方式提供给广大开发者使用的搜索引擎平台。在搜索引擎中,分词是最基础但很重要的功能,其效果会直接影响文档的召回。分词歧义会导致引擎无法召回目标文档。例如:
乒乓球拍卖完了 ==> 乒乓球/拍卖/完了
乒乓球拍 ==> 乒乓/球拍
在上面的case中,短语“乒乓球拍”不同的上下文中分词的结果不一样。假如文档的内容为“乒乓球拍卖完了”,用户通过查询词“乒乓球拍”是无法召回该文档的。
OpenSearch的用户来自各行各业,类似上述例子的场景会被不同的用户遇到。分析线上query时,发现不少用户由于分词效果不理想,对同一个字段用不同的分词器建了多个索引(如单字分词,模糊分词,中文基础分词),查询时同时查多个索引已达到召回文档的目的。这种做法不仅会消耗更多的系统资源,而且通常效果会不太好。
支持用户对分词干预显得尤为重要。OpenSearch内部是一个多租户多应用共用的系统,因此,还需要确保应用间的干预是完全隔离的,不会互相影响。
基本思路
要对分词结果的干预,第一直觉就是用户可以定制分词器。有一种做法就是用户自己提供分词器,系统集成用户的分词器,这种方式对系统或者用户来说都太重了。系统需要对用户的分词器做审核,不能影响系统的稳定性;同时用户还需要理解分词接口等细节。当然,用户来可以自己分词,并将分词结果用于索引构建和查询,这要求用户自身有较强的技术,同时自身也会遇到需要干预的地方。
OpenSearch采用另一个方式:
- 系统提供通用中文分词器,适用于绝大多数的场景;
- 提供面向特定行业领域的分词器,如视频分词器、电商分词器、人名分词器等;通过这种方式可以优化一些特定领域的分词效果,以尽量满足用户的需求;
- 开放分词干预的接口,让用户进一步对分词结果进行定制化处理。用户可以在系统提供的基础分词器,通过结合自己的干预词条创建自定义分词器,并将该分词器应用在相应的索引字段中,达到干预索引和查询时的分词结果,确保搜索召回。
针对不同的场景,系统提供了两种类型的干预词条:语义实体和语义切分.
- 语义实体:主要用于一些系统尚未识别的实体词,干预后,该词的切分总是能保持一致,不受其所在的上下文影响。
- 语义切分:用于指定在特定上下文中,短语的切分方式,而不影响该短语在其他上下文中的切分方式。
系统流程
由用户自定义分词干预的数据,需要系统对用户的干预进行管理,包括:
- 对用户:
- 干预数据的推送
- 干预数据的查看
- 干预数据的使用
- 对系统:
- 干预数据合法性检查,保证词条干预能正常生效
- 干预数据量控制,这主要是对系统的保护;
- 干预数据生效后,才能被用户进行使用。如果用户的干预数据没有完全生效,就被用于索引的构建,会导致部分文档的分词结果和预期干预的不一样,出现无法被召回的情况。
用户词典数据管理
图中1至7为用户词典数据流,当用户创建词典时,系统会该词典分配一个惟一的id,词典数据会在ConfigServer内进行合法性检查,在经过几个模块和消息队列之后,会在BuildService那边建好索引,索引数据被分词服务加载起来,在分词的时候进行使用。
在索引构建时,会将词典数据构建两种不同类型的索引:kv索引和倒排索引。
- kv索引是以用户词条的原词做key,干预后的分词做为value,用于分词时使用。
- 对词典id构建倒排索引,达到可以根据id获得整个词典的所有内容,方便用户查看词典的详情。
在图中5.1时,词典数据被写到了DB。这是为了在有些情况下,需要用户的干预数据进行索引重建,此时可以从数据库获得全量的干预数据。
干预生效
这里包括两个方面:
- 推送的干预数据生效判断。由于整个数据流中,词典数据流转的地方都是严格按序处理的,因此在用户的词典数据最后增加一个哨兵doc,通过检查这个哨兵doc的状态,来判断用户的词典数据有没有全量生效;
- 干预数据在索引构建和查询生效。
- 在对文档进行索引构建时,当用户使用了干预数据时,会将对应的字段内容以及分词器的配置传给分词服务,分词服务返回分词结果,BuildService根据该结果对文档建索引,供在线searcher加载提供查询服务;
- 查询时,Agg收到查询请求时,会将从ConfigServer获取到的索引和分词配置信息,和用户的查询词相关的信息一起发给分词服务,并用分词服务返回的分词结果查询引擎。
- 这样就保证索引构建和查询时分词结果的一致性。
后续工作
- 为了保证查询和索引构建时的分词效果一致性,用户对分词词典内容的修改,或者对自定义分词器的修改,当前的产品逻辑上要求对用户对索引进行重建。为了效果,牺牲了一定的易用性。后续会提供机制,让用户自己选择是否需要索引重建。同时,支持在查询支持指定分词器。
- 上面的流程中,词典数据的管理流程比较复杂。后续将通过迁移到OpenSearch统一的干预服务中去。
- 分词器的迭代更新,建立合理有效的分词器模型、系统和行业词典内容的更新机制。
最后
OpenSearch的自定义分词服务中使用的中文分词器选择用AliNLP_WS,这里特别感谢iDST-NLP-自然语言基础技术团队的大力支持。
附录自定义分词器使用流程
推荐与搜索技术钉钉交流群