Unstructured專家分享RAG應(yīng)用中文檔分塊(Chunking)的最佳實(shí)踐
近日,Maria Khalusova在Unstructured官方博客分享了有關(guān)分塊的最佳實(shí)踐。
Unstructured成立于2022年9月,致力于解決自然語言處理(NLP)和大型語言模型(LLM)應(yīng)用中的數(shù)據(jù)預(yù)處理問題。公司總部位于美國,專注于將非結(jié)構(gòu)化數(shù)據(jù)轉(zhuǎn)化為LLM可以處理的格式,當(dāng)下流行的pdf解析庫就來自于它們,它們在數(shù)據(jù)預(yù)處理方面擁有非常前沿的技術(shù)和經(jīng)驗(yàn)。
為什么需要分塊?
出于多種原因,在為 RAG 準(zhǔn)備數(shù)據(jù)時(shí),分塊是必不可少的預(yù)處理步驟。
1)上下文窗口限制
首先從基礎(chǔ)開始。檢索到的塊將直接作為上下文輸入到提示中,以便LLM生成響應(yīng)。這意味著所有檢索到的塊的總長度至少不能超過LLM的上下文窗口。盡管當(dāng)下許多LLM有相當(dāng)大的上下文窗口,但實(shí)際上并不希望填滿上下文窗口,因?yàn)檫@些LLM會面臨“大海撈針”的問題(延伸閱讀:超長上下文窗口大模型的“照妖鏡”——大海撈針實(shí)驗(yàn),大模型“打假”必知必會)。另外,開發(fā)者可能還想以其他方式利用這個(gè)大上下文窗口,比如提供詳細(xì)的指令、角色描述或一些少樣本示例(few-shot)。
此外,如果打算使用相似性搜索并嵌入(embedding)文檔,必須考慮到嵌入模型也有一個(gè)有限的上下文窗口。這些模型不能嵌入超過其上下文窗口最大長度的文本。這個(gè)限制因具體模型而異,但可以在模型的描述中找到這些信息,例如在Hugging Face Hub上的模型卡片上。一旦知道將使用哪種模型來生成嵌入,就能確定文本塊的最大值(以token為單位,而不是字符或單詞)。嵌入模型通常在上下文窗口大小上的最大值約為8K token或更少,這相當(dāng)于英語中的大約6200個(gè)單詞。為了直觀理解有多大,比如,整個(gè)《指環(huán)王》系列,包括《霍比特人》,大約有576,459個(gè)單詞,所以如果想利用這個(gè)語料庫進(jìn)行RAG與相似性搜索,需要將其分成至少93個(gè)塊。
2)塊大小對檢索精度的影響
雖然嵌入模型對其可以嵌入的標(biāo)記數(shù)量規(guī)定了硬性的最大限制,但這并不意味著分塊必須達(dá)到這個(gè)長度。這只是意味著它們不能超過這個(gè)長度。事實(shí)上,在許多情況下,使用每個(gè)分塊的最大長度(如 6200 字(8K 標(biāo)記))可能會過長。這里有幾個(gè)令人信服的理由來選擇較小的語塊。
回想一下當(dāng)我們嵌入一段文本以獲得嵌入向量時(shí)會發(fā)生什么。大多數(shù)嵌入模型都是編碼器類型的轉(zhuǎn)換器模型,輸入文本的最大長度為 768。不管你給模型的是 10 個(gè)字的句子還是 1000 個(gè)字的段落,得到的嵌入向量的維度都是一樣的,都是 768。其工作原理是,模型首先將文本轉(zhuǎn)換為token,在預(yù)訓(xùn)練過程中為每個(gè)token學(xué)習(xí)了一個(gè)向量表征。然后,它將應(yīng)用一個(gè)池化操作,將單個(gè)token表征平均為一個(gè)單向量表征。
常見的池化類型包括:
- CLS池化:特殊CLS token的向量表征成為整個(gè)序列的表征
- 平均池化:token向量表征的平均值作為整個(gè)序列的表征返回
- 最大池化:具有最大值的token向量表征成為整個(gè)序列的表征
其目標(biāo)是將細(xì)粒度的token級表征壓縮成單一的固定長度表征,其中包含整個(gè)輸入序列的含義。這種壓縮本身就是有損的。對于較大的塊,表征可能會變得過于粗糙,可能會掩蓋重要的細(xì)節(jié)。為確保精確檢索,文本塊必須擁有有意義且細(xì)致入微的表征。
現(xiàn)在,請考慮另一個(gè)潛在問題。一個(gè)大塊可能包含多個(gè)主題,其中一些可能與用戶查詢相關(guān),而另一些則不相關(guān)。在這種情況下,單個(gè)向量中每個(gè)主題的表示可能會變得模糊,這同樣會影響檢索精度。
另一方面,較小的片段可以保持重點(diǎn)突出的上下文,從而可以更精確地匹配和檢索相關(guān)信息。通過將文檔分解成有意義的片段,檢索器可以更準(zhǔn)確地找到特定段落或事實(shí),從而最終提高 RAG 性能。那么,在保持上下文完整性的前提下,文件塊可以有多???這取決于文檔的性質(zhì),可能需要進(jìn)行一些試驗(yàn)。通常情況下,250 個(gè) token 左右的塊大?。ㄏ喈?dāng)于約 1000 個(gè)字符)是一個(gè)合理的實(shí)驗(yàn)起點(diǎn)。
分塊的常見方法
1)字符級分塊
將大文檔分割成小塊的最基本方法是將文本分成 N 個(gè)字符大小的塊。通常在這種情況下,還會指定一定數(shù)量的字符,這些字符應(yīng)在連續(xù)的文本塊之間重疊。這在一定程度上降低了句子或觀點(diǎn)在相鄰兩塊之間的邊界被突然切斷的可能性。不過,可以想象,即使有重疊,每個(gè)塊的固定字符數(shù)加上固定的重疊窗口,也不可避免地會導(dǎo)致信息流中斷、不同主題混合,甚至句子在一個(gè)詞的中間被分割。字符分割法完全不考慮文檔結(jié)構(gòu)。
2)句子級分塊或遞歸分塊
字符分割是一種簡單化的方法,完全沒有考慮到文檔的結(jié)構(gòu)。這種方法完全依賴于固定的字符數(shù),經(jīng)常會導(dǎo)致句子在中途甚至在詞的中間被拆分,效果并不好。
解決這一問題的方法之一是使用遞歸分塊法,這種方法有助于保留單個(gè)句子。使用這種方法,您可以指定一個(gè)有序的分隔符列表來指導(dǎo)分割過程。例如,以下是一些常用的分隔符:
- "\n\n" - 雙換行符,通常表示段落斷開
- "\n" - 單換行符
- "." - 句號
- " " - 空格
如果按照指定的順序使用上述分隔符,過程將是這樣的。首先,遞歸分塊會在每次出現(xiàn)雙新行("\n\n")時(shí)分解文檔。然后,如果這些分段仍然超過了所需的分塊大小,它將在新行處進(jìn)一步分解它們("\n"),以此類推。
雖然這種方法大大降低了中途斷句的可能性,但仍然無法捕捉到復(fù)雜的文檔結(jié)構(gòu)。文檔通常包含多種元素,如段落、章節(jié)頁眉、頁腳、列表、表格等,所有這些元素都有助于文檔的整體組織。然而,上述遞歸分塊法主要考慮的是段落和句子,而忽略了其他結(jié)構(gòu)上的細(xì)微差別。
此外,文檔以多種本地格式存儲,因此必須為每種不同的文檔類型設(shè)計(jì)不同的分隔符。上面的列表可能對純文本很有效,但對于標(biāo)記符,你需要一個(gè)更細(xì)致、更有針對性的分隔符列表;如果是 HTML 或 XML 文檔,還需要另一個(gè)列表,等等。將這種方法擴(kuò)展到處理 PDF 和 PowerPoint 演示文稿等基于圖像的文檔,會帶來更多復(fù)雜性。如果使用場景涉及各種非結(jié)構(gòu)化文檔,那么統(tǒng)一應(yīng)用遞歸分塊很快就會成為一項(xiàng)繁重的任務(wù)。
使用Unstructured智能分塊
這就意味著,你不必再想辦法區(qū)分文檔的各個(gè)部分。Unstructured 已經(jīng)完成了這些繁重的工作,直接展示不同的文檔元素,這些元素封裝了文檔中的段落、表格、圖片、代碼片段和其他任何有意義的文本單元。在完成分區(qū)步驟后,文檔已經(jīng)被劃分為更小的片段。這是否意味著文檔已經(jīng)分塊?不完全是,但已經(jīng)成功了一半!
分區(qū)后得到的某些文檔元素可能仍會超出嵌入模型的上下文窗口或所需的塊大小。這些需要進(jìn)一步分割。相反,有些文檔元素可能太小,無法包含足夠的上下文。例如,一個(gè)列表被分割成單個(gè)的 ListItem元素,但你可以選擇將這些元素合并成一個(gè)單一的塊,只要它們?nèi)匀环掀迷O(shè)置的塊大小。
從系統(tǒng)劃分為離散元素的文檔開始,Unstructured 提供的智能分塊策略可以做到這一點(diǎn):
- 確保信息流不中斷,防止簡單的字符分塊造成的中途分詞。
- 控制塊的最大和最小尺寸。
- 保證不同的主題或想法,如不同主題的獨(dú)立章節(jié),不會被合并。
智能分塊比遞歸分塊更進(jìn)一步,它實(shí)際上考慮到了文檔的語義結(jié)構(gòu)和內(nèi)容。
智能分塊提供了四種策略,它們在保證分塊內(nèi)容純凈度方面各有不同:
- 基本分塊策略:這種方法可以在遵守最大分塊大小限制的前提下,將連續(xù)元素組合起來,最大限度地填充每個(gè)分塊。如果單個(gè)孤立的元素超過了最大硬限制,就會被分成兩個(gè)或更多塊。
- 按標(biāo)題分塊策略:該策略利用分區(qū)過程中識別的文檔元素類型來理解文檔結(jié)構(gòu),并保留章節(jié)邊界。這就意味著,單個(gè)數(shù)據(jù)塊永遠(yuǎn)不會包含出現(xiàn)在兩個(gè)不同章節(jié)中的文本,從而確保主題保持自足,提高檢索精度。
- 按頁面分塊策略(僅支持API調(diào)用):該策略專為每一頁都能傳遞獨(dú)特信息的文檔而設(shè)計(jì),可確保來自不同頁面的內(nèi)容絕不會混雜在同一個(gè)分塊中。當(dāng)檢測到一個(gè)新頁面時(shí),即使下一個(gè)元素可以放在之前的內(nèi)容塊中,也會完成現(xiàn)有的內(nèi)容塊并開始一個(gè)新的內(nèi)容塊。
- 按相似性分塊策略(僅支持API調(diào)用):當(dāng)文檔結(jié)構(gòu)無法提供明確的主題邊界時(shí),可以使用 "通過相似性 "策略。該策略使用 "sentence-transformers/multi-qa-mpnet-base-dot-v1 "嵌入模型來識別在主題上相似的順序元素,并將它們組合成塊。
Unstructured 智能分塊策略的另一個(gè)優(yōu)勢是可普遍適用于各種文檔類型。不需要像遞歸分塊那樣,為每個(gè)文檔硬編碼和維護(hù)分隔符列表??梢暂p松嘗試分塊大小和分塊策略,為任何給定的使用場景找出最佳方案。
結(jié)論
分塊是任何 RAG 系統(tǒng)中必不可少的預(yù)處理步驟之一。設(shè)置時(shí)的選擇會影響檢索質(zhì)量,進(jìn)而影響系統(tǒng)的整體性能。以下是設(shè)計(jì)分塊步驟時(shí)需要注意的一些事項(xiàng):
- 嘗試不同的塊大小:雖然大塊可能包含更多上下文,但也會導(dǎo)致表述粗糙,對檢索精度產(chǎn)生負(fù)面影響。最佳塊大小取決于文檔的性質(zhì),但要在不丟失重要上下文的情況下優(yōu)化較小的塊。
- 利用巧妙的分塊策略:選擇分塊策略,在有語義意義的邊界上分隔文本,避免信息流中斷或內(nèi)容混雜。
- 評估分塊選擇對 RAG 整體性能的影響:為您的特定用例設(shè)置評估集,并跟蹤分塊大小和分塊策略實(shí)驗(yàn)對整體性能的影響。無論文檔類型如何,您只需調(diào)整一兩個(gè)參數(shù),非結(jié)構(gòu)化技術(shù)就能簡化分塊實(shí)驗(yàn)。
原文:https://unstructured.io/blog/chunking-for-rag-best-practices
本文轉(zhuǎn)載自?? AI工程化??,作者:ully
