Milvus
Zilliz
フロントページへ
  • ユーザーガイド
  • Home
  • Docs
  • ユーザーガイド

  • 検索

  • テキスト蛍光ペン

テキスト・ハイライターCompatible with Milvus 2.6.8+

MilvusのHighlighterは、テキストフィールドのマッチした用語をカスタマイズ可能なタグで囲み、注釈を付けます。ハイライティングは文書がマッチした理由を説明し、結果の読みやすさを向上させ、検索やRAGアプリケーションでのリッチレンダリングをサポートします。

ハイライトは、最終検索結果セットの後処理として実行されます。検索候補、フィルタリングロジック、ランキング、スコアリングには影響しません。

Highlighterは3つの独立した制御を提供します:

  • ハイライトされる用語

    ハイライトされる用語を選択できます。例えば、BM25の全文検索で使用される検索語や、テキストベースのフィルタリング式TEXT_MATCH 条件など)で指定されるクエリ語をハイライトします。

  • ハイライトされた用語の表示方法

    各マッチの前後に挿入されるタグを設定することで、マッチした用語がハイライト出力でどのように表示されるかを制御できます。たとえば、{} のような単純なマーカーや、<em></em> のような HTML タグを使用して、リッチなレンダリングを行います。

  • ハイライトされたテキストの返し方

    フラグメントの開始位置、長さ、フラグメントの数など、ハイライトした結果をフラグメントとして返す方法を制御できます。

以下のセクションでは、これらのシナリオについて説明します。

BM25 全文検索を実行すると、返された結果の検索語がハイライトされ、文書がクエリに一致する理由を説明しやすくなります。BM25 全文検索の詳細については、「全文検索」を参照してください。

このシナリオでは、ハイライトされた用語は、BM25全文検索で使用された検索用語から直接来ています。Highlighterはこれらの用語を使用して、最終結果でマッチしたテキストに注釈を付けます。

以下のコンテンツがテキスト・フィールドに保存されているとします:

Milvus supports full text search. Use BM25 for keyword relevance. Filters can narrow results.

ハイライターの設定

BM25 全文検索で検索語をハイライトするには、LexicalHighlighter を作成し、BM25 全文検索の検索語のハイライトを有効にします:

from pymilvus import LexicalHighlighter

highlighter = LexicalHighlighter(
    pre_tags=["{"],              # Tag inserted before each highlighted term
    post_tags=["}"],             # Tag inserted after each highlighted term
    highlight_search_text=True   # Enable search term highlighting for BM25 full text search
)

この例では

  • pre_tagspost_tags で、ハイライトされたテキストが出力にどのように表示されるかを制御します。この場合、マッチした語は{} でラップされます(たとえば、{term} )。複数のタグをリストとして指定することもできます (例:["<b>", "<i>"])。複数の用語がハイライトされた場合、タグは順番に適用され、マッチした順番で回転します。

  • highlight_search_text=True Milvusに、BM25全文検索の検索用語をハイライトのソースとして使用するように指示します。

Highlighterオブジェクトを作成したら、その設定をBM25全文検索リクエストに適用します:

results = client.search(
    ...,
    data=["BM25"],      # Search term used in BM25 full text search
    highlighter=highlighter # Pass highlighter config here
)

ハイライト出力

ハイライトを有効にすると、Milvusはハイライトされたテキストを専用のhighlight フィールドに返します。デフォルトでは、ハイライト出力は最初にマッチした語から始まるフラグメントとして返されます。

この例では、検索語は"BM25" であるため、返される結果の中でハイライトされています:

{
    ...,
    "highlight": {
        "text": [
            "{BM25} for keyword relevance. Filters can narrow results."
        ]
    }
}

返されるフラグメントの位置、長さ、数を制御するには、「ハイライトされたテキストをフラグメントとして返す」を参照してください。

フィルタリングにおける検索語の強調表示

検索語の強調表示に加えて、テキスト・ベースのフィルタリング式で使われる語句も強調表示できます。

現在のところ、TEXT_MATCH のフィルタリング条件のみが、クエリ用語の強調表示に対応しています。詳しくは、テキストマッチを参照してください。

このシナリオでは、強調表示される語句はテキストベースのフィルタリング式に由来します。フィルタリングはどの文書がマッチするかを決定し、ハイライターはマッチしたテキストスパンに注釈を付けます。

以下のコンテンツがテキストフィールドに格納されているとします:

This document explains how text filtering works in Milvus.

ハイライターの設定

フィルタリングで使われるクエリー用語をハイライトするには、LexicalHighlighter を作成し、フィルタリング条件に対応するhighlight_query を定義します:

from pymilvus import LexicalHighlighter

highlighter = LexicalHighlighter(
    pre_tags=["{"],              # Tag inserted before each highlighted term
    post_tags=["}"],             # Tag inserted after each highlighted term
    highlight_query=[{
        "type": "TextMatch",     # Text filtering type
        "field": "text",         # Target text field
        "text": "text filtering" # Terms to highlight
    }]
)

この構成では

  • pre_tagspost_tags は、ハイライトされたテキストが出力にどのように表示されるかを制御します。この場合、マッチした用語は{} (たとえば、{term} )でラップされます。複数のタグをリストとして指定することもできます(例:["<b>", "<i>"] )。複数の用語が強調表示される場合、タグは順番に適用され、一致する順番で回転します。

  • highlight_query は、どのフィルタリング用語をハイライトするかを定義します。

Highlighterオブジェクトが作成されたら、同じフィルタリング式とHighlighter設定を検索リクエストに適用します:

results = client.search(
    ...,
    filter='TEXT_MATCH(text, "text filtering")',
    highlighter=highlighter # Pass highlighter config here
)

出力のハイライト

フィルタリングでクエリータームのハイライトが有効になっている場合、Milvusはハイライトされたテキストを専用のhighlight フィールドに返します。デフォルトでは、ハイライト出力は最初にマッチした語から始まるフラグメントとして返されます。

この例では、最初にマッチした語は"text" であるため、ハイライトされたテキストはその位置から始まります:

{
    ...,
    "highlight": {
        "text": [
            "{text} {filtering} works in Milvus."
        ]
    }
}

返されるフラグメントの位置、長さ、数を制御するには、「ハイライトされたテキストをフラグメントとして返す」を参照してください。

フラグメントベースのハイライト出力

デフォルトでは、Milvusはハイライトされたテキストを、最初にマッチした語から始まるフラグメントとして返します。フラグメント関連の設定により、ハイライトされる単語を変更することなく、フラグメントの返され方をさらに制御することができます。

以下の内容がテキストフィールドに保存されていると仮定します:

Milvus supports full text search. Use BM25 for keyword relevance. Filters can narrow results.

ハイライターの設定

ハイライトされたフラグメントの形状を制御するには、LexicalHighlighter でフラグメント関連のオプションを設定します:

from pymilvus import LexicalHighlighter

highlighter = LexicalHighlighter(
    pre_tags=["{"],
    post_tags=["}"],
    highlight_search_text=True,
    fragment_offset=5,     # Number of characters to reserve before the first matched term
    fragment_size=60,      # Max. length of each fragment to return
    num_of_fragments=1     # Max. number of fragments to return
)

この設定では

  • fragment_offset は、ハイライトされる最初の単語の前に、先頭のコンテキストを予約します。

  • fragment_size 各フラグメントに含まれるテキストの量を制限します。

  • num_of_fragments 返されるフラグメントの数を制御します。

Highlighterオブジェクトを作成したら、検索リクエストに設定を適用します:

results = client.search(
    ...,
    data=["BM25"],
    highlighter=highlighter # Pass highlighter config here
)

ハイライト出力

フラグメントベースのハイライトを有効にすると、Milvusはハイライトされたテキストをhighlight フィールドにフラグメントとして返します:

{
    ...,
    "highlight": {
        "text": [
            "Use {BM25} for keyword relevance. Filters can narrow results."
        ]
    }
}

この出力では

  • fragment_offset が設定されているため、フラグメントは{BM25} から正確に開始しません。

  • num_of_fragments が 1 であるため、フラグメントは 1 つだけ返されます。

  • フラグメントの長さの上限はfragment_size です。

