title: 贝壳找房智能客服
subtitle: 贝壳找房智能客服
date: 2021-10-31
author: NSX
catalog: true
tags:
- 贝壳找房
- 智能问答系统

一、背景

贝壳智能客服主要解决经纪人在业务中遇到的常见的问题,主要场景有闲聊、卡片触发、精准问答、sug、QA问答。对于非寒暄的场景下,QA问答的占比是最大的,有70%以上,而QA问答效果强烈依赖于数据建设。

QA问答的场景所需的模块大致分为数据层、NLU层、召回层和排序层,数据建设为整个流程中的语义召回、匹配、排序提供足够的query和title的匹配对。

整个智能客服的架构如下图所示:

2021-10-31-智能客服-贝壳找房 - 图1

其中,意图识别NLU的结构如下:

2021-10-31-智能客服-贝壳找房 - 图2

  • NLU 层:NLU 层是对用户输入的 query 进行解析,包含意图识别、分词与词法分析、短语改写等功能。意图识别是为了识别出 query 的意图,我们通过日志分析总结出了 116 个意图,其中包含 7 个 Task 意图,1 个寒暄意图,和 108 个具体业务意图,会根据不同的意图识别结果走不同的 bot。这里的意图识别模型用的是 fastText,该模型有高效的训练速度和较高的识别准确率,做出来的结果也可以达到上线使用的标准。词法分析维护了一些词典,通过词典匹配能获得 query 中的关键词和关键短语。短语改写的目的是为了纠错,比如“搏学考试”手误输入成了“博学考试”,短语改写便能将其纠正,query 改写后能更容易召回正确答案。
  • 召回层:召回层是将候选答案从 FAQ 库中拿回,获得待排序的候选集。此处用了两种召回方式:检索召回和语义召回。检索召回会根据 NLU 层的意图识别与词法分析结果进行关键词和意图的加权,同时,n-gram 的使用也一定程度上减弱了分词错误带来的负面影响。语义召回是将相似问构建成一个 faiss 索引,这些相似问已经由知识库运营人员总结成标准问,并和知识产生了挂接。query 和相似问会被映射到同一个语义向量空间,通过 KNN 能快速拿到和 query 最相近的相似问,从而拿到最可能回答 query 的答案。下图直观展示了语义召回的过程:

2021-10-31-智能客服-贝壳找房 - 图3

  • 排序层:排序层是将召回层拿到的候选知识进行排序,将和 query 最相关的知识尽可能往前排。排序模型采用了 GBDT,GBDT 作为一种常用的树模型,可天然地对原始特征进行特征划分、特征组合和特征选择,并得到高阶特征属性和非线性映射。我们考虑用 GBDT 可以组合多种特征,可扩展性强,并且后期验证 GBDT 的效果好于单独使用匹配算法效果,因此,当前匹配算法在排序层中作为一种特征来使用
  • 返回层:query 经过上述处理之后会对处理结果进行返回。四种返回层场景展示,依次是 Chat-bot,Task-Bot,KBQA 和 QA-Bot:

三、FAQ数据挖掘流程

3.1 标准问生产流程

标准问的挖掘流程可以分为三大部分:挖掘可用query并推送、标注人员进行标准问生产、知识库的知识挂接。2021-10-31-智能客服-贝壳找房 - 图4

标准问的整体挖掘流程从拿到埋点日志开始,选择点踩query、无召回query和有返回知识但是用户没有点击的query(这些query是适合标准问产出,为整个召回排序提效的数据),然后经过分类去除寒暄等意图的query,faiss召回和query相似的现有标准问,然后把query聚类后推送给标注人员。

数据会根据意图推送给不同的标注人员,标注人员会首先判断query是否有效,若是无效query则直接结束标注,有效query会先和现有的标准问进行判断是否匹配,若匹配,则选出正确的,若不匹配,则总结成新标准问。最终获得推送query和对应的标准问。

