復雜文檔也能一鍵讀懂?PaddleOCR VL + RAG 給出新答案
當文檔包含復雜表格、數學公式或多欄排版時,傳統 OCR 工具往往會產出雜亂內容,需要手動整理。
就在上周,我逛 GitHub 時看到了百度新近開源的 PaddleOCR-VL-0.9B。
老實講,看到它只有 9 億參數時,我第一反應是:“哦,又一個小模型來湊熱鬧?”但出于職業好奇,我還是要問一句:它能打嗎?結果完全把我震住了。
這不只是 OCR,這是文檔理解的一次量子飛躍
PaddleOCR-VL 遠超我的預期。它在全球權威評測榜 OmniDocBench v1.5 的綜合性能中拿到 92.6 的分數,位列全球第一;推理速度相較 MinerU2.5 提升 14.2%,相較 dots.ocr 提升 253.01%。
我最直觀的感受是:它非常準,甚至“準得過分”!不愧是能登頂的第一名模型。
今天我會圍繞四個關鍵挑戰來測試 PaddleOCR-VL:公式識別、表格識別、閱讀順序與結構、手寫體識別。
先看公式識別。我上傳了一張包含復雜數學公式的圖片。可以看到,模型處理得非常好——對上標、下標以及冗長復雜的表達式都能精準解析。
接著是表格識別。這是出了名的難題,表格樣式多,有的帶邊框,有的不帶,且包含大量數字,模型非常容易誤判。我用 PaddleOCR-VL 處理了多種表格樣例,準確率真的很能打。
另一個大難點是文檔結構與閱讀順序的理解。現代文檔不僅內容更復雜,而且版式變化很大:多欄設計、圖文混排、折頁、彩色印刷、傾斜掃描、手寫批注……這些都會讓 OCR 更困難。正確的閱讀順序并不總是簡單的自上而下、從左到右。
PaddleOCR-VL 的技術報告展示了它幾乎“像人一樣”理解復雜結構。無論是學術論文、多欄報刊,還是技術報告,它都能智能分析版面,并恢復符合人類直覺的閱讀順序。
最后,即使面對更復雜的版式,PaddleOCR-VL 依然非常穩定。比如這張手寫便簽:它混合了文本、數字、段落與圖片,左右、上下都有分欄,這類版面通常只有人才能理清頭緒。
PaddleOCR VL 有何獨特之處?
PaddleOCR VL 不再只是簡單的文本識別,而是能夠真正“理解”文檔結構。無論是學術論文、多欄報刊還是技術報告,PaddleOCR-VL 都能智能理解版面布局,并自動按正確的順序組織內容。
同時,它還能準確抽取復雜內容,例如文檔中的表格、數學公式、手寫筆記、圖表數據,并將其轉換成可直接使用的結構化數據。
此外,PaddleOCR-VL 支持 109 種語言的識別,覆蓋中文、英文、法語、日語、俄語、阿拉伯語、西班牙語等多語種場景,極大提升了模型在多語文檔中的識別與處理能力。
PaddleOCR VL 是如何訓練的
PaddleOCR-VL 由兩部分組成:PP-DocLayoutV2 和 PaddleOCR-VL-0.9B。
其中核心是 PaddleOCR-VL-0.9B,它將一個預訓練視覺編碼器(visual encoder)與動態分辨率預處理器(dynamic resolution preprocessor)、兩層 MLP projector,以及一個預訓練大語言模型(LLM)集成到一起。
其預處理技術使用原生動態高分辨率(native dynamic high resolution)。視覺編碼器采用 NaViT 風格編碼器(NaViT style encoder),支持原生分辨率輸入。
這一設計減少了幻覺(hallucinations),并提升了多模態視覺語言模型 PaddleOCR-VL-0.9B 的表現。
Projector 高效地把視覺編碼器的特征對接到語言模型的 embedding 空間。
在自回歸語言模型(autoregressive language model)中,序列是按 token 逐個生成的。這意味著解碼器的規模會直接影響整體推理時延,模型越小,解碼越快。
Let's start coding
現在我們一步步來,拆解如何搭建一個強大的推理應用。先安裝模型所需的依賴庫。我們用 pip 安裝:
!pip uninstall -y torch paddlepaddle paddlepaddle-gpu
!pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118
!pip install paddleocr paddlepaddle
!pip install langchain langchain-community langchain-openai faiss-cpu sentence-transformers openai python-dotenv下一步照例是導入相關庫,隨著我們繼續,你會逐漸理解它們的作用,并進行一些基礎配置。
PaddleOCR:以業界領先的準確率,將文檔和圖像轉換為結構化、對 AI 友好的數據(如 JSON 與 Markdown),為 AI 應用提供支撐。
import torch
from paddleocr importPaddleOCR
from langchain.text_splitterimportRecursiveCharacterTextSplitter
from langchain_community.vectorstoresimportFAISS
from langchain_community.embeddingsimportHuggingFaceEmbeddings
from langchain_openai importChatOpenAI
from langchain.chainsimportRetrievalQA
from langchain.docstore.documentimportDocument于是我構建了這個 SimpleRAG 系統:用 PaddleOCR-VL 做文本抽取,用 OpenAI 生成回答。下面我來講講我是怎么做的。
在初始化階段,我配置了核心組件——使用 HuggingFace 的 BGE embeddings 做向量表示,使用 GPT-4o 作為對話模型,temperature 設為 0 以獲得穩定回復。我還初始化了稍后會構建的 vectorstore 和 QA chain。
在抽取方法上,一開始我嘗試了 HuggingFace transformers 版本的 PaddleOCR,結果報了一個關于 image tokens 不匹配的詭異錯誤;隨后安裝 PaddlePaddle 又把 PyTorch 搞壞了(不得不重啟環境,按正確順序重裝);接著我還得一路猜 API,因為有的方法已經棄用,新的參數也不一樣。
真正的突破來自我直接打印了返回結果對象的結構——原來它就是一個列表,列表里只有一個字典,而那個字典里有個鍵叫 rec_texts,里面就是識別到的所有文本字符串列表。
所以,與其去訪問什么復雜的嵌套結構比如 .boxes.text,我只需要判斷結果是不是字典,拿 rec_texts 這個鍵,把其中的字符串擴展進我的列表就好了。
class SimpleRAG:
def__init__(self):
self.embeddings = HuggingFaceEmbeddings(model_name="BAAI/bge-small-en-v1.5")
self.llm = ChatOpenAI(model="gpt-4o", temperature=0)
self.vectorstore = None
self.qa_chain = None
self.ocr = PaddleOCR(use_textline_orientation=True, lang='en')
defextract_text_from_images(self, image_paths: list):
docs = []
for path in image_paths:
result = self.ocr.predict(input=path)
text_lines = []
for res in result:
ifisinstance(res, dict) and'rec_texts'in res:
text_lines.extend(res['rec_texts'])
text = "\n".join(text_lines) if text_lines else"No text found"
docs.append(Document(page_content=text, metadata={'source': path}))
return docs在 build_index 中,我會先從所有圖片中抽取文本,再用 RecursiveCharacterTextSplitter 將文檔切分為 1000 字符、重疊 200 字符的塊,用 BGE embeddings 構建 FAISS vectorstore,并搭建一個基于 GPT-4o 的 RetrievalQA chain,每次檢索 top-3 的相關片段。
對于 query,我只需把問題傳給 QA chain,它會完成檢索與生成,并返回答案。
def build_index(self, image_paths: list):
docs = self.extract_text_from_images(image_paths)
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
splits = text_splitter.split_documents(docs)
self.vectorstore = FAISS.from_documents(splits, self.embeddings)
self.qa_chain = RetrievalQA.from_chain_type(
llm=self.llm,
retriever=self.vectorstore.as_retriever(search_kwargs={"k": 3})
)
defquery(self, question: str):
returnself.qa_chain.invoke(question)
# Usage
rag = SimpleRAG()
rag.build_index(["Your pic"])
answer = rag.query("extract all the table?")
print(answer)結語:
在這個 AI 技術飛速演進的時代,我們經常被“史上最強”“顛覆性”之類的宣傳包圍。然而真正有價值的突破,往往來自那些解決了具體問題、讓技術更易用的創新。
PaddleOCR-VL 也許不會登上大眾科技頭條,但對于每天都要處理文檔的開發者而言,它可能正是久等的答案。
畢竟,最好的技術,是能靜靜融入日常工作、讓你幾乎察覺不到它的存在。PaddleOCR-VL 正在扎實地朝這個方向邁進。
Reference:
本文轉載自??PyTorch研習社??,作者:AI研究生

















