这个功能的起因是两句话,都是我自己说的。
第一句:「Kuvex」,识别出来是「酷贝克斯」。
第二句:「P3 Air」,识别出来是「P3L」。
两种错,危险程度差很远
第一种一眼就知道错了——中文音译,看着就不对,顺手改掉。
第二种要命:P3L 看起来像一个合法的型号。我自己都要想一下才确定「SUNMI 好像没有 P3L 这个产品,我说的应该是 P3 Air」。这种错误插进文档里,事后基本发现不了。
而根因不是模型不行,是我的英文发音——我说 Air,它听成 L。这是我个人的问题,不是通病。这一点后面很关键。
我们一直在扔掉有用的信息
Xtype 早就有个人词库:你纠正过的专有名词会被记下来,下次开麦时作为提示带给识别引擎,让它倾向于输出正确写法。
但提示只是倾向。口音重、语速快、中文语境太强的时候,它照样吐错。
翻代码时发现一件事:每次纠正,我们其实同时拿到了「错的那个」和「对的那个」——Corin → Kozen、CR一百 → CR100、Smart Tab → SmartTag。但代码只把右边存进词库,左边直接扔了。
结果是词库越长越乱:Kozen 和 KOZEN 各占一条,P3H、P3Mix、P3 并排躺着,谁也不知道它们是不是同一个东西。
事前提示 + 事后兜底
所以加了第二层:别名归一。识别返回之后、插入之前,把已知的错法换成正确写法。
数据全部来自你已经做过的纠正——不用手动录入,你越用它越准。
两层是互补的:词库让模型倾向输出对的,别名在它没做到的时候兜住。
三个刻意的限制
要批准才生效。 候选默认躺着不动,你去点「启用」它才工作。理由就是 P3L 那种情况:看起来合法的替换一旦搞错,是静默污染正文,比识别错更难发现。批准是一次点击,换终身受益。
短词不收。 一旦生成「三 → 3」这种映射,之后说「三个方案」就变成「3个方案」。所以中文少于 3 个字、英文少于 4 个字符的候选直接不提。
但这条把 P3L 也挡住了——它只有 3 个字符。查了一下词库发现规律:痛点几乎全是产品型号,它们都带数字;危险的通用词(Pro、Mac、API、Web)都不带。于是规则改成「3 个字符也收,但必须带数字」。实测型号类 7 个全过,通用词 9 个全挡。
替换要看得见。 发生替换时状态栏写清楚换了几处,词典里能看到每条用过多少次。这是这个项目的一条根本规矩:逻辑必须在界面上看得见,藏在代码里的业务逻辑算违约。
一条不会改的边界
别名永远只在你这台电脑上,不上传、不和其他用户共享。
原因就是开头那句:错误来源是个人口音。我说 Air 被听成 L,所以「P3L → P3 Air」对我成立。但如果 SUNMI 真有 P3L 这个型号,另一个人说 P3L 就会被我的规则改错。
共享别名等于互相污染。 这条哪怕以后做了多机同步也不变——它只跟着你的账号走,不进任何公共词表。