由于一条标准问,对应的不同城市的知识会有不同,比如同样是问“业绩分配比例”,可能北京的业绩分配结果和天津的不同,所以标准问需要查找和挂接所有城市的知识,挂接完成后标准问就和一条知识一样被存储在知识库中。

2021-10-31-智能客服-贝壳找房 - 图5

3.2 相似问生产流程

相似问的整体挖掘流程和标准问类似,也是从拿到埋点日志开始,选择点击标准问的query,同样经过分类去除寒暄等意图的query,判断query和标准问的相似度是否较高 ,若足够高,达到设定的阈值则进行推送。2021-10-31-智能客服-贝壳找房 - 图6

标注人员只需要判断,query和标准问是否是在问同一问题,若是,query是否需要改写为更为完整通用的句子,然后把改写后或者直接可用的相似问推入线上知识库即可。

由于日志中的标准问已经挂接了知识,产出的相似问不需要在进行知识挂接,且标注人员只需要对现有query进行修改,标注简单。相似问和标准问相比产出快、产量高。

四、相似问挖掘实践

下面来具体介绍一下,相似问挖掘中我们所尝试的各种算法以及效果。

相似问挖掘中所尝试的模块主要有在召回层使用数据增强的同义词替换,聚类、knn和生成式方法,以及排序层的相似度排序。

4.1 数据增强—同义词替换

同义词替换所需的数据有标准问和同义词组,其中同义词又可分为行业同义词(知识生产人员积累)和日常同义词(算法挖掘+人工筛选)。

替换方式分为简单同义词和同义词组两种,简单同义词是标准问进行分词后替换,若为同义词组的话,则直接替换不需分词。

行业同义替换后效果如下图所示(std表示标准问,替换的同义词用”[ ]”标出),其中“核销、下架、无效”为同义词,“查询、查看、查找”为同义词,行业同义词是人工积累获得,替换后可直接使用,不需要人工过滤。

2021-10-31-智能客服-贝壳找房 - 图7

日常同义词质量没有行业同义词高,替换后query需人工过滤。如下图中“哪里、在哪儿”是同义词,标准问“签后报单的入口在哪里?”替换为“签后报单的入口在在哪儿? ”,是不通顺的。但日常同义词数据量大,当其他相似问挖掘方法产出有限时,同义词替换可作为兜底数据。

2021-10-31-智能客服-贝壳找房 - 图8

4.2 相似度–cos相似度

计算用户query和点击的标准问之间的相似度,若query和标准问的相似度足够高,则把该query作为标准问的相似问。这里我们使用的是cos相似度,阈值设置为0.6,如下图可知,标准问为“VR带看没有声音怎么办?”点击这条标准问的query有“vr来电不响 ”、“vr带看没声音 ”、“为什么我的小被vr讲房没有声音呢”,和标准问的相似度都达到了0.6以上,经过人工判断,可知,只有“vr带看没声音”和原标准问的意思相同,是原标准问的相似问。而第二个例子,由于query“vr讲房稿在那里 ”应该是“vr讲房稿在哪里 ”,所以是标准问“VR讲房的模板是什么?”的相似问,但需修改错别字。

2021-10-31-智能客服-贝壳找房 - 图9

4.3 聚类–KMeans/DBSCAN

聚类算法用到用户query和标准问,做法是将query和标准问映射到同一空间一起进行聚类,根据聚类结果,将每个类中的query作为该聚类中的标准问的相似问。

2021-10-31-智能客服-贝壳找房 - 图10

尝试的具体算法有KMeans聚类(k=80,数据量1k+),聚类效果为每个聚类的query个数较均衡,但聚类后query意图分散,图中可以看出聚类label=2时,query包含有离职、转店、审核等意图。

2021-10-31-智能客服-贝壳找房 - 图11

处理KMeans聚类还尝试了DBSCAN聚类,DBSCAN聚类是基于密度的距离,不需要设置聚类个数,但是需要设置类内最大距离,这里希望聚在一起的query意图足够相近,设置类内最大距离较小,导致每个聚类的query个数相差较大,聚类个数有1k+,大多为单点,但同一类内的query意图分散,图中可以看出聚类label=1时,query包含有手机号、房源录入、400电话、贝壳币等意图。

