* feat(engine): 合法输入纠错扩展到多字、漏字,纠错读音按原始区间消耗字母 jiuzheeyang 切成 jiu'zhe'e'yang 全合法,多打的 e 原本纠不回「就这样」;多字纠错的 读音又与原始字母不等长,buuhui 选「不会」后会剩下一个 i。 - legal_input_correction_cuts(原 legal_input_transposition_cuts)认换位、多字、漏字 三类静态表读法,不认邻键与生成式空间;末尾音节按漏字读出的(nia -> nian)视为 还没打完,跳过;k-best 先取 9 条再过滤,长句里纠正不被别处的读法挤掉 - 改变字母数的纠正代价 3.0(换位 2.0);字面切分本身是真词时不认改变字母数的读法, 少一个音节的句子在语言模型里天然分高(邪恶 -> 些、答案 -> 但) - 新增 correction_cut_for_reading / corrected_reading_raw_length:选词按纠错切分 记录的原始区间消耗字母,预编辑也按它分隔(jiu'zhee'yang) - AutocorrectCut 恢复 has_generated,供合法输入路径排除生成式读法 * fix(engine): 被裁掉的合法输入纠错读法不再误标原读法的候选 合法输入上的纠错读法登记进了全局纠错标记表,即使裁决时被丢掉也照样参与按读音字母 的标记匹配:xiee 按多一个 e 读成 xie 被丢掉后,邪恶后面的前缀单字 写/些/血 读音 也是 xie,全被标成纠错。 改为不登记,只在 arbitrate_legal_corrections 里给真正用上的那条纠错读法的整读音 候选打标,标记随结果进缓存。 * feat(engine): 结构性贵档纠错读法可按整句分领衔 shiideya 的换位读法 shi + ide->die(权重 10,是爹呀)比多字读法 shii->shi(权重 12, 是的呀)便宜一档。#592 只在同档内做上下文消解,贵档读法一律排在最后,「是的呀」 连首页都进不了。 - 上下文消解把前 2 条贵档读法也解码,不要求词库有整词;总分 = 路径分 - 手误代价, 代价按纠错表权重换算(权重 x 0.2:换位 2.0、漏字 2.2、多字 2.4) - 只收由结构性手误(换位、漏字、多字)构成的贵档读法:邻键只比漏字贵 0.4 分, 常用词的语言模型优势会把 zhowei 的「周围」挤成「作为」 - AutocorrectCutSegment 记录每段的纠正权重,用来区分纠正类型 - 预编辑跟随领衔读法分隔也覆盖切不成合法音节的输入(shii'de'ya) - eval_quanpin_autocorrect 新增 --word-lattice,量产品默认开词格时的排序 评测(--word-lattice,300 样本,seed 42)各档 R@1/R@3 不低于改动前:mixed R@1 79.7/76.7/78.3/70.3 -> 82.3/81.7/81.3/78.0,insertion 83.3/74.7/72.7/52.0 -> 91.3/89.3/90.0/83.7,deletion 持平或上升,ambiguous 持平。 * fix(engine): 纠错上下文消解在任一整句来源开启时生效 上下文消解只认 word_lattice 开关。只开万象重排、不显示 Trigram 整句时(词格在内部 照样解码),整段被跳过,shiideya 退回静态排序,「是爹呀」又领衔。 - 新增 SentenceAssociationOptions::any_sentence_source,门控改看它;全关时仍是纯 静态排序,#592 的「关联关闭 = 静态路径」不变 - 贵档胜者没有整词也没有整句行时(重排模型未载入),由它的最长前缀词领衔,不让 主切的行顶回首位
4.1 KiB
engine/tests
本目录产出两个独立二进制,都通过 add_subdirectory 链接 engine/CMakeLists.txt 的正式引擎库 MetasequoiaIme::Engine(不另抄源文件清单,编译选项与出货构建一致),互不依赖:
| 目标 | main | 用途 |
|---|---|---|
imetest |
src/test_pinyin.cpp |
引擎测试:全拼/双拼会话、退格、词典增删与查询时序;注册源只有 test_pinyin.cpp,CI 不执行,仅作本地跑测试的入口 |
eval_quanpin_autocorrect |
src/eval_quanpin_autocorrect.cpp |
全拼纠错离线评测:采样真实 msime.db 注错,测召回(R@1/R@3)、读音还原与温态延迟 |
构建
cmake --preset default
cmake --build build --config Release --target <imetest | eval_quanpin_autocorrect>
两个目标共用同一份引擎库,只多编各自的 main。日常改代码跑 imetest 即可,按需单独构建评测目标。
eval_quanpin_autocorrect:离线评测工具
这是评测工具,不是测试,永远进不了 CI:
- 依赖真实的
msime.db(用--db指定)和server/assets/tables资源目录(在仓库根目录运行,或--resource指定)。 - 不挂测试框架、不进断言,产出的是 markdown/CSV 报告,供人工对照基线。
- 存在的理由:纠错阈值、门逻辑(gate)或错误类型改动后,需要用同一把尺子复测。固定种子保证逐档样本一致,数字与历史基线可比。基线口径是「改动后各档不得低于基线值」的零回归门禁。
注错的变体生成规则(交换/邻键/漏字/多字、QWERTY 邻键表、长度与合法音节过滤)与 server/scripts/generate_quanpin_autocorrect.py 必须逐键一致——两侧漂移会让注错模型脱离纠错表的假设空间,基线失去可比性。改任一侧时在同一个提交里同步另一侧。
--seeds-file <路径> 是独立数据入口:每行 typo<TAB>期望key[<TAB>期望词](# 注释、空行跳过,期望词缺省时取该 key 的最高权重词),产出独立的 Seed suite 报告节与 seeds 聚合 CSV 行。它豁免于上述逐键一致契约——种子表度量的正是契约外与用户反馈直接相关的场景(误报/漏报样例固化)。
资源目录要求:引擎加载 sc.lm(词格)与 sentence-model-*.safetensors(神经重排),而 server/assets/tables 只有 dict_pinyin.dat、helpcode.txt、user_dict.dat——模型文件不入库。本机没有把模型放进 tables 时,用安装数据目录拼一个隔离资源目录(只读模型拷贝 + msime.db 副本),--db 与 --resource 都指过去;直接指安装目录也可以,但评测进程会以读写方式打开 --db,拷贝副本更干净。
沙箱环境下子进程可能被拒绝在 %TEMP% 下新建目录(表现为 create_directories: Access is denied. 后直接退出),把 TEMP/TMP 环境变量指到仓库内的已存在目录再跑即可。
历史基线与采集笔记在归档任务目录:.trellis/tasks/archive/2026-09/09-12-quanpin-autocorrect-patent/eval/(阶段 0 基线)与 09-13-quanpin-insertion-autocorrect/eval/(insertion 上线前后对照)。
运行
# 仓库根目录执行;--model 可选 mixed|deletion|ambiguous|insertion|outside
# outside = 表外形状注错(非相邻替换/远键插入),度量生成式纠错空间的覆盖增益,
# 与静态表形状构造性不相交——该档 R@1 在无生成空间的代码上恒为 0。
./engine/tests/build/bin/Release/eval_quanpin_autocorrect.exe `
--db <msime.db 路径> `
--samples 300 --seed 42 --model mixed `
--csv eval-mixed.csv > eval-mixed.md
产品默认开着词格整句联想,纠错的上下文消解(同档消解、结构性贵档读法按整句分领衔)只在词格开启时生效。要量产品实际的排序,加 --word-lattice,并让 --resource 指向带 sc.lm 的目录;不加时测到的是纯静态排序,与历史基线口径一致。
参数细节与报告分节说明见 src/eval_quanpin_autocorrect.cpp 文件头注释。