珠海網(wǎng)站建設(shè)優(yōu)化推廣班級(jí)優(yōu)化大師官網(wǎng)
Elasticsearch 是一款功能強(qiáng)大的開(kāi)源搜索引擎,可用于全文搜索、分析和數(shù)據(jù)可視化。傳統(tǒng)上,Elasticsearch 以其執(zhí)行基于關(guān)鍵字/詞匯的搜索的能力而聞名,其中文檔基于精確或部分關(guān)鍵字匹配進(jìn)行匹配。然而,Elasticsearch 已經(jīng)發(fā)展到支持語(yǔ)義搜索 —— 一種專(zhuān)注于理解單詞和短語(yǔ)背后的含義,而不僅僅是匹配關(guān)鍵字的方法。
Elasticsearch 中的語(yǔ)義搜索可實(shí)現(xiàn)更直觀和上下文感知的搜索體驗(yàn),即使查詢(xún)中沒(méi)有精確的關(guān)鍵字,也可以找到相關(guān)信息。本文將探討如何在 Elasticsearch 中實(shí)現(xiàn)語(yǔ)義搜索、其優(yōu)勢(shì)和實(shí)際用例。
語(yǔ)義搜索
語(yǔ)義搜索是一種超越傳統(tǒng)基于關(guān)鍵字的搜索的技術(shù),它考慮了搜索查詢(xún)的上下文、意圖和含義。與專(zhuān)注于文字匹配的關(guān)鍵字搜索不同,語(yǔ)義搜索了解單詞和概念之間的關(guān)系,從而實(shí)現(xiàn)更準(zhǔn)確、更相關(guān)的搜索結(jié)果。
例如,在基于關(guān)鍵字的搜索中,查詢(xún) “l(fā)aptop battery life” 可能會(huì)返回包含這些確切單詞的文檔。但是,語(yǔ)義搜索可能會(huì)返回討論相關(guān)概念的文檔,例如 “l(fā)ong-lasting laptops”、“energy-efficient devices”,甚至 “portable computers with extended battery life.”。
Elasticsearch 如何支持語(yǔ)義搜索
Elasticsearch 通過(guò)多種技術(shù)組合支持語(yǔ)義搜索,包括:
- 向量表示:使用預(yù)訓(xùn)練模型(如 BERT(來(lái)自 Transformers 的雙向編碼器表示))將文本轉(zhuǎn)換為可捕獲語(yǔ)義含義的密集向量嵌入。
- 相似度評(píng)分:測(cè)量查詢(xún)向量和文檔向量之間的相似度,以根據(jù)語(yǔ)義相關(guān)性對(duì)搜索結(jié)果進(jìn)行排名。
- 自定義分析器:創(chuàng)建自定義標(biāo)記器、過(guò)濾器和分析器,以增強(qiáng)語(yǔ)義理解的方式預(yù)處理文本數(shù)據(jù)。
- 與機(jī)器學(xué)習(xí)模型集成:利用與 Elasticsearch 集成的機(jī)器學(xué)習(xí)模型執(zhí)行實(shí)體識(shí)別、情感分析等任務(wù)
架構(gòu) —— 使用 Elasticsearch 進(jìn)行語(yǔ)義搜索
Elasticsearch 中兩個(gè)非常重要的概念是文檔和索引。
文檔
文檔是字段及其相關(guān)值的集合。每個(gè)文檔都是一個(gè) JSON 對(duì)象,其中包含結(jié)構(gòu)化格式的數(shù)據(jù)。例如,代表一本書(shū)的文檔可能包含標(biāo)題、作者和出版日期等字段。
索引
索引是文檔的集合,以高度優(yōu)化的格式存儲(chǔ),旨在執(zhí)行高效搜索。索引類(lèi)似于關(guān)系數(shù)據(jù)庫(kù)中的表,但它們更靈活,可以存儲(chǔ)復(fù)雜的數(shù)據(jù)結(jié)構(gòu)。
要使用 Elasticsearch,你需要將數(shù)據(jù)組織成文檔,然后將所有文檔添加到索引中。這使 Elasticsearch 能夠根據(jù)搜索查詢(xún)高效地搜索和檢索相關(guān)文檔。
在 Elasticsearch 中實(shí)現(xiàn)語(yǔ)義搜索
1. 設(shè)置 Elasticsearch
首先,確保你已啟動(dòng)并運(yùn)行 Elasticsearch。你可以通過(guò)啟動(dòng) Elasticsearch 的 Docker 容器來(lái)遠(yuǎn)程連接到 elasticsearch:
docker run -it \--rm \--name elasticsearch \-p 9200:9200 \-p 9300:9300 \-e "discovery.type=single-node" \-e "xpack.security.enabled=false" \docker.elastic.co/elasticsearch/elasticsearch:8.4.3
2.?數(shù)據(jù)加載和預(yù)處理
在此步驟中,我們將加載 documents.json 文件并對(duì)其進(jìn)行預(yù)處理,以使層次結(jié)構(gòu)扁平化,使其適合Elasticsearch。documents.json文件包含課程列表,每個(gè)課程都有一個(gè)文檔列表。我們將提取每個(gè)文檔并向其中添加一個(gè)課程字段,指示它屬于哪個(gè)課程。
import jsonwith open('documents.json', 'rt') as f_in:docs_raw = json.load(f_in)
Elasticsearch 要求所有內(nèi)容都處于同一層次結(jié)構(gòu)中,在本例中,我們有兩個(gè)層次,course 和 documents:
documents = []for course_dict in docs_raw:for doc in course_dict['documents']:doc['course'] = course_dict['course']documents.append(doc)documents[1]
#Output
{'text': 'GitHub - DataTalksClub data-engineering-zoomcamp#prerequisites','section': 'General course-related questions','question': 'Course - What are the prerequisites for this course?','course': 'data-engineering-zoomcamp'}
3.?使用預(yù)訓(xùn)練模型創(chuàng)建嵌入
要執(zhí)行語(yǔ)義搜索,我們需要將文檔轉(zhuǎn)換為密集向量(嵌入),以捕獲文本的語(yǔ)義含義。我們將使用來(lái)自 Sentence Transformers 庫(kù)的預(yù)訓(xùn)練模型來(lái)生成這些嵌入。然后將這些嵌入編入 Elasticsearch 索引。這些嵌入使我們能夠執(zhí)行語(yǔ)義搜索,其目標(biāo)是找到與給定查詢(xún)上下文相似的文本。
文本和問(wèn)題字段是包含主要信息的實(shí)際數(shù)據(jù)字段,而其他字段(如 section 和 course)則更具分類(lèi)性,信息量較少,無(wú)法創(chuàng)建有意義的嵌入。
- 安裝 sentence_transformers 庫(kù)。
- 加載預(yù)訓(xùn)練模型并使用它來(lái)為我們的文檔生成嵌入。
from sentence_transformers import SentenceTransformer
model = SentenceTransformer("all-mpnet-base-v2")#created the dense vector using the pre-trained model
operations = []
for doc in documents:# Transforming the title into an embedding using the modeldoc["text_vector"] = model.encode(doc["text"]).tolist()operations.append(doc)
4. 連接到 Elasticsearch
在此步驟中,我們將建立與 Elasticsearch 實(shí)例的連接。確保 Elasticsearch 正在運(yùn)行。
from elasticsearch import Elasticsearch# Connect to the Elasticsearch instance
es_client = Elasticsearch('http://localhost:9200')
# Check the connection
print(es_client.info())
5. 創(chuàng)建映射和索引
我們將定義映射并在 Elasticsearch 中創(chuàng)建索引,生成的嵌入也將存儲(chǔ)在其中。
映射是指定如何在 Elasticsearch 中構(gòu)建和索引文檔及其字段的過(guò)程。每個(gè)文檔由各種字段組成,每個(gè)字段都分配有特定的數(shù)據(jù)類(lèi)型。
與數(shù)據(jù)庫(kù)模式類(lèi)似,映射概述了文檔的結(jié)構(gòu),詳細(xì)說(shuō)明了字段、它們的數(shù)據(jù)類(lèi)型(例如字符串、整數(shù)或日期)以及如何索引和存儲(chǔ)這些字段。
通過(guò)定義文檔和索引,我們確保索引就像書(shū)中的目錄一樣,有助于高效搜索。
index_settings = {"settings": {"number_of_shards": 1,"number_of_replicas": 0},"mappings": {"properties": {"text": {"type": "text"},"section": {"type": "text"},"question": {"type": "text"},"course": {"type": "keyword"},"text_vector": {"type": "dense_vector", "dims": 768, "index": True, "similarity": "cosine"},}}
}index_name = "course-questions"
# Delete the index if it exists
es_client.indices.delete(index=index_name, ignore_unavailable=True)
# Create the index
es_client.indices.create(index=index_name, body=index_settings)
6. 將文檔添加到索引
然后,我們將預(yù)處理后的文檔及其嵌入添加到 Elasticsearch 索引中。這使得 Elasticsearch 能夠有效地存儲(chǔ)和管理文檔,從而實(shí)現(xiàn)快速準(zhǔn)確的搜索查詢(xún)。
for doc in operations:try:es_client.index(index=index_name, document=doc)except Exception as e:print(e)
7. 查詢(xún)搜索引擎
當(dāng)用戶(hù)輸入搜索查詢(xún)時(shí),它會(huì)被轉(zhuǎn)換為嵌入并在 Elasticsearch 索引中進(jìn)行搜索。結(jié)果會(huì)根據(jù)其與查詢(xún)的相關(guān)性進(jìn)行評(píng)分。
search_term = "windows or mac?"
vector_search_term = model.encode(search_term)query = {"field": "text_vector","query_vector": vector_search_term,"k": 5,"num_candidates": 10000,
}
res = es_client.search(index=index_name, knn=query, source=["text", "section", "question", "course"])
res["hits"]["hits"]
執(zhí)行關(guān)鍵字搜索和高級(jí)搜索(過(guò)濾結(jié)果)
只要你直接使用用戶(hù)輸入并將該信息傳遞到你的搜索功能中,這就變成了關(guān)鍵字搜索。
response = es_client.search(index=index_name,query={"bool": {"must": {"multi_match": {"query": "windows or python?", "fields": ["text", "question","course","title"],"type": "best_fields"}},"filter": {"term": {"course": "data-engineering-zoomcamp"}}}}
)
執(zhí)行語(yǔ)義搜索和高級(jí)搜索
為了讓 Elasticsearch 執(zhí)行語(yǔ)義搜索,我們應(yīng)該傳遞從最終用戶(hù)那里收到的信息并將其轉(zhuǎn)換為向量嵌入,并且該向量嵌入是傳遞到搜索函數(shù)中的向量嵌入。
knn_query= {"field": "text_vector","query_vector":vector_search_term,"k": 5,"num_candidates" : 10000
}
response=es_client.search(index=index_name,query={"match": {"course": "data-engineering-zoomcamp"},},knn=knn_query,size=5,explain=True)
以下是主要步驟的簡(jiǎn)要介紹:
將從最終用戶(hù)收到的搜索詞轉(zhuǎn)換為向量嵌入。
- 將此向量嵌入傳遞到高級(jí)語(yǔ)義搜索函數(shù)中。
- 將結(jié)果限制在特定部分,在本例中為 “General course-related questions”。同樣,它可以限制為特定課程,例如 “Data Engineering Zoom Camp.”?;菊Z(yǔ)義搜索和高級(jí)語(yǔ)義搜索之間的一個(gè)顯著區(qū)別在于結(jié)果的評(píng)分?;菊Z(yǔ)義搜索分?jǐn)?shù)范圍在 0 到 1 之間,其中 0 表示匹配度低,1 表示匹配度高。
使用 Explain 關(guān)鍵字解釋分?jǐn)?shù)為了進(jìn)一步了解分?jǐn)?shù)計(jì)算,Elasticsearch 提供了 explain=true 關(guān)鍵字。此工具描述了如何計(jì)算分?jǐn)?shù),提供了有價(jià)值的見(jiàn)解。有了這些信息,人們可以開(kāi)發(fā)出更符合特定用戶(hù)或業(yè)務(wù)需求的自定義評(píng)分函數(shù)。
更多閱讀,請(qǐng)參閱:Elasticsearch:使用 Open AI 和 Langchain 的 RAG - Retrieval Augmented Generation (二)