文本分塊(Text Splitting),RAG不可缺失的重要環(huán)節(jié)
本文介紹了在增強(qiáng)檢索生成(RAG)流程中,文本分塊的重要性和實(shí)現(xiàn)方式。詳細(xì)解釋了為什么要對文本進(jìn)行切分及代碼示例,展示了分塊后的效果。通過合理分塊,可以有效應(yīng)對模型的輸入限制,提升檢索與生成的質(zhì)量,是構(gòu)建高效 LLM 應(yīng)用的關(guān)鍵步驟之一。
1. 文檔分塊的原因
2. 文檔分塊的基本思路
2.1 基于長度的分塊類型
2.2 代碼實(shí)現(xiàn)
2.2 拆分結(jié)果
3. 圖形化顯示分塊
總結(jié)
在快速發(fā)展的自然語言處理(NLP)領(lǐng)域,增強(qiáng)檢索生成(RAG)已成為提高 AI 生成響應(yīng)的準(zhǔn)確性和相關(guān)性的強(qiáng)大技術(shù)。
在 RAG 的核心步驟中,有一個(gè)至關(guān)重要的步驟:“文本分塊(Text Splitting)”。
它的主要作用就是把一大段文本切分成更小、更合理的片段,這樣模型才能更好地理解、處理或者存儲(chǔ)這些內(nèi)容。
比如說,如果你有一篇幾千字的文章,直接丟給模型處理,很可能會(huì)超過它的最大上下文長度(就是它一次能“看”的最多字?jǐn)?shù))。這個(gè)時(shí)候就得用 文本分塊(Text Splitting)來把文章拆成幾段,讓每一段都不超出模型的處理能力,而且盡量保證語義完整、段落自然,不要斷在奇怪的地方。
除了應(yīng)對長度限制,還有個(gè)原因是為了更精準(zhǔn)地做 embedding、搜索或者問答。
舉個(gè)例子,如果你用 RAG 來做知識(shí)庫問答,先要把整個(gè)文檔轉(zhuǎn)成 embedding(向量表示),然后做向量檢索找出相關(guān)內(nèi)容。
如果一整篇文章不拆開,那 embedding 的顆粒度太粗,問答的時(shí)候很容易不準(zhǔn)。所以切得好不好,直接影響最后答案的相關(guān)性和準(zhǔn)確性。
1. 文檔分塊的原因
拆分文檔有幾個(gè)原因:
- 處理不均勻的文檔長度:現(xiàn)實(shí)世界的文檔集合通常包含不同大小的文本。拆分確保對所有文檔進(jìn)行一致的處理。
- 克服模型限制:許多嵌入模型和語言模型都有最大輸入大小限制。拆分允許我們處理那些否則會(huì)超出這些限制的文檔。
- 提高表示質(zhì)量:對于較長的文檔,嵌入或其他表示形式的質(zhì)量可能會(huì)隨著過多信息而降低。拆分可以導(dǎo)致每個(gè)部分更加集中和準(zhǔn)確的表示。
- 增強(qiáng)檢索精度:在信息檢索系統(tǒng)中,拆分可以提高搜索結(jié)果的粒度,從而允許查詢與相關(guān)文檔部分的更精確匹配。
- 優(yōu)化計(jì)算資源:處理較小的文本塊可以更加節(jié)省內(nèi)存,并允許更好的并行處理任務(wù)。
2. 文檔分塊的基本思路
最基本的分塊方法是根據(jù)文檔的長度進(jìn)行拆分。這種簡單而有效的方法確保每個(gè)塊不會(huì)超過指定的大小限制。
基于長度拆分的主要好處:簡單明了的實(shí)現(xiàn)、一致的塊大小、易于適應(yīng)不同模型的要求。缺點(diǎn)就是: 過于死板,忽視文本結(jié)構(gòu)。
2.1 基于長度的分塊類型:
- 基于token的:根據(jù)token數(shù)量分割文本,這在使用語言模型時(shí)非常有用。
- 基于字符的:根據(jù)字符數(shù)量分割文本,這在不同類型的文本中可能更為一致。
2.2 代碼實(shí)現(xiàn)
以基于字符的拆分為例來了解分塊的基本思路:
需要了解的概念
- 塊大小(Chunk Size)- 每個(gè)數(shù)據(jù)塊包含的字符數(shù),比如 50、100、100,000 等。
- 塊重疊(Chunk Overlap)- 相鄰數(shù)據(jù)塊之間重疊的字符數(shù)量。這樣做是為了避免將一個(gè)完整語境拆成幾部分,但會(huì)導(dǎo)致各塊之間出現(xiàn)重復(fù)數(shù)據(jù)。
使用LangChain創(chuàng)建 CharacterTextSplitter 實(shí)例,設(shè)置三個(gè)關(guān)鍵參數(shù):
- chunk_size=15 :每個(gè)分割塊的最大字符數(shù)為15
- chunk_overlap=5 :相鄰塊之間重疊的字符數(shù)為5,這有助于保持上下文連貫性
- separator='' :使用空字符串作為分隔符,意味著將按照純字符數(shù)量進(jìn)行分割,而不是按照特定分隔符(如句號、空格等)
from langchain.text_splitter import CharacterTextSplitter
text = "青云山連綿百里,峰巒起伏,最高有七峰,高聳入云,平日里只見白云環(huán)繞山腰,不識(shí)山頂真容。青云山山林密布,飛瀑奇巖,珍禽異獸,在所多有,景色幽險(xiǎn)奇峻,天下聞名。"
text_splitter = CharacterTextSplitter(chunk_size=15, chunk_overlap=5, separator='')
docs = text_splitter.create_documents([text])
for doc in docs:
print('-' * 50)
print(doc)
2.2 拆分結(jié)果
根據(jù)設(shè)置的參數(shù)(chunk_size=15和chunk_overlap=5),文本被分成了8個(gè)片段,每個(gè)片段大約包含15個(gè)字符(包括標(biāo)點(diǎn)符號),相鄰片段之間有5個(gè)字符的重疊,這確保了文本的連貫性。
例如:"起伏,最高"這部分內(nèi)容在第一段末尾和第二段開頭都出現(xiàn),這就是重疊的效果
分割后的每個(gè)片段都保持了基本的可讀性,雖然有些句子被切分開了。
最后一個(gè)片段"奇峻,天下聞名。"因?yàn)槭俏谋灸┪?,所以長度較短,不足15個(gè)字符
--------------------------------------------------
page_cnotallow='青云山連綿百里,峰巒起伏,最高'
--------------------------------------------------
page_cnotallow='起伏,最高有七峰,高聳入云,平'
--------------------------------------------------
page_cnotallow='聳入云,平日里只見白云環(huán)繞山腰'
--------------------------------------------------
page_cnotallow='云環(huán)繞山腰,不識(shí)山頂真容。青云'
--------------------------------------------------
page_cnotallow='真容。青云山山林密布,飛瀑奇巖'
--------------------------------------------------
page_cnotallow=',飛瀑奇巖,珍禽異獸,在所多有'
--------------------------------------------------
page_cnotallow=',在所多有,景色幽險(xiǎn)奇峻,天下'
--------------------------------------------------
page_cnotallow='奇峻,天下聞名。'
3. 圖形化顯示分塊
通過www.chunkviz.com可以以圖形化的方式看到分塊結(jié)果。
總結(jié)
文本分塊雖然看起來只是把文本切成小段,但它在大語言模型的應(yīng)用中扮演著非常重要的角色。
它不僅解決了模型上下文長度的限制問題,還直接影響了后續(xù)任務(wù)的效果,比如 embedding 的精度、搜索的相關(guān)性、問答的準(zhǔn)確性等等。
切分策略得當(dāng),不僅能提升模型的理解力,還能讓整個(gè)系統(tǒng)運(yùn)行得更高效、更智能。所以在設(shè)計(jì) LLM 應(yīng)用時(shí),文本分塊絕對不是一個(gè)可以忽略的細(xì)節(jié),而是值得精心打磨的核心組件之一。
本文轉(zhuǎn)載自??AI取經(jīng)路??,作者:AI取經(jīng)路
