sc.lm 此前只能手工投放,重装即失效,发布包里也没有它。这里把它变成一个被钉住、 可复现、自动参与打包的产品输入。 它不走词库那条路:词库 release 由本仓库之外的构建器产出,资产集合和摘要在产品锁 里逐一钉死,加一项要对方先发新版。改为独立钉住上游语料,与 libime 自己的做法一致。 - language-model/lock.json 钉住上游 URL、语料摘要、转换参数和产物摘要。转换是 确定性的(已在 MSVC 14.44 与 14.50 两套工具链上验证产物摘要一致),所以产物 摘要可以像下载摘要一样钉死。 - scripts/build-language-model.ps1 下载、校验、转换、再校验,写临时文件后改名, 中途失败不会留下摘要对不上的 sc.lm。幂等,摘要对得上直接返回。 - 它只 configure engine/ngram 一个目录,不拉 vcpkg 和 SQLite:转换工具只依赖 kenlm 自己,而打包机上未必装得起引擎的全部依赖。 - Invoke-LocalTest.ps1 打完整包前自动调用它,轻量包本就不带数据文件,不调。 - 打包脚本只断言文件存在,摘要由构建脚本负责,与词库交给 product_lock.py 校验 的分工一致。缺模型让打包失败而不是跳过:引擎对缺模型是静默降级的,运行期不会 暴露,打包是唯一拦得住的地方,package-files.ps1 为此加了反向用例。 模型是 LGPL-2.1-or-later 的第三方数据,声明随之安装为 libime-lm-NOTICE.md。 安装脚本无需改动,它已按通配收集资源目录。产物与语料不进仓库,只进锁与声明。
词格整句打分用的语言模型
本目录钉住 sc.lm 的来源,并放置生成它所需的声明。sc.lm 是一个 kenlm 三元模型,
engine/ngram 把它 mmap 起来给词格的整句候选打分;缺了它引擎会退回启发式打分,
整句候选只是变差,不会停止工作(见 engine/docs/runtime-architecture.md)。
模型本身不在仓库里,也不随词库发布下发。它由 scripts/build-language-model.ps1
从 lock.json 钉住的上游 ARPA 现场转换而来:
.\scripts\build-language-model.ps1
该脚本下载 ARPA 压缩包、校验其 SHA-256、按 lock.json 里的参数转换成 sc.lm,
再校验产物的 SHA-256。转换是确定性的,所以产物摘要可以像下载摘要一样钉死。
脚本是幂等的:sc.lm 已存在且摘要正确时直接返回,不重新下载也不重新转换。
installer\Invoke-LocalTest.ps1 在打完整包前会自动调用它,因此日常跑 test.ps1
不需要手工执行。
上游与 libime 用的是同一份数据和同一组参数(见 libime 的 data/CMakeLists.txt),
这样我们编出来的模型与 fcitx5 发行版里的 zh_CN.lm 等价。lock.json 的
build.order 必须与 engine/ngram/CMakeLists.txt 里的 KENLM_MAX_ORDER 一致,
否则运行时读不懂编出来的文件。
NOTICE.md 是随产品安装的授权声明,安装后名为 libime-lm-NOTICE.md。它进仓库,
因为它是需要评审的声明文本,不是可以重新生成的产物。