メインコンテンツまでスキップ

Lexical Highlighter

Zilliz Cloud の Highlighter は、テキストフィールド内の一致した語句をカスタマイズ可能なタグで囲むことで注釈を付けます。ハイライトは、ドキュメントが一致する理由を説明し、結果の可読性を高め、検索や RAG アプリケーションでのリッチなレンダリングをサポートします。

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

Highlighter では、次の 3 つの独立した制御項目を提供します。

  • ハイライトする語句

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

  • ハイライトする語句のレンダリング方法

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

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

    フラグメントとして返されるハイライト結果について、フラグメントの開始位置、長さ、返される数を制御できます。

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

BM25 全文検索を実行する際に、返された結果内の検索語句をハイライトして、ドキュメントがクエリに一致した理由を説明できます。BM25 全文検索の詳細は、全文検索 を参照してください。

このシナリオでは、ハイライトされる語句は BM25 全文検索で使用される検索語句から直接取得されます。Highlighter はこれらの語句を使用して、最終結果内の一致したテキストに注釈を付けます。

テキストフィールドに次の内容が格納されているとします。

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

Highlighter 設定

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

python
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_tags と post_tags は、ハイライトされたテキストが出力でどのように表示されるかを制御します。この場合、一致した語句は {} で囲まれます(例: {term})。複数のタグをリストとして指定することもできます(例: ["<b>", "<i>"])。複数の語句がハイライトされる場合、タグは順番に適用され、一致した順序に従ってローテーションされます。

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

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

python
results = client.search(
collection_name="highlighter_demo",
data=["BM25"], # Search term used in BM25 full text search
search_params={"metric_type": "BM25"},
highlighter=highlighter # Pass highlighter config here
)

ハイライト出力

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

この例では、検索語句は "BM25" であるため、返された結果内で次のようにハイライトされます。

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

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

フィルタリングでのクエリ語句のハイライト​

検索語句のハイライトに加えて、テキストベースのフィルタリング式で使用される語句をハイライトできます。

Notes

現在、クエリ語句のハイライトでは TEXT_MATCH フィルタリング条件のみがサポートされています。詳細は、テキストマッチ を参照してください。

このシナリオでは、ハイライトされる語句はテキストベースのフィルタリング式から取得されます。フィルタリングはどのドキュメントが一致するかを決定し、Highlighter は一致したテキストの範囲に注釈を付けます。

テキストフィールドに次の内容が格納されているとします。

plaintext
This document explains how text filtering works in Milvus.

Highlighter 設定

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

python
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_tags と post_tags は、ハイライトされたテキストが出力でどのように表示されるかを制御します。この場合、一致した語句は {} で囲まれます(例: {term})。複数のタグをリストとして指定することもできます(例: ["<b>", "<i>"])。複数の語句がハイライトされる場合、タグは順番に適用され、一致した順序に従ってローテーションされます。

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

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

python
results = client.search(
collection_name="highlighter_demo",
data=["BM25"],
filter='TEXT_MATCH(text, "text filtering")',
search_params={"metric_type": "BM25"},
highlighter=highlighter # Pass highlighter config here
)

ハイライト出力

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

この例では、最初に一致した語句は "text" であるため、返されるハイライトされたテキストはその位置から始まります。

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

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

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

デフォルトでは、Zilliz Cloud は最初に一致した語句から始まるフラグメントとしてハイライトされたテキストを返します。フラグメント関連の設定を使用すると、ハイライトする語句を変更せずに、フラグメントの返却方法をさらに制御できます。

テキストフィールドに次の内容が格納されているとします。

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

Highlighter 設定

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

python
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 オブジェクトを作成したら、Highlighter 設定を検索リクエストに適用します。

python
results = client.search(
collection_name="highlighter_demo",
data=["BM25"],
search_params={"metric_type": "BM25"},
highlighter=highlighter # Pass highlighter config here
)

ハイライト出力

フラグメントベースのハイライトが有効な場合、Zilliz Cloud は highlight フィールドにハイライトされたテキストをフラグメントとして返します。

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

この出力では:

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

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

  • フラグメントの長さは fragment_size によって上限が設定されます。

例​

事前準備​

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

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

コレクションを準備する
python
from pymilvus import (
MilvusClient,
DataType,
Function,
FunctionType,
LexicalHighlighter,
)

client = MilvusClient(uri="YOUR_CLUSTER_ENDPOINT")
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" を検索語句として使用します。

  • Highlighter は、"test" のすべての出現箇所を { タグと } タグで囲みます。

python
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', {}).get('fragments', [])}")
print()
期待される出力
plaintext
['{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" をハイライトリストに追加します。

  • Highlighter は、一致したすべての語句("my"、"test"、"doc")を { と } で囲みます。

python
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', {}).get('fragments', [])}")
print()
期待される出力
plaintext
['{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)。

python
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', {}).get('fragments', [])
print(f" Doc {i+1}: {frags}")
print()
期待される出力
plaintext
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 全文検索で複数のクエリを使用して検索する場合、各クエリの結果は独立してハイライトされます。1 つ目のクエリの結果にはその検索語句のハイライトが含まれ、2 つ目のクエリの結果にはその検索語句のハイライトが含まれます。以下同様です。各クエリは同じ highlighter 設定を使用しますが、それぞれ独立して適用します。

次の例では:

  • 1 つ目のクエリは、結果セット内の "test" をハイライトします。

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

python
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', {}).get('fragments', [])}")
print()
期待される出力
plaintext
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 タグ​

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

python
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', {}).get('fragments', [])}")
print()
期待される出力
plaintext
['<mark>test</mark> doc']
['<mark>test</mark> doc']