一个知识库的搜索加了"拼写纠错":用户打错字时自动纠正。上线后"零结果率"降了 6 个点,而"搜到完全不相关内容"的投诉涨了——因为纠错把"专有名词"当成了拼写错误:A3_images 被"纠正"成 A3image。
拼写纠错的边界是"什么算"错""。它靠"编辑距离"与"词频"判断,而"专有名词、内部代号、缩写"恰恰是"低频且不像常见词"的那类——于是它们最容易被"纠正"。
1. 纠错的三种判据
| 判据 | 风险 |
|---|---|
| 编辑距离(与词典比对) | 专有名词被改 |
| 词频("更像常见词") | 低频术语被改 |
| 上下文概率(语言模型) | 成本高、可能过度纠正 |
第二项是最常见的误改来源:"低频"在统计上等于"像错字"第二项的"另一面"是"高频词极其安全":"报销""申请""流程"几乎不会被改——于是"纠错"的问题集中在"专名与术语"上。
——而内部代号天然低频。
2. "该不该纠正"的三条规则
| 规则 | 说明 |
|---|---|
| 只在"零结果"时纠错 | 不干扰"有结果"的查询 |
| 保留"原文优先" | 纠错只作为"补充结果" |
| 专有名词不纠 | 白名单(代号/缩写/版本号) |
第一项的"判据"是"零结果 = 用户与索引之间断了一次":只有断的时候才值得"猜一下"——而"有结果"时纠错只是"多此一举"。
第一项是"最省心"的策略:原文有结果就不纠——于是"你确定的东西"不会被改,而"真的搜不到"仍有救。
第三项需要一个"白名单维护机制",而它常被忽略第三项的"自动化"很可行:从"代码仓库的文件名/常量名"与"查询日志里的高频短词"里抽白名单——于是"新加一个代号"不必"手动登记"。
:代号是随项目增加的,于是"白名单"必须能从"查询日志/代码"里自动收集。
"白名单"可以用一个"正则规则 + 词表"两段式实现,规则部分零维护:
// 三段"不纠"规则(正则,成本为零)
1 ^[A-Za-z0-9_.\-]+$ → 含下划线/点的标识符(A3_images、d-0042)
2 ^[A-Z]{2,6}$ → 全大写缩写(SLA、QPS、RAG)
3 .*\d.* → 含数字(v2.3、ERR4021)
// 词表部分:从"查询日志的高频短词"与"代码里的文件名"定期抽取
3. "零结果纠错"的三种实现
| 实现 | 说明 |
|---|---|
| 二次查询(用纠正词再搜) | 简单,成本 1 次 |
| 候选词提示("你是不是想搜 X") | 最安全(用户决定) |
| 自动替换(直接返回纠正结果) | 最激进(可能误导) |
第二项的"代价"是"多一次交互":于是在"移动端"(多一步就是流失)与"搜索框自动补全"场景里,产品往往选择"自动替换"——此时"白名单"就是唯一防线。
第二项是"最不容易出错"的:它把"决定权"交给用户——代价是"多一次点击",收益是"不会悄悄改错"。
4. "编辑距离"的三个坑
| 坑 | 表现 |
|---|---|
| 距离阈值太宽 | 改太多 |
| 中英文混排 | 距离算不对 |
| 长度短(2–3 字) | 距离 1 就是"另一个词" |
第三项在中文上很实际:"订单"与"定单"距离为 1,而它们是两个不同的词第三项的"量化"是"短词里"编辑距离 1"的候选太多":2 个字,距离 1 的常见组合可能有几十个——于是"猜哪个"基本是随机的。
(一个业务词,一个常见错写)——于是"短词"应当"不纠"。
// 三种"不该纠"的输入(按长度/形态)
长度 ≤ 2:不纠(距离 1 就是另一个词)
含数字或下划线:不纠(代号/版本/文件名)
全大写缩写:不纠(如 SLA、QPS)
// 判据:这个输入"像不像一个专有名词"
"纠错候选"的生成也要"限流",否则"候选一大堆"等于"没有候选":
// 三条"候选"规则(按优先级)
1 距离 1 且词频 ≥ 阈值的候选,最多 2 个
2 同音/近音(拼音)候选,最多 1 个
3 超过 2 个候选 → 只显示"没有找到,请检查关键词",不做替换
// 判据:候选 ≤ 3 时用户才愿意看;> 3 时"都不对"
5. "纠错效果"的三种度量
| 指标 | 说明 |
|---|---|
| 零结果率(纠错后) | 应下降 |
| 首条点击率 | 不该下降(下降说明误导) |
| "搜到错误内容"投诉 | 应不上升 |
第二项的"测量"要"分群":"纠错触发的查询"单看(不含未触发的),否则"整体点击率"会被大量正常查询稀释,看不出问题。
第二项是"最关键"的:如果纠错让"首条点击率"下降,说明用户被"正确的错结果"骗了——而那比"零结果"更伤。
"纠错是否误改"可以抽查,而抽查的对象应当是"纠错触发"的那一小撮:
// 每周 20 条抽查(只看"触发纠错"的查询)
原查询 → 纠正后 → 首条结果 → 判定(对/误/无法判断)
误改率 = 误 / 20
// 判据:误改率 > 10% → 先收紧规则(长度/形态),而不是"再加词表"
6. 排错:五种"纠错相关问题"
| 现象 | 成因 | 处理方向 |
|---|---|---|
| 专有名词被改 | 无白名单 | 加白名单 + 长度规则 |
| 纠正后结果更差 | 词频判据把"术语"当错字 | 只在零结果纠 |
| 中文短词被乱改 | 距离阈值太宽 | 短词不纠 |
| 用户不知道被改了 | 自动替换无提示 | 改"候选提示" |
| 纠错越来越激进 | 无度量 | 看首条点击率 |
第五项是"治理"问题:**没有"首条点击率"这个反向指标,"纠错"只会"越加越多"**第五项的"具体表现"是"每次上线都"零结果率又降了 1%",而"投诉"也在涨——因为两个指标的方向相反,而只有一个被挂在看板上。
——因为每次都是"零结果降了"。
"零结果"还有个"非拼写"的原因,纠错救不了它——而它常被混在一起看:
// 零结果的三种成因(只有第一种能靠纠错救)
1 拼写错("报消"→"报销") → 纠错有效
2 说法不同("核销"vs"报销") → 同义词扩展
3 语料里真没有 → 补文档
// 判据:纠错上线后"零结果率没降" → 问题在 2/3,不在拼写
7. 边界:什么情况不必纠错
| 场景 | 为什么 | 做法 |
|---|---|---|
| 查询以"精确标识"为主(编号/错误码) | 纠错必然错 | 不纠 |
| 用户是专家(内部工具) | 不需要 | 不纠 |
| 词典很小(术语为主) | 纠错代价高 | 不纠 |
| 已有"同义词扩展"兜住 | 覆盖了"说法不同" | 不纠 |
最后一条与"体验"有关的边界:"纠错要不要告诉用户":不告诉(自动替换)会让"我明明搜对了"的困惑,告诉(候选提示)会让"多一步"。所以"自动替换"只适合"低风险词"(常见错写)。
判断口径一句话:"用户的输入是"自然语言"还是"标识符"。自然语言("怎么申请报销"),纠错有价值;标识符(ERR_4021、A3_images),纠错只会帮倒忙。
最后一个"产品"提醒:纠错的价值要按"用户查得到的那部分"衡量,而不是"零结果率"。因为"零结果 → 纠正 → 有结果但不对"在指标上是"改善",在体验上是"更糟"——而只有"首条点击率"与"误改率"能分开这两件事。
8. 自测
- 三种纠错判据里,哪一种最容易"误改专有名词"?为什么"低频"等于"像错字"?
- "只在零结果时纠错"为什么最省心?它保护了什么?
- "候选提示"与"自动替换"的取舍是什么?为什么前者更安全?
- 为什么中文"2–3 字"的词不该纠错?
- "首条点击率"为什么是纠错的反向指标?它不降说明什么?
- 判断"是否需要纠错"的那个问题是什么?