Milvus 3.0 开源解读|自定义词典如何优化BM25 与Text Match 的专业词理解能力

2026-08-122 分钟阅读

搜“iPhone 15 Pro Max”,找到的却是iPhone 15 vs HUAWEI Mate 80 Pro Max的文章;搜“odsseia”,结果漏掉了一大批关键词是“Odyssey”这样其实是同一指代但拼写变体的内容。

在做搜索业务时,类似上文的这种误召、漏召经历,其实并不罕见。这时候,很多人第一反应是调 BM25 参数、改匹配条件、换 embedding,甚至再上一层 reranker。

但在检索系统中,原始文本其实不会直接进入 BM25 或 text match。它会先经过 analyzer,被转换成 token,再进入倒排索引和后续的匹配、统计与打分。

过程中,如果词项切错了、漏掉了,或者包含太多噪声,后面的打分公式再精细,也是在错误的基础上计算相关性。

也就是说,如果词表存在缺陷,那么整套检索系统从源头就无法准确识别业务场景里的核心实体与概念,后续再多优化都无济于事。

自定义词典的价值就在这里。它能告诉搜索系统:哪些字符串代表完整的业务概念,哪些应该拆开,哪些应该忽略,哪些表达等价,哪些概念可以扩展。

自定义词典,如何影响 BM25 与Text Match

词表治理是影响 BM25 与Text Match 表现的根基。

通用分词器在处理专业术语或复合短语(如“语义搜索”、“全文检索”“向量数据库”)时,经常会将其拆解为普通基础词。这种切割不仅破坏了底层的词项(Token)边界,也会同时导致 BM25 评分偏离和 Text Match 召回失控。

比如对BM25 来说,其词频(TF)、逆文档频率(IDF)和文档长度评分完全依赖词项统计。一旦分词粒度出现偏差,统计数据就会失真。

以“语义搜索”为例:分词把它拆成 “语义”和“搜索”两个单独的词本身没有太大问题,但如果没有把 “语义搜索” 当成一个完整固定短语,并给予更高权重。那系统检索的时候,只要文章里带 “搜索” 二字,比如讲搜索接口、搜索日志的普通内容,都会因为高频匹配拿到很高分数。反倒那些真正专门讲解语义搜索本身的专业文章,专属特征被淹没在海量泛结果里,权重被稀释,导致排名靠后很难被搜到。

在医疗(药品名、疾病名)、金融(指标术语、监管术语)、电商(规格型号)及企业知识库(API 名、算法名、内部系统名)等场景中,这种失真尤为明显。自定义词典能够将专业词汇锁定为独立的统计单元,使 BM25 的 TF/IDF 计算完全基于业务语义,而非零散的字符。

而对Text Match 来说,很多人会以为 text match 是简单的字符串包含或完全匹配,所以不太需要词典。但实际上,Text match 也是基于词项工作的:查询文本会先被切成 token,再用这些 token 去匹配倒排索引,且任意token相同就算作有效的匹配,如果词项边界不清晰,召回范围就会偏离预期。

例如搜索“全文检索”时,若被切分为“全文”和“检索”,系统就会错误捞出“全文报告生成”或“日志检索接口”等文档。这些结果虽然凑巧包含了字符碎片,但与搜索意图无关。

这种情况下,自定义词典的作用在于固定 Token 边界,让“全文检索”、“向量数据库”、“权限模板”等专有名词成为明确的单个匹配单元。这能让文本匹配摆脱检索字词的某种组合。

(至于词语之间的顺序与邻近关系,那是后续 Phrase Match短语匹配解决的问题,自定义词典解决的是更上游的词项边界问题。)

词表治理时,如何控制平衡泛化与精准

不论BM25还是文本匹配,表面上处理 token,但真正寻找的是文本背后的概念。但token 与概念并不总是一一对应:同一个概念可能被拆成多个 token,多个 token 也可能组合成一个更具体的概念。

这就导致,词表治理容易陷入两个极端。

一种倾向是认为 token 越多越好,以为更多 token 能带来更强的泛化和联想能力。但代价是存储、索引和搜索开销同步上升:token 越多,倒排索引中的词项和 posting list 越多,写入、索引构建、查询匹配与打分需要处理的数据都会增加。

另一种倾向是过度压缩 token 数量。搜索变快、存储变少,但联想能力下降:查询一个宽泛概念时,系统无法召回那些只在更具体概念中出现的文档。

真实业务中,我们通常同时需要在两者之间取个平衡。企业搜索、电商搜索、技术文档检索中,有些地方需要联想,例如输入“检索”时希望也找到“搜索”;有些地方需要精准,例如搜索“向量数据库”时,不能被大量只含“向量”或“数据库”的文档淹没。

所以,自定义词典不是简单地“多加词”。搜索系统需要精准区分这是“一个完整的技术概念”和“两个词刚好都出现过”,然后控制当前场景下哪些地方需要泛化,哪些地方需要精准;哪些概念应该被拆开,哪些概念应该被组合并保留下来;以及哪些概念应该被无效化、等价化,或者只做单向扩展。