準備

蛍光ペンを使用する前に、コレクションが適切に設定されていることを確認してください。

以下の例では、BM25 全文検索とTEXT_MATCH クエリをサポートするコレクションを作成し、サンプル文書を挿入します。

コレクションの準備

from pymilvus import (
    MilvusClient,
    DataType,
    Function,
    FunctionType,
    LexicalHighlighter,
)

client = MilvusClient(uri="http://localhost:19530")
COLLECTION_NAME = "highlighter_demo"

# Clean up existing collection
if client.has_collection(COLLECTION_NAME):
    client.drop_collection(COLLECTION_NAME)

# Define schema
schema = client.create_schema(enable_dynamic_field=False)
schema.add_field(field_name="id", datatype=DataType.INT64, is_primary=True, auto_id=True)
schema.add_field(
    field_name="text",
    datatype=DataType.VARCHAR,
    max_length=2000,
    enable_analyzer=True,  # Required for BM25
    enable_match=True,     # Required for TEXT_MATCH
)
schema.add_field(field_name="sparse_vector", datatype=DataType.SPARSE_FLOAT_VECTOR)

# Add BM25 function
schema.add_function(Function(
    name="text_bm25",
    function_type=FunctionType.BM25,
    input_field_names=["text"],
    output_field_names=["sparse_vector"],
))

# Create index
index_params = client.prepare_index_params()
index_params.add_index(
    field_name="sparse_vector",
    index_type="SPARSE_INVERTED_INDEX",
    metric_type="BM25",
    params={"inverted_index_algo": "DAAT_MAXSCORE", "bm25_k1": 1.2, "bm25_b": 0.75},
)

client.create_collection(collection_name=COLLECTION_NAME, schema=schema, index_params=index_params)

# Insert sample documents
docs = [
    "my first test doc",
    "my second test doc",
    "my first test doc. Milvus is an open-source vector database built for GenAI applications.",
    "my second test doc. Milvus is an open-source vector database that suits AI applications "
    "of every size from running a demo chatbot to building web-scale search.",
]
client.insert(collection_name=COLLECTION_NAME, data=[{"text": t} for t in docs])
print(f"✓ Collection created with {len(docs)} documents\n")

# Helper for search params
SEARCH_PARAMS = {"metric_type": "BM25", "params": {"drop_ratio_search": 0.0}}

# Expected output:
# ✓ Collection created with 4 documents

この例では、BM25 全文検索で検索語を強調表示する方法を示します。

  • BM25 全文検索では、検索語として"test" を使用します。

  • ハイライトは、"test" の出現箇所をすべて{} タグで囲みます。

highlighter = LexicalHighlighter(
    pre_tags=["{"],
    post_tags=["}"],
    highlight_search_text=True,  # Highlight BM25 query terms
)

results = client.search(
    collection_name=COLLECTION_NAME,
    data=["test"],
    anns_field="sparse_vector",
    limit=10,
    search_params=SEARCH_PARAMS,
    output_fields=["text"],
    highlighter=highlighter,
)

for hit in results[0]:
    print(f"  {hit.get('highlight', {}).get('text', [])}")
print()

期待される出力

['{test} doc']
['{test} doc']
['{test} doc. Milvus is an open-source vector database built for GenAI applications.']
['{test} doc. Milvus is an open-source vector database that suits AI applications of every size from run']

例 2:フィルタリングでクエリ用語を強調表示する

この例では、TEXT_MATCH フィルタでマッチした用語を強調表示する方法を示します。

  • BM25 全文検索では、クエリ用語として"test" を使用します。

  • queries パラメーターが"my doc" をハイライトリストに追加します。

  • ハイライトは、マッチしたすべての用語 ("my","test","doc") を{ で囲みます。}

highlighter = LexicalHighlighter(
    pre_tags=["{"],
    post_tags=["}"],
    highlight_search_text=True,   # Also highlight BM25 term
    highlight_query=[                     # Additional TEXT_MATCH terms to highlight
        {"type": "TextMatch", "field": "text", "text": "my doc"},
    ],
)

