首发于微信公众号“Shopee技术团队”。
摘要
在主流的搜索引擎、购物 App 和 Chatbot 等应用中,下拉推荐可以有效地帮助用户快速检索所需要的内容,已经成为一项必需且标配的功能。本文将介绍 Shopee Chatbot 团队在 Chatbot 中从 0 到 1 构建下拉推荐功能的过程,并分享模型迭代优化的经验。
特别地,针对东南亚市场语种繁多的挑战,我们探索了多语言和多任务的预训练语言模型,并将其应用于下拉推荐中的向量召回,以优化召回效果。另一方面,为了使下拉推荐尽可能帮助用户,并解决用户的问题,我们针对用户点击与问题解决这两个目标进行了同时建模,在多目标优化方面也做了探索。
1. 业务背景
1.1 Shopee Chatbot
随着 Shopee 业务的扩张,消费者对客服咨询的需求不断攀升。Shopee Chatbot 团队致力于基于人工智能技术打造 Chatbot 与人工客服 Agent 的有机结合,通过 Chatbot 来解决用户日常的咨询诉求,给用户提供更好的体验,缓解和减轻人工客服的压力,也帮助公司节省大量人力资源成本。目前,我们已经在多个市场上线了 Chatbot。如上图所示,用户可以通过 Shopee App 中的 Mepage 体验我们的 Chatbot 产品。
我们也在持续不断地打磨 Shopee Chatbot 产品,增强其功能,给用户提供更好的体验,帮助用户解决购物过程中所遇到的问题。在 Shopee Chatbot 的众多功能中,下拉推荐是其中一个重要的功能。
1.2 下拉推荐
下拉推荐,又名输入建议、搜索建议、自动补全或问题推荐等,已经成为主流搜索引擎、购物 App 和 Chatbot 等众多产品里的一项必需且标配的功能。其大致功能为:在用户输入查询词的时候,显示与输入 query 语义相关的推荐 suggestion,供用户选择。通过这种方式,它可以协助用户更快地表达其想要检索的内容,进而帮助用户快速检索到所需要的内容。
在 Shopee Chatbot 中,我们也希望 Chatbot 具有下拉推荐的功能,从而能更快更好的解决用户的问题,提升用户的购物体验。
2. 整体方案
针对目前 Chatbot 的场景,为了使它具备下拉推荐的功能,我们借鉴搜索和推荐的场景,使用召回+排序的流程,如下图所示。针对用户当前的搜索输入,找到最相似和最相关的 suggesiton,作为推荐建议。为此,我们需要搭建推荐候选池、多路召回以及排序模块。
2.1 推荐候选池
2.1.1 构建流程
目前,我们构建推荐候选池的方式比较简单,包括 3 个步骤:
- 使用多种来源的数据,包括解决方案的标题、用于意图识别的标注数据以及大量的聊天日志;
- 然后进行一些预处理,例如删除太短或太长的消息,并使用编辑距离或聚类删除一些重复的 query;
- 最后,为了控制建议的质量,我们要求各市场当地的业务审查这些 query,或将它们改写为标准化的 query。譬如,我们会进行纠错,并删除脏字。
2.1.2 推荐样例
以下是我们推荐候选池中的一些推荐样例。对于每一个 suggestion,我们也有相应的解决方案。当用户点击该推荐 suggestion 时,我们会给用户相应的解决方案作为答案。
推荐 suggestion | 解决方案 |
---|---|
May I know the status of my order? | 解决方案1 |
I have not received my order yet. | 解决方案1 |
Why is my order not delivered yet? | 解决方案1 |
Why i cannot activate my shopeepay? | 解决方案2 |
Why am I unable to set up my shopeepay account for my refund? | 解决方案2 |
What is shopeepay? | 解决方案3 |
I would like to check on my shopeepay status. | 解决方案4 |
Why is my order cancelled? | 解决方案5 |
When is the delivery time for my order? | 解决方案6 |
2.2 多路召回
对于召回,我们采用了多路召回再合并的方式,目前包括文本召回和向量召回两种方式。
2.2.1 文本召回
对于文本召回,我们采用了业界标准的方案,使用 Elasticsearch (ES) 来进行关键词匹配召回。除了基于 ES 的 BM25 分数[1] 进行排序外,我们还用解决方案的 CTR 来作为加权因子,以进一步提升召回的效果。
2.2.2 向量召回
文本召回容易理解和实现,但其效果依赖于 query 跟 suggestion 是否有匹配的关键词。为了召回和 query 用词不同但是表达语义相同的 suggestion,往往需要对 query 进行纠错、丢词、同义词替换和改写等处理,尤其是当字面完全匹配的 suggestion 不多的时候。
在我们的场景中,用户输入 query 较长,表述偏口语化,因此挖掘停词和同义词成本较高。另外,Shopee Chatbot 面向不同的地区和不同的语种,场景和数据的多样性也增加了算法工作的成本。
考虑到这点,我们采用了向量召回[2] 的方式,从大量的弱监督、用户行为日志来训练向量召回模型,用 query 向量和 suggestion 向量来衡量两者的语义相似性,以隐式的同义改写召回来作为文本召回的补充,在一定程度上缓解这种问题。
向量召回的方案对于多地区和多语言均适用,降低了适配成本。另外也能进行跨语言召回,譬如输入 query 是中文,召回英文的 suggestion。
由于目前的推荐候选池都是单一语种的,例如英文,如果用户输入中文,仅依靠文本召回,无法返回合适的推荐 suggestion 给用户。而依靠跨语言的向量召回,则也能推荐语义相关的 suggestion,如“where to use my voucher”和“哪里可以用优惠券”,具有相似的语义。
另外,对于某些多语言市场,例如 MY 和 PH,我们也只需准备一个多语言的向量召回模型,就能实现不同语言的理解和召回,而无需针对各单一语种分别训练召回模型。
为了实现向量召回,我们需要有一个文本编码器,能对文本进行编码,得到对应的向量,再进行向量召回。通常有以下两种方法:
1)基于双塔模型
在双塔模型[2] 中,我们分别有 query 塔和 suggestion 塔分别对用户输入 query 和推荐 suggestion 进行编码,映射到稠密向量。基于 query 和 suggestion 的向量,可以计算两者的相似度,如余弦相似度。对于相关的 query 和 suggestion,我们希望两者的相似度越大,反之希望其相似度越小。因此根据该相似度与 query 和 suggestion 是否相关,可以计算损失,训练模型。
2)基于预训练语言模型
另一种方法是使用一些预训练的模型作为文本编码器,例如预训练的语言模型。该方法现在被广泛应用在诸多 NLP 场景,并且是目前许多 NLP 应用中的 state-of-the-art 方法。具体在我们的应用中,我们使用 Facebook 的跨语言预训练语言模型 XLM[3],结合对应的分词器,它可以处理 100 多种语言。
2.2.3 基于多语言和多任务预训练的向量召回
1)继续预训练(Continue Pre-train)
由于 Facebook 的 XLM 基于公开数据进行训练,为了使其能更好地适配我们的场景和数据,我们通过继续使用领域内和任务内的语料库进行继续预训练(continue pre-train)来提升模型性能。具体来说,参考文献[4],我们使用 3 阶段方法:
- 阶段一:使用来自不同市场、不同语言的大量聊天日志作为无标注数据,训练多语言的 Masked Language Modelling 任务(M-MLM)[3];
- 阶段二:使用来自意图识别模块的点击日志作为弱标注数据(构造方式如下图所示),训练多语言的意图分类任务(M-CLS)。跟阶段一类似,我们也采用不同市场的数据来进行多任务训练;
- 阶段三:使用来自意图识别模型的标注数据,使用意图分类任务(CLS)来进一步微调 XLM。对于不同市场的意图分类任务,我们分别使用相应的语料进行单独微调。
2)知识蒸馏(Knowledge Distillation)
为了使大型预训练语言模型可用于在线服务,我们进一步对其进行知识蒸馏[5],将大模型(teacher)变成更小的模型(student),如 TextCNN,示意图如上图所示。
在实践中,我们使用了以下 3 项技术来提升蒸馏的效果:
- 引入 noise:参考文献[6],我们在蒸馏的过程中,引入 noise 来提升模型学习特征表示的鲁棒性,同时也提升样本的利用效率,使得其能覆盖更全面的数据输入分布;
- 利用大量的半监督数据:参考文献[6],我们利用聊天记录的无标注数据以及点击日志的弱标注数据等大量的半监督数据,充分学习 teacher 大模型 XLM 在更全面的数据输入分布上的特征表示分布;
- 2 阶段蒸馏:为了最大限度保留和学习 teacher 大模型 XLM 的知识,我们也采用了和领域预训练类似的 2 阶段的方法进行蒸馏,分别从领域预训练的第二阶段和第三阶段的所得到的 teacher 大模型 XLM 依次蒸馏。
下图所示为完整的继续预训练和蒸馏过程。
2.2.4 实验效果
1