如何使用本地 AI 模型自動化 PDF 資料擷取而不需雲端 API

最可靠的本地 PDF 擷取工作流程通常是一個流程線,而非單一的 AI 提示:首先從 PDF 中恢復可信賴的文字和版面,然後要求本地模型將該內容映射到嚴格的結構(Schema),最後在儲存前驗證欄位。將每個 PDF 頁面直接傳給視覺模型可能有效,但與使用原生 PDF 文字或 OCR(當這些足夠時)相比,這通常較慢、更耗費硬體資源,且更難稽核。

如果你的目標是「無雲端 API」,這個區別很重要。你仍然可以在自己的機器上使用本地 API——例如 Ollama 在 localhost 上的 HTTP 端點——而無需將文件內容傳送到託管服務。Ollama 聲明,當模型在本地運行時,提示和回應不會傳回給 Ollama,並且它提供了一個禁用雲端功能的僅本地模式。Docling 同樣預設保持遠端服務禁用,儘管模型檔案在設定期間可能仍需要下載,除非你預先取得它們以供離線使用。

正確的技術堆疊取決於 PDF 類型。具有可選取文字的數位原生發票需要與掃描收據、複雜財務表格或圖像密集型表單不同的方法。本指南比較了這些選項,並提供了一個四階段自動化模式,你可以將其調整用於發票、合約、採購訂單、申請表、報告和其他重複性文件。

快速建議:根據文件類型選擇流程線

PDF 類型實用的本地流程線主要優勢主要權衡
具有乾淨可選取文字的數位原生 PDFPyMuPDF → 本地文字 LLM → JSON 驗證速度快且硬體負載相對較輕純文字擷取可能會遺失閱讀順序或表格關係
具有簡單頁面的掃描 PDFOCRmyPDF/Tesseract → PyMuPDF → 本地文字 LLM在 AI 擷取前將頁面圖像轉換為可搜尋文字OCR 錯誤會變成模型輸入錯誤
包含文字、掃描件和表格的混合 PDFDocling 或 OCRmyPDF(跳過/重做模式)→ 本地 LLM對混合內容和文件結構有更好的控制更多的依賴項和處理時間
版面密集的表單、表格、圖表或具有視覺意義的頁面Docling 本地流程線或本地視覺模型 → 結構化輸出保留更多視覺/版面上下文通常需要更多運算能力和更強的驗證

沒有通用的贏家。如果你的文件是可預測的且包含嵌入文字,解析器加上小型本地語言模型可能在成本、速度和可重複性方面勝過大得多的視覺工作流程。如果文字的位置是意義的一部分——例如,具有合併單元的表格或標籤和值在空間上配對的表單——則版面感知處理變得更有價值。

步驟 1:在選擇 OCR 或 AI 之前對 PDF 進行分類

首先確定文件是否已經包含可用的文字。數位原生(Born-digital)意味著 PDF 是由軟體生成的,通常包含可選取和複製的文字物件。掃描 PDF 可能僅包含頁面圖像,因此常規文字解析器幾乎不會返回任何內容。

PyMuPDF 的官方文件展示了使用 page.get_text() 的直接文字擷取。一個最小的本地測試如下所示:

import pymupdf

def extract_native_text(pdf_path: str) -> str:
    pages = []
    with pymupdf.open(pdf_path) as doc:
        for page in doc:
            pages.append(page.get_text())
    return "\f".join(pages)

text = extract_native_text("invoice.pdf")
print(text[:1000])

請參閱官方 PyMuPDF 基礎知識。PyMuPDF 也警告說,純 PDF 文字可能不會以自然閱讀順序出現,並且可能包含意外的換行符。這是解析器的限制,不一定是 AI 問題。

最佳適用:文字複製/貼上已經有效且欄位易於從附近標籤識別的發票、對帳單、報告和表單。

注意:頁面可能包含微小的文字層加上大型掃描圖像。因此,僅檢查「是否存在某些文字」並不是完美的掃描偵測器。對於生產自動化,請檢查代表性文件,而不是依賴單一的通用字元計數閾值。

行動:取 20–50 個代表性 PDF 並將其分類為數位原生、掃描、混合和版面密集組。你的流程線應根據文件行為進行路由,而不僅僅是根據檔案副檔名。

AI 生成的插圖,顯示掃描和數位 PDF 檔案作為本地資料擷取流程線的輸入
PDF 輸入階段的 AI 生成插圖。這是一張概念工作流程圖像,不是特定 PDF 應用程式的截圖或基準測試結果。

