載入中

本教學將透過一個實際範例,示範完整的 RAG(Retrieval-Augmented Generation,檢索增強生成)實作。我們將從零開始建立一個向量資料庫,並使用一份範例報告文件執行 RAG 工作流程的全部五個步驟。

設定向量資料庫

此實作使用自訂的 VectorIndex 類別,負責儲存嵌入向量並執行相似度搜尋。這個類別提供了我們進行向量資料庫操作所需的核心功能。

五步驟 RAG 實作

步驟 1:依章節切分文字

首先,我們使用先前介紹過的以章節為基礎的切分方法,載入並切分我們的來源文件:

python
with open("./report.md", "r") as f:
    text = f.read()

chunks = chunk_by_section(text)

這會將我們的報告拆分成可以獨立處理的邏輯章節。

步驟 2:為每個區塊產生嵌入向量

接下來,我們使用列表推導式為每個區塊建立嵌入向量:

python
embeddings = [generate_embedding(chunk) for chunk in chunks]

這個步驟涉及多次 API 呼叫,因此需要一些時間才能完成。每個區塊都會被轉換成數值向量表示。

步驟 3:將嵌入向量儲存到向量資料庫中

現在我們建立向量儲存區,並將嵌入向量及其對應的文字一併填入:

python
store = VectorIndex()

for embedding, chunk in zip(embeddings, chunks):
    store.add_vector(embedding, {"content": chunk})

這裡的關鍵在於,我們同時儲存了嵌入向量和原始文字。僅僅取回一串數字並沒有用處——我們需要的是與這些嵌入向量對應的實際文字內容。這個元資料讓我們之後能夠取得有意義的結果。

步驟 4:產生使用者查詢的嵌入向量

當使用者提出問題時,我們會將其轉換成相同的嵌入格式:

python
user_embedding = generate_embedding("What did the software engineering dept do last year?")

這會建立使用者問題的向量表示,可用於與我們儲存的嵌入向量進行比較。

步驟 5:搜尋並檢索相關區塊

最後,我們搜尋向量儲存區,找出最相似的內容:

python
results = store.search(user_embedding, 2)

for doc, distance in results:
    print(distance, "\n", doc["content"][0:200], "\n")

這會回傳兩個最相關的區塊,以及它們的餘弦距離分數。距離越小,表示相似度越高。

理解結果

搜尋結果會依相關性排序。在我們的範例中,軟體工程章節的距離最小(0.71),因此是最相關的匹配結果。方法論章節則以 0.72 的距離排名第二。

距離指標能幫助您了解系統對每個結果相關性的信心程度。距離越近,表示與使用者查詢的匹配度越好。

為何要將文字與嵌入向量一併儲存

一個關鍵的設計決策,就是將原始文字與每個嵌入向量一併儲存。如果沒有這樣做,您只會取回一堆數字陣列,這對於產生回應並沒有用處。透過納入來源文字,您就能立即使用檢索到的區塊,為您的語言模型提供上下文。

這樣就完成了核心的 RAG 工作流程,不過在實際應用場景中,還有其他可以提升效能的優化與改進方式。