2021-10-31-智能客服-贝壳找房 - 图12

4.4 k近邻

用到的数据是用户query(圆圈表示)和标注标准问的query(菱形表示),将标注标准问的query和用户query映射到同一空间,查看离用户query最近的k个query所对应的标准问类别,若用户query周围大于的k/2的query都对应同一标准问,则用户query也作为该标准问的相似问。

2021-10-31-智能客服-贝壳找房 - 图13

knn所用数据为用户query和标注标准问的query,根据数据量的大小、k值大小分别进行对比实验。

2021-10-31-智能客服-贝壳找房 - 图14

测评1和测评3说明数据从2500增加到6w时,准确率从0.567增加到0.786(绿框),测评3和4说明了k值从5减到3时准确率从0.732增加到0.786(黄框)。

实验还尝试了在数据量一定时,分别使用k=3标注query和k=5标注query,且只有两者标注一致时才作为标签使用,发现标注的query的标签为对应标准问的准确率为0.838,可知叠加不同k值下的效果进行标注时效果较好(蓝框)。

但是测评1-5都是对训练集进行测试,测评6为对测试集进行测试,发现数据量6w时,训练集的准确率为0.732,测试集的准确率为0.599,可知模型对新数据的判断效果不佳(红圈),但是随着数据量的增长,knn效果会有所提升,后期数据积累到一定水平时,该方法还存在尝试的价值。

4.5 生成式—seq2seq+attention/SLCVAE

生成式算法需要的训练数据为标准问和标注标准问的query,以标准问为输入,对应的query为输出,训练GEN模型。预测则是输入标准问,以生成的新query作为相似问。

2021-10-31-智能客服-贝壳找房 - 图15

这里采用了两种生成式模型,seq2seq+attention和SLCVAE模型。

seq2seq+attention是在seq2seq的基础上,添加attention(注意力),当前的输入与目标状态越相似,那么在当前的输入的权重就会越大,说明当前的输出越依赖于当前的输入。

2021-10-31-智能客服-贝壳找房 - 图16

我们在统计了模型训练30轮、40轮、50轮之后的结果发现,生成的query会有字重复现象,停止较慢,且生成的query质量不高的现象。

2021-10-31-智能客服-贝壳找房 - 图17

然后尝试了阿里在19年提出的SLCVAE模型,说起SLCVAE模型要先从AE(AutoEncoder)模型开始,它就是简单的encoder、decoder,encoder输出的中间向量是确定的,为了增加输出的多样性,出现了VAE(Variational AutoEncoder),即学习输入的均值和方差采样得到中间向量,来保证解码的多样性。

而SLCVAE(Self Labeling Conditional Variational Auto Encoder)模型则是添加了输出作为Conditional来限制生成的结果,并且添加Labeling phase,解码共用相同的参数网络。

2021-10-31-智能客服-贝壳找房 - 图18

SLCVAE的最终的效果如下:pred0、pred1、pred3、pred4都是原训练集里存在的数据,只有pred2是新生成的query。可以看出生成的query会有“照搬”训练集的情况出现,生成的query质量尚可但数量少。尝试增加数据量(37w+),”照搬”情况依然存在,调整参数增加输出的多样性,query质量下降。

2021-10-31-智能客服-贝壳找房 - 图19

4.6 算法对比

最后关于相似问的各种算法实践,进行了3个方面的对比:

  • 挖掘难度:同义词替换>聚类、knn、生成式> 相似度

从挖掘难度上看,同义词替换难度最大,相似度的方式难度最小,原因是同义词替换需要依赖同义词,同义词的积累和总结是一个长期的过程。而聚类、knn、生成式方法,则需要标准问和标注标准问的数据,而相似度挖掘只需要标准问即可。

  • 数据产量:日常同义词>相似度>行业同义词

