16 条知识库配 8 个用户问句,检索式在阈值 0.30 下只答出 3 条、拒答 5 条,其中 3 条是误拒; 关键词规则命中 4 条全对,却漏掉另外 4 条。两套办法的长短正好相反。
上一节判情感,这一节做问答。语音助手、客服机器人、FAQ 自动回复,底层都是这一套。
一、三种机器人,三种难度
- 规则式。关键词命中就给固定答案。最便宜,覆盖最窄。
- 检索式。把用户问句和知识库里的问题算相似度,取最像的那条,顺便给它的答案。
- 生成式。让模型直接写答案。最灵活,也最容易编。 Demo 只做前两种。生成式要模型,沙箱里没有,也不假装跑过。 但前两种不是过时的东西:线上客服系统绝大多数还是规则加检索,生成式只在兜底环节用。 原因很实际——答错了要担责。
二、检索式的核心是一个阈值
检索式必须回答一个问题:最像的那条到底够不够像?不够像就该拒答,转人工,而不是硬答。 Demo 的阈值定在 0.30。低于它一律拒答。 结果很不好看:8 个问句只答出 3 条,拒了 5 条。 而拒掉的 5 条里,有 3 条知识库里明明有答案——「我想退款怎么弄」对应「怎么申请退款」, 相似度只有 0.267。 为什么这么低?因为用户问句短。 「我想退款怎么弄」7 个字,知识库问题 6 个字,字面只共享「怎么」两个字。余弦被长度拖死了。
三、规则式的短与长
规则表只有 5 个词:退款、发票、密码、人工、营业时间。命中 4 条,条条对。 它漏掉的 4 条是:东西坏了怎么处理、优惠券在哪里领、会员多少钱一年、你们几点上班。 注意最后一条:「你们几点上班」和「营业时间」是一个意思,但字面一个字都不重。 规则表写「营业时间」,用户说「几点上班」,两边对不上。 这是规则式的通病:它只认自己写下的词。要覆盖「几点上班」,就得再写一条同义词,写不完。
四、实际系统怎么拼
三段式,按顺序走: 1. 规则先过。命中硬关键词直接答,这部分零风险。 2. 检索兜底。规则没命中,走相似度检索,分数够高就答。 3. 转人工。检索分数也低,直接转人工,别硬猜。 这个顺序的道理是:能不猜就不猜。规则答错概率最低,检索次之,生成最高。 按可靠性从高到低排,先把可靠的用完。 还有一件事要在设计阶段定:拒答阈值不是越高越好。定高了,用户问十句被拒八句,体验直接崩; 定低了,答错的比例上去,投诉跟着来。这个数只能拿真实日志调。
五、动手 Demo:客服机器人:检索匹配加阈值拒答,对照关键词规则
16 条知识库问答,8 个用户问句;用字符 bigram 余弦找最像的问题,相似度低于 0.30 就拒答; 打出每个问句的最像项、相似度和动作;再用 5 条关键词规则跑一遍做对照,打出各自命中几条。
best, bv = u'', -1.0
for k, a in FAQ:
v = cos_bg(q, k) # 字符 bigram 余弦
if v > bv:
bv, best = v, k
if bv < 0.30:
action = u'拒答' # 阈值以下不硬猜
实跑输出:
--------------------------------------------------------------------
聊天机器人:检索式匹配 + 阈值拒答
--------------------------------------------------------------------
知识库条目 16 条
用户问句 8 条
拒答阈值 0.30
用户问句 最像的知识库问题 相似度 动作
--------------------------------------------------
我想退款怎么弄 怎么申请退款 0.267 拒答
发票能开吗 能开发票吗 0.500 作答
忘记密码了 密码忘了怎么办 0.144 拒答
转人工 怎么联系人工客服 0.167 拒答
你们几点上班 怎么申请退款 0.000 拒答
东西坏了怎么处理 商品坏了怎么办 0.354 作答
优惠券在哪里领 优惠券怎么用 0.401 作答
会员多少钱一年 会员有什么权益 0.250 拒答
作答 3 条
拒答 5 条
规则版对照:命中关键词就直接给答案。
规则词 命中问句 对应条目 命中的是
----------------------------------------------
退款 1 退款 我想退款怎么弄
发票 1 发票 发票能开吗
密码 1 密码 忘记密码了
人工 1 人工客服 转人工
营业时间 0 营业时间 —
规则版命中 4 条
规则版漏掉 4 条
两套方法的长短正好相反:规则命中 4 条,条条对,但「东西坏了怎么处理」「优惠券在哪里领」「会员多少钱一年」「你们几点上班」这 4 条它管不了;
检索只答出 3 条,还把「我想退款怎么弄」「忘记密码了」「转人工」这三条本来有答案的判成了拒答——短问句和长问题的余弦天生偏低,固定阈值一刀切必然误伤。
真做客服机器人,常见的结构是规则兜底 + 检索补充 + 转人工:关键词硬命中直接答,命中不了再走检索,检索分低就转人工,别硬猜。
看相似度那一列:最高的才 0.500(发票能开吗),最低的 0.000(你们几点上班)。 整列都偏低,是短问句的通病。 「东西坏了怎么处理」拿到 0.354,刚好过线,答对了。 这条能过,是因为「坏了」和「商品坏了」有实际重叠。 「会员多少钱一年」0.250 被拒。知识库里是「会员有什么权益」,两者只共享「会员」,确实不像。 规则版 4 条命中全对,但覆盖只有一半。两套办法合起来才能到 6 条左右,还剩两条要靠同义词表或转人工。
30 秒实验
- 把阈值从 0.30 降到 0.15,看作答几条、答错几条。
- 给规则表加一条「几点上班」对应营业时间,看命中变几条。
- 想一想:为什么生成式机器人不适合做第一道兜底?
常见误区
- 「检索式准确率低就是模型差」——短问句的余弦天生偏低,是度量的问题。
- 「阈值越低覆盖越高越好」——答错的比例会一起上去。
- 「上了大模型就不需要规则了」——规则零风险、零成本,永远该放第一道。
自测三问(点开对答案)
1. 检索式机器人为什么必须有拒答阈值? —— 不设阈值,最像的那条即使只有 0.05 也会被当成答案,答错还看不出来。 2. 短问句的相似度为什么天然偏低? —— 字面重叠少,余弦被长度拖下来,跟语义像不像关系不大。 3. 实际客服系统为什么按「规则→检索→人工」这个顺序? —— 可靠性从高到低排,能确定的不猜,猜不准的交给人。文字问答做完了,下一节换成声音:把说话变成文字。
- ☐ (本节完,下一节 6.2.3 语音识别:将声音转化为文字的科技奇迹)