Выделитель текстаCompatible with Milvus 2.6.8+
Выделитель в Milvus аннотирует совпадающие термины в текстовых полях, оборачивая их настраиваемыми тегами. Выделение помогает объяснить, почему документ совпадает, улучшает читаемость результатов и поддерживает богатый рендеринг в приложениях поиска и RAG.
Выделение выполняется как этап постобработки конечного набора результатов поиска. Оно не влияет на поиск кандидатов, логику фильтрации, ранжирование или оценку.
Выделитель обеспечивает три независимых измерения контроля:
Какие термины выделяются
Вы можете выбрать, откуда берутся выделенные термины. Например, выделить поисковые термины, используемые в полнотекстовом поиске BM25, или термины запроса, указанные в выражениях фильтрации на основе текста (например, условия
TEXT_MATCH).Как отображаются выделенные термины
Вы можете управлять тем, как совпавшие термины отображаются в результатах подсветки, настраивая метки, вставляемые до и после каждого совпадения. Например, используйте простые маркеры, такие как
{}, или HTML-теги, такие как<em></em>, для богатой визуализации.Как возвращается выделенный текст
Вы можете управлять тем, как выделенные результаты возвращаются в виде фрагментов, включая начало фрагментов, их длину и количество возвращаемых фрагментов.
В следующих разделах рассматриваются эти сценарии.
Выделение поисковых терминов в полнотекстовом поиске 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указывает 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 примените конфигурацию 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."
]
}
}
В этом выводе:
Фрагмент не начинается точно с
{BM25}, потому что установлено значениеfragment_offset.Возвращается только один фрагмент, потому что
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-теги
Для подсветки можно использовать любые теги, например 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']