写点什么

爱奇艺逗芽表情搜索分析与实践

  • 2020-06-23
  • 本文字数:4845 字

    阅读完需:约 16 分钟

爱奇艺逗芽表情搜索分析与实践

随着互联网时代的发展,表情包成为现在大家网上交流的必备工具,针对表情搜索的产品需求,爱奇艺逗芽技术团队经历了从 ElasticSearch 到 Lucene 再到结合语义的搜索实践之路。不同阶段的技术选型可能可以为大家提供一些中小体量业务垂直领域搜索的落地思路。

逗芽表情搜索

爱奇艺逗芽表情(https://douya.iqiyi.com)是一款通过视频 AI 算法算法,针对 UGC、PGC 等来源进行表情图片生产,并在爱奇艺内外部多渠道分发的创新产品。用户通过文字输入搜索好玩有趣的表情图片是逗芽的核心功能之一。


通过文字进行表情搜索常见的请求类别包括:


  1. 实体名称, 比如热门的明星名、角色名、影视剧名等,以及实体的别名与缩写;

  2. 偏口语化的感情、动作描述 ,如“开心”,“抱抱”,“想睡了”等;

  3. 实体与动作的组合,如“加油蔡徐坤”,“虞书欣说的好”;

  4. 流行的梗、短语,如“奥力给”,“专业团队”,“我是谁我在哪”;

  5. 表达完整含义的句子,如“你好,很高兴认识你”。



在不考虑视觉语义嵌入(Visual-Semantic embedding)[1]及其他相关度比较方式的情况下, 表情图片的搜索主要依赖于用户请求与图片标签(文本格式)的相关度做检索。 标签可能包括图片中的实体、文案、动作、情绪、类别等内容,具体标签的生产一般会结合算法与人工标注,不在本次讨论范围之内。对于不同类别的标签,在匹配时可能有不同的排序策略。另外在搜索口语化的短语、短句时,需要有一定的泛化能力来满足召回。在业务层面,不同业务可能还需要过滤不同的图片来源、类型、大小等。

表情搜索的技术选型

目前关于“全文检索”比较流行的技术选型当属 ElasticSearch(ES)[2],它是一款基于 Lucene [3]的开源分布式近实时搜索引擎,对外提供了简单易用的 HTTP API。



图 1 ElasticSearch 索引分层


一个 ES 索引可以切分为多个 shard(分片)并分布式的存储,来实现数据的横向扩展,同时 Shard 也支持复制来提高数据的可用性。Segment(分段)为 Lucene 维护的最小倒排索引单元,一个 Lucene 索引可能包括一到多个 segment。新的文档会写到内存缓存并以较小的时间间隔写入新的 segment,避免耗时的大索引重建,提供了近实时检索支持。


一个图片文档主要包括三类字段:


一类,是图片元信息如各个尺寸的大小、分辨率、CDN 地址等;


二类,是运营相关信息如图片的来源、入库时间、审核、推荐状态等;


三类,是前面提到的标签信息如图片的文案、人物、表情、动作、分类标签等。


依赖上述字段 ES search API 可以通过布尔查询过滤符合业务需求的图片,再通过 function_score 自定义评分函数进行图片排序,比如不同标签字段和运营字段在匹配时可以有不同的权重。因此对不同的业务会去维护不同的相对复杂的查询 JSON 文件。



图 2 ES 图片搜索框架


在服务架构上我们使用 HBase 配合 ES 做图片总库,其中 HBase 保存了全量图片各个阶段处理的所有信息,如算法提取的特征、图片来源详情等,ES 保存了一定时间段内已去重待运营的和已审核通过的图片文档。线上搜索 ES 和运营 ES 隔离,一方面减少了搜索集群的索引文档数量(从数千万到近百万)让索引文件能尽可能在操作系统文件缓存中,另一方面避免了运营操作导致的文件缓存频繁换出。多地 ES 集群通过消息队列实现和主库间的数据同步,提供了跨地域的服务高可用。基于 ES 的搜索架构可以满足我们早期业务的搜索需求。

搜索服务的技术升级

随着对搜索需求的提高,基于 ES 的搜索服务逐渐遇到瓶颈:新接入的业务要求更高的 QPS 和更低的延时,产品也希望通过更定制化的排序逻辑来提高搜索相关度。在一段时间的原型调研后,我们开始使用 Lucene 来替换 ES 做搜索。



图 3 Lucene 架构


切换到 Lucene 意味着从 ES HTTP API 切换到 Java 库调用的方式,ES 提供的分布式索引管理和秒级近实时索引功能也不再可用。但是 Lucene 提供的接口足以让开发者通过相对简单的编码实现单个索引的创建和搜索功能。并且 Lucene 提供了如 Analyzer 在内的扩展机制让开发者能方便的做一些高级定制。


总体上切换到 Lucene 基于如下考虑:


  1. 业务对搜索内容实时性要求不高,可以按天离线创建只读索引,百万量级索引的构建在十分钟内就可以完成,在必要时(如有图片急需上下线)也可以运营通过接口手动触发索引创建。

  2. 百万量级索引大小在一百兆字节左右,可以轻松放全量保存在单机内存中,不需要做分片和搜索合并,保证了性能。

  3. 不同业务间索引隔离,配合容器可以针对业务独立部署,横向扩展和跨地域部署都极为方便。

  4. 更容易定制分词、排序等功能。



图 4 Lucene 搜索框架


服务架构上索引服务(Indexer)服务负责离线索引,定期从图片总库中创建不同业务的 Lucene 索引,搜索服务(Searcher)服务根据配置获取对应的业务 Lucene 索引,在线运行 Lucene 搜索。索引和搜索服务使用了相同的 Analyzer,定制使用了 HanLP 分词器和外部词典(ES IK [4]也支持远程词典,不过同样需要在词典更新后定期更新索引)做 Tokenizer,自定义了否定词结合 TokenFilter,确保如“不开心”这类词不被分词为“不”和“开心”。


索引服务和搜索服务通过 Zookeeper 进行索引信息的同步。不同业务方包含了不同版本号,不同版本号有不同的索引创建规则。不同时间创建的索引信息会写入对应到业务方对应版本号节点下。索引服务定期更新分词器使用的实体、停用词词典,并扫描图片总库将不同业务方需要的图片标签信息和图片 ID 写入不同的 Lucene 索引。完成写入的索引通过 forceMerge 优化索引分段,保存到对象存储保存中,并更新对应 Zookeeper 节点。搜索服务通过监听相关 Zookeeper 节点在线更新索引,并回收旧的索引。


业务服务通过 gRPC 访问搜索服务,再通过图片 ID 获取图片元信息存储返回给用户。图片元信息使用多级缓存优化性能,如内存缓存配合 CouchBase,也可以将原 ES 搜索引擎作为图片元信息的降级存储。


基于 Lucene 的搜索架构 QPS 扩展方便,性能也由原 300 毫秒的 P99 延时下降到 100 毫秒以内,搜索相关度也有提高,满足了业务需求。

语义召回

表情搜索一个比较明显的特点是请求中包含有较多日常情绪、动作类短语,在召回时如果仅使用 TF-IDF 或 BM25 做字符级别的召回,容易导致召回或相关度偏低的情况。通过引入语义层面的召回我们可以解决这个问题,比如,“兴高采烈”在 Lucene 下很难召回图片,通过语义则可以关联到“眉开眼笑”、“喜滋滋”等相关标签图片提高召回;“混吃等死”在 Lucene 下会把“等”字单独分出来导致“等着”、“等你”这类相关度比较低的图片被召回,通过语义相似度过滤也可以避免这种情况。


语义召回可以拆解为用户请求和图片标签的短文本相似度检索问题。将图片库内图片标签编码为固定长度的稠密向量,并存储到向量索引中,就可以实现用户请求和标签的最近邻查找。像 Annoy 或 Faiss 等向量索引都可以做到千万量级下的毫秒级召回。


将短文本映射到稠密向量的方式也有不少,在 NLP 领域可以被归纳到句嵌入(sentence embedding)范畴。句嵌入编码可以利用 RNN、DAN(Deep Averaging Network)、Transformer 等多种编码器对句子做编码的监督学习。下图即为 Google 2019 年提出的多语言句编码器的多任务训练框架[5]。



图 5 Google Universal Sentence Encoder 训练结构


句嵌入编码也可以直接使用预训练模型,先利用大语料非监督学习训练出来的词向量(如 Word2Vec、Fasttext)或上下文编码器(如 BERT、ELMo)进行 token 级别的编码,再通过工程或统计方式(平均、TF-IDF、SIF 等)将非固定长度的 token 编码转化为固定长度的句嵌入。


在对比测试并考虑开发成本的基础上,逗芽目前使用了预训练词向量取平均的方式进行句嵌入编码,并进行了一些针对性优化。


我们采用基础分词加 BiMM (Bi-directional Maximal Matching)的方式来尽可能匹配词向量词典中更长的词,提高短语、短句的匹配度。其次由于词向量本身基于词语在语料中的上下文训练,导致不少反义词或同类词向量空间中距离较近,如“难过”和“开心”,“美女”和“帅哥”,不符合语义召回的预期,我们通过自定义反义词词典进行了词向量 counter-fitting [6]微调,提升语义相关度。



图 6 Glove 词向量最近邻 counter-fitting 前后对比


语义召回的离线索引和在线检索的服务均由 Python 实现,对外提供 gRPC 接口。词向量和文案标签使用 Annoy [7]索引存储,词向量相对需要较多内存(8G 左右),但是 Annoy 通过 mmap 进行加载,多个进程间可以共享内存,内存使用效率较高。服务通过容器平台部署,语义召回平均请求耗时约 15 毫秒,单机 QPS 约 500。

排序策略

在引入语义召回后我们把用户搜索请求做实体与非实体的区分,实体部分直接通过 Lucene 召回。非实体部分 Lucene 和语义都做召回,Lucene 召回部分对匹配的长度和顺序做了较严格的要求,语义召回部分会找到相似的 topN 标签,再过 Lucene 全匹配召回对应图片。



图 7 结合语义召回


搜索服务在拿到语义和实体的召回后再进行统一排序,排序过程中我们将实体部分和非实体部分的相关性得分压缩到同一分数区间内,然后辅助以图片质量分进行排序。其中图片质量分会在索引阶段通过图片来源、时效性、热度等信息预先计算好,在排序时再从索引中读取。在加入语义和完善排序策略后搜索相关度有了明显提升,针对高频和非高频搜索请求测试 NDCG [8]分数提高近 20%。

神配图应用

神配图是将用户输入直接添加到图片上的一种新型表情交互方式,神配图返回的图片也可以作为表情搜索的一个较好补充,尤其在用户搜索不到图片的情况下。



图 8 神配图示例


神配图原始图片的召回和前面语义召回部分类似,原始图片的文案、情绪、动作等标签经过句编码后构建成向量索引,用户请求句编码后在向量索引上做最近邻召回。在接口返回前再对神配图召回和搜索结果进行融合与排序。


由于文字需要实时添加到图片上,我们目前使用了读请求的后端加字方式,即搜索结果返回时并没有真正的图片加字,只有在用户端上请求访问图片的 CDN 地址时并回源时才进行图片的生产,保证了接口性能和整体用户体验。

总结和展望

本文回顾了逗芽表情搜索在不同业务阶段的不同实现方式。在定制化要求不多,实时性和吞吐量需求也不是很强的情况下 ElasticSearch 可以的满足大部分使用场景。在定制化和服务能力需求更高的情况下,可以先基于 ES 做针对性的优化和配置,如果还不能满足需求可以考虑直接使用 Lucene。在语义召回方面,可以优先使用预训练模型,以较低的开发成本获得相对明显的提升。如果服务体量更大可能需要从倒排索引开始自建搜索引擎,就不在本次讨论范围之内了。


目前逗芽表情搜索还有很多待优化的空间,例如标注语料优化句编码模型让语义召回更准确;引入更多维度特征或 L2R 优化排序;支持实时性更高的增量索引等等。产品上还有不少和搜索相关的应用场景可以继续挖掘,如个性化推荐、表情对话、以图搜图、基于视觉语义的图片检索等等。


搜索是一件原型容易,优化难的开发任务。软件工程没有银弹,搜索实现也没有,但是作为开发者我们可以根据团队资源和业务需求找到合适的搜索落地之路。



参考文档


[1] 视觉语义嵌入(Visual-Semantic embedding)Frome, A. 2013. Devise: A deep visual-semantic embedding model


[2] ElasticSearch(ES)https://www.elastic.co/cn/


[3] Lucenehttps://lucene.apache.org/


[4] ES IKhttps://github.com/medcl/elasticsearch-analysis-ik


[5] 多语言句编码器的多任务训练框架https://ai.googleblog.com/2019/07/multilingual-universal-sentence-encoder.html


[6] counter-fitting: Nikola Mrki. 2016. Counter-fitting Word Vectors to Linguistic Constraints


[7] Annoyhttps://github.com/spotify/annoy


[8] NDCGhttps://en.wikipedia.org/wiki/Discounted_cumulative_gain


本文转载自公众号爱奇艺技术产品团队(ID:iQIYI-TP)。


原文链接


https://mp.weixin.qq.com/s?__biz=MzI0MjczMjM2NA==&mid=2247487284&idx=1&sn=e16bd60dd58669d5b4d66a412c3aa7e0&chksm=e9769317de011a01678269186fa9432b31d4c2517c85c631632fe9e6b770a2ef7a46e4eefc85&scene=27#wechat_redirect


2020-06-23 14:052063

评论

发布
暂无评论
发现更多内容

北京国家会计学院千人共聚一堂,大型企业财务数智化盛会!

用友BIP

智能财务 财务共享

接口测试|HttpRunner模拟发送GET请求&自动生成测试报告

霍格沃兹测试开发学社

HttpRunner

人力场景全覆盖——中企出海之宝岛台湾

用友BIP

全球化 中企出海

【有奖调研】HarmonyOS新物种,鸿蒙流量新阵地——元服务邀你来答题!

HarmonyOS SDK

HMS Core

软件测试/测试开发丨Python 控制流:循环、判断

测试人

Python 程序员 控制流 循环 判断

强强联合!中软国际携手用友,全面重构全球人力资源数字化系统

用友BIP

数智人力

对标世界一流,直面全面预算管理差距

用友BIP

全面预算 财务共享

推送服务接入指导(HarmonyOS篇)

HarmonyOS SDK

HMS Core

奇妙敏捷之旅·青岛站,真的太酷啦!

禅道项目管理

打工人集体患上AI焦虑症,真的会被AI取代?

牵着蜗牛去散步

人工智能 腾讯云 腾讯 AI集训营

如何优雅地使用Low Code提高开发效率

引迈信息

低代码 JNPF

Video-LLaMA 开源,大语言模型也能读懂视频了!

Zilliz

计算机视觉 AIGC Towhee LLM

Blender 十大重点功能带你一次了解!

Finovy Cloud

blender

新手必看:Postman Newman 详细使用指南

Liam

程序员 测试 开发 Postman API

中企出海台湾篇之人力需求

用友BIP

全球化 中企出海

数智平台多维数据库:新时代的数据管理利器

用友BIP

数据库 数智平台

数据分析提效5倍,国有集团企业数字化历程 | 数字化标杆

袋鼠云数栈

数字化转型 数据治理 企业号 6 月 PK 榜

Nautilus Chain测试网迎阶段性里程碑,模块化区块链拉开新序幕

鳄鱼视界

中企出海之宝岛台湾薪资结算

用友BIP

中企出海

全面解析数据治理

郑州埃文科技

数据治理

华为新员工在学的课程长啥样? 扫码立即揭晓!

华为云PaaS服务小智

华为 培训 华为云

如何通过数智平台多维数据库实现价值替代?

用友BIP

数据库 数智平台

分享三个java低代码开发平台,每个都很能打,建议收藏

优秀

低代码 低代码开发平台 java低代码开发平台

数智化时代,如何利用数智人力高效管理人才?

用友BIP

数智人力

只需 2 小时,变身 Flink 实战派:Flink-Learning实战营火热报名中

Apache Flink

大数据 flink 实时计算

阿里云携手开放原子开源基金会倡议发起云原生工作委员会,两大开源项目达成捐赠意向

阿里巴巴云原生

阿里云 开源 云原生

用友BIP全球司库十问之银行账户统一管理怎么做?

用友BIP

全球司库

热烈祝贺埃文科技北京、上海、深圳分公司成立

郑州埃文科技

分公司成立

数智赋能与低代码:是医药行业的创新引擎还是心魔歧途

加入高科技仿生人

低代码 数智化 数智化转型 数智赋能 医药行业

迈向世界一流财务管理体系,全面预算管理体系不可或缺

用友BIP

财务共享

爱奇艺逗芽表情搜索分析与实践_AI&大模型_爱奇艺技术产品团队_InfoQ精选文章