高維向量搜索:在 Elasticsearch 8.X 中利用 dense_vector 的實戰(zhàn)探索
近年來,隨著深度學習技術的發(fā)展,向量搜索引發(fā)了人們的廣泛關注。早在 Elasticsearch在7.2.0 版本引入了dense_vector字段類型,支持存儲高維向量數(shù)據(jù),如詞嵌入或文檔嵌入,以進行相似度搜索等操作。在本文中,我將展示如何在Elasticsearch 8.X 版本中使用 dense_vector 進行向量搜索。
一、背景介紹
首先,我們需要了解一下dense_vector。dense_vector是Elasticsearch用于存儲高維向量的字段類型,通常用于神經(jīng)搜索,以便利用NLP和深度學習模型生成的嵌入來搜索相似文本。你可以在這個鏈接找到更多關于dense_vector的信息。
在接下來的部分,我將展示如何創(chuàng)建一個簡單的Elasticsearch索引,該索引包含基于文本嵌入的向量搜索功能。
二、生成向量:利用Python處理
首先,我們需要用Python和BERT模型來生成文本嵌入。以下是我們如何做到這一點的示例:
import?torch
from?transformers?import?BertTokenizer,?BertModel
tokenizer?=?BertTokenizer.from_pretrained("bert-base-uncased")
model?=?BertModel.from_pretrained("bert-base-uncased")
def?get_bert_embedding(text):
????inputs?=?tokenizer(text,?return_tensors="pt",?max_length=128,?truncation=True,?padding="max_length")
????with?torch.no_grad():
????????outputs?=?model(**inputs)
????return?outputs.last_hidden_state[:,?:3,?:].numpy()
def?print_infos():
????docs?=?["占地100畝的燒烤城在淄博僅用20天即成功新建,現(xiàn)在已成為萬人爭搶“烤位”的熱門去處。",
????????????"淄博新建的一座占地100畝的燒烤城在短短20天內建成,吸引了眾多燒烤愛好者,如今“烤位”已是一位難求。",
????????????"在淄博,一座耗時20天新建的占地100畝的燒烤城成為眾人矚目的焦點,各種美味燒烤讓萬人爭奪“烤位”,可謂一座難求。",
????????????"淄博一般指淄博市。?淄博市,簡稱“淄”,齊國故都,山東省轄地級市,Ⅱ型大城市"]
????for?doc?in?docs:
????????print(?f"Vector?for?'{doc}':",?get_bert_embedding(?doc?)?)
????
if?__name__?==?'__main__':
????print_infos()
在上述腳本中,我們定義了一個函數(shù) get_bert_embedding 來生成每個文檔的向量表示。然后,我們生成了四個不同的文檔向量,并將其輸出打印到控制臺。如下圖所示:

