
文檔處理流水線PDF解析與分塊策略詳解RAG系統的效果好不好很大程度上取決于知識庫的質量。而知識庫的質量第一步就在文檔處理。文檔從原始文件到變成可以檢索的向量塊中間要經過好幾步。加載、解析、清洗、分塊、向量化。每一步沒做好都會影響最終的檢索效果。很多人做RAG上來就搞向量數據庫、搞高級檢索算法。結果文檔處理沒做好后面再怎么優化都有限。地基打歪了樓蓋得再高也不結實。這一篇我們講文檔處理的完整流程。每一步做什么有哪些常見的坑怎么選擇合適的分塊策略。文檔處理的完整流程一個標準的文檔處理流水線大概分這么幾步。第一步加載。把原始文件讀進來PDF、Word、Excel、網頁各種格式都有。這一步的目標是把不同格式的文件統一轉換成純文本。第二步清洗。原始文本里有很多沒用的東西。頁眉頁腳、頁碼、目錄、水印、廣告、導航欄。這些東西要清理掉不然會混進檢索結果里影響質量。第三步分塊。把長文本切成一小塊一小塊的。塊太大了搜不準太小了又丟失上下文。切多大、怎么切里面有學問。第四步向量化。把每個文本塊轉換成向量存到向量數據庫里。這樣后面才能做語義檢索。第五步元數據。給每個塊加上元數據。來源文件、頁碼、章節、作者、時間。這些信息后面檢索的時候能用得上也方便溯源。這五步看起來簡單每一步都有不少細節。我們一個一個說。文檔加載加載是第一步不同格式有不同的加載器。上一篇文件處理工具里講過這里簡單回顧一下。PDF用PyMuPDFLoader或者UnstructuredPDFLoader。效果好的優先選PyMuPDF有圖片和復雜排版的用Unstructured加OCR。Word用Docx2txtLoader。需要結構信息用python-docx自己解析。Excel用pandas處理最方便。網頁用BeautifulSoup或者UnstructuredHTMLLoader。加載階段最容易出的問題是格式解析不準確。特別是PDF同樣是PDF用不同工具生成的解析出來的質量天差地別。我的建議是先拿你實際的文檔樣本測一下。看看解析出來的文本對不對、順序亂不亂、表格能不能讀、圖片里的文字要不要OCR。測完了再選合適的工具。別想當然地覺得所有PDF都能用同一種方式處理。實際項目里不同來源的PDF可能要寫不同的處理邏輯。文本清洗加載出來的原始文本通常是不干凈的。有很多噪音需要清理。常見的噪音有這些。頁眉頁腳和頁碼。幾乎所有長文檔都有。每頁重復出現不清理的話會被當成正文內容影響檢索。目錄和索引。文檔前面的目錄后面的索引都是導航用的不是正文。重復的版權聲明和免責聲明。很多文檔每頁底部都有重復很多遍。網頁的導航欄、廣告、推薦閱讀。爬下來的網頁大部分內容都是這些正文只占一小部分。亂碼和特殊字符。格式轉換的時候容易出現。清理的方法根據不同的情況來。頁眉頁腳可以根據位置信息去掉。PyMuPDF能拿到每個文本塊的坐標根據坐標判斷是不是頁眉頁腳。重復內容可以用相似度檢測。連續很多頁都出現的相同內容大概率是頁眉頁腳或者版權聲明。網頁用專門的正文提取庫。比如BeautifulSoup配合規則或者用newspaper3k、trafilatura這類專門的正文提取工具。清洗這一步很重要。臟數據進臟數據出。文本不干凈后面檢索出來的結果也會亂七八糟。文本分塊分塊是文檔處理里最關鍵的一步。切多大、怎么切直接影響檢索效果。分塊太大有什么問題。一個塊里內容太多可能只有一小部分跟問題相關但整塊都被檢索出來了。無關信息太多會稀釋有效內容影響大模型的判斷。也浪費Token。分塊太小又有什么問題。一個完整的意思被切成好幾塊單看哪一塊都不完整。檢索的時候可能只搜到一半上下文丟了回答就不準確。所以塊大小要合適。多大算合適沒有標準答案。跟你的文檔類型、用戶提問方式、用的Embedding模型都有關系。常見的經驗值是普通文檔200到500個中文字或者500到1000個英文詞。代碼文檔可以大一點800到1500個Token。FAQ類的可以小一點一個問答對就是一塊。這只是經驗值。實際項目里最好的辦法是做實驗。試幾種不同的塊大小看哪種效果最好。常見的分塊方法固定大小分塊。最簡單的方法。按字符數或者Token數切每塊固定大小。塊之間可以有一些重疊防止意思被切斷。LangChain里的RecursiveCharacterTextSplitter就是干這個的。它會優先按段落、句子、單詞來切盡量保持語義完整。fromlangchain.text_splitterimportRecursiveCharacterTextSplitter splitterRecursiveCharacterTextSplitter(chunk_size500,chunk_overlap50,separators[\n\n,\n,。,, ],)chunkssplitter.split_text(long_text)這種方法簡單通用大部分場景都能用。效果也還可以。按結構分塊。根據文檔的結構來切。標題、段落、列表、表格按結構單元來分。一塊就是一個相對完整的語義單元。比如Markdown文檔可以按標題層級來分。一個H2下面的內容作為一塊。或者一個H3下面的內容作為一塊。Word和HTML也可以按結構來分。標題、段落、表格每個元素單獨處理。按結構分塊的好處是語義更完整。一個章節講的是同一個主題放在一塊很合理。效果通常比固定大小分塊好。缺點是需要解析文檔結構。格式不規范的文檔結構解析不準分出來的塊也有問題。語義分塊。更高級的分法。用Embedding來判斷每句話的語義相似度語義變化大的地方就切一刀。這樣每一塊內部的語義是連貫的。聽起來很美好實際用起來效果不一定更好。而且速度慢、成本高。除非對分塊質量要求特別高不然不太推薦。我的建議說了這么多分塊方法到底用哪個。我的建議是先用最簡單的。遞歸字符分割chunk_size設500overlap設50。先把系統跑起來看效果怎么樣。效果不好再分析原因。是檢索不到相關內容還是搜到的內容不完整。是塊太大了還是太小了。然后針對性地調。不要一開始就追求最復雜的方案。很多時候固定大小分塊就夠用了。把精力花在更影響效果的地方比如重排序、Prompt優化、HyDE這些收益更大。還有一個經驗。塊里最好帶上上文信息。比如每一塊的開頭加上所屬的文檔標題和章節標題。這樣檢索的時候塊的上下文更完整相關性判斷也更準。元數據每個文本塊除了內容本身還要附上一些元數據。常見的元數據有這些。來源信息。文件名、文件路徑、URL。用來溯源。位置信息。頁碼、行號、章節。告訴用戶答案在文檔的什么位置。分類信息。文檔類型、產品分類、部門。用來做過濾。時間信息。創建時間、更新時間。可以按時間排序也可以判斷新舊。作者信息。誰寫的誰負責。元數據的用處很大。檢索的時候可以按元數據過濾只在指定的范圍內搜。回答問題的時候可以引用來源增加可信度。不要嫌麻煩。加元數據花不了多少時間后面會很有用。下一篇我們講向量數據庫。切好的文本塊怎么存進去怎么搜出來。