数据产量上来说,由于聚类、knn、生成式方法产出效果不好,没有进行测评。剩下的日常同义词占比最大,相似度挖掘是以日志为基础,能够持续挖掘数量也很多,行业同义词由于数量较少,所以产出有限。

  • 数据质量:行业同义词>日常同义词>相似度>聚类、knn、生成式

虽然行业同义词产量少,但是数据质量是最高的,因为它是纯人工积累的,然后是日常同义词,之后是相似度,最后是聚类、knn和生成式方法。

五、匹配算法实践

5.1 数据准备

随着标准问数量的增加,知识库中存在大量query和标准问的匹配对,将这些匹配对当作正样本,label为1。将query随机抽取一条与之不匹配的标准问作为负样本,label为0。共产生12w+的训练样本和5000条测试样本,正负样本比例为1:1。标准问是由人工标注总结,因此数据集质量较高,正样本匹配关系很强,数据比较规整。训练样本展示:

2021-10-31-智能客服-贝壳找房 - 图20

5.2 模型训练

我们对4种交互型的深度语义匹配模型进行尝试,分别是ABCNN(ABCNN-1,ABCNN-2,ABCNN-3),PairCNN,ESIM和Bimpm。使用交互型匹配模型的原因如下:

  1. 交互型的深匹配模型能很好地把握语义焦点,对上下文重要性进行合理建模。
  2. 从训练集数据来看,正样本是人工标注的有监督数据,交互型模型能保证较高的准确率。

四种模型都有优秀的表现效果,因线上使用的模型是ABCNN-2,这里为大家展示该模型的部分实现代码。

  1. #attention矩阵
  2. def make_attention_mat(x1, x2):
  3. # 作者论文中提出计算attention的方法 在实际过程中反向传播计算梯度时 容易出现NaN的情况 这里面加以修改
  4. # euclidean = tf.sqrt(tf.reduce_sum(tf.square(x1 - tf.matrix_transpose(x2)), axis=1))
  5. # return 1 / (1 + euclidean)
  6. x1 = tf.transpose(tf.squeeze(x1, [-1]), [0, 2, 1])
  7. # 矩阵乘法einsum('ij,jk->ik', m0, m1) # output[i,k] = sum_j m0[i,j] * m1[j, k]
  8. attention = tf.einsum("ijk,ikl->ijl", x1, tf.squeeze(x2, [-1]))
  9. return attention
  10. #全部cnn层相关操作
  11. def CNN_layer(variable_scope, x1, x2, d):
  12. with tf.variable_scope(variable_scope):
  13. #卷积
  14. left_conv = convolution(name_scope="left", x=pad_for_wide_conv(x1), d=d, reuse=False)
  15. right_conv = convolution(name_scope="right", x=pad_for_wide_conv(x2), d=d, reuse=True)
  16. #获得注意力矩阵
  17. left_attention, right_attention = None, None
  18. att_mat = make_attention_mat(left_conv, right_conv)
  19. left_attention, right_attention = tf.reduce_sum(att_mat, axis=2), tf.reduce_sum(att_mat, axis=1)
  20. #pooling(average pooling(w-ap)和qverage pooling(all-ap))
  21. left_wp = w_pool(variable_scope="left", x=left_conv, attention=left_attention)
  22. left_ap = all_pool(variable_scope="left", x=left_conv)
  23. right_wp = w_pool(variable_scope="right", x=right_conv, attention=right_attention)
  24. right_ap = all_pool(variable_scope="right", x=right_conv)
  25. return left_ap, right_ap
  26. #x1,x2是需要匹配的文本embedding后的结果
  27. x1_expanded = tf.expand_dims(x1, -1)
  28. x2_expanded = tf.expand_dims(x2, -1)
  29. #average pooling(all-ap)最终获得为列向量
  30. LO_0 = all_pool(variable_scope="input-left", x=x1_expanded)
  31. RO_0 = all_pool(variable_scope="input-right", x=x2_expanded)
  32. #x1,x2全部cnn层相关操作后所得特征
  33. LO_1, RO_1 = CNN_layer(variable_scope="CNN-1", x1=x1_expanded, x2=x2_expanded, d=d0)
  34. #计算相似度
  35. #作者论文中提出计算相似度的方法是将L01_1,R0_1拼接后进行逻辑回归,这里为了简化计算直接将all_pooling层和L01_1,R0_1分别计算相似度后拼接,然后进行逻辑回归
  36. self.sims = [cos_sim(LO_0, RO_0), cos_sim(LO_1, RO_1)]