步驟 2:在本地擷取文字——或者僅在需要時使用 OCR

選項 A:用於乾淨數位 PDF 的 PyMuPDF

如果文字層可靠,直接擷取通常是最簡單的路徑。它避免了 OCR 延遲,並避免了將 OCR 字元錯誤引入已正確編碼的文字中。對於長文件,你可以保留頁面分隔符並處理頁面組或邏輯章節,而不是一次性將整個文件傳遞給模型。

權衡:純文字便宜且快速,但表格、多欄頁面、頁首、頁尾和閱讀順序可能需要額外處理。如果這些關係對目標欄位很重要,請轉向版面感知表示,而不是在糟糕的源文字上堆積提示指令。

選項 B:用於掃描頁面的 OCRmyPDF 加上 Tesseract

Tesseract 是一個開源 OCR 引擎。其當前使用者手冊記錄了 5.x 系列以及透過單獨的訓練資料檔案對多種語言的支持。OCRmyPDF 將 OCR 包裝在 PDF 特定處理周圍,以便掃描頁面可以獲得可搜尋的文字層。

對於某些頁面已包含文字的混合文件,當前的 OCRmyPDF 版本支持 skip 模式:

ocrmypdf --mode skip input.pdf searchable.pdf

官方 OCRmyPDF 進階文件解釋說,--mode skip 會保留具有現有文字的頁面不變,並對需要 OCR 的頁面進行處理。同一文件描述了 redo 用於替換檢測到的先前 OCR,以及 force 用於柵格化並對所有內容進行 OCR。請謹慎使用 force,因為柵格化可能會丟棄向量優勢並扁平化互動內容。

關於 Tesseract 安裝、語言和命令列行為,請使用官方 Tesseract 使用者手冊。OCR 語言很重要:例如,如果你的發票包含英文和德文,請安裝並配置適當的語言資料,而不是假設預設的英文模型能同樣好地處理兩者。

選項 C:當結構很重要時使用 Docling

Docling 專為具有版面、表格、OCR 和本地視覺語言處理選項的文件轉換而設計。其專案文件列出了進階 PDF 理解、表格結構、OCR 和無損 JSON/Markdown 樣式輸出,並旨在為敏感和氣隙(air-gapped)工作流程提供本地執行。

基本的 Python 轉換可以非常簡短:

from docling.document_converter import DocumentConverter

converter = DocumentConverter()
doc = converter.convert("input.pdf").document

markdown = doc.export_to_markdown()
structured = doc.export_to_dict()

請參閱官方 Docling 快速入門。Docling 也支持本地 VLM 流程線和幾個 OCR 後端。其進階選項解釋說,遠端服務呼叫需要明確選擇加入,而模型工件可以預先取得以供離線使用。

最佳適用:複雜表格、標題、多欄報告、混合掃描件,或者當你希望獲得可重用的文件表示而不是純文字轉儲時。

權衡:該流程線比簡單的 PDF 解析器更重。使用它是因為額外的結構提高了你的擷取準確性——而不僅僅是因為它有更多的組件。

行動:選擇能保留你的目標結構所需資訊的最輕量級擷取方法。不要對乾淨的嵌入文字進行 OCR,也不要丟棄決定意義的版面。

AI 生成的插圖,比較掃描 PDF 的 OCR 與數位 PDF 的直接文字擷取
為掃描件選擇 OCR 並為數位原生 PDF 選擇直接擷取的 AI 生成插圖。它代表決策概念,而不是真實的 OCR 應用程式介面。

步驟 3:使用本地模型將恢復的內容映射到嚴格結構

一旦你有了可信賴的源內容,就讓本地模型做它擅長的事情:語義映射。不要問「從這張發票中提取所有內容」,而是定義你實際需要的欄位。

例如:

from pydantic import BaseModel
from typing import Optional

class LineItem(BaseModel):
    description: str
    quantity: Optional[float]
    unit_price: Optional[float]
    amount: Optional[float]

class Invoice(BaseModel):
    invoice_number: Optional[str]
    invoice_date: Optional[str]
    vendor_name: Optional[str]
    currency: Optional[str]
    subtotal: Optional[float]
    tax: Optional[float]
    total: Optional[float]
    items: list[LineItem]

Ollama 當前的結構化輸出文件支持透過 format 欄位傳遞 JSON Schema 並使用 Pydantic 驗證回應。本地呼叫可以如下所示:

from ollama import chat

schema = Invoice.model_json_schema()

