Video thumbnail for 原来这就是RAG 一看就懂的AI检索机制

RAG 原理詳解:一看就懂的AI檢索增強生成技術

Summary

Language:

Quick Abstract

身為程式設計師,你是否曾因大型語言模型(LLM)產生幻覺而苦惱?這份摘要將介紹 RAG (Retrieval Augmented Generation),一種解決方案,透過檢索相關資訊增強模型,讓回答更精準。 我們將說明 RAG 的原理、嵌入模型(Embedding Model)如何運作、向量資料庫的角色,以及 RAG 的局限性與改進方向。

  • 快速掌握:

    • RAG 旨在解決 LLM 在處理大量資訊時產生的幻覺問題。

    • 嵌入模型 將文本轉換為向量,利用向量間的距離判斷文本相關性。

    • 向量資料庫 專門儲存和檢索向量數據,是 RAG 的核心元件。

    • Chunking(分塊)將文件切割成小塊,提升檢索效率,但也可能造成語義斷裂。

    • RAG 並非完美,對於需要全局視角的提問,效果有限。

    • RAG 是一種折衷方案,在 LLM 的上下文窗口限制下,盡可能確保答案的準確性。

RAG 的核心在於預處理文件,將其切割成小塊(Chunking),並使用嵌入模型將每個小塊轉換成向量。這些向量儲存在向量資料庫中。當使用者提問時,問題也會被轉換成向量,並在資料庫中檢索與問題最相關的文本片段,將其作為上下文與問題一同送入 LLM,從而提升回答品質,減少幻覺產生。 然而,Chunking 策略和缺乏全局視角是 RAG 的主要挑戰。

一位倒霉程序員的困境與RAG架構

你是一位倒霉的程序員。此刻,你正盯著一份令人沮喪的內部文件,編寫一個更讓人頭疼的程序。不出所料,你很快就遇到了問題。你向大型模型求助,但原來它從未見過你的文件。於是,它開始自信地胡言亂語。它的答案聽起來完全合理,但與你的問題毫無關係。人們稱之為「模型幻覺」。

聰明的解決之道

不過你是個聰明的程序員,很快就想出了解決方案:把文件和問題一起發送給模型。這次,AI給出了正確答案,問題似乎解決了。

新問題接踵而至

但不久,新問題出現了。你的文件越來越大,答案可能只隱藏在其中一小部分,甚至分散在各個片段中。當AI看到整個文件時,實際上很難找到關鍵信息。簡言之,信息太多,模型很容易分心。

RAG的誕生

聰明的你很快想到:「如果我不發送整個文件呢?」「只發送與問題真正相關的部分?」當然可以!這正是RAG(檢索增強生成)旨在解決的問題。

如何判斷文本相關性

那麼,如何確定一段文本是否與用戶的問題相關呢?我們需要一種新的模型,稱為嵌入模型。

嵌入模型的特性

嵌入模型也以一段文本作為輸入,但與大型語言模型不同,它的輸出是一個固定長度的數組。例如,OpenAI的text-embedding-3-small模型輸出一個1536維的數組,而text-embedding-3-large模型輸出一個3072維的數組。無論輸入的是一個完整的句子還是一整段話,模型輸出的數組長度始終是固定的。

用距離衡量相關性

可以把這個數組看作是對原始內容的損失壓縮。信息被濃縮了,但含義仍然保留。相似內容的壓縮結果也會非常接近。因此,我們可以使用這些數組之間的距離來確定兩段文本是否相關。

用座標系解釋

為了便於解釋,讓我們畫一個與數組長度相同維度的座標系。假設我們使用一個非常糟糕的嵌入模型,其輸出數組只包含兩個數字,那麼我們可以畫一個2D座標系。每段文本在這個座標系中佔據一個點,嵌入模型會嘗試將含義相似的文本放置得更靠近彼此。

高維空間的優勢

當然,2D座標系無法準確表示所有的距離關係。在現實中,嵌入模型的實際向量空間超過1000維,甚至是3000+維的座標系。在這樣的高維空間中,句子之間的距離關係可以表達得更加準確。

RAG的工作流程

