语境预测 (User Predict):上下文联想与候选调频
user_predict.lua由 Processor、Translator 和 Filter 三部分协同工作:记录用户实际输入形成的上下文关联,在移动端按需生成上屏后联想,在桌面端或移动端reorder模式中根据上文重新调整当前候选顺序。
当前版本采用稳定记录模型:
因此,当前文档应以 c 值计数、负值墓碑、上下文隔离、分支裁剪和事务回滚 为核心理解 User Predict。
一、User Predict 现在负责什么?
当前模块主要承担三类用户可感知功能:
- 上屏后联想(Post Predict)
- 输入中的上下文调频(Context Reorder)
- 数字后的量词提权(Classifier Boost)
此外还包含:
- 回头码兜底交换
- S / 2 / 1 / P 四级关联查询
- S-Gram 长上文前缀桥接
- 关联学习与分支裁剪
- 上屏后立即退格的数据库回滚
- 预测候选主动删除
- 导入 / 导出
- 多端数据合并所需的稳定记录与墓碑状态
二、先用一个简单例子理解“学习”
一次有效的连续上下文即可建立关联。
例如测试:
注意两次上屏之间不要超过当前:
也就是默认约 5 秒的上下文窗口。
完成这次连续输入后,数据库已经可以形成:
的有效关联。
之后再次输入并上屏:
如果开启了预测总开关:
- 移动端
post模式可以直接出现“族长”联想; reorder模式下,再输入“族长”对应编码时,“族长”可以根据上下文被提前。
第一次有效学习会把对应关联写成:
后续再次学习同一关联时继续递增:
三、总开关:prediction
User Predict 受 Rime Option:
统一控制。
当前 Base 方案中:
如果这个 Option 关闭:
量词调频也位于同一个 Filter 中,并随整体预测 Filter 的运行状态共同工作。
四、桌面端与移动端并不是同一种显示方式
桌面端
当前 Lua 在非移动设备上会直接指定:
因此桌面端开启 prediction 后,默认工作方式就是:
输入中的上下文候选调频
而不是上屏后再弹出 › 联想候选。
换句话说:
mobile_predict_style 在 PC 上不会改变这一点。
移动端
移动端才读取:
支持:
当前 Base 方案配置:
因此移动端默认使用上屏后联想。
五、Post:上屏后的联想预测
当移动端使用:
并且当前上文存在可用预测时,Lua 会在输入区压入:
作为预测占位符,然后由 User Predict Translator 生成:
的候选。
例如:
上屏后可能出现:
选择其中一个预测候选后,它会正常上屏,并继续作为新的语境参与后续预测。
普通按键会结束当前联想界面
如果正在显示 › 预测,此时开始正常输入:
Lua 会关闭当前预测候选,清掉占位符,再让新的按键继续交给后续 Rime 输入流程。
因此 Post 模式不会要求先手动关闭预测才能继续打字。
数字键
在非 T9 环境下,预测状态中直接按数字会结束联想并提交对应数字。
T9 中数字本身属于编码,因此会退出预测状态后把数字继续交还给 T9 输入流程。
六、Reorder:输入中的上下文调频
reorder 不会生成 › 占位符。
它先根据刚刚上屏的上下文查询预测记录,再在你开始输入下一个词时扫描当前正常候选。
如果某个正常候选正好存在于预测结果中,就根据预测排名将它提前。
例如已经形成:
的关联。
之后:
原始候选可能是:
上下文调频后可以变成:
七、量词提权
User Predict Filter 还包含独立的数字后量词提权。
例如已经直接输入:
随后输入某个与量词同码的拼音时,只要当前候选文字存在于量词表中,就可以被优先提升。
例如:
可以优先得到:
而不是普通语境下更高频的其他同码字。
默认量词表
当前方案通过:
提供自定义列表,例如:
custom_classifiers:
- 个只名位口人头匹条群批伙多
- 张把件台部块根颗粒滴片朵面扇顶栋座所辆艘架盏支枝杆
- 双对副套打串束排阵堆叠摞扎
- 杯瓶盒包份碗锅盆桶袋罐盘
- 次场局回趟顿番遍声项宗桩款步招
- 年月天周岁秒分刻代期届任夜季
- 本册篇首句段卷幅节堂门帖字行
- 米寸尺里斤两吨克升元角毛笔百千万亿
Lua 会把列表内容合并成快速查找表。
关闭量词提权
如果不需要,可以把列表清空:
这样量词查找表为空,就不会执行数字后的分类提权。
八、回头码兜底交换
当前版本仍然保留:
这个功能不是正常的 N-Gram 上下文预测,而是针对“删掉当前编码后重新输入同一编码”的回头场景。
简单理解:
它主要用于同码候选首次顺序不合预期时的快速兜底。
当前 Base 配置
当前方案中:
也就是说,代码功能存在,但当前 Base 默认没有开启。
需要使用时:
九、当前真正的防污染机制
当前版本通过输入语境过滤减少无效学习。
1. 上下文超时
默认:
两次上屏之间超过这个时间,就切断当前记忆链。
因此:
过很久之后再输入:
不会被强行视为同一段即时语境。
2. 单次上屏超过 4 字不进行普通关联学习
当前基础规则:
防止超长整句直接大量污染短上下文模型。
3. 连续重复不学习
例如:
不会继续制造自循环关联。
4. ABA 折返过滤
类似:
的快速折返会被识别,避免把短时间来回修改误学成高价值关联。
5. 非中文内容切断语境
当前普通学习主要接受:
如果上屏内容属于其他不适合学习的文本,会重置当前语境链。
6. 标点隔离
普通句末标点通常意味着语境结束。
但对于:
这类常见句末助词,Lua 保留了白名单,使:
能够正常完成句尾处理,而不是在助词上屏时提前产生异常关联。
十、四字词还有一条直接学习通道
当前 v12 对恰好四个汉字的最终上屏文本提供专门学习逻辑。
例如一次上屏:
如果它正好由四个汉字构成,会自动按:
建立 1-Gram:
这条记录不要求该四字文本原本在候选列表里处于什么位置。
也就是说,四字纯中文内容可以在第一次有效上屏后直接建立:
关联。
十一、S / 2 / 1 / P 四级查询
当前查询仍然使用四层模型:
不同层级使用不同的基础倍率:
候选基础权重则直接来自记录中的正 c 值。
十二、S-Gram:手工维护的静态关联
S-Gram 不是运行时自动学习层。
它专门用于:
当前运行时:
- 只读取 S 记录
- 不自动学习 S
- 不自动增加 S 的
c - 不参与普通分支淘汰
- 删除预测候选时也不会给 S 写删除墓碑
因此它属于长期静态记忆。
权重
查询时:
因此相对于动态 2 / 1 / P 层拥有最高优先级。
但它并不是“某个不可修改的隐藏后门”,而是一类明确的数据记录。
十三、v12 新增:S-Gram 长上文前缀桥接
假设手工导入:
完整关联本来是:
但用户可能只先输入:
v12 会扫描同一个 S 家族,发现存在更长的静态上文:
于是可以先给出桥接候选:
选择这个桥接候选后,Lua 会保留完整强上下文:
然后优先查询:
继续得到:
可以理解为:
桥接限制
当前源码内部限制包括:
这些属于当前内部策略,暂时没有对应 YAML 参数。
十四、2-Gram:双上文关联
2-Gram 使用最近两个上屏单元作为上下文:
例如:
查询倍率:
为了限制上下文规模,当前只有满足:
时才写入 / 查询 2-Gram。
十五、1-Gram:主要动态关联
1-Gram 是最直接的:
例如:
查询倍率:
当上文长度较长时,查询会从末尾最多 4 个字开始逐级回退:
一旦当前回退层已经找到结果,就停止继续向更短后缀下降。
十六、P-Gram:长上文后缀兜底
P-Gram 用于保存较长上文的部分后缀关系。
例如一个较长上文无法直接作为普通 1-Gram 使用时,可以将其后部若干字作为:
继续查找下一词。
查询倍率最低:
因此它主要承担:
普通关联没有命中时的抗抖动兜底。
当一个 P 候选实际被用户继续上屏后,正常的 commit 学习流程又会根据真实上下文重新写入 1 / 2 等动态关联。
所以不需要再把它描述成一个独立的“P-Gram 手动转正按钮”。
十七、当前排名方式
当前预测权重可以简化为:
其中:
记录本身只要:
就是有效预测记录。
十八、现在如何控制数据库规模?
当前主要通过:
控制同一上下文前缀下保留的动态分支数量。
查询某一个动态 Gram 时:
- 读取当前前缀下记录
- 按
c降序 - 保留前
max_memory_branches - 超出的动态记录写入负
c墓碑
S-Gram 属于静态数据,不参与这一步动态分支裁剪。
因此因此,同一上下文下只有排名较高的动态分支继续保持有效状态,超出分支上限的记录会被标记删除。
十九、c 值与负墓碑
当前数据库记录采用稳定形式:
记录尾部为:
正 c
表示当前关联有效:
每次再次学习同一条关联时,绝对值继续增加。
负 c
表示这条关联已经被删除:
删除时不会简单抹掉 raw key,而是:
例如:
删除后:
如果以后再次重新学习该关联,则会从当前绝对值继续增加,并恢复为正值:
这样可以避免:
这类状态折返。
二十、上屏后立即退格:事务回滚
当前每次上屏学习时,Lua 会记录本次真正改动了哪些数据库键,以及:
如果上屏后没有进行其他正常输入,并在:
规定的时间窗口内立刻按 Backspace,User Predict 会尝试撤销刚才这次上屏造成的数据库学习。
例如:
对应的刚刚新增 / 增强的预测关联可以一起回滚。
回滚的是预测数据库事务
User Predict 负责恢复它自己刚才写入的数据库状态。
屏幕上文字究竟怎样被 Backspace 删除,仍由当前 Rime 前端和编辑环境共同处理。
防止误回滚旧事务
只要上屏后又进行了其他普通按键操作:
后面的 Backspace 不会继续把更早以前的预测学习一起撤销。
二十一、主动删除预测候选
当当前菜单选中:
的预测候选时,模块可以响应前端删除通知,也支持带 Control / Shift 的 Delete 或 BackSpace 类按键删除预测关联。
常见操作可以继续使用:
但数据库层的实际行为不是“物理销毁”,而是:
并同时处理与当前上文相关的 P-Gram 兜底记录。
S-Gram 不允许这样删除
如果当前预测来自:
或者只是 S-Gram 生成的虚拟桥接候选,删除逻辑会直接放行,不给它写墓碑。
静态 S 数据只能通过外部数据文件 / 导入数据自行维护。
二十二、导出 /outpredict
在任意输入框输入:
会将当前预测数据库导出到 Rime 用户目录:
当前格式为三列:
例如:
S-Gram 也使用同一格式:
二十三、导入 /inpredict
准备:
放在 Rime 用户目录,然后输入:
即可导入。
导入时比较 c 的状态强度。
合并规则
假设:
则采用:
如果:
绝对值相同,则负墓碑优先:
因此当前合并原则是:
这套逻辑不依赖设备本地时钟。
二十四、如何手工添加 S-Gram?
S-Gram 推荐通过导入文件维护。
例如希望:
始终作为静态高优先级关联。
在:
中写:
三个字段之间使用真实 Tab。
然后输入:
导入即可。
长句示例
例如:
写成:
导入后除了完整上文命中,还可以利用 v12 的 S 前缀桥接功能。
S-Gram 当前统一使用:
二十五、当前真正有效的 YAML 参数
v12 当前读取的主要配置如下:
| 参数 | 作用 | Lua 回退值 / 当前方案 |
|---|---|---|
db_name |
User Predict 数据库名称 | Lua 回退 lua/predict |
mobile_predict_style |
移动端模式:post / reorder / off |
当前 Base:post |
enable_fallback_reorder |
回头码首二候选兜底交换 | Lua 内部默认 true;当前 Base 显式 false |
max_candidates |
Post 联想显示上限及预测结果控制参数 | Lua 回退 5;当前 Base 10 |
max_predictions |
Post 连续预测链深度上限 | 3 |
max_memory_branches |
单一动态上下文最多保留的有效分支 | 15 |
context_timeout |
即时上下文与 Undo 窗口,毫秒 | 5000 |
custom_classifiers |
数字后量词提权字符集 | 当前方案自定义列表 |
二十六、推荐的 Custom Patch
例如:
patch:
# 移动端:上屏后联想
"user_predict/mobile_predict_style": "post"
# 开启回头码兜底
"user_predict/enable_fallback_reorder": true
# 联想显示数量
"user_predict/max_candidates": 5
# Post 连续联想深度
"user_predict/max_predictions": 3
# 单个上下文保留的动态分支数量
"user_predict/max_memory_branches": 15
# 即时上下文有效时间 / Undo 时间窗口
"user_predict/context_timeout": 5000
移动端如果只需要上下文调频:
移动端如果暂时不需要 User Predict 的 Post / Reorder:
off 不等于删除数据库
off 只是关闭当前移动端的预测呈现方式。
历史数据库仍然保留,之后重新切回 post 或 reorder 可以继续使用。
二十七、如何固定开启 prediction?
当前 Base 的 switches 中:
位于第 6 项。
列表从 0 开始计数,因此当前 Base 对应:
表示方案初始化时默认:
不要长期把 @5 当作固定接口
@5 只代表当前 Base 版本中第 6 个 Switch。
Pro 或后续版本如果调整了 switches 顺序,索引可能变化。
因此修改其他方案时,应先检查实际 switches 数组,再确定对应索引。
二十八、当前版本可以怎样理解?
当前 User Predict 的核心由以下几部分组成:
整体流程可以概括为:
用户连续上屏
↓
验证是否属于有效语境
↓
写入 1 / 2 / P 动态关联
↓
正 c 累计学习强度
↓
下次根据 S → 2 → 1 → P 查询
↓
移动端 Post 或输入中 Reorder
↓
误选可 Undo
主动删除写负 c 墓碑
S-Gram 则始终保持独立: