暂无图片
暂无图片
5
暂无图片
暂无图片
暂无图片

官宣:Milvus 2.6引入多语言分析器,全文搜索再升级,助力业务全球化

ZILLIZ 2025-07-25
461

好消息, Milvus 全文搜索功能升级又来啦!多语言分析器(Multi-language Analyzers)正式官宣发布!

其实,早在 Milvus 2.5.0 中首次引入基于 BM25 的全文搜索时,我们就已经通过配置可自定义的文本分析器(Analyzer),来为非结构化文本提供高效、可靠的检索方式。

但我们一直觉得,搜索不能只停留在能用、可靠这个层面就此止步。

尤其是在大模型创业全球化的当下,每一个企业都有站在全球聚光灯下三分钟的机会。相应的,他们的数据基础设施,尤其是向量数据库,比如天然具备适应多语言的能力。在这一背景下,靠一个通用方案去处理所有语言,其实是不现实的。

2.5 做了个开头,现在我们继续往前走了一步——让 Milvus 在处理不同语言的文本时,能更聪明、更省事儿一点。

因此,随着 Milvus 2.6 的发布,我们对这一功能进行了二次升级,多语言分析器(Multi-language Analyzers)正式登场。

那么究竟什么场景更适合这一功能?它要如何使用?效果如何?在下文中,我们将一一为您解读。

01 

背景解读

一个通用分析器搞定一切的时代过去了

在文本搜索这件事上,无论你是走关键词路线,还是用 BM25 这类稀疏向量方法搞全文检索,分析器(Analyzer)都是绕不开的一环——它的好坏,直接决定了最终搜索效果的好坏。

而分析器(Analyzer)的职责,说简单点,就是把用户看得懂的文本,变成系统能理解的 token 序列。这中间涉及到识别语言、大小写统一、无意义词去除、词干提取、同义词扩展等等环节。

Milvus 2.6 在这方面做了不少升级。我们重新加强了 Analyzer 的能力,尤其是在多语言支持和自定义配置这两块,用户可以更自由地搭配不同的分词器和过滤器,构建适合自己业务的文本处理链路。

过去的Milvus 2.5 的分析器是个不错的起点。用户可以定义一套包含字符过滤器、分词器、token 过滤器的pipeline,用于文本的索引和搜索。对于像英语这样的单一语言,可以按空格分词、统一大小写、去掉 the is and 这类停用词等等方式构建一个标准的分词器。

但当你的文本里混进了中文、日语、韩语,情况就开始变复杂了。

其难点主要有两方面:

  1. 针对复杂语言的分词器不好找:对于中文、日语、韩文这种没有空格的语言来说,必须靠专门的分词器来智能切词。而这些分词器大多是为某一种语言设计的,想让它们同时应对多种语言,往往力不从心。

  2. 简单语言的处理规则会打架:对于英语、法语这种规则简单的语言,共用一个基础分词器问题不大,但后续的过滤规则(比如词干提取或词形还原)一旦混用,很容易出错。适用于英语的规则,套到法语上可能就南辕北辙了。

所以,如果希望靠一个通用的分析器方案搞定所有语言,很可能最后哪个语言都不满意,搜索质量整体下滑。

02 

解决方案

Milvus 2.6引入先进多语言分析器

为了应对前文所述的这些挑战,我们引入了一套新的功能

多语言分析器:一个集合,多种语言,各用各的规则

以前一个字段只能配一个分析器,现在我们可以给集合里的每种语言各配一个。比如有个评论字段,混着英文、中文和日文。现在,Milvus 能自动判断是哪种语言,然后该用英文分析器的用英文的,该用 CJK(中日韩)分析器的就用 CJK 的。每条评论按母语处理,准确度自然就上来了。

提示:这个方案目前只支持 BM25 搜索,而且需要在插入数据时提供每条数据对应的语言类型。操作方式可以是加个专门的语言字段。

语言识别分词器:自动语言检测  

语言识别分词器是一种独特的分词器,可以涵盖多种分析器配置。它可以对输入文本进行语言检测,并根据检测结果动态切换分词器,简化了多语言处理的配置。

工作原理:语言识别分词器必须配置为字典,分词器类型设置为“language_identifier”。在分词器的“analyzers”字段中,可以将多个分析器配置为映射,其中键表示分析器名称,值包含分析器参数。必须始终指定一个“默认”分析器。

检测器:目前,Milvus 支持 “whatlang” 和 “lingua” 两种检测器。Whatlang 提供更快的检测,但准确性通常低于 Lingua。默认的检测器是 whatlang,通过“identifier”字段进行配置。在分词过程中,Milvus 会选择与检测到的语言匹配的分析器。如果检测失败或不存在相应的分析器,将使用默认分析器。此外,我们还可以利用“mapping”字段将多个名称指向同一分析器。  这两种检测器支持不同的语言集。Whatlang 支持 71 种语言,而 Lingua 支持 75 种语言。

提示:语言识别过程可能会引入写操作的延迟,而且其准确性具有固有的局限性,特别是在短语或混合语言片段中,检测性能可能不尽如人意。

ICU 分词器:强大的通用后备方案

如果前两种解决方案对于实际需求来说过于复杂,Milvus 还引入了新集成的 ICU分词器。它是利用 Unicode 标准的规则来进行词语拆分的老牌库,规则写得细,支持语言多,什么日语、德语、阿拉伯语都能分得七七八八。适用于各种语言和字符集,即使单一的分词器能够同时处理多种复杂和简单的语言,尤其适用于没有专门分词器的多语言。

提示: ICU 分词器只在一个分析器内运行,也就是说所有语言将共享相同的过滤器。如果打算执行进一步的语言特定处理,例如词干提取或词形还原,那么为一种语言定义的规则很可能会与另一种语言的规则发生冲突。因此,ICU 分词器最适合作为多语言或语言识别分词器方案中的默认分析器,主要用于处理那些没有明确定义的语言。

03 

基于pymilvus 的实际效果演示

理论说完,接下来直接上代码。

下面是用 pymilvus
 构建多语言搜索集合的完整例子。我们先定义好通用的分析器配置,然后分成两个部分——一个是用多语言分析器的方式,另一个是用语言识别分词器的方式,分别演示怎么建集合、插入数据、搜索。

步骤1:配置Milvus 客户端

