使用 LlamaIndex 和 Milvus 進行全文搜尋
全文檢索使用精確的關鍵字匹配,通常利用 BM25 等演算法來依據相關性排列文件。在檢索增強世代 (RAG)系統中,此方法會檢索相關的文字,以增強 AI 所產生的回應。
同時,語意搜尋會詮釋上下文的意義,以提供更廣泛的結果。結合這兩種方法可創造出混合搜尋,改善資訊檢索,尤其是在單一方法無法達到要求的情況下。
使用Milvus 2.5 的 Sparse-BM25 方法,原始文字會自動轉換為稀疏向量。這樣就不需要手動生成稀疏嵌入,並實現混合搜尋策略,在語義理解和關鍵字相關性之間取得平衡。
在本教程中,您將學習如何使用 LlamaIndex 和 Milvus 來建立一個使用全文檢索和混合檢索的 RAG 系統。我們會先單獨實作全文檢索,然後透過整合語意檢索來強化它,以獲得更全面的結果。
在繼續本教學之前,請確保您熟悉全文檢索以及在 LlamaIndex 中使用 Milvus 的基本知識。
先決條件
安裝相依性
在開始之前,請確定您已安裝下列依賴項目:
$ $pip install llama-index-vector-stores-milvus
$ $pip install llama-index-embeddings-openai
$ $pip install llama-index-llms-openai
如果您使用的是 Google Colab,您可能需要重新啟動運行時(導航至介面頂端的「運行時」功能表,並從下拉式功能表中選擇「重新啟動會話」)。
設定帳號
本教程使用 OpenAI 進行文字嵌入和答案產生。您需要準備OpenAI API 密鑰。
import openai
openai.api_key = "sk-"
若要使用 Milvus 向量存儲,請指定您的 Milvus 伺服器URI (可選擇使用TOKEN)。若要啟動 Milvus 伺服器,您可以依照Milvus 安裝指南設定 Milvus 伺服器,或直接免費試用Zilliz Cloud。
Milvus Standalone、Milvus Distributed 和 Zilliz Cloud 目前支援全文搜尋,但 Milvus Lite 尚未支援(計畫在未來實施)。如需更多資訊,請聯絡 support@zilliz.com。
URI = "http://localhost:19530"
# TOKEN = ""
下載範例資料
執行下列指令可將範例文件下載至「data/paul_graham」目錄:
$ mkdir -p 'data/paul_graham/'
$ $wget 'https://raw.githubusercontent.com/run-llama/llama_index/main/docs/docs/examples/data/paul_graham/paul_graham_essay.txt' -O 'data/paul_graham/paul_graham_essay.txt'
--2025-03-27 07:49:01-- https://raw.githubusercontent.com/run-llama/llama_index/main/docs/docs/examples/data/paul_graham/paul_graham_essay.txt
Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 185.199.108.133, 185.199.109.133, 185.199.110.133, ...
Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|185.199.108.133|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 75042 (73K) [text/plain]
Saving to: ‘data/paul_graham/paul_graham_essay.txt’
data/paul_graham/pa 100%[===================>] 73.28K --.-KB/s in 0.07s
2025-03-27 07:49:01 (1.01 MB/s) - ‘data/paul_graham/paul_graham_essay.txt’ saved [75042/75042]
使用全文檢索的 RAG
將全文檢索整合至 RAG 系統,可平衡語意檢索與精確且可預測的關鍵字檢索。您也可以選擇只使用全文檢索,但建議結合全文檢索與語意檢索,以獲得更好的檢索結果。為了示範的目的,我們將在此展示單獨的全文檢索和混合檢索。
要開始使用,請使用SimpleDirectoryReaderLoad 載入 Paul Graham 撰寫的文章「What I Worked On」:
from llama_index.core import SimpleDirectoryReader
documents = SimpleDirectoryReader("./data/paul_graham/").load_data()
# Let's take a look at the first document
print("Example document:\n", documents[0])
Example document:
Doc ID: 16b7942f-bf1a-4197-85e1-f31d51ea25a9
Text: What I Worked On February 2021 Before college the two main
things I worked on, outside of school, were writing and programming. I
didn't write essays. I wrote what beginning writers were supposed to
write then, and probably still are: short stories. My stories were
awful. They had hardly any plot, just characters with strong feelings,
which I ...
使用 BM25 進行全文檢索
LlamaIndex 的MilvusVectorStore 支援全文檢索,可實現高效率的關鍵字檢索。透過使用內建函式作為sparse_embedding_function ,它會應用 BM25 計分來對搜尋結果進行排序。
在本節中,我們將示範如何使用 BM25 實作一個 RAG 系統來進行全文檢索。
from llama_index.core import VectorStoreIndex, StorageContext
from llama_index.vector_stores.milvus import MilvusVectorStore
from llama_index.vector_stores.milvus.utils import BM25BuiltInFunction
from llama_index.core import Settings
# Skip dense embedding model
Settings.embed_model = None
# Build Milvus vector store creating a new collection
vector_store = MilvusVectorStore(
uri=URI,
# token=TOKEN,
enable_dense=False,
enable_sparse=True, # Only enable sparse to demo full text search
sparse_embedding_function=BM25BuiltInFunction(),
overwrite=True,
)
# Store documents in Milvus
storage_context = StorageContext.from_defaults(vector_store=vector_store)
index = VectorStoreIndex.from_documents(documents, storage_context=storage_context)
Embeddings have been explicitly disabled. Using MockEmbedding.
上述程式碼將範例文件插入 Milvus 並建立索引,以啟用全文搜尋的 BM25 排序。它停用了密集嵌入,並使用BM25BuiltInFunction 與預設參數。
您可以在BM25BuiltInFunction 參數中指定輸入和輸出欄位:
input_field_names (str):輸入文字欄位(預設:「文字」)。它表示 BM25 演算法應用於哪個文字欄位。如果使用不同文字欄位名稱的自己的集合,請變更此項。output_field_names (str):儲存此 BM25 函式輸出的欄位(預設值:"sparse_embedding")。
一旦向量儲存設定完成,您就可以使用 Milvus 以「sparse」或「text_search」查詢模式執行全文檢索查詢:
import textwrap
query_engine = index.as_query_engine(
vector_store_query_mode="sparse", similarity_top_k=5
)
answer = query_engine.query("What did the author learn at Viaweb?")
print(textwrap.fill(str(answer), 100))
The author learned several important lessons at Viaweb. They learned about the importance of growth
rate as the ultimate test of a startup, the value of building stores for users to understand retail
and software usability, and the significance of being the "entry level" option in a market.
Additionally, they discovered the accidental success of making Viaweb inexpensive, the challenges of
hiring too many people, and the relief felt when the company was acquired by Yahoo.
自訂文字分析器
分析器在全文檢索中扮演重要的角色,可將句子分割成字元,並執行詞彙處理,例如刪除字莖和停頓字。它們通常是特定於語言的。如需詳細資訊,請參閱Milvus 分析器指南。
Milvus 支援兩種類型的分析器:內建分析器和自訂分析器。預設情況下,BM25BuiltInFunction 使用標準的內建分析器,它會根據標點符號來標記文字。
若要使用不同的分析器或自訂現有的分析器,您可以傳值給analyzer_params 參數:
bm25_function = BM25BuiltInFunction(
analyzer_params={
"tokenizer": "standard",
"filter": [
"lowercase", # Built-in filter
{"type": "length", "max": 40}, # Custom cap size of a single token
{"type": "stop", "stop_words": ["of", "to"]}, # Custom stopwords
],
},
enable_match=True,
)
混合搜尋與 Reranker
混合搜尋系統結合語意搜尋與全文搜尋,可優化 RAG 系統的檢索效能。
以下範例使用 OpenAI embedding 進行語意搜尋,並使用 BM25 進行全文檢索:
# Create index over the documnts
vector_store = MilvusVectorStore(
uri=URI,
# token=TOKEN,
# enable_dense=True, # enable_dense defaults to True
dim=1536,
enable_sparse=True,
sparse_embedding_function=BM25BuiltInFunction(),
overwrite=True,
# hybrid_ranker="RRFRanker", # hybrid_ranker defaults to "RRFRanker"
# hybrid_ranker_params={}, # hybrid_ranker_params defaults to {}
)
storage_context = StorageContext.from_defaults(vector_store=vector_store)
index = VectorStoreIndex.from_documents(
documents,
storage_context=storage_context,
embed_model="default", # "default" will use OpenAI embedding
)
如何運作
此方法將文件儲存於 Milvus 套件中,並同時擁有兩個向量欄位:
embedding:由 OpenAI 嵌入模型產生的密集嵌入,用於語意搜尋。sparse_embedding:使用 BM25BuiltInFunction 計算的 Sparse embeddings,用於全文搜尋。
此外,我們使用「RRFRanker」及其預設參數應用了重排策略。若要自訂 reranker,您可以依照Milvus Reranking 指南設定hybrid_ranker 和hybrid_ranker_params 。
現在,讓我們使用範例查詢來測試 RAG 系統:
# Query
query_engine = index.as_query_engine(
vector_store_query_mode="hybrid", similarity_top_k=5
)
answer = query_engine.query("What did the author learn at Viaweb?")
print(textwrap.fill(str(answer), 100))
The author learned several important lessons at Viaweb. These included the importance of
understanding growth rate as the ultimate test of a startup, the impact of hiring too many people,
the challenges of being at the mercy of investors, and the relief experienced when Yahoo bought the
company. Additionally, the author learned about the significance of user feedback, the value of
building stores for users, and the realization that growth rate is crucial for the long-term success
of a startup.
這種混合方法可透過同時利用語意和關鍵字為基礎的檢索,確保在 RAG 系統中提供更精確、更能感知上下文的回應。