在实践中,不同语言的边界不同,不同业务场景关注的概念也不同,自定义词典需要根据实际情况做灵活变通。

中文场景:解决概念发现问题

中文文本没有天然的空格边界,所以搜索首先要解决“从连续文本里发现 token”的问题。没有词典,系统很难判断“向量数据库”是一个完整概念,还是“向量”和“数据库”两个词刚好连续出现。

Milvus 使用的中文分词能力已经带有默认词典,可以覆盖通用场景里的常见词。但默认词典不会天然知道公司产品名、内部项目名、医学术语、金融产品、商品型号、技术缩写,也很难及时覆盖新出现的专业词汇。

这就是中文自定义词典最基础的作用:补充更贴近业务场景的词汇表,让专业概念能够被正确发现。

另外,中文概念还常有多级组合关系:从“向量”到“向量数据库”,再到“分布式向量数据库”。如果希望保留多粒度召回,可以使用更偏泛化的分词模式,让组合概念和子概念都进入索引;如果更关注精确和速度,可以使用更少泛化的模式,减少 token 数量。这时就更依赖自定义词典保证关键领域词能被正确提取。

英文和法语:处理复合词和专业词组

如果说中文自定义词典更多是在做“概念发现”,那么英文、法语里的这些词典更多是在已有 token 边界上做“概念拆分”和“概念组合”。

英文、法语等语言通常可以通过空格和标点完成基础 token 发现。再进一步,还可以通过词干提取或词形归一化,让 runrunsrunning 这类词在概念上靠近。

但这并不意味着这类语言不需要自定义词典。英文里有大量复合词和专业环境下的固定词组:有些 token 太粗,需要拆开;有些连续 token 单独看都很普通,组合起来才是专业概念。

  • decompounder. 用于拆分复合词,把过粗的 token 拆成更小概念。例如技术文档、商品描述、内部命名里常见的复合写法,如果不拆开,搜索组成部分时就可能丢召回。
  • phrase_dictionary . 即将支持的词组词典,用于把词典中声明的连续 token 组合成稳定概念。它适合产品名、专业术语、专有名词,以及不希望被过度泛化的固定表达。

跨语言通用词典:停用词与同义词

除了语言本身带来的差异,还有一些词典场景几乎适用于所有语言。它们不一定改变基础分词,但会决定哪些概念应该进入检索,哪些概念应该被忽略,哪些概念应该被扩展。

  • stop words. 用于去掉没有检索价值,或在当前 collection 中区分度太低的概念。除了通用虚词,企业文档里的“系统”“平台”“服务”“模块”这类高频模板词,也可能在特定场景中成为噪声。
  • synonym. 用于处理相同含义的不同表达,或者需要单向扩展的上下位概念。比如“搜索”和“检索”可以视为等价;某些场景下,搜索上位概念希望召回下位概念内容,但搜索下位概念时不希望反向扩展到所有上位内容。

实际使用中,我们可以将几种自定义词典组合使用:领域词典负责发现和保留专业概念,decompounder 和 phrase_dictionary 分别处理拆分与组合,stop words 降低噪声,synonym 补足表达差异和概念引申。

词典为什么必须成为一个独立的能力

当词典只有三五个词时,把它写在配置里似乎也可以。但真实系统里的词典通常不是这样。

一个企业知识库可能有几千个内部术语。一个电商系统可能有几十万个品牌、型号、规格和别名。一个医疗搜索系统可能需要维护大量药品名、疾病名和检查项目。一个技术文档系统可能持续增加新的 API、参数、错误码和组件名。

这些词表会变化。新产品发布、文档改版、业务线合并、术语标准化,都会带来词典更新。

所以,自定义词典更自然的形态是文件,而不是几行内联配置。

文件有几个优势:

  • 可以批量维护大量词条。
  • 可以由搜索团队、业务团队、数据团队共同维护。
  • 可以进入版本管理和审查流程。
  • 可以在多个 collection 或应用之间复用。
  • 可以独立测试、灰度和回滚。

把词典当成文件,也意味着我们承认它是检索质量的一部分。它和 embedding model、index 参数、reranker 一样,都会影响最终搜索体验。

也正因为词典是业务资产,最终需要被稳定分发、版本化、复用和保护,在分布式系统中,如何做好这一点,就变得尤为重要。

如何在单机与分布式系统中使用自定义词典?

单机或共享存储下使用自定义词典

最简单的使用方式,是让 Milvus 读取本地词典文件。

本地文件模式适合两类场景:单机 Milvus,或者所有相关节点都能访问同一份共享磁盘、共享文件系统的部署。在这些场景里,文件路径本身就是稳定的,Milvus 进程看到的是同一份词典文件。

使用时,只用准备词典文件,置于 Milvus 进程可访问的路径,然后在 collection 的文本字段配置中引用即可。

例如,一个 jieba 自定义词典可以包含:

Plaintext
向量数据库
语义搜索
全文检索
混合搜索

字段配置引用后,相关文本进入索引和查询时,这些领域词便可以作为稳定的检索单元参与 BM25 或文本匹配。

停用词文件也类似:

Plaintext
的
是
在
了
和

同义词文件可以维护查询表达和文档表达之间的映射,例如:

Plaintext
搜索, 检索, 查询
向量, 矢量, vector
删除, 移除, drop
红色,红 => 玫瑰红,蔷薇红 //搜索红色时可以搜索对应的扩展色,但是搜索具体扩展色时不会扩展到宽泛的红色。

只要路径稳定、文件可见性一致,本地文件就是最直接的使用方式。

本地文件在分布式环境中的局限

一旦进入无共享文件系统、也无统一资源分发机制的分布式环境,本地文件会迅速变为运维问题。

Milvus 集群包含多个进程,查询、建索引、导入、compaction 等阶段可能在不同节点执行。若 collection 依赖某词典文件,那么所有相关节点需要看到同一份文件,这带来几个实际问题。

  • 文件分发困难. 需要确保每个 QueryNode、DataNode 或相关组件上都有同样的文件。
  • 路径容易不一致. 某个节点上的路径是 /data/dicts/domain.txt,另一个节点可能没有这个目录。
  • 扩缩容会引入新节点. 新节点启动后,如果没有提前准备词典文件,就可能无法正确处理依赖该词典的 collection。
  • 容器和本地盘并不总是稳定. 重启、迁移、镜像更新、本地目录清理,都可能让文件丢失。
  • 生命周期不可控. 如果某个 collection 已经依赖一份词典,人工删除或替换本地文件可能导致线上行为变化,但系统本身并不知道这个依赖关系。
  • 权限和审计困难. 谁可以添加词典?谁可以删除词典?哪些 collection 正在使用它?如果只靠手工拷贝文件,这些问题很难管理。

也就是说,本地文件只适合单机或共享磁盘场景;但在普通分布式部署里,它不是理想的资源分发方式。

分布式环境中使用File Resource做集群级的文件管理

为从根本上解决上述问题,Milvus 引入 file resource 概念。它不是专为某种 analyzer 或词典设计,而是 Milvus 管理外部文件的通用机制。

File resource 可以理解为 Milvus 认识的一份外部文件。文件本身放在对象存储中,Milvus 保存它的资源名、存储路径和元数据,并负责把它同步或下载到需要使用它的节点上。

这带来的变化是:配置不再直接依赖某台机器上的本地路径,而是引用一个由 Milvus 管理的资源。文件内容本身可以是词典,也可以是后续其他需要由集群统一管理的文件;file resource 关心的是“这份文件如何被 Milvus 识别、分发和保护”。

Plaintext
resource_name = shared_text_assets
file_name = resource.txt

而不是每个节点上的具体本地路径。

注册成 file resource 后,Milvus 可以管理这份文件的元数据、分发、缓存和生命周期。节点可以在需要时同步或下载文件。创建 collection 时,Milvus 可以验证资源是否存在,并记录 collection 对资源的引用。资源被 collection 使用时,系统可以阻止误删。

这正是本地文件模式缺失的部分。

File resource 带来的不是一个新的分词能力,而是一套更可靠的资源管理方式,让 Milvus 集群能更清晰的认识并管理的资源:

  • 文件集中存放在对象存储。
  • Milvus 通过资源名管理文件。
  • 节点自动同步或按需下载。
  • collection 记录自己依赖的资源。
  • 被使用中的资源不能被误删。
  • 资源的添加、删除、查看可以进入权限体系。

对使用 Milvus 的团队来说,这意味着 jieba 自定义词典、停用词表、同义词表、复合词拆分词表这类文件,都可以集中放在对象存储里,通过资源名被 collection 引用,并由 Milvus 负责把文件分发到需要它的节点上。查询、索引构建、导入、compaction 等流程看到的都是同一份受管理的词典,而不是各个节点上手工维护的本地文件。

更重要的是,file resource 也为词典的后续演进留下了空间。词典既然是业务资产,就一定会更新:新产品名会加入,旧术语会下线,同义词关系会调整,停用词也会随着数据变化而变化。未来可以在 file resource 的基础上,通过 alter collection 修改 collection 引用的 file resource,实现词典版本替换

再进一步,file resource 本身也可以引入版本管理,让团队更清楚地知道某个 collection 正在使用哪一版词典,并支持更安全的灰度、回滚和审计。

小结

对 BM25 与文本匹配而言,词项质量是影响其表现的关键一环,通过自定义词典,我们可以让 Milvus 更懂你的业务文本。

具体选型时,我们可以使用本地文件应对单机或共享存储场景;当集群需要自主管理文件分发、验证和生命周期时,file resource 是更合适的机制。它可以将词典文件变为集群级资源,使自定义词典在分布式 Milvus 中稳定、可控地运行。

AI Assistant