使用 Milvus 2.5 開始混合語意/全文本搜尋
在這篇文章中,我們將教您如何快速使用新的全文檢索功能,並將其與傳統的以向量嵌入為基礎的語意檢索結合。
需求
首先,確保您已經安裝 Milvus 2.5:
pip install -U pymilvus[model]
並使用Milvus 文檔中的安裝指示,擁有一個運行中的 Milvus Standalone (例如:在您的本機上)。
建立資料模式和搜尋索引
我們匯入所需的類別和函式:
from pymilvus import MilvusClient, DataType, Function, FunctionType, model
您可能已經注意到 Milvus 2.5 的兩個新項目,Function
和FunctionType
,我們稍後會解釋。
接下來,我們使用 Milvus Standalone 開啟資料庫,也就是在本機建立資料模式。請注意,Milvus Lite 目前不支援全文檢索,只支援 Milvus Standalone 和 Milvus Distributed。
client = MilvusClient(uri="http://localhost:19530")
schema = client.create_schema()
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=1000, enable_analyzer=True)
schema.add_field(field_name="dense", datatype=DataType.FLOAT_VECTOR, dim=768),
schema.add_field(field_name="sparse", datatype=DataType.SPARSE_FLOAT_VECTOR)
{'auto_id': False, 'description': '', 'fields': [{'name': 'id', 'description': '', 'type': <DataType.INT64: 5>, 'is_primary': True, 'auto_id': True}, {'name': 'text', 'description': '', 'type': <DataType.VARCHAR: 21>, 'params': {'max_length': 1000, 'enable_analyzer': True}}, {'name': 'dense', 'description': '', 'type': <DataType.FLOAT_VECTOR: 101>, 'params': {'dim': 768}}, {'name': 'sparse', 'description': '', 'type': <DataType.SPARSE_FLOAT_VECTOR: 104>}], 'enable_dynamic_field': False}
您可能已經注意到enable_analyzer=True
參數。這會告訴 Milvus 2.5 在這個欄位上啟用詞彙分析器,並建立一個詞彙和詞彙頻率的列表,這是全文檢索所需要的。sparse
欄位將保存文件的向量表示,作為從解析text
產生的字元袋。
但我們如何連接text
和sparse
欄位,並告訴 Milvussparse
應如何從text
計算出來?這就是我們需要調用Function
物件並將其加入模式的地方:
bm25_function = Function(
name="text_bm25_emb", # Function name
input_field_names=["text"], # Name of the VARCHAR field containing raw text data
output_field_names=["sparse"], # Name of the SPARSE_FLOAT_VECTOR field reserved to store generated embeddings
function_type=FunctionType.BM25,
)
schema.add_function(bm25_function)
{'auto_id': False, 'description': '', 'fields': [{'name': 'id', 'description': '', 'type': <DataType.INT64: 5>, 'is_primary': True, 'auto_id': True}, {'name': 'text', 'description': '', 'type': <DataType.VARCHAR: 21>, 'params': {'max_length': 1000, 'enable_analyzer': True}}, {'name': 'dense', 'description': '', 'type': <DataType.FLOAT_VECTOR: 101>, 'params': {'dim': 768}}, {'name': 'sparse', 'description': '', 'type': <DataType.SPARSE_FLOAT_VECTOR: 104>, 'is_function_output': True}], 'enable_dynamic_field': False, 'functions': [{'name': 'text_bm25_emb', 'description': '', 'type': <FunctionType.BM25: 1>, 'input_field_names': ['text'], 'output_field_names': ['sparse'], 'params': {}}]}
Function
物件的抽象比應用全文檢索的抽象更廣泛。將來,它可能會用於一個欄位需要成為另一個欄位的函數的其他情況。在我們的案例中,我們透過函式FunctionType.BM25
來指定sparse
是text
的函式。BM25
是指資訊檢索中常用的度量,用於計算查詢與文件的相似度(相對於文件集合)。
我們使用 Milvus 的預設嵌入模型,即paraphrase-albert-small-v2:
embedding_fn = model.DefaultEmbeddingFunction()
下一步是加入我們的搜尋索引。我們有一個用於密集向量,另一個用於稀疏向量。索引類型是SPARSE_INVERTED_INDEX
與BM25
,因為全文搜尋所需的搜尋方法與標準密集向量的不同。
index_params = client.prepare_index_params()
index_params.add_index(
field_name="dense",
index_type="AUTOINDEX",
metric_type="COSINE"
)
index_params.add_index(
field_name="sparse",
index_type="SPARSE_INVERTED_INDEX",
metric_type="BM25"
)
最後,我們建立集合:
client.drop_collection('demo')
client.list_collections()
[]
client.create_collection(
collection_name='demo',
schema=schema,
index_params=index_params
)
client.list_collections()
['demo']
如此一來,我們就有了一個空的資料庫,可以接受文字文件並執行語意和全文檢索!
插入資料和執行全文檢索
插入資料與 Milvus 以前的版本沒有什麼不同:
docs = [
'information retrieval is a field of study.',
'information retrieval focuses on finding relevant information in large datasets.',
'data mining and information retrieval overlap in research.'
]
embeddings = embedding_fn(docs)
client.insert('demo', [
{'text': doc, 'dense': vec} for doc, vec in zip(docs, embeddings)
])
{'insert_count': 3, 'ids': [454387371651630485, 454387371651630486, 454387371651630487], 'cost': 0}
在進行混合搜尋之前,讓我們先說明一次全文搜尋:
search_params = {
'params': {'drop_ratio_search': 0.2},
}
results = client.search(
collection_name='demo',
data=['whats the focus of information retrieval?'],
output_fields=['text'],
anns_field='sparse',
limit=3,
search_params=search_params
)
搜索參數drop_ratio_search
指的是在搜索算法過程中要丟掉得分較低的文件的比例。
讓我們來查看結果:
for hit in results[0]:
print(hit)
{'id': 454387371651630485, 'distance': 1.3352930545806885, 'entity': {'text': 'information retrieval is a field of study.'}}
{'id': 454387371651630486, 'distance': 0.29726022481918335, 'entity': {'text': 'information retrieval focuses on finding relevant information in large datasets.'}}
{'id': 454387371651630487, 'distance': 0.2715056240558624, 'entity': {'text': 'data mining and information retrieval overlap in research.'}}
執行混合語意與全文檢索
現在讓我們結合我們所學到的知識來執行混合搜尋,將獨立的語意搜尋和全文搜尋結合起來,再加上一個reeranker:
from pymilvus import AnnSearchRequest, RRFRanker
query = 'whats the focus of information retrieval?'
query_dense_vector = embedding_fn([query])
search_param_1 = {
"data": query_dense_vector,
"anns_field": "dense",
"param": {
"metric_type": "COSINE",
},
"limit": 3
}
request_1 = AnnSearchRequest(**search_param_1)
search_param_2 = {
"data": [query],
"anns_field": "sparse",
"param": {
"metric_type": "BM25",
"params": {"drop_ratio_build": 0.0}
},
"limit": 3
}
request_2 = AnnSearchRequest(**search_param_2)
reqs = [request_1, request_2]
ranker = RRFRanker()
res = client.hybrid_search(
collection_name="demo",
output_fields=['text'],
reqs=reqs,
ranker=ranker,
limit=3
)
for hit in res[0]:
print(hit)
{'id': 454387371651630485, 'distance': 0.032786883413791656, 'entity': {'text': 'information retrieval is a field of study.'}}
{'id': 454387371651630486, 'distance': 0.032258063554763794, 'entity': {'text': 'information retrieval focuses on finding relevant information in large datasets.'}}
{'id': 454387371651630487, 'distance': 0.0317460335791111, 'entity': {'text': 'data mining and information retrieval overlap in research.'}}
您可能已經注意到了,這與具有兩個獨立語意欄位的混合搜尋(自 Milvus 2.4 起可用)沒有什麼不同。在這個簡單的範例中,結果與全文檢索相同,但對於較大的資料庫和特定關鍵字檢索,混合檢索的召回率通常較高。
總結
您現在已經具備了使用 Milvus 2.5 執行全文和混合語意/全文搜尋所需的所有知識。請參閱下列文章,以瞭解更多關於全文搜尋如何運作,以及為什麼它是語意搜尋的補充:
- 需求
- 建立資料模式和搜尋索引
- 插入資料和執行全文檢索
- 執行混合語意與全文檢索
- 總結
On This Page
Try Managed Milvus for Free
Zilliz Cloud is hassle-free, powered by Milvus and 10x faster.
Get StartedLike the article? Spread the word