텍스트 하이라이터Compatible with Milvus 2.6.8+
Milvus의 하이라이터는 텍스트 필드에서 일치하는 용어를 사용자 지정 가능한 태그로 감싸서 주석을 달 수 있습니다. 하이라이팅은 문서가 일치하는 이유를 설명하고, 결과 가독성을 높이며, 검색 및 RAG 애플리케이션에서 풍부한 렌더링을 지원하는 데 도움이 됩니다.
강조 표시는 최종 검색 결과 세트의 후처리 단계로 실행됩니다. 후보 검색, 필터링 로직, 순위 또는 채점에는 영향을 미치지 않습니다.
하이라이터는 세 가지 독립적인 차원의 제어 기능을 제공합니다:
강조 표시되는 용어
강조 표시되는 용어의 출처를 선택할 수 있습니다. 예를 들어, BM25 전체 텍스트 검색에 사용되는 검색어 또는 텍스트 기반 필터링 표현식 (예:
TEXT_MATCH조건)에 지정된 쿼리 용어를 강조 표시할 수 있습니다.강조 표시된 용어가 렌더링되는 방식
각 검색어 전후에 삽입되는 태그를 구성하여 일치하는 용어가 강조 표시 출력에 표시되는 방식을 제어할 수 있습니다. 예를 들어
{}같은 간단한 마커나<em></em>같은 HTML 태그를 사용하여 리치 렌더링할 수 있습니다.강조 표시된 텍스트가 반환되는 방식
조각이 시작되는 위치, 길이, 반환되는 조각 수 등 강조 표시된 결과가 조각으로 반환되는 방식을 제어할 수 있습니다.
다음 섹션에서는 이러한 시나리오에 대해 설명합니다.
BM25 전체 텍스트 검색에서 검색어 강조 표시하기
BM25 전체 텍스트 검색을 수행할 때 반환된 결과에서 검색어를 강조 표시하여 문서가 쿼리와 일치하는 이유를 설명하는 데 도움을 줄 수 있습니다. BM25 전체 텍스트 검색에 대해 자세히 알아보려면 전체 텍스트 검색을 참조하세요.
이 시나리오에서 강조 표시된 용어는 BM25 전체 텍스트 검색에 사용된 검색어에서 직접 가져온 것입니다. 하이라이터는 이러한 용어를 사용하여 최종 결과에서 일치하는 텍스트에 주석을 달 수 있습니다.
다음 콘텐츠가 텍스트 필드에 저장되어 있다고 가정합니다:
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_tags과post_tags은 강조 표시된 텍스트가 출력에 표시되는 방식을 제어합니다. 이 경우 일치하는 용어는{}(예:{term})로 래핑됩니다. 여러 개의 태그를 목록으로 제공할 수도 있습니다(예:["<b>", "<i>"]). 여러 용어가 강조 표시되면 태그가 순서대로 적용되고 일치 순서에 따라 회전합니다.highlight_search_text=True는 밀버스에게 BM25 전체 텍스트 검색의 검색어를 강조 표시된 용어의 소스로 사용하도록 지시합니다.
하이라이터 개체가 생성되면 해당 구성을 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_tags및post_tags은 강조 표시된 텍스트가 출력에 표시되는 방식을 제어합니다. 이 경우 일치하는 용어는{}(예:{term})로 래핑됩니다. 여러 개의 태그를 목록으로 제공할 수도 있습니다(예:["<b>", "<i>"]). 여러 개의 용어가 강조 표시되면 태그가 순서대로 적용되고 일치 순서에 따라 회전합니다.highlight_query는 강조 표시할 필터링 용어를 정의합니다.
하이라이터 개체가 생성되면 동일한 필터링 표현식과 하이라이터 구성을 검색 요청에 적용합니다:
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반환되는 조각 수를 제어합니다.
하이라이터 객체가 생성되면 검색 요청에 하이라이터 구성을 적용합니다:
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이기 때문에 하나의 조각만 반환됩니다.조각의 길이는
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
예 1: BM25 전체 텍스트 검색에서 검색어 강조 표시하기
이 예에서는 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 전체 텍스트 검색에서 여러 쿼리로 검색할 경우 각 쿼리의 결과가 독립적으로 강조 표시됩니다. 첫 번째 쿼리의 결과에는 해당 검색어에 대한 하이라이트가 포함되고, 두 번째 쿼리의 결과에는 해당 검색어에 대한 하이라이트가 포함되는 등의 방식입니다. 각 쿼리는 동일한 highlighter 구성을 사용하지만 독립적으로 적용됩니다.
아래 예시에서는
첫 번째 쿼리는 결과 집합에서
"test"을 강조 표시합니다.두 번째 쿼리는 결과 집합에서
"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']