先初始化一下 Milvus 的连接,同时也定义好要用的集合名字。如果集合之前就存在了,我们先清掉,避免冲突。

    from pymilvus import MilvusClient, DataType, Function, FunctionType
    # 1. Setup Milvus Client
    client = MilvusClient("http://localhost:19530")
    COLLECTION_NAME = "multilingual_test"
    if client.has_collection(collection_name=COLLECTION_NAME):
        client.drop_collection(collection_name=COLLECTION_NAME)

    步骤2:为多种语言定义分析器

    在这里,我们定义了一个分析器字典。这个字典包含了各个语言特定分析器的定义。这些单独的分析器定义将在后续步骤中由多语言分析器和语言标识符分词器中有大用。

      # 2. Define analyzers for multiple languages
      # These individual analyzer definitions will be reused by both methods.
      analyzers = {
          "Japanese": { 
              # Use lindera with japanese dict 'ipadic' 
              # and remove punctuation beacuse lindera tokenizer will remain punctuation
              "tokenizer":{
                  "type""lindera",
                  "dict_kind""ipadic"
              },
              "filter": ["removepunct"]
          },
          "English": {
              # Use build-in english analyzer
              "type""english",
          },
          "default": {
              # use icu tokenizer as a fallback.
              "tokenizer""icu",
          }
      }

      步骤3A:多语言分析器实操

      本节展示了如何创建集合、插入数据以及用multi_analyzer_params进行搜索。这种方法需要在插入时通过专用字段(例如 language
      )明确提供每个文档的语言。

      (1)使用多语言分析器创建集合
        # --- Option A: Using Multi-Language Analyzer ---
        print("\n--- Demonstrating Multi-Language Analyzer ---")
        # 3A. reate a collection with the Multi Analyzer
        mutil_analyzer_params = {
            "by_field""language",
            "analyzers": analyzers,
        }
        schema = MilvusClient.create_schema(
            auto_id=True,
            enable_dynamic_field=False,
        )
        schema.add_field(field_name="id", datatype=DataType.INT64, is_primary=True)# Apply our multi-language analyzer to the 'title' field
        schema.add_field(field_name="language", datatype=DataType.VARCHAR, max_length=255, nullable = True)
        schema.add_field(field_name="text", datatype=DataType.VARCHAR, max_length=25565, enable_analyzer=True, multi_analyzer_params = mutil_analyzer_params)
        schema.add_field(field_name="text_sparse", datatype=DataType.SPARSE_FLOAT_VECTOR) # Bm25 Sparse Vector
        # add bm25 function
        text_bm25_function = Function(
            name="text_bm25",
            function_type=FunctionType.BM25,
            input_field_names=["text"],
            output_field_names=["text_sparse"],
        )
        schema.add_function(text_bm25_function)
        index_params = client.prepare_index_params()
        index_params.add_index(
            field_name="text_sparse",
            index_type="AUTOINDEX"# Use auto index for BM25
            metric_type="BM25",
        )
        client.create_collection(
            collection_name=COLLECTION_NAME,
            schema=schema,
            index_params=index_params
        )
        print(f"Collection '{COLLECTION_NAME}' created successfully.")

        (2)插入多语言分析器的数据并加载集合
          # 4A. Insert data for Multi-Language Analyzer and load collection# Insert English and Japanese movie titles, explicitly setting the 'language' field
          client.insert(
              collection_name=COLLECTION_NAME,
              data=[
                  {"text""The Lord of the Rings""language""English"},
                  {"text""Spirited Away""language""English"},
                  {"text""千と千尋の神隠し""language""Japanese"}, # This is "Spirited Away" in Japanese
                  {"text""君の名は。""language""Japanese"}, # This is "Your Name." in Japanese
              ]
          )
          print(f"Inserted multilingual data into '{COLLECTION_NAME}'.")
          # Load the collection into memory before searching
          client.load_collection(collection_name=COLLECTION_NAME)

          (3) 对多语言分析器执行搜索操作
            # 5A. Perform a full-text search with Multi-Language Analyzer# When searching, explicitly specify the analyzer to use for the query string.
            print("\n--- Search results for Multi-Language Analyzer ---")
            results_multi_jp = client.search(
                collection_name=COLLECTION_NAME,
                data=["神隠し"],
                limit=2,
                search_params={"metric_type""BM25""analyzer_name""Japanese"}, # Specify Japanese analyzer for query
                consistency_level = "Strong",
            )
            print("\nSearch results for '神隠し' (Multi-Language Analyzer):")
            for result in results_multi_jp[0]:
                print(result)
            results_multi_en = client.search(
                collection_name=COLLECTION_NAME,
                data=["Rings"],
                limit=2,
                search_params={"metric_type""BM25""analyzer_name""English"}, # Specify English analyzer for query
                consistency_level = "Strong",
            )
            print("\nSearch results for 'Rings' (Multi-Language Analyzer):")
            for result in results_multi_en[0]:
                print(result)
            client.drop_collection(collection_name=COLLECTION_NAME)
            print(f"Collection '{COLLECTION_NAME}' dropped.")

            (4)效果展示

            步骤3B:语言识别分词器实操

            本节将展示如何创建集合、插入数据以及使用 language_identifier 分词器进行搜索。这一段演示的是怎么用 language_identifier
             分词器建集合、插数据、搜内容。

            它的好处是:不用手动告诉系统这段文本是什么语言,Milvus 会自己看着办,相应的,语言字段也不是必须的,除非你自己想留个标记当元数据用。

            (1)  使用语言标识符分词器创建集合
              # --- Option B: Using Language Identifier Tokenizer ---
              print("\n--- Demonstrating Language Identifier Tokenizer ---")
              # 3A. create a collection with language identifier
              analyzer_params_langid = {
                  "tokenizer": {
                      "type""language_identifier",
                      "analyzers": analyzers # Referencing the analyzers defined in Step 2
                  },
              }
              schema_langid = MilvusClient.create_schema(
                  auto_id=True,
                  enable_dynamic_field=False,
              )
              schema_langid.add_field(field_name="id", datatype=DataType.INT64, is_primary=True)
              # The 'language' field is not strictly needed by the analyzer itself here, as detection is automatic.# However, you might keep it for metadata purposes.
              schema_langid.add_field(field_name="text", datatype=DataType.VARCHAR, max_length=25565, enable_analyzer=True, analyzer_params = analyzer_params_langid)
              schema_langid.add_field(field_name="text_sparse", datatype=DataType.SPARSE_FLOAT_VECTOR) # BM25 Sparse Vector# add bm25 function
              text_bm25_function_langid = Function(
                  name="text_bm25",
                  function_type=FunctionType.BM25,
                  input_field_names=["text"],
                  output_field_names=["text_sparse"],
              )
              schema_langid.add_function(text_bm25_function_langid)
              index_params_langid = client.prepare_index_params()
              index_params_langid.add_index(
                  field_name="text_sparse",
                  index_type="AUTOINDEX"# Use auto index for BM25
                  metric_type="BM25",
              )
              client.create_collection(
                  collection_name=COLLECTION_NAME,
                  schema=schema_langid,
                  index_params=index_params_langid
              )
              print(f"Collection '{COLLECTION_NAME}' created successfully with Language Identifier Tokenizer.")

              (2)插入语言标识符分词器的数据并加载集合
                # 4B. Insert Data for Language Identifier Tokenizer and Load Collection
                # Insert English and Japanese movie titles. The language_identifier will detect the language.
                client.insert(
                    collection_name=COLLECTION_NAME,
                    data=[
                        {"text""The Lord of the Rings"},
                        {"text""Spirited Away"},
                        {"text""千と千尋の神隠し"}, 
                        {"text""君の名は。"},
                    ]
                )
                print(f"Inserted multilingual data into '{COLLECTION_NAME}'.")
                # Load the collection into memory before searching
                client.load_collection(collection_name=COLLECTION_NAME)

                (3): 执行语言标识符分词器的搜索和清理操作
                  # 5B. Perform a full-text search with Language Identifier Tokenizer# No need to specify analyzer_name in search_params; it's detected automatically for the query.
                  print("\n--- Search results for Language Identifier Tokenizer ---")
                  results_langid_jp = client.search(
                      collection_name=COLLECTION_NAME,
                      data=["神隠し"],
                      limit=2,
                      search_params={"metric_type""BM25"}, # Analyzer automatically determined by language_identifier
                      consistency_level = "Strong",
                  )
                  print("\nSearch results for '神隠し' (Language Identifier Tokenizer):")
                  for result in results_langid_jp[0]:
                      print(result)
                  results_langid_en = client.search(
                      collection_name=COLLECTION_NAME,
                      data=["the Rings"],
                      limit=2,
                      search_params={"metric_type""BM25"}, # Analyzer automatically determined by language_identifier
                      consistency_level = "Strong",
                  )
                  print("\nSearch results for 'the Rings' (Language Identifier Tokenizer):")
                  for result in results_langid_en[0]:
                      print(result)
                  client.drop_collection(collection_name=COLLECTION_NAME)
                  print(f"Collection '{COLLECTION_NAME}' dropped.")

                  (4)效果展示



                  04 一个彩蛋

                  完整代码参考:

                  https://zilliverse.feishu.cn/wiki/UA2wwhTVxiUJsLkFFvQcvWi8njg?preview_comment_id=7530617598963564548

                  除了多语言分析器,在Milvus今年的roadmap中,围绕检索能力,我们还将提供以下功能的持续升级

                  • 高级匹配:新增 phrase_match 和 multi_match功能

                  • 分词器升级:通过扩展分词支持和增加可观察性来增强 analyzer

                  • JSON 优化:通过 JSON 索引实现高效过滤

                  • 融合标量排序:基于标量字段的结果排序

                  • 高级 Reranker:基于模型的重新排序和自定义评分函数

                  如果对以上功能感兴趣,欢迎在评论区中指出,我们将加快建设您pick的功能。


                  推荐阅读
                  90%的AI生成代码都是抄的,但Claude和Gemini连代码检索都不会做
                  Agent 还是 Workflow?其实80%的agent需求可以用Workflow搞定
                  ES vs Milvus vs PG vector :LLM时代的向量数据库选型指南

                  深度教程|Milvus + Kimi K2,打造生产级的专业问答助手



                  最后修改时间:2025-07-25 10:18:35
                  文章转载自ZILLIZ,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                  评论