有了這個向量空間,如果用戶提出一個問題,比如「Wang喜歡吃什麼?」我們可以將這個問題輸入到同一個嵌入模型中進行處理。它也會被映射到座標系中的一個點。嵌入模型會將「Wang喜歡吃什麼?」這樣的問題放置在「Wang喜歡吃瓜」或「Wang喜歡吃瓜」等語義片段附近。

選擇相關文本

程序可以計算每個現有點與這個問題點之間的距離,然後選擇幾個最接近的文本片段。這些片段作為上下文,與用戶的問題一起發送給AI模型。這樣,AI模型看到的只是與問題高度相關的內容,幻覺的風險因此大大降低。這就是RAG架構。

處理長文件

回到之前的問題:如果文件太長怎麼辦?在用戶提出問題之前,我們可以對文件進行預處理。

文件分塊

首先,將整個文件分成許多小塊。有很多方法可以做到這一點:按字數、按段落、按句子,當然還有更複雜的方法。這個過程有一個特殊的名稱,聽起來很高級:「分塊」,就是切成碎片的意思。

轉換為向量

分塊後,下一步是對每個小文本片段進行嵌入,將它們轉換成長度統一的數組,或者更專業地說,向量。

存儲與檢索

但僅有這些向量是不夠的。我們還需要存儲每個向量與其原始文本片段之間的映射。通常,我們使用數據庫來存儲數據。但傳統數據庫擅長根據精確的數值查找記錄,而這些值不是向量。

向量數據庫的應用

我們現在尋找的不是像「等於X」這樣的精確匹配,而是哪個向量最接近與我們的問題相對應的向量。這是傳統數據庫無法做到的。因此,專門為這種情況設計了向量數據庫。在向量數據庫中,每條數據都可以有一個相關的向量。查詢時,輸入一個向量,數據庫會找到其向量最接近輸入向量的數據。這個功能非常適合存儲嵌入結果。常見的向量數據庫包括Pinecone、ChromaDB,以及PostgreSQL與pgvector插件的組合等。

完整的RAG流程

這樣,我們就完成了文件分塊、編碼和存儲。所有的分塊及其相應的嵌入都準備好被檢索。當用戶提出問題時,我們首先使用相同的嵌入模型將問題也轉換成向量。然後,從向量數據庫中檢索距離最近的幾段內容。這些內容與用戶的問題一起發送給AI模型,一個完整的RAG架構就完成了。

RAG的缺陷

然而,RAG本身並不是一個完美的架構,它有一些固有的缺陷。

分塊問題

首先是如何對文章進行分塊的問題。由於每篇文章的結構和順序都不同,無論是按句子、按段落還是使用更複雜的分塊算法,當文章變得複雜時,沒有一種方法可以適應所有情況。文章中的一些關鍵內容有時會被不恰當地切斷。

缺乏全局視角

第二個問題是RAG缺乏全局視角。例如,如果用戶問:「這篇文章中出現了多少次‘我’這個字?」這個問題實際上與文章中的每個句子都有關,但與任何一個特定的句子都沒有強烈的關聯。對於沒有哪個句子特別相關,但整個文本都有點相關的問題,RAG通常無法處理。

改進方案

為了解決這些不足,出現了許多改進方案。例如,在預處理過程中,將所有的「我」統一替換成「Wang」,甚至讓大型模型參與分塊過程,根據語義自動確定斷點和切割方式。但截至目前,還沒有真正完美的解決方案。

總結

RAG本質上是一種壓縮形式。文件太長,所以我們分塊、過濾、建立索引。保留重要的,丟棄不重要的。其實我們的日常生活也是如此。每天面對這麼多人、這麼多事,我們逐漸學會分類和權衡。「這是緊急的,那可以等。」「這需要記住」,而其他事情也許可以忘記。我們認為這是成熟,頭腦清醒。但有時,當事情分得太細時,難免會失去上下文,誤解原意。一些曾經重要的事情可能會失去聯繫。就像那個老同桌,或者那個給你發最後一條消息只是「lol」的親密朋友。不是他們變得不重要了,只是我們各自生活的向量座標越來越遠。

幾天前,我偶然發現了一張我們一起玩遊戲的舊截圖。我盯著它看了很久。突然,我意識到,那時候,他的DPS真的很低!這是程序員Wang。下次見。

Was this summary helpful?