5.3 效果测评

5000条测评数据的情况下,上述模型都取得了较好的匹配效果。

2021-10-31-智能客服-贝壳找房 - 图21

耗时来看Bimpm训练耗时较长,相比于其他模型收敛速度较慢,整体的耗时排序为t(ABCNN) < t(PairCNN) < t(ESIM) < t(Bimpm),ABCNN的三种算法训练时间没有明显差别。需要特别说明的是,由于Bimpm模型复杂,在cpu上训练时间过长,最终的训练是在GPU上完成。

准确率来看ABCNN-3和PairCNN的准确率低于95%,剩余都高于95%。ABCNN的三种算法中,ABCNN-1和ABCNN-2的效果相差较小,ABCNN-3的网络结构综合了ABCNN-1和ABCNN-2的结构,但是实验效果并没有更好,反而更差,从侧面反映网络结构更复杂,准确率不一定就更好。

5.4 经验与踩坑

Q:数据对模型有什么影响?

A: 数据质量决定了模型效果的好坏,也尝试采用点击title与query计算相似度,大于某个阈值作为正样本,未点击title与query计算相似度,小于某个阈值作为负样本,因存在错误数据,模型训练效果大打折扣。

Q: 除了数据外,ABCNN模型训练效果受什么影响?

A: ABCNN模型最初几轮的训练效果与模型的随机初始值有很大关系,初始值较差和较好的时候训练达到相同效果的情况下,训练epoch number相差10多轮不足为奇。

Q:为何Bimpm训练时间长?

A: Bimpm模型结构相对复杂,从训练时间上和内存使用率上来说,bimpm应该是放在有GPU情况下考虑选择的模型,并且用原文的参数进行训练时会遇到显存用尽的报错,上表中的结果是删掉两层全连接层,并且减少了神经元个数后训练得出的。

Q:复杂模型的构建与训练有什么建议?

A: 检查写的神经网络是否本身有问题,训练时先用小样本,再逐步增大样本量,通过是否过拟合来判断网络是否正确。

五、总结与展望

当前的深度语义匹配模型已经在贝壳智能客服的在线咨询主场景中使用,模型上线后,QA-bot的列表点击率有了2%的绝对提升,对于一些简单的问题已经能够将较匹配的答案排到top3。

但是对于需要深度语义及具有知识背景的问题,如:“A3到A4需要多少分”的问题,还没有办法将答案“经纪人积分与级别是如何对应的?”排在靠前的位置。当前正在进行知识图谱方向的开发,对知识库内的知识进行结构化的梳理,希望在匹配的同时能够具有简单的推理,来更好的理解用户语言背后的需求。

展望:

  1. 数据是效果的基础,智能客服效果所依赖的FAQ库也需要不断的知识扩充,如何通过自动或半自动的方法挖出更多高质量的相似问或者标准问,为知识运营人员提效,也是我们现阶段正在探索的方向。
  2. 当前的匹配算法仅作为一种特征使用在gbdt排序模型中,后期随着匹配算法的不断积累,会将所有的匹配模型进行整合,以一种更通用的模块化的方式,为有文本匹配需求的各个业务场景提供匹配算法的支持。

参考

【深度语义匹配模型】实践篇:语义匹配在贝壳找房智能客服中的应用

智能客服系统的构建与算法迭代

贝壳智能客服中的数据建设