既然我們已經從概念上理解了 RAG 流程,讓我們逐步實作它。我們將完整走過一個範例,示範如何對文本進行分塊、生成嵌入、將它們儲存在向量資料庫中,並執行相似性搜尋。
五步驟 RAG 實作
我們的實作遵循先前討論過的相同五個步驟:
- 按章節對文本進行分塊
- 為每個區塊生成嵌入
- 建立向量儲存並將每個嵌入加入其中
- 為使用者的問題生成嵌入
- 搜尋儲存以找出最相關的區塊

此圖表展示了我們如何將使用者查詢轉換為嵌入,並搜尋我們的向量資料庫以找出最相關的內容。
步驟 1:對文本進行分塊
首先,我們載入文件並將其拆分為可管理的區段:
python
with open("./report.md", "r") as f:
text = f.read()
chunks = chunk_by_section(text)
chunks[2] # Test to see the table of contents我們使用先前相同的 chunk_by_section 函式,將文件拆分為邏輯區段。
步驟 2:生成嵌入
接下來,我們一次為所有區塊建立嵌入:
python
embeddings = generate_embedding(chunks)嵌入函式已更新,可同時處理單一字串和字串列表,使其在批次處理時更有效率。
步驟 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")此搜尋會回傳兩個最相關的區塊,以及它們的相似度分數(餘弦距離)。

搜尋結果向我們展示了文件中哪些區段與使用者的問題最相關,並附有相似度分數。
理解結果
當我們執行關於軟體工程部門的範例查詢時,我們得到:
- 第 2 節:軟體工程,距離為 0.71(最接近的匹配)
- 方法論章節,距離為 0.72(第二接近)
較低的距離值表示較高的相似度,因此第 2 節與我們的查詢最相關。
接下來是什麼?
此實作在基本情況下運作良好,但在某些情境下,它的表現不如預期。在接下來的章節中,我們將探討如何改進,使我們的 RAG 系統更加穩健和準確。
關鍵要點是,RAG 本質上是關於將文本轉換為數字(嵌入),有效地儲存這些數字,然後在使用者提出問題時,使用數學相似性來找出相關內容。