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