再談大模型長文本分塊,以及分塊在RAG中的作用? 原創(chuàng)
“ 向量數(shù)據(jù)庫的檢索原理,就是存儲不同數(shù)據(jù)之間的向量關(guān)系,在檢索時通過向量關(guān)系查詢相關(guān)數(shù)據(jù) ”
文本分塊也就是chunk技術(shù)是大模型領(lǐng)域中非常重要的一項技術(shù),原因就在于大模型眾所周知的問題,上下文窗口限制;雖然說現(xiàn)在大模型的窗口經(jīng)過幾次擴容之后已經(jīng)達到了一個非常可觀的長度,但依然還存在很多問題。
比如說,長文本導(dǎo)致的模型幻覺問題;中間丟失現(xiàn)象等多種性能問題;而且,在RAG技術(shù)中,長文本也是一個亟待解決的問題。
而現(xiàn)在業(yè)內(nèi)普遍的處理方式就是文本分塊,把一段長文本根據(jù)某種方式拆分成多種小的文本塊;這樣就有助于大模型進行處理,也能間接降低大模型的幻覺等問題。
文本分塊
在大模型上下文窗口中文本分塊就比較好理解,這就類似于我們平常看一本很厚的書;我們無法做到一次就給全部看完,因此常見的做法就是今天看一點,明天看一點,然后一段時間之后就看完了。
而我們在看書的過程中,比如昨天看了一部分停了下來;今天接著看,但可能我們一時想不起來昨天看到哪里了;因此就會找到昨天看的大概位置再往前一點,這樣有助于我們回憶昨天看的內(nèi)容;也有助于上下文的連貫性。
而大模型長文本處理有一種方式也是采用類似的方式,那就是把文本按照chunk_size進行分塊;然后使用chunk_overlap重疊一部分內(nèi)容。而chunk_overlap重疊的部分就相當(dāng)于我們看書時往前看的一部分,這樣有助于上下文的連貫性,特別是對大模型這種沒有記憶能力的系統(tǒng)來說。
而在代碼方面具體的表現(xiàn)就如下所示,加載文檔之后使用分詞工具根據(jù)不同的長度進行分詞,分詞的長度和重疊部分就是由chunk_size和chunk_overlap來指定,之后再轉(zhuǎn)化為向量。
"""
加載文檔
"""
def load_documents(directory=dir_path):
loader = DirectoryLoader(directory)
documents = loader.load()
# for document in documents:
# print(document)
# 文檔分割
text_spliter = CharacterTextSplitter(chunk_size=256, chunk_overlap=10)
spliter_docs = text_spliter.split_documents(documents)
return spliter_docs當(dāng)然,在一些沒有語義相關(guān)的上下文中,也可以不使用chunk_overlap參數(shù);只根據(jù)chunk_size或其它方式進行分塊。比如說,今天工作日我在上班;今天天氣不錯;這兩句話從語義上來說沒有任何相關(guān)性,因此可以進行完全分塊。
雖然說文本分塊是大模型技術(shù)中很常見的一種處理方式,但現(xiàn)在有一個疑問就是;在大模型上下文窗口中這樣的使用方式很容易理解;但在RAG中就存在一個問題。
RAG中一般使用向量數(shù)據(jù)庫作為數(shù)據(jù)的存儲方式,原因就在于向量數(shù)據(jù)庫能很好的保證文本之間的語義關(guān)系(也有圖像關(guān)系,混合關(guān)系等多種情況)。
但長文本被分塊之后,在向量數(shù)據(jù)庫中的表現(xiàn)形式也是一條一條的記錄;如果說一條語義相關(guān)的長文本被拆分成多個小塊,然后存儲在向量數(shù)據(jù)庫的不同位置。

這時在進行向量檢索時,向量數(shù)據(jù)庫是怎么保證檢索內(nèi)容的相關(guān)性的?
難道是因為具有語義相關(guān)的內(nèi)容被保存在相近距離的向量空間中?比如歐氏距離就是通過計算不同向量之間的距離來表示其相關(guān)性。
但如果面對著百億級以上的向量存儲需求,向量數(shù)據(jù)庫怎么保證快速且準(zhǔn)確高效的檢索到相關(guān)數(shù)據(jù)?
個人猜測,長文本被拆分之后,為了保證語義相關(guān)性,因此采用了chun_overlap的方式來讓拆分的文本有重疊的內(nèi)容;根據(jù)這些重疊的內(nèi)容,在進行向量計算的時候會把這相關(guān)的數(shù)據(jù)放到一塊;或者能夠通過一種方式進行快速檢索。
如下圖所示,文本被拆分之后,因為有chunk_overlap參數(shù)關(guān)聯(lián)文本的語義關(guān)系;那么,在向量數(shù)據(jù)庫中就會把語義相關(guān)的內(nèi)容記錄到更近的位置;這樣在檢索的時候,就可以根據(jù)向量之間的關(guān)系獲取相關(guān)的數(shù)據(jù)。

這就類似于傳統(tǒng)SQL語句的like功能,可以根據(jù)某個字段或語句查詢到多條記錄;然后再從這多條記錄中篩選出語義相關(guān)性最高的數(shù)據(jù)。
但這同樣有新的問題,那就是chunk_overlap只是文檔拆分的一種方式;還有很多其它的方式可以拆分;那么這就說明一件事,chunk_overlap只是一種表象,核心在于怎么保證上下文語義的相關(guān)性;如果不使用chunk_overlap的方式,或者不使用歐式距離的計算方式, 那么怎么才能保證文本上下文的相關(guān)性呢?
而且,我們都知道大模型是經(jīng)過訓(xùn)練和微調(diào)的方式,通過不斷調(diào)整神經(jīng)網(wǎng)絡(luò)的參數(shù)值來“學(xué)習(xí)”不同文本(多模態(tài))數(shù)據(jù)之間的關(guān)系,那這個學(xué)習(xí)的過程是不是就是在不斷的計算向量之間的關(guān)系?
原文鏈接:??https://mp.weixin.qq.com/s/VL10Snh_jqbtGLR38vOXMQ??

















