Microsoft为多种语言提供分词器和词干分析器。 本主题描述如何实现和使用自定义断词器和词干还原器,以适用于超出Microsoft所提供的语言和区域设置。
注释
自定义词语分隔符暂时不可用。 2018 年 7 月,对 Windows Server 2019 进行了更改,该更改阻止了没有Microsoft签名的 DLL 被 SearchIndexer.exe加载。 此限制于 2021 年 1 月解除。
本主题按如下所示进行组织:
注册语言资源 DLL
每个语言资源 DLL 必须实现并导出以下入口点。 DLL 可以注册到任何文件夹中。
- DllMain 是 DLL 的标准入口点。
- DllRegisterServer 在注册表中注册 DLL,例如
regsvr32.exe %SystemRoot%\MyFolder\wordbreaker.dll - DllCanUnloadNow 使客户端能够通过组件对象模型(COM)调用此入口点,以确定是否可以卸载语言资源 DLL。
- DllUnRegisterServer 从注册表中删除 DLL。
注册语言
注册表包含专门用于正在编制索引的语言的条目,这些条目控制索引和查询过程中的语言特定部分。 这些注册表条目可以在以下注册表键下找到。
HKEY_LOCAL_MACHINE
SYSTEM
CurrentControlSet
ContentIndex
Control
Language
实现 Word 分词器
断字器实现 IWordBreaker。 IWordBreaker::BreakText 方法执行所有文本处理和分析。 若要实现断词组件,必须使用语言启发式。 这包括有关语法和形态的信息。 可能还需要一个字词列表来排除或包括这些字词。 从排除字词列表中生成语言区域设置的干扰词文件。 有关语言注意事项以及这些注意事项如何影响断字符实现的详细信息,请参阅 语言和 Unicode 注意事项。
IWordBreaker::BreakText 的主要用途是连续处理从 TEXT_SOURCE 提供的文本,直到所有文本处理完毕,或者直到分词器遇到错误。 在此数据处理循环中, IWordBreaker::BreakText 调用分析方法以及执行该进程的特定任务的实用工具方法。 例如,德语断字符可以处理复合词,而法语断字符可能会处理变音符或附着语素。 断词器执行的具体功能及其在执行这些任务时采用的策略完全取决于该语言的要求。
断字时,断字符识别可能具有多种表现形式的单词的“可替代的”形式。 生成的字词之间没有隐含语义关系。 事实上,原始词可能不包括在替代项列表中。 替代形式保存在索引中与原始单词相同的位置,以表明它们是相同的。
在索引中包含文档时,为每个单词分配一个整数值,该值表示偏移量或单词与文档开头的距离。 查询中单词之间的相对距离与全文索引中存储的偏移量进行比较。 查询“Where is Kyle's document”与偏移 n 处的“Where”、n+1 处的“is”、n+2 处的“Kyle”和 n+3 处的“document”匹配的任何文档。 “Kyle 的文档在数据库中的提交位置?” 表示为:
| 位置 | 是 | 凯尔·凯尔的品牌 |
文档 | 提交 | in | the | 数据库数据库 |
在此示例中,断字符在索引中存储“Kyle”(“Kyle's”)和“database”(“数据库”)的替代形式。 断字符在以下情况下产生和存储替代词:在索引创建过程中。
- 如果替代词可能在查询中作为单个单词出现
- 如果词干分析器不太可能从替代项中推导出原始词汇
生成替代词表单会增加查询表示和匹配句子的方式的数量,如以下变体所示:
- 在数据库中归档的 Kyle 文档的位置在哪里
- 凯尔在数据库中提交的文档在哪里
- Kyle 的文档在数据库中被归档的位置在哪里?
- 凯尔的文档在数据库中的存档位置
WordSink 和 PhraseSink
断字符器使用 IWordSink 和 IPhraseSink 对象来收集和存储从文本中提取的所有字词和短语。 断字符以尽可能接近文档中原始单词形式的方式存储单词。 IPhraseSink 在查询时存储短语。 短语能够提高查询结果的相关性,因为较长的词序列更罕见,并且比短小的短语更有区别性。 当索引器在查询时将短语放在 IPhraseSink 中时,它会创建断字符的实例来将短语分解为单词。 然后,索引器通过检查短语中的单词是否在索引中彼此相邻来评估该短语。 例如,如果索引中出现“ABCD”,位置 为 x、 x+1、 x+2 和 x+3,则如果在查询中提交“ABCD”的任何相邻子字符串,则短语匹配将发生。 此策略对于基于字符的断字符有效,用于在索引创建期间拆分短语和长词,并在查询期间生成短语。
休息
分隔符是单词之间的空格。 空格、标点符号、格式设置或仅语言本身的性质可能会导致中断。 索引器使用的分隔符有四种不同类型的分隔符:词尾(EOW)、句子结尾(EOS)、段落结尾(EOP)和章节结尾(EOC)。 EOW 断点是默认断点。 每个标记后,每个中断都表示两端单词之间的语义距离不同。 EOW 分隔的字词具有最紧密的语义链接,依次后跟 EOS、EOP 和 EOC。 对 IWordSink::P utBreak 的多次调用是累积的,类似于插入 null 单词或句子。
可伸缩性、性能和安全性
断词系统响应同时调用的方式在很大程度上取决于您选择的线程模型。 索引器是单线程应用程序。 要让分词器在单线程环境中发挥作用,必须使用“自由”或“双重”线程模型来编写分词器。 分词器不得使用“单元线程模型”注册到 COM。
我们建议断字器避免使用全局状态,并将数据存储到断字器的实例中。 应在断字符实现中存储的唯一内容是参数 fQuery 和 ulMaxTokenSize。 断字程序的速度不应比英语断字程序所建立的基准慢超过两倍。 断字符性能在硬件能力增强时也会有所提高。
索引器的断词器在本地系统的安全上下文中运行。 应编写代码以管理缓冲区,并实现正确的堆叠。 所有字符串副本都必须进行显式检查,以防止缓冲区溢出。 应始终验证缓冲区的分配大小,并针对缓冲区的大小测试数据的大小。 字符断错器无法假定传递给 IWordBreaker::BreakText 方法的文本是格式良好的。 有关断字符疑难解答的详细信息,请参阅 语言资源和最佳做法疑难解答。
实现词干分析器
词干分析器实现 IStemmer 接口。 IStemmer::GenerateWordForms 方法为特定输入词生成一系列偏转单词窗体。 要实现词干分析器组件,必须拥有关于该语言的启发式方法。 这包括有关形态的信息。 可能还需要一个字词列表来排除或包括这些字词。 有关语言注意事项以及这些注意事项如何影响词干分析器实现的详细信息,请参阅 语言和 Unicode 注意事项。
我们建议词干分析器不应生成属格或所有格形式。 例如,“David”不会作为“David's”的备选形式生成。在分析“David's”时,断字符会生成“David”和“David's”。
词干分析器使用 IWordFormSink 对象来收集替代词列表。 IWordFormSink::PutWord 从词干分析器生成最终单词。 在所有情况下,此最终单词与 IStemmer::GenerateWordForms 中的输入词相同。 例如,给定词“游”,词干提取器通过调用 IWordFormSink::PutAltWord 生成以下单词形式:“游泳”、“游泳者”、“游”、“游过”和“游过”。 词干分析器通过 IWordFormSink::P utWord 生成“游泳”。
可伸缩性、性能和安全性
词干分析器(如分词器)必须使用“自由”线程模型,并在使用 COM 注册时将其线程模型设置为“自由”或“两者皆可”。Windows 搜索会同时从不同线程调用词干分析器的单独实例。 因此,词干分析器应具有最少的实例数据。
词干分析器准确性对查询相关性产生重大影响。 如果词干分析器对文本进行错误的词干化处理,查询可能会返回不可预知和不准确的结果。 词干分析器每秒必须处理数百个查询,而不会对查询性能产生负面影响。 随着硬件功能的提高,词干分析器性能应有所提高。 有关词干分析器故障排除的信息,请参阅 语言资源和最佳做法疑难解答。
Windows 搜索的词干分析器在本地安全上下文中运行。 应编写代码以管理缓冲区,并实现正确的堆叠。 所有字符串副本都必须进行显式检查,以防止缓冲区溢出。 应始终验证缓冲区的分配大小,并针对缓冲区的大小测试数据的大小。
相关主题