results = client.search(
    collection_name=COLLECTION_NAME,
    data=["test"],
    anns_field="sparse_vector",
    limit=10,
    search_params=SEARCH_PARAMS,
    output_fields=["text"],
    highlighter=highlighter,
)

for hit in results[0]:
    print(f"  {hit.get('highlight', {}).get('text', [])}")
print()

期待される出力

['{my} first {test} {doc}']
['{my} second {test} {doc}']
['{my} first {test} {doc}. Milvus is an open-source vector database built for GenAI applications.']
['{my} second {test} {doc}. Milvus is an open-source vector database that suits AI applications of every siz']

例 3:ハイライトをフラグメントとして返す

この例では、クエリは"Milvus" を検索し、以下の設定でハイライトの断片を返します:

  • fragment_offset ハイライトされた最初のスパンの前の 20 文字までを先行コンテキストとして保持します(デフォルトは 0)。

  • fragment_size 各フラグメントを約 60 文字に制限します(デフォルトは 100)。

  • num_of_fragments テキスト値ごとに返されるフラグメントの数を制限する(デフォルトは 5)。

highlighter = LexicalHighlighter(
    pre_tags=["{"],
    post_tags=["}"],
    highlight_search_text=True,
    fragment_offset=20,  # Keep 20 chars before match
    fragment_size=60,    # Max ~60 chars per fragment
)

results = client.search(
    collection_name=COLLECTION_NAME,
    data=["Milvus"],
    anns_field="sparse_vector",
    limit=10,
    search_params=SEARCH_PARAMS,
    output_fields=["text"],
    highlighter=highlighter,
)

for i, hit in enumerate(results[0]):
    frags = hit.get('highlight', {}).get('text', [])
    print(f"  Doc {i+1}: {frags}")
print()

期待される出力

Doc 1: ['my first test doc. {Milvus} is an open-source vector database ']
Doc 2: ['my second test doc. {Milvus} is an open-source vector database']

例 4: 複数クエリの強調表示

BM25 全文検索で複数のクエリを使用して検索する場合、各クエリの結果は個別に強調表示されます。最初のクエリの結果にはその検索語のハイライトが含まれ、2 番目のクエリの結果にはその検索語のハイライトが含まれます。各クエリは同じhighlighter 設定を使用しますが、個別に適用されます。

以下の例では

  • 最初のクエリは、その結果セットで"test" をハイライトします。

  • 2番目のクエリは、その結果セットで"Milvus" をハイライトします。

highlighter = LexicalHighlighter(
    pre_tags=["{"],
    post_tags=["}"],
    highlight_search_text=True,
)

results = client.search(
    collection_name=COLLECTION_NAME,
    data=["test", "Milvus"],  # Two queries
    anns_field="sparse_vector",
    limit=2,
    search_params=SEARCH_PARAMS,
    output_fields=["text"],
    highlighter=highlighter,
)

for nq_idx, hits in enumerate(results):
    query_term = ["test", "Milvus"][nq_idx]
    print(f"  Query '{query_term}':")
    for hit in hits:
        print(f"    {hit.get('highlight', {}).get('text', [])}")
print()

期待される出力

Query 'test':
  ['{test} doc']
  ['{test} doc']
Query 'Milvus':
  ['{Milvus} is an open-source vector database built for GenAI applications.']
  ['{Milvus} is an open-source vector database that suits AI applications of every size from running a dem']

例 5: カスタム HTML タグ

ウェブUI用のHTMLセーフタグなど、任意のタグをハイライトに使用できます。これはブラウザで検索結果をレンダリングするときに便利です。

highlighter = LexicalHighlighter(
    pre_tags=["<mark>"],
    post_tags=["</mark>"],
    highlight_search_text=True,
)

results = client.search(
    collection_name=COLLECTION_NAME,
    data=["test"],
    anns_field="sparse_vector",
    limit=2,
    search_params=SEARCH_PARAMS,
    output_fields=["text"],
    highlighter=highlighter,
)

for hit in results[0]:
    print(f"  {hit.get('highlight', {}).get('text', [])}")
print()

期待される出力

['<mark>test</mark> doc']
['<mark>test</mark> doc']