RAG:讓大模型知道更多東西
雖然我們說大模型的特點之一是知識豐富,但這里的知識僅限于通用的知識,也就是網上能夠很容易找到的知識。對于一些特定的知識,比如你所在業(yè)務領域的知識,它就一無所知了。個中緣由,不言而喻,大模型訓練時,根本不可能拿到你們公司的數據。如果我打算為自己的業(yè)務開發(fā)一個聊天機器人,也就是說,讓聊天機器人知道我的業(yè)務,該怎么辦呢?拋開訓練一個屬于自己的大模型這種成本高昂的辦法,常見的解決方案有兩種:模型微調:使用業(yè)務信息對已經訓練好的模型進行微調。RAG:在上下文中帶有業(yè)務信息,讓大模型據此進行整合。相比于模型微調,RAG 的方案成本要低一些,而且更加靈活,實現起來也更簡單一些,所以,它也成為了現在解決這個問題的首選。這一講,我們就來了解一下 RAG。
RAG
RAG 是 Retrieval-Augmented Generation 的縮寫,也就是檢索增強生成。這是什么意思呢?就是通過檢索的方式,對要處理的內容進行增強之后再去生成。
我們把大模型應用和檢索增強結合起來理解一下。大模型有很多不知道的東西,比如,我們的業(yè)務。怎么讓大模型了解我們的業(yè)務呢?最簡單的方式就是每次請求時,把業(yè)務相關的內容放在提示詞里告訴大模型。
問題是,業(yè)務相關的內容從何而來?這就是我們要在本地檢索的內容。換言之,所謂檢索增強生成,就是我們在本地檢索到相關的內容,把它增強到提示詞里,然后再去做內容生成。
下面是一個 RAG 系統(tǒng)處理用戶請求的極簡流程示意圖:
圖片
- 用戶發(fā)起請求
- 根據用戶的問題在相關資料中進行查詢
- 獲取到資料中的相關內容
- 組成完整的提示詞發(fā)給大模型
- 將大模型的回復發(fā)給用戶
對比普通的聊天機器人,差別就是在這個過程中,要去到相關資料中進行查詢,再將查詢得到的相關信息和用戶問題拼裝成完整的提示詞發(fā)給大模型。
有了對 RAG 流程的初步認識,接下來的問題就是,怎樣到相關資料中查詢。既然要查詢,必然是有個地方能夠存儲這些資料的。對于程序員來說,最熟悉的存儲方案一定是數據庫。
對于大模型應用開發(fā)而言,我們要根據文本去找相關內容。在業(yè)務系統(tǒng)開發(fā)中,我們經常做的文本匹配是用 SQL 語句的 like。但是,這種匹配對于大模型應用而言,就顯得非常單薄了,因為它只能進行“字面”意義上的匹配,無法進行“語義”層面的匹配。如果想進行“語義”的匹配該怎么做呢?這就輪到向量登場了。
向量和向量數據庫
向量,我們說過,許多 AI 算法處理的都不是文字,而是向量。采用向量的方案,“語義”的匹配程度就轉換成了向量之間的相似程度。計算向量相似度的算法有很多,比如,余弦相似度、內積、歐氏距離等等。
有了向量,當用戶提出問題時,處理過程就變成了將問題轉換為向量,然后計算向量之間的距離,找到與問題向量最接近的文檔向量,從而實現“語義”的匹配。
在開源社區(qū)里,已經有很多人提供了這樣的模型,我們需要做的就是把模型部署起來,然后,調用這個模型。當然,也有人把已經訓練好的模型部署成一個服務,這樣,我們就可以直接調用現成的服務。
OpenAI 就提供了一個專門負責將文本轉換成向量的 API——Embeddings。
我們可以根據需要,選擇自己部署模型,或是選擇別人提供的服務。不同的 Embedding 模型之間的差異主要取決于訓練樣本,比如有的模型會在中文處理上表現得比較好。到這里,我們知道了可以用向量進行文本內容的匹配。但是,我們要到哪里去匹配呢?
正如我們處理任何業(yè)務數據一樣,在使用數據之前,第一步需要做的是,存儲業(yè)務數據。在 RAG 系統(tǒng)中,我們要把數據存放到哪里呢?我們需要一個數據庫,只不過,我們需要的既不是 Oracle、MySQL 這樣的關系數據庫,也不是 MongoDB、Redis 這樣的 NoSQL 數據庫。因為我們后續(xù)處理的都是向量,所以,我們需要的是向量數據庫。
向量數據庫并不是突然冒出來的。2000 年左右,加州大學伯克利分校的研究人員開始嘗試開發(fā)向量數據庫,用來存儲和查詢高維向量。2010 年,VectorWise 公司發(fā)布了第一個商業(yè)向量數據庫。隨著 AI 應用的興起,人們對于向量數據庫的興趣日漸濃厚。在大模型興起之后,隨著 RAG 的蓬勃發(fā)展,向量數據庫一下子站到舞臺中央,開始成為許多大模型應用的重要組件。
向量數據庫與傳統(tǒng)數據庫有很大的差別,在使用方式上,傳統(tǒng)數據庫搜索信息傾向于精確匹配,而向量數據庫的匹配則是語義上的接近。
在實現上二者也存在不小的差別,比如,由于向量本身通常維度會很多,如果按照傳統(tǒng)數據庫的方式直接進行存儲,將會帶來很多問題。向量數據庫需要把向量數據作為一個完整的單元處理,底層存儲結構也需要根據這個特點進行規(guī)劃。另外,向量數據格式也相對單一,每個維度的數據往往都是固定的數據格式(浮點數、二進制整數等)。
所以,向量數據庫就可以有針對性地找到一些優(yōu)化手段,比如,相關的數學運算可以更好地利用 CPU 緩存機制加速,甚至可以利用 CPU/GPU 的硬件特性;再比如,采用高效的數據壓縮技術,這樣就能夠顯著地減少存儲空間。
索引
到這里,我們講的都是怎樣使用數據,也就是檢索的過程。其實,還有一個關鍵的問題沒有解決,這些數據從何而來,怎么跑到向量數據庫里去的。這就是 RAG 另外一個重要的過程:索引(Indexing)。
下面是一個常見的索引過程:
圖片
在這個過程里面,我們會先對信息源做一次信息提取。信息源可能是各種文檔,比如 Word 文檔、PDF 文件,Web 頁面,甚至是一些圖片。從這些信息源中,我們把內容提取出來,也就是其中的文本。
接下來,我們會把這些文本進行拆分,將其拆分成更小的文本塊。之所以要拆分,主要是原始的文本可能會比較大,這并不利于檢索,還有一點重要原因是,我們前面說過,要把檢索到的信息拼裝到提示詞里,過大的文本可能會造成提示詞超過模型有限的上下文窗口。
再來,就是把文本塊轉換成向量,也就是得到 Embedding 的過程。前面我們說過,這個過程往往是通過訓練好的模型來完成的。到這里,我們就把信息轉換成了向量。最后一步,就是把得到的向量存儲到向量數據庫中,供后續(xù)的檢索使用。
至此,我們對常見的 RAG 流程已經有了基本了解。但實際上,RAG 領域正處于一個快速發(fā)展的過程中,有很多相關技術也在不斷地涌現:
雖然采用向量搜索對于語義理解很有幫助,但一些人名、縮寫、特定 ID 之類的信息,卻是傳統(tǒng)搜索的強項,有人提出混合搜索的概念,將二者結合起來;
通過各種搜索方式,我們會得到很多的候選內容,但到底哪個與我們的問題更相關,有人引入了重排序(Rerank)模型,以此決定候選內容與查詢問題的相關程度;
除了在已有方向的努力,甚至還有人提出了 RAG 的新方向。我們前面討論的流程前提條件是把原始信息轉換成了向量,但這本質上還是基于文本的,更適合回答一些事實性問題。它無法理解更復雜的關系,比如,我的朋友里誰在 AI 領域里工作。所以,有人提出了基于知識圖譜的 RAG,知識圖譜是一種結構化的語義知識庫,特別適合找出信息之間的關聯(lián)。
由此你可以看到,想要打造一個好的 RAG 應用并不是很容易的一件事,但在一些技術框架支持下,上手編寫一個 RAG 應用卻不是什么難事。
總結
RAG 是 Retrieval-Augmented Generation 的縮寫,也就是檢索增強生成的意思。它主要是為了解決大模型本身知識匱乏的問題。RAG 應用的主要流程包括索引、檢索和生成。
目前常見的 RAG 技術是依賴于將文本轉換成向量,以實現語義上的匹配。將文本轉成向量,我們通常會使用專門的 Embedding 模型,而對向量進行檢索,則使用向量數據庫。索引就是把信息放到向量數據庫中,而檢索就是把信息提取出來,提取出來的信息與用戶提示詞合并起來,再到大模型去完成生成的過程。
如果今天的內容你只能記住一件事,那請記住,RAG 是為了讓大模型知道更多的東西。