Files
msime-windows/engine/core/syllable_helpcode.h
T
fanlusky fae80660c1 feat(engine,server,windows,ui-html): 双拼句中辅助码
在完整音节后敲反引号,接着的字母筛这个音节上的字:第一码大小写均可,
紧跟的大写字母是第二码,之后可以接着打,一个输入里可以有多段。开关
helpcode.shuangpin_mid_sentence_helpcode 默认关闭。

约束在整句解码时生效,而不是解完再筛:
- Google 解码器在 add_char_qwerty 里送 extend_mtrx_nd 之前按约束过滤词条,
  锁住的字带着上下文重新整句解码;约束变化时整段重解,不污染增量搜索。
- kenlm 词格建图时按约束筛边,受约束的跨度不截断地查词库;神经重排只在
  词格 n-best 里挑,自动满足约束。
- 普通词条、云和 AI 候选按同一规则收尾校验;满足不了就不出整句。

反引号段在请求里换成手动分隔符,原串留给宿主回读与预编辑显示;选词推进
时剩余音节上的约束随原串保留。输入形状规则放在 contracts/mid_sentence_helpcode.h,
TSF、Server、引擎共用,新增 Worker opcode MidSentenceHelpcodeChanged = 28。
googlepinyinime-rev 已与上游解绑,AGENTS 与 UPSTREAM.md 同步说明。
2026-10-02 02:20:37 +08:00

58 lines
2.1 KiB
C++

#pragma once
#include <cstddef>
#include <string>
#include <vector>
// 句中辅助码(双拼):在一个完整音节后面敲反引号,接着的字母筛这个音节上的字。
//
// ulpb`x 第二个音节「鹤」位置上的字,辅助码第一码必须是 x
// ulpb`xY 同上,第二码必须是 y(第二码要用大写才参与筛选)
// ulpb`xihfa 约束留在第二个音节上,后面照常往下打
//
// 一个输入串里可以有多段。约束在整句解码时就生效(kenlm 词格建图筛边、Google 解码器
// 建格子筛字),而不是解完再筛,所以被锁住的字会带着上下文重新整句打分。
struct SyllableHelpcode
{
// 受约束的音节,按去掉反引号段之后的双拼切分计,0 起。
std::size_t syllable = 0;
// 第一码,小写字母。
char first = 0;
// 第二码,小写字母;0 表示没有第二码,只按第一码筛。
char second = 0;
bool operator==(const SyllableHelpcode &other) const
{
return syllable == other.syllable && first == other.first && second == other.second;
}
bool operator!=(const SyllableHelpcode &other) const
{
return !(*this == other);
}
};
using SyllableHelpcodes = std::vector<SyllableHelpcode>;
// 辅助码表里查到的码(如 "ek")是否满足这一条约束。
inline bool syllable_helpcode_matches(const SyllableHelpcode &helpcode, const std::string &code)
{
if (code.empty() || code[0] != helpcode.first)
return false;
return helpcode.second == 0 || (code.size() > 1 && code[1] == helpcode.second);
}
// 缓存键用的签名:同一串拼音带不同约束,候选不同,不能共用缓存。
inline std::string syllable_helpcodes_signature(const SyllableHelpcodes &helpcodes)
{
std::string signature;
for (const auto &helpcode : helpcodes)
{
signature += '`';
signature += std::to_string(helpcode.syllable);
signature += helpcode.first;
if (helpcode.second != 0)
signature += helpcode.second;
}
return signature;
}