結果參考:
Vector?for?'占地100畝的燒烤城在淄博僅用20天即成功新建,現(xiàn)在已成為萬人爭搶“烤位”的熱門去處。':?[[[-0.2703271???0.38279012?-0.29274252?...?-0.24937081??0.7212287
????0.0751707?]
??[?0.01726123??0.1450473???0.16286954?...?-0.20245396??1.1556625
???-0.112049??]
??[?0.51697373?-0.01454506??0.1063835??...?-0.2986216???0.69151103
????0.13124703]]]
Vector?for?'淄博新建的一座占地100畝的燒烤城在短短20天內建成,吸引了眾多燒烤愛好者,如今“烤位”已是一位難求。':?[[[-0.22879271??0.43286988?-0.21742335?...?-0.22972387??0.75263715
????0.03716223]
??[?0.1252176??-0.02892866??0.17054333?...?-0.30524847??0.94903445
???-0.46865308]
??[?0.42650488??0.34019586?-0.01442122?...?-0.17345914??0.6688627
???-0.75012964]]]
三、實戰(zhàn)探索:向Elasticsearch中導入和搜索向量
3.1 創(chuàng)建索引
我們首先需要在Elasticsearch中創(chuàng)建一個新的索引來存儲我們的文檔和它們的向量表示。以下是創(chuàng)建索引的API調用:
PUT?/my_vector_index
{
??"mappings":?{
????"properties":?{
??????"title":?{
????????"type":?"text"
??????},
??????"content_vector":?{
????????"type":?"dense_vector",
????????"dims":?3
??????}
????}
??}
}
在上述代碼中,我們創(chuàng)建了一個名為 my_vector_index 的索引,并定義了兩個字段:title 和 content_vector。其中,content_vector 字段的類型被設置為 dense_vector,并指定其維度為3,這與我們前面生成的BERT向量維度一致。
3.2 導入數(shù)據(jù)
接下來,我們可以將我們的文檔及其相應的向量導入到索引中。以下是一個示例的批量導入API調用:
POST?my_vector_index/_bulk
{"index":{"_id":1}}
{"title":"占地100畝的燒烤城在淄博僅用20天即成功新建,現(xiàn)在已成為萬人爭搶“烤位”的熱門去處。","content_vector":[-0.2703271,?0.38279012,?-0.29274252]}
{"index":{"_id":2}}
{"title":"淄博新建的一座占地100畝的燒烤城在短短20天內建成,吸引了眾多燒烤愛好者,如今“烤位”已是一位難求。","content_vector":[-0.22879271,?0.43286988,?-0.21742335]}
{"index":{"_id":3}}
{"title":"在淄博,一座耗時20天新建的占地100畝的燒烤城成為眾人矚目的焦點,各種美味燒烤讓萬人爭奪“烤位”,可謂一座難求。","content_vector":[-0.24912262,?0.40769795,?-0.26663426]}
{"index":{"_id":4}}
{"title":"淄博一般指淄博市。?淄博市,簡稱“淄”,齊國故都,山東省轄地級市,Ⅱ型大城市","content_vector":["0.32247472,?0.19048998,?-0.36749798]}
在這個例子中,我們使用了Elasticsearch的_bulk 接口批量導入數(shù)據(jù)。每個文檔的數(shù)據(jù)由兩行組成:一行包含文檔的ID,另一行包含文檔的標題和內容向量。注意向量的值與我們在Python代碼中生成的值是相同的。
3.3 執(zhí)行檢索
創(chuàng)建并導入數(shù)據(jù)后,我們可以執(zhí)行一次相似性檢索。我們將使用腳本評分查詢,其中我們的評分腳本將計算查詢向量與每個文檔的內容向量之間的余弦相似度。
以下是一個API調用的例子:
GET?my_vector_index/_search
{
??"query":?{
????"script_score":?{
??????"query":?{
????????"match_all":?{}
??????},
??????"script":?{
????????"source":?"cosineSimilarity(params.query_vector,?'content_vector')?+?1.0",?
????????"params":?{
??????????"query_vector":?[-0.2703271,?0.38279012,?-0.29274252]??
????????}
??????}
????}
??}
}
在上述查詢中,我們定義了一個腳本評分查詢script_score。該查詢首先執(zhí)行一個匹配所有文檔的查詢(match_all),然后根據(jù)我們的腳本對每個文檔進行評分。
評分腳本cosineSimilarity(params.query_vector, 'content_vector') + 1.0計算查詢向量和每個文檔的content_vector字段之間的余弦相似度,并將結果加1(因為余弦相似度的范圍是-1到1,而Elasticsearch的評分必須是非負的)。
我們拿文檔1的向量作為檢索條件,執(zhí)行結果如下:

四、結語
基于向量的搜索方法正在不斷發(fā)展,Elasticsearch也在不斷改進和擴展其功能以跟上這一趨勢。
為了充分利用Elasticsearch的能力,請確保關注其官方文檔和更新,以便了解最新的功能和最佳實踐。使用dense_vector字段和相關的搜索方法,我們可以在Elasticsearch中實現(xiàn)復雜的向量搜索,為用戶提供更精確和個性化的搜索體驗。
推薦閱讀
更短時間更快習得更多干貨!
和全球?近2000+?Elastic 愛好者一起精進!
大模型時代
,
搶先
一步學習進階干貨
!