prompt = f"""
Extract the invoice into the supplied schema.

Rules:
- Use only information present in the source.
- Use null when a field is not found.
- Do not infer missing invoice numbers, dates, tax, or totals.
- Preserve line items individually.

SOURCE:
{text}
"""

response = chat(
    model="gpt-oss",
    messages=[{"role": "user", "content": prompt}],
    format=schema,
    options={"temperature": 0},
)

invoice = Invoice.model_validate_json(response.message.content)

這遵循了 Ollama 官方結構化輸出文件中的模式,該文件建議使用可重用的結構和較低的溫度(如零)以獲得更具確定性的結構化補全。

上面的模型名稱是來自 Ollama 自己的結構化輸出文件的示例,並非聲稱它是每個擷取工作的最佳模型。對於具有清晰標籤的重複性發票,較小的模型可能就足夠了;較強的模型可能有助於處理模糊的合約或不一致的版面,但通常需要更多的記憶體和處理時間。

文字模型還是視覺模型?

當解析器/OCR 輸出已經保留了你需要的欄位關係時,使用文字模型。當視覺位置至關重要或文字轉換持續遺失結構時,使用具有視覺能力的本地模型。Ollama 的官方視覺文件支持向本地視覺模型輸入圖像,其結構化輸出功能可以與具有視覺能力的模型結合使用。

然而,將每個頁面渲染為圖像會改變權衡:

  • 必須處理更多像素;
  • 高解析度頁面消耗更多運算和記憶體;
  • 對於長 PDF,頁面批次處理變得重要;
  • 視覺模型仍然可能捏造欄位或誤讀數字;
  • 你需要一種方法將擷取的值追溯回頁面或源區域。

行動:從解析器/OCR 文字加上結構約束的本地 LLM 開始。僅將困難的頁面類型升級到本地 VLM,而不是為每個頁面支付視覺成本。

AI 生成的插圖,顯示本地 AI 模型識別欄位並從文件內容產生結構化資料
本地模型階段的 AI 生成插圖。它不描繪真實的 Ollama 螢幕,也不暗示本地模型可以在無需驗證的情況下擷取每個欄位。

步驟 4:在寫入 JSON、CSV、Excel 或資料庫之前進行驗證

結構有效的 JSON 並不自動代表事實正確。模型可能會產生具有錯誤值的有效欄位。因此,最後一個階段應盡可能使用確定性檢查。

對於發票,有用的檢查包括:

  • 必需的身份欄位:如果你的工作流程需要,發票號碼或供應商名稱必須存在。
  • 日期解析:使用固定策略解析日期,而不是信任像 03/04/26 這樣模糊的字串。
  • 算術:在定義的容差範圍內比較行項目金額總和與文件小計。
  • 總計:驗證小計加上稅款和其他費用是否與總計一致。
  • 貨幣:不要因為文件是英文就假設是美元。
  • 來源:儲存源檔案名、頁碼、擷取時間戳,以及可選的原始 PDF 雜湊值。
  • 審查佇列:將缺失、衝突或低置信度的情況路由進行人工審查,而不是靜默填充值。

基本的批次結構可以將擷取與驗證分開:

from pathlib import Path
import json

for pdf_path in Path("inbox").glob("*.pdf"):
    source_text = extract_native_text(str(pdf_path))

    # If text is unusable, run your OCR or Docling branch here.
    record = extract_with_local_model(source_text)

    errors = validate_record(record)

    if errors:
        save_for_review(pdf_path, record, errors)
    else:
        output = Path("processed") / f"{pdf_path.stem}.json"
        output.write_text(
            json.dumps(record, ensure_ascii=False, indent=2),
            encoding="utf-8"
        )

輔助函數故意保持應用程式特定,因為發票、合約、稅表、實驗室報告和採購訂單之間的驗證規則差異巨大。通用驗證器會產生虛假的信心。

如果你需要 CSV 或 Excel,僅展平實際屬於行和列的欄位。對於具有重複行項目的文件,創建一個文件級表格和一個由文件 ID 連結的第二個行項目表格通常比強制將每個欄位放入一個寬電子表格行更清晰。

行動:在處理數千個檔案之前定義驗證規則。針對標記的樣本集進行測試,並記錄欄位級準確性,而不僅僅是「文件成功處理」。

AI 生成的插圖,顯示將本地擷取的 PDF 資料儲存到 Excel、CSV 或 JSON
本地匯出目標(如 Excel、CSV 和 JSON)的 AI 生成插圖。這是一個概念端點,並非每個 PDF 都可以在無需審查的情況下轉換的證據。

實用的完全本地架構

對於許多中小型自動化工作,這種職責劃分比一體化模型更容易維護:

PDF inbox
   |
   +-- born-digital --> PyMuPDF -------------------+
   |                                               |
   +-- scanned/mixed --> OCRmyPDF/Tesseract -------+--> normalized text/layout
   |                                               |
   +-- layout-heavy --> Docling -------------------+
                                                   |
                                                   v
                                         local LLM / VLM
                                                   |
                                            JSON Schema
                                                   |
                                                   v
                                   deterministic validation
                                                   |
                            +----------------------+----------------+
                            |                      |                |
                           JSON                   CSV             database

這種設計允許你獨立交換組件。如果 OCR 品質較弱,請改進 OCR 層而無需重新訓練 LLM。如果本地模型太慢,請使用較小的模型而無需更改 PDF 解析器。如果某個供應商的發票需要特殊的表格處理,僅將那些檔案通過 Docling 或視覺分支路由。

Ollama vs. llama.cpp vs. Docling VLM:你應該選擇哪個本地執行時?

選項何時使用優勢權衡
Ollama你想要最容易的本地模型 API 和結構約束輸出簡單的 localhost API、結構化 JSON、相容模型的視覺支持抽象層給你的低層執行時控制比裸推理引擎少
llama.cpp你想要直接的 GGUF 控制、命令列部署或輕量級本地伺服器本地 CLI/伺服器和語法/JSON 結構約束生成更多的模型/執行時細節由你負責
Docling VLM你的主要挑戰是文件版面轉換而不是一般的聊天樣式擷取以文件為中心的本地 VLM 流程線,具有 Markdown/HTML/DocTags 樣式輸出最好將其視為文件轉換組件,而不是每個業務規則擷取步驟的替代品

官方 llama.cpp 儲存庫記錄了本地 llama-server 和語法約束生成;當前的伺服器程式碼也接受 JSON 結構約束。Docling 的視覺模型文件列出了用於文件轉換的本地 VLM 選項。

不要僅根據模型排行榜選擇執行時。對於 PDF 擷取,實際的衡量標準是欄位準確性、每份文件的吞吐量、你機器上的記憶體使用量、你的版面失敗率、啟動複雜度,以及你檢查錯誤結果的容易程度。

如何保持流程線真正本地化

「無雲端 API」應該是一個你可以驗證的部署屬性,而不僅僅是一個行銷標籤。

Ollama

Ollama 的官方 FAQ 表示本地提示和答案不會傳回給 Ollama。它還記錄了雲端禁用設定:

OLLAMA_NO_CLOUD=1

或等效的 disable_ollama_cloud 伺服器設定。根據其驗證文件,Ollama 的本地 API 運行在 http://localhost:11434,並且本地存取不需要驗證。

請記住,綁定到 localhost 的服務與暴露給你的 LAN 的服務不同。如果你更改其綁定位址或將其放置在另一個伺服器後面,你負責存取控制。

Docling

Docling 預設保持遠端服務使用禁用。其文件還區分了處理隱私與模型獲取:除非你預先下載,否則模型可能會在首次使用時被獲取。對於氣隙系統,請在連接的暫存機器上使用 docling-tools models download 或以其他方式預先暫存批准的模型工件,然後將離線環境指向該本地工件目錄。

行動:在處理敏感文件之前,在作業系統或網路層阻擋出站網路存取,並在監控連接的同時運行測試。應用程式設定很有用,但網路控制提供了一個獨立的驗證層。

本地 AI 無法解決的問題

本地運行改善了資料控制選項,但它不會自動使擷取正確、合規或安全。本地檔案仍然可能透過除錯日誌、臨時目錄、備份、共用資料夾、過度寬鬆的服務或複製的匯出洩漏。本地模型也可能像託管模型一樣產生幻覺值。

不要將模型作為高影響欄位(如銀行帳號、付款指示、合約日期、醫療值或監管識別碼)的唯一驗證器。對於這些,請與源文字進行比較,應用確定性驗證,並在置信度不足時要求人工審查。

在自動化整個資料夾之前如何測試

建立一個包含你實際收到的案例的小型標記評估集:

  • 乾淨的數位 PDF;
  • 低解析度掃描;
  • 旋轉或傾斜的頁面;
  • 多頁發票;
  • 跨頁表格;
  • 缺失的可選欄位;
  • 不同的日期和數字格式;
  • 至少一個故意困難的文件。

對於每個目標欄位,將擷取值與真實值進行比較。測量識別碼的精確匹配、金額的數值容差和行項目的行級準確性。同時記錄處理時間和發送至人工審查的文件百分比。

如果更簡單的 PyMuPDF 加上 LLM 路徑達到你所需的準確性,請保留它。如果掃描件是主要失敗原因,請改進 OCR。如果表格關係是問題,請測試 Docling。如果視覺定位的欄位仍然困難,請將該子集通過本地視覺模型路由。這種分階段升級通常比將最重的模型應用於每個頁面給你更好的速度和硬體使用控制。

結論

一個好的本地 PDF 擷取系統將文件閱讀語義擷取分開。當 PDF 已經包含良好的文字時使用 PyMuPDF;當頁面是掃描件時使用 OCRmyPDF/Tesseract;當結構和表格很重要時使用 Docling;當你需要靈活映射到業務結構時使用本地 Ollama 或 llama.cpp 模型。僅在視覺版面添加了文字流程線無法可靠保留的資訊時使用本地視覺。

最終要求是驗證。JSON Schema 可以約束模型回應的形狀,但它無法證明金額、日期、名稱或帳號與源匹配。如果你設計流程線使得不確定的文件可見且可審查,你可以自動化很大一部分 PDF 資料擷取,而無需將文件交給雲端 API——也無需假裝本地 AI 消除了品質控制的需求。

留下評論

如何阻止 CrewAI 代理執行冗餘任務:實用去重指南

如何阻止 CrewAI 代理執行冗餘任務:實用去重指南

透過修復任務所有權、依賴關係、委託、重試、流程觸發器、狀態持久性、快取和冪等性,防止 CrewAI 代理重複工作。

HubSpot Free CRM vs Zoho CRM for Solo Real Estate Agents: Which Fits Better in 2026?

HubSpot Free CRM vs Zoho CRM for Solo Real Estate Agents: Which Fits Better in 2026?

Compare HubSpot Free CRM and Zoho CRM Free for solo real estate agents, including contact limits, pipelines, email, automation, mobile tools, and upgrade tradeoffs.

如何在 Windows 11 上使用 LM Studio 離線執行 DeepSeek

如何在 Windows 11 上使用 LM Studio 離線執行 DeepSeek

在 Windows 11 上使用 LM Studio 本地執行 DeepSeek。了解適合一般 PC 的模型、如何下載與載入、驗證離線使用,以及解決常見問題。

如何利用提示詞壓縮技術將 API Token 成本降低 50%

如何利用提示詞壓縮技術將 API Token 成本降低 50%

透過四種實用的提示詞壓縮技術、緩存友好的佈局、結構化輸出以及保留品質的評估計畫,來降低 LLM API 成本。

如何使用 n8n 和 Claude 建立免費的 AI 內容再利用流程(真正免費的部分是什麼)

如何使用 n8n 和 Claude 建立免費的 AI 內容再利用流程(真正免費的部分是什麼)

使用自託管的 n8n 和 Claude 建立可免費託管的 AI 內容再利用流程,包含結構化輸出、審核閘門以及現實的 API 成本指南。

如何將本地 Ollama 模型連接至 Obsidian 以進行個人知識管理

如何將本地 Ollama 模型連接至 Obsidian 以進行個人知識管理

將 Ollama 連接至 Obsidian 以實現本地 AI 聊天與感知資料庫的 PKM。學習設定、品質檢查、本地嵌入、隱私限制,以及何時更換模型。

逐步指南:使用 AI 代理自動化每週競爭對手監控

逐步指南:使用 AI 代理自動化每週競爭對手監控

使用 AI 代理、網路搜尋、有證據支持的變更偵測、GitHub Actions 排程以及人工審核,建立每週競爭對手監控工作流程。

Claude 系統提示詞:如何為技術文件設定語氣界線

Claude 系統提示詞:如何為技術文件設定語氣界線

學習如何使用 Claude 系統提示詞,為一致的技術文件設定清晰的語氣、受眾、格式、不確定性及風格界線。

如何保護您的本地 RAG 系統免受提示注入攻擊

如何保護您的本地 RAG 系統免受提示注入攻擊

透過針對資料攝取、檢索、存取控制、提示邊界、工具權限、輸出驗證及紅隊測試的實用控制措施,保護本地 RAG 系統免受提示注入攻擊。

如何修復 Outlook「無法傳送郵件但可接收」錯誤

如何修復 Outlook「無法傳送郵件但可接收」錯誤

Outlook 能收信但無法寄信?按實用順序診斷寄件匣、離線模式、密碼、SMTP 設定、帳戶限制、設定檔及增益集。