Files
fanlusky d30d2946e4 feat(installer): 打包时生成并安装词格语言模型 sc.lm
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。
安装脚本无需改动,它已按通配收集资源目录。产物与语料不进仓库,只进锁与声明。
2026-09-19 10:08:39 +08:00
..

词格整句打分用的语言模型

本目录钉住 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。它进仓库, 因为它是需要评审的声明文本,不是可以重新生成的产物。