系统提示

波斯语字形看起来一样,为什么搜索仍会漏掉结果:Yeh、Kaf与规范化边界

波斯语字形在屏幕上相近,底层码位仍可能不同;Unicode规范化也不会自动合并所有语言变体。本文区分字符身份、标准规范化、语言特定搜索映射与ZWNJ处理。

编辑把一条波斯语标题复制到站内搜索,页面上明明能看到相同的词,结果却显示零条。换一个键盘重新输入后,文章又出现了。字体没有明显变化,底层字符却可能已经不同;这类问题不能只用肉眼检查。

字形相近不等于字符相同

波斯语使用扩展的阿拉伯字母系统。Unicode 16.0核心规范说明,阿拉伯字母会依照前后连接位置呈现不同形态,但同一个字母原则上只有一个字符值。也就是说,初始、居中、末尾和独立形态通常由排版系统决定,不应把每一种外形另存成不同字符。

困难在于,阿拉伯语、波斯语、乌尔都语等语言共享许多字形骨架,同时也有各自需要的字符。U+064A是ARABIC LETTER YEH,U+06CC是ARABIC LETTER FARSI YEH。两者在部分连接位置很像,却仍是不同码位。类似地,阿拉伯Kaf与波斯Keheh也可能在字体中显得接近。

数据库比较的是字符序列,不是屏幕截图。若索引收录的是Farsi Yeh,而查询输入Arabic Yeh,简单的逐码位匹配就会失败。字体若把两者画得接近,问题还会被遮住。此时“看起来一样”只能说明渲染相似,不能证明编码相同。

NFC不会自动统一所有语言变体

Unicode规范化表单用于处理标准定义的规范等价或兼容等价。例如,一个带附加符号的字符有时既能写成预组形式,也能写成基础字符加组合符号;规范化可把允许等价的序列转换到共同形式,以便直接比较。

Unicode核心规范明确区分规范化与排序。规范化判断字符串是否具有标准定义的等价关系,不负责按语言习惯产生排序键,也不允许应用随意改写等价关系。NFC、NFD、NFKC和NFKD各自有确定算法,不是一张可以任意扩充的错别字替换表。

因此,Farsi Yeh与Arabic Yeh即使在某些字体和位置相似,也不能只凭视觉关系断言NFC会把它们合并。语言字母变体、拼写变体和搜索同义关系往往超出规范等价范围。把所有文本跑一遍NFC是合理的基础步骤,却不是波斯语搜索规范化的全部。

兼容规范化也要谨慎。NFKC可能折叠某些为兼容而编码的表现形式,适合部分检索键,却可能丢失原始表现差异。用于展示、引用或语言研究的正文不应被无条件覆盖。更稳妥的做法是保存原文,另建经过说明的检索字段。

为什么搜索端和写入端必须用同一规则

若入库时把Farsi Yeh转换成Arabic Yeh,而查询端保留原输入,结果仍会分裂。反过来也一样。真正有效的检索规范化必须在索引与查询两端执行同一版本、同一顺序的规则,并保留测试样例证明每一次映射符合产品目标。

规则顺序也会影响结果。一般可以先完成编码解码与Unicode标准规范化,再处理已获批准的语言特定映射,最后执行大小写、标点或空白等与业务有关的步骤。波斯语没有拉丁字母那样的大小写变化,但数字、空白、组合符号和控制字符仍需要明确策略。

不要把显示修复和搜索修复混在一起。排版系统依据字符的连接属性选择字形;搜索系统则建立比较键。为了让字形连接正确而加入或移除控制字符,可能改变文本结构。为了扩大召回而折叠字母,也可能让原本应区分的其他语言文本发生碰撞。

一张映射表为何需要语言和场景边界

同一个平台可能同时收录波斯语、阿拉伯语和乌尔都语。如果全站把所有Yeh类字符压成一个码位,波斯语查询的召回率也许提高,却可能破坏其他语言中的真实区别。Unicode第九章特别指出,Yeh Barree在阿拉伯语和波斯语环境可视为某些位置的样式变体,但在乌尔都语中承担独立元音功能。

这说明映射策略必须知道目标语料。只服务波斯语新闻的索引,可以采用经过验证的波斯语检索映射;多语言档案则宜先做语言识别或分栏索引。无法确定语言时,宁可保留原码位并增加候选查询,也不要永久改写唯一正文。

映射还需要可逆性说明。搜索键不一定要完全可逆,因为它的目的可能是提高召回;展示正文、法律记录、姓名和学术语料却通常需要保存原样。把检索字段与原始字段分开,能让系统在扩大匹配时仍可回到真实输入。

规范化之外还有空格和ZWNJ

波斯语检索不只受Yeh和Kaf影响。普通空格与零宽非连接符ZWNJ会改变词形连接和分词结果。2025年的PerSpaCor研究把空格与ZWNJ纠错建模为字符级序列标注。并使用Bijankhan与Peykare语料中超过1270万预处理和标注词训练模型。

这项研究的最佳模型取得97.26%的宏平均F1,加入用户输入的交互版本达到98.38%。这些数字说明模型在其数据和任务定义下表现良好,却不代表任何网页、方言或领域都能达到相同结果。语料来源、预处理方式和错误类型仍是适用边界。

更重要的是,ZWNJ问题不能用“删除所有不可见字符”解决。它虽没有可见宽度,却会阻止相邻字母连接,并参与波斯语正字法与词形呈现。无条件删除可能让词形粘连;全部替换成普通空格又可能改变分词。它需要单独规则和单独测试。

用码位检查代替截图猜测

排查时先截取一个确定漏搜的词,分别输出原文和查询的Unicode码位序列。若看到U+064A与U+06CC、U+0643与U+06A9等差异,就能把问题从“字体怪异”缩小为“比较键不同”。同时记录文本经过了哪一种规范化表单。

随后建立最小测试集。每组包含原始文本、输入方式、期望匹配和不应匹配的反例。测试至少覆盖波斯语键盘、阿拉伯语键盘、复制自PDF或网页的文本,以及含组合符号和ZWNJ的词。只有正例而没有反例,会让映射越做越宽。

对现有资料库,先统计字符分布,不要直接批量覆盖。确认每类变体出现在哪些语言、字段和来源,再决定是重建搜索键、扩展查询,还是清理明确的输入错误。任何改写都应保留原值、规则版本和变更记录。

上线后分别观察召回与碰撞。漏搜减少是好事,但若两个原本不同的姓名、术语或语言形式被合并,也代表精确率下降。搜索规范化的目标不是“字符越少越好”,而是在明确语境中减少无意义差异,同时保留有意义区别。

可执行的检索处理边界

第一层只做Unicode标准规范化,并记录采用NFC还是其他形式。第二层在明确为波斯语的检索字段中处理经验证的Yeh、Kaf等映射。第三层单独处理空白、ZWNJ、数字和标点,每一项都要有正反测试。

具体检查可以压缩成四句话。U+064A ARABIC LETTER YEH与U+06CC FARSI YEH是不同码位。数据库按字符序列建立比较键;相近字形若码位不同,逐码位搜索就会漏掉结果。Unicode规范化处理标准定义的等价序列;语言特定搜索规范化处理产品决定要折叠的输入变体。输出漏搜词的Unicode码位,在索引与查询端运行同一规则,并用应匹配和不应匹配的样例共同验证。

视觉相似不能证明码位相同;Unicode规范化只处理标准定义的等价关系。波斯语搜索还需要语言特定的比较策略,但策略应落在可重建的搜索字段,而不是覆盖原始文本。只要索引端与查询端使用同一规则,并保留语言边界和反例,漏搜问题才有机会被稳定修正。

资料来源

  • Unicode联盟:《The Unicode Standard, Version 16.0—Chapter 9》,发布或更新于 2024-09-10
  • Unicode联盟:《The Unicode Standard, Version 16.0—Chapter 3》,发布或更新于 2024-09-10
  • ACL Anthology / RANLP:《PerSpaCor: Correcting Space and ZWNJ Errors in Persian Text with Transformer Models》,发布或更新于 2025-09-01

参考资料

  • Unicode联盟,《The Unicode Standard, Version 16.0—Chapter 9》,2024年。
  • Unicode联盟,《The Unicode Standard, Version 16.0—Chapter 3》,2024年。
  • Ebrahimkhani与Ansari,《PerSpaCor》,RANLP 2025。