🐦 第13章 实战案例:智能客服
📄 一句话概括

测试集要分三层判:答对、答错、该答没答。只算一个「准确率」会把最贵的错盖掉。 第一版二十句:答对 16、答错 3、该答没答 1。三句答错全是「一句话里有两个话题」。 第二版补了七个词、判法改成「数票、并列就转人工」:答对 18、答错 0、该答没答 2。

📝 本章和前面几章的关系

这一节没有新节点,只有一张测试集和两版结果。它是全书里最像工程的一节。 三层判定这个分法值得记住:它把「答错」和「不答」分开了。 很多团队只算准确率,结果答错和不答混在一起,看不出改动到底改善了哪一样。 本沙箱没有真模型,这里的「判类」用关键词表替身。替的是模型那一步,不是测试方法本身。

一、三层判定,不是一个准确率

判定 含义 代价
答对 答到该答的那条 最好
答错 答了,但答的是另一条 最贵:用户会照着做
该答没答 转人工了,可其实答得上 次贵:多用一次人工

只算一个准确率会把最贵的错盖掉。 二十句错三句,准确率 85%,听着还行; 可要是那三句全是答错,用户拿着错答案走了,损失比转人工大得多。 所以测试集要一句一句标:这句该答哪条。标不出来,说明你自己也没想清它该走哪条路。 标注这一步是本节的真正门槛。二十句标半小时,比跑十遍脚本有用。

二、第一版:谁先撞算谁

第一版的判法是「关键词表从上往下找,第一个命中的就定类」。跑出来答对 16、答错 3、该答没答 1。 三句答错的原因一模一样:句子里有两个话题,谁先撞上关键词就归谁。 「发票能开保温杯的吗」先撞「保温」,「退货要发票吗」先撞「退」, 「保温杯能放背包侧袋吗」干脆被当成产品问题答了——可知识库根本没写侧袋。

表里最后一句最典型:它是个产品问题,可知识库里没有这一条,正确答案是转人工。 模型(这里是关键词表)不知道「没有」,它只知道「撞上了保温」。

三、那一句「该答没答」

「内胆什么材质的」被转人工了,可它该答「316 不锈钢内胆」。 原因:文档写的是「316 不锈钢内胆」,用户说的是「什么材质」,一个词都对不上。 关键词表里没有「材质」这两个字。 这一类错最容易被忽略:它表现成「转人工」,不响不亮,只是人工量悄悄涨。

要发现它,只有一条路:测的时候把「该答哪条」标上。不标,它永远藏着。

四、第二版:补词 + 数票

两个改动。一是补七个词:材质、不锈钢、保冷、碳酸、饮料、背包、侧袋。 二是判法从「谁先撞算谁」改成「每个类各数命中几个词,取最高的」。 再跑一遍:答对 18、答错 0、该答没答 2。 三句答错全没了。「发票能开保温杯的吗」两票打平,判不出来,转人工; 「保温杯能放背包侧袋吗」里「背包」「侧袋」两票压过「保温」一票,也转人工。

并列就转人工,是这一版最关键的一条规则。 判不出来的时候,宁可转,不可猜。

五、代价和指标

指标 第一版 第二版
答对率 80% 90%
误答率 15% 0%
转人工率 5% 10%

该答没答从 1 句涨到 2 句,转人工率从 5% 涨到 10%。 这不是退步——把一句答错换成一句转人工,是升级。 判据是这个:误答率必须朝零走,转人工率可以涨一点。 反过来就麻烦了。 如果一个改动让答对率和误答率一起涨,那不是优化,是把风险换了个位置藏起来。 这种改动最危险,因为它表面上「更准了」。

六、动手 Demo:二十句测试集,跑两遍

二十句标注好的测试集,第一版按「谁先撞算谁」跑,第二版改成「数票、并列转人工」。 每一版都分三层记:答对、答错、该答没答。

def judge2(text, kw):
    cnt = {}
    for k, tag in kw:
        if k in text:
            cnt[tag] = cnt.get(tag, 0) + 1
    top = max(cnt.values())
    win = [t for t, n in cnt.items() if n == top]
    return u'X' if len(win) > 1 else win[0]   # 并列就转人工

实跑输出:

--------------------------------------------------------------------
二十句测试集,跑两遍
--------------------------------------------------------------------


  ① 第一遍:一个词命中就定类
  --------------------------------------------------------------------
  第一版:答对 16、答错 3、该答没答 1,共 20 句。
  二十句里答错 3 句、该答没答 1 句。

  ② 错在哪几句
  --------------------------------------------------------------------

| 用户说 | 该答 | 实答 | 判定 |
|---|---|---|---|
| 内胆什么材质的 | 产品-保温 | 该转人工 | 该答没答 |
| 发票能开保温杯的吗 | 通用-发票 | 产品-保温 | 答错 |
| 退货要发票吗 | 通用-发票 | 产品-退货 | 答错 |
| 保温杯能放背包侧袋吗 | 该转人工 | 产品-保温 | 答错 |

  三句答错的都是同一件事:句子里有两个话题,谁先撞上关键词就归谁。
  「发票能开保温杯的吗」先撞「保温」,「退货要发票吗」先撞「退」,
  「保温杯能放背包侧袋吗」干脆被当成产品问题答了——可知识库根本没写侧袋。
  「内胆什么材质的」是另一类:文档写「316 不锈钢内胆」,用户说「什么材质」,一个词都不沾。

  ③ 第二遍:补词 + 改成数票
  --------------------------------------------------------------------
  第二版:答对 18、答错 0、该答没答 2,共 20 句。
  补了 7 个词,判法从「谁先撞算谁」改成「谁票多算谁」,并列就转人工。
  三句答错全没了:「发票能开保温杯的吗」两票打平,判不出,转人工;
  「保温杯能放背包侧袋吗」里「背包」「侧袋」两票压过「保温」一票,归给转人工。
  代价是该答没答从 1 句涨到 2 句。 这不是退步——把一句答错换成一句转人工,是升级。

  ④ 三个指标,哪个最贵
  --------------------------------------------------------------------

| 指标 | 第一版 | 第二版 | 为什么 |
|---|---|---|---|
| 答对率 | 80% | 90% | 看整体水平 |
| 误答率 | 15% | 0% | 答错还答得像真的,最伤信任 |
| 转人工率 | 5% | 10% | 太高说明知识库太薄 |

  第二版三个数都朝好的方向动了:答对涨、误答归零、转人工只多一句。这种改法才叫优化。
  反过来,如果一个改动让答对率涨了、误答率也涨了,那就不是优化——是把风险换了个位置藏起来。
  ! 调阈值就是在这三个数之间换:阈值调高,误答降、转人工升。没有哪个设置全赢。

①第一版二十句:答对 16、答错 3、该答没答 1。 ②四句没答对的全列出来了:三句答错、一句该答没答。 ③三句答错的共同点是「一句话两个话题」,谁先撞关键词就归谁。 ④第二版补七个词、改成数票:答对 18、答错 0、该答没答 2。 ⑤三个指标从 80 / 15 / 5 变成 90 / 0 / 10,误答归零才是重点。

30 秒实验

  1. 标二十句测试集,每句写「该答哪条」。标不出来的,说明那条路你自己也没定。
  2. 故意写三句「一句话两个话题」的话,看你们的链会答哪个。答错了不可怕,不知道它答了哪个才可怕。
  3. 把误答率和转人工率分开记。只记准确率,你永远不知道改动改善了哪一样。

常见误区

  1. 「准确率 85% 就可以上线。」那 15% 里要是有答错的,用户拿着错答案走了。
  2. 「转人工率高说明做得差。」转人工比答错便宜。该转的时候转,是设计。
  3. 「并列的时候随便挑一个。」并列说明判不出来,挑一个就是赌。要转人工。
自测三问(点开对答案) 1. 为什么测试要分三层判? —— 只算准确率会把最贵的「答错」和次贵的「该答没答」混在一起,看不出改动改善了哪样。 2. 三句答错的共同原因是什么? —— 一句话里有两个话题,判法是谁先撞关键词就归谁,于是归错了。 3. 第二版用什么规则消掉了答错? —— 每个类各数命中几个词取最高,并列就转人工。宁可转,不可猜。

测完了,最后一节把它发出去:人设、开场白、渠道,还有 FAQ 怎么自动更新。

相关笔记