Home
» Domeinen
»
PDF-gegevensextractie automatiseren met lokale AI-modellen zonder cloud-API
PDF-gegevensextractie automatiseren met lokale AI-modellen zonder cloud-API
De meest betrouwbare lokale PDF-extractiewerkstroom is meestal een pijplijn, geen enkele AI-prompt: herstel eerst betrouwbare tekst en lay-out uit de PDF, vraag vervolgens een lokaal model om die inhoud af te beelden op een strikt schema, en valideer ten slotte de velden voordat je ze opslaat. Het rechtstreeks sturen van elke PDF-pagina naar een vision-model kan werken, maar is vaak langzamer, hardware-intensiever en moeilijker te auditen dan het gebruik van native PDF-tekst of OCR wanneer die voldoende zijn.
Dit onderscheid is belangrijk als je doel “geen cloud-API” is. Je kunt nog steeds een lokale API op je eigen machine gebruiken—bijvoorbeeld het HTTP-eindpunt van Ollama op localhost—zonder documentinhoud naar een gehoste service te sturen. Ollama stelt dat prompts en antwoorden niet worden teruggestuurd naar Ollama wanneer modellen lokaal draaien, en biedt een alleen-lokaal modus die cloudfuncties uitschakelt. Docling houdt externe services standaard ook uitgeschakeld, hoewel modelbestanden mogelijk nog moeten worden gedownload tijdens de installatie, tenzij je ze vooraf ophaalt voor offline gebruik.
De juiste stack hangt af van de PDF. Geboren-digitale facturen met selecteerbare tekst vereisen een andere aanpak dan gescande bonnetjes, ingewikkelde financiële tabellen of beeldrijke formulieren. Deze gids vergelijkt die opties en geeft een vierfasen automatiseringspatroon dat je kunt aanpassen aan facturen, contracten, inkooporders, aanvraagformulieren, rapporten en andere terugkerende documenten.
Snelle aanbeveling: kies de pijplijn op basis van het documenttype
PDF-type
Praktische lokale pijplijn
Belangrijkste voordeel
Belangrijkste afweging
Geboren-digitale PDF met schone selecteerbare tekst
PyMuPDF → lokaal tekst-LLM → JSON-validatie
Snel en relatief licht voor hardware
Gewone extractie kan leesvolgorde of tabelrelaties verliezen
Gescande PDF met eenvoudige pagina's
OCRmyPDF/Tesseract → PyMuPDF → lokaal tekst-LLM
Zet pagina-afbeeldingen om in doorzoekbare tekst vóór AI-extractie
OCR-fouten worden invoerfouten voor het model
Gemengde PDF met tekst, scans en tabellen
Docling of OCRmyPDF in skip/redo-modus → lokaal LLM
Bettere controle over gemengde inhoud en documentstructuur
Meer afhankelijkheden en verwerkingstijd
Lay-outrijke formulieren, tabellen, diagrammen of visueel betekenisvolle pagina's
Docling lokale pijplijn of lokaal vision-model → gestructureerde output
Behoudt meer visuele/lay-outcontext
Vereist meestal meer rekenkracht en sterkere validatie
Er is geen universele winnaar. Als je documenten voorspelbaar zijn en ingebedde tekst bevatten, kan een parser plus een klein lokaal taalmodel beter presteren dan een veel grotere vision-workflow op het gebied van kosten, snelheid en reproduceerbaarheid. Als de positie van de tekst deel uitmaakt van de betekenis—bijvoorbeeld een tabel met samengevoegde cellen of een formulier waar labels en waarden ruimtelijk gekoppeld zijn—wordt lay-outbewuste verwerking waardevoller.
Stap 1: Classificeer de PDF voordat je OCR of AI kiest
Bepaal eerst of het document al bruikbare tekst bevat. Geboren-digitaal betekent dat de PDF is gegenereerd vanuit software en meestal tekstobjecten bevat die kunnen worden geselecteerd en gekopieerd. Een gescande PDF kan alleen pagina-afbeeldingen bevatten, dus een normale tekstparser geeft weinig of niets terug.
De officiële documentatie van PyMuPDF toont directe tekstextractie met page.get_text(). Een minimale lokale test ziet er als volgt uit:
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])
Zie de officiële PyMuPDF-basisprincipes. PyMuPDF waarschuwt ook dat platte PDF-tekst mogelijk niet in natuurlijke leesvolgorde verschijnt en onverwachte regeleinden kan bevatten. Dat is een beperking van de parser, niet per se een AI-probleem.
Beste fit: facturen, overzichten, rapporten en formulieren waar tekst kopiëren/plakken al werkt en de velden eenvoudig te identificeren zijn aan de hand van nabijgelegen labels.
Let op: een pagina kan een kleine tekstlaag plus een grote gescande afbeelding bevatten. Simpelweg controleren of “er enige tekst bestaat” is daarom geen perfecte scan-detectie. Voor productieautomatisering moet je representatieve documenten inspecteren in plaats van te vertrouwen op één universele drempelwaarde voor het aantal tekens.
Actie: neem 20–50 representatieve PDF's en classificeer ze in groepen geboren-digitaal, gescand, gemengd en lay-outrijk. Je pijplijn moet routeren op basis van documentgedrag, niet alleen op basis van bestandsextensie.
AI-gegenereerde illustratie van de PDF-invoerfase. Het is een conceptuele workflowafbeelding, geen screenshot van een specifieke PDF-toepassing of een benchmarkresultaat.
Stap 2: Extraheer tekst lokaal—or gebruik OCR alleen wanneer nodig
Optie A: PyMuPDF voor schone digitale PDF's
Als de tekstlaag betrouwbaar is, is directe extractie normaal gesproken de eenvoudigste route. Het vermijdt OCR-latentie en voorkomt dat OCR-tekenfouten worden geïntroduceerd in tekst die al correct was gecodeerd. Voor lange documenten kun je paginascheiders behouden en paginagroepen of logische secties verwerken in plaats van het hele document tegelijk aan het model door te geven.
Afweging: platte tekst is goedkoop en snel, maar tabellen, meerkolompagina's, koppen, voetten en leesvolgorde kunnen extra afhandeling vereisen. Als die relaties belangrijk zijn voor de doelvelden, ga dan over naar een lay-outbewuste representatie in plaats van prompt-instructies op slechte brontekst te stapelen.
Optie B: OCRmyPDF plus Tesseract voor gescande pagina's
Tesseract is een open-source OCR-engine. De huidige gebruikershandleiding documenteert de 5.x-serie en ondersteuning voor veel talen via aparte getrainde gegevensbestanden. OCRmyPDF wikkelt OCR rond PDF-specifieke verwerking, zodat gescande pagina's een doorzoekbare tekstlaag kunnen krijgen.
Voor een gemengd document waar sommige pagina's al tekst bevatten, ondersteunen huidige OCRmyPDF-versies een skip-modus:
ocrmypdf --mode skip input.pdf searchable.pdf
De officiële OCRmyPDF geavanceerde documentatie legt uit dat --mode skip pagina's met bestaande tekst met rust laat en de pagina's OCR't die dat nodig hebben. Dezelfde documentatie beschrijft redo voor het vervangen van gedetecteerde eerdere OCR en force voor het rasteriseren en OCR'en van alle inhoud. Gebruik force voorzichtig, omdat rasterisatie vectorvoordelen kan discarteren en interactieve inhoud kan platdrukken.
Voor Tesseract-installatie, talen en command-line gedrag, gebruik de officiële Tesseract-gebruikershandleiding. OCR-taal is belangrijk: als je facturen Engels en Duits bevatten, installeer en configureer dan de juiste taalgegevens in plaats van aan te nemen dat het standaard Engelse model beide even goed zal verwerken.
Optie C: Docling wanneer structuur ertoe doet
Docling is ontworpen voor documentconversie met opties voor lay-out, tabel, OCR en lokale vision-taalverwerking. De projectdocumentatie noemt geavanceerd PDF-begrip, tabelstructuur, OCR en verliesloze JSON/Markdown-stijl outputs, met lokale uitvoering bedoeld voor gevoelige en air-gapped workflows.
Zie de officiële Docling quickstart. Docling ondersteunt ook lokale VLM-pijplijnen en verschillende OCR-backends. De geavanceerde opties leggen uit dat aanroepen naar externe services expliciete opt-in vereisen, terwijl modelartefacten vooraf kunnen worden opgehaald voor offline gebruik.
Beste fit: complexe tabellen, koppen, meerkolomrapporten, gemengde scans, of gevallen waarin je een herbruikbare documentrepresentatie wilt in plaats van een platte tekstdump.
Afweging: de pijplijn is zwaarder dan een eenvoudige PDF-parser. Gebruik het omdat de extra structuur je extractienauwkeurigheid verbetert—niet alleen omdat het meer componenten heeft.
Actie: kies de lichtste extractiemethode die de informatie behoudt die je doelschema nodig heeft. OCR geen schone ingebedde tekst, en gooi lay-out niet weg wanneer lay-out de betekenis bepaalt.
AI-gegenereerde illustratie van het kiezen van OCR voor scans en directe extractie voor geboren-digitale PDF's. Het vertegenwoordigt het beslissingsconcept, niet de interface van een echte OCR-toepassing.
Stap 3: Beeld de herstelde inhoud af op een strikt schema met een lokaal model
Zodra je betrouwbare broninhoud hebt, gebruik je het lokale model voor waar het goed in is: semantische afbeelding. In plaats van te vragen: “Extraheer alles uit deze factuur”, definieer je de velden die je daadwerkelijk nodig hebt.
Bijvoorbeeld:
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]
De huidige documentatie over gestructureerde outputs van Ollama ondersteunt het doorgeven van een JSON Schema via het format-veld en het valideren van de respons met Pydantic. Een lokale aanroep kan er zo uitzien:
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)
Dit volgt het patroon in de officiële Structured Outputs-documentatie van Ollama, die herbruikbare schema's en een lage temperatuur zoals nul aanbeveelt voor meer deterministische gestructureerde voltooiingen.
De modelnaam hierboven is een voorbeeld uit de eigen gestructureerde-outputdocumentatie van Ollama, niet een bewering dat het het beste model is voor elke extractietaak. Een kleiner model kan voldoende zijn voor repetitieve facturen met duidelijke labels; een sterker model kan helpen bij ambiguë contracten of inconsistente lay-outs, maar zal over het algemeen meer geheugen en verwerkingstijd vereisen.
Tekstmodel of vision-model?
Gebruik een tekstmodel wanneer de parser/OCR-output al de veldrelaties behoudt die je nodig hebt. Gebruik een vision-capabel lokaal model wanneer visuele positie essentieel is of de tekstconversie consequent structuur verliest. De officiële Vision-documentatie van Ollama ondersteunt invoer van afbeeldingen naar lokale vision-modellen, en de functie voor gestructureerde outputs kan worden gecombineerd met vision-capabele modellen.
Echter, het renderen van elke pagina naar een afbeelding verandert de afweging:
er moeten meer pixels worden verwerkt;
pagina's met hoge resolutie verbruiken meer rekenkracht en geheugen;
pagina-batching wordt belangrijk voor lange PDF's;
visuele modellen kunnen nog steeds een veld verzinnen of een getal verkeerd lezen;
je hebt een manier nodig om geëxtraheerde waarden terug te volgen naar een pagina of bronregio.
Actie: begin met parser/OCR-tekst plus een schema-beperkt lokaal LLM. Escaleer alleen de moeilijke paginatypes naar een lokaal VLM in plaats van de vision-kosten voor elke pagina te betalen.
AI-gegenereerde illustratie van de lokale modelfase. Het beeldt geen echt Ollama-scherm af en impliceert niet dat een lokaal model elk veld zonder validatie kan extraheren.
Stap 4: Valideer voordat je JSON, CSV, Excel of een database schrijft
Schema-valide JSON is niet automatisch feitelijk correct. Een model kan geldige velden met de verkeerde waarden produceren. De laatste fase moet daarom waar mogelijk deterministische controles gebruiken.
Voor een factuur zijn nuttige controles onder andere:
Vereiste identiteitsvelden: factuurnummer of leveranciersnaam moet aanwezig zijn als je workflow die nodig heeft.
Datumverwerking: verwerk datums met een vast beleid in plaats van ambiguë strings zoals 03/04/26 te vertrouwen.
Rekenkunde: vergelijk de som van de regelbedragen met de subtotaal van het document binnen een gedefinieerde tolerantie.
Totalen: verifieer of subtotaal plus belasting en andere kosten consistent is met het totaal.
Valuta: ga niet uit van USD omdat het document in het Engels is.
Herkomst: sla de bronbestandsnaam, paginanummer, extractietijdstempel en optioneel een hash van de originele PDF op.
Reviewwachtrij: routeer ontbrekende, tegenstrijdige of laagvertrouwensgevallen voor menselijke review in plaats van stilzwijgend waarden in te vullen.
Een basis batchstructuur kan extractie scheiden van validatie:
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"
)
De helperfuncties zijn bewust applicatiespecifiek gelaten omdat validatieregels enorm verschillen tussen facturen, contracten, belastingformulieren, laboratoriumrapporten en inkooporders. Een universele validator zou vals vertrouwen creëren.
Als je CSV of Excel nodig hebt, platdruk alleen de velden die daadwerkelijk in rijen en kolommen thuishoren. Voor documenten met herhaalde regelitems is het vaak schoner om één documentniveau-tabel en een tweede tabel voor regelitems te maken die gekoppeld zijn via een document-ID, in plaats van elk veld in één brede spreadsheetrij te dwingen.
Actie: definieer validatieregels voordat je duizenden bestanden verwerkt. Test tegen een gelabelde steekproefset en registreer veldnauwkeurigheid, niet alleen “documenten succesvol verwerkt”.
AI-gegenereerde illustratie van lokale exportdoelen zoals Excel, CSV en JSON. Het is een conceptueel eindpunt, geen bewijs dat elke PDF zonder review kan worden geconverteerd.
Een praktische volledig lokale architectuur
Voor veel kleine en middelgrote automatiseringstaken is deze verdeling van verantwoordelijkheden eenvoudiger te onderhouden dan een alles-in-één-model:
Dit ontwerp stelt je in staat componenten onafhankelijk uit te wisselen. Als de OCR-kwaliteit zwak is, verbeter je de OCR-laag zonder het LLM opnieuw te trainen. Als het lokale model te traag is, gebruik je een kleiner model zonder de PDF-parser te veranderen. Als facturen van één leverancier speciale tabelafhandeling nodig hebben, routeer je alleen die bestanden via Docling of een vision-tak.
Ollama vs. llama.cpp vs. Docling VLM: welke lokale runtime moet je kiezen?
Optie
Gebruik het wanneer
Sterkte
Afweging
Ollama
Je wilt de eenvoudigste lokale model-API en schema-beperkte output
Eenvoudige localhost-API, gestructureerde JSON, vision-ondersteuning voor compatibele modellen
Abstractie geeft je minder low-level runtime-controle dan een kaal inferentie-engine
llama.cpp
Je wilt directe GGUF-controle, command-line implementatie of een lichte lokale server
Lokale CLI/server en grammatica/JSON-schema beperkte generatie
Meer model/runtime-details zijn jouw verantwoordelijkheid
Docling VLM
Je belangrijkste uitdaging is documentlay-outconversie in plaats van algemene chat-stijl extractie
Documentgerichte lokale VLM-pijplijn met Markdown/HTML/DocTags-stijl outputs
Beschouw het als een documentconversiecomponent, niet als vervanging voor elke business-rule extractiestap
De officiële llama.cpp-repository documenteert een lokale llama-server en grammatica-beperkte generatie; huidige servercode accepteert ook JSON-schema-beperkingen. De Vision Models-documentatie van Docling noemt lokale VLM-opties voor documentconversie.
Kies geen runtime alleen op basis van een modelleaderboard. Voor PDF-extractie zijn de praktische maatstaven veldnauwkeurigheid, doorvoer per document, geheugengebruik op je machine, faalpercentage op je lay-outs, opstartcomplexiteit en hoe eenvoudig je verkeerde resultaten kunt inspecteren.
Hoe houd je de pijplijn echt lokaal
“Geen cloud-API” moet een implementatie-eigenschap zijn die je kunt verifiëren, niet alleen een marketinglabel.
Ollama
De officiële FAQ van Ollama zegt dat lokale prompts en antwoorden niet worden teruggestuurd naar Ollama. Het documenteert ook een instelling om cloud uit te schakelen:
OLLAMA_NO_CLOUD=1
of de equivalente disable_ollama_cloud serverinstelling. De lokale API van Ollama draait op http://localhost:11434 en vereist geen authenticatie voor lokale toegang, volgens de authenticatiedocumentatie.
Vergeet niet dat een service die aan localhost is gebonden anders is dan een die aan je LAN is blootgesteld. Als je het bind-adres wijzigt of het achter een andere server plaatst, ben jij verantwoordelijk voor toegangscontrole.
Docling
Docling houdt het gebruik van externe services standaard uitgeschakeld. De documentatie maakt ook onderscheid tussen privacy bij verwerking en modelverwerving: modellen kunnen bij eerste gebruik worden opgehaald, tenzij je ze vooraf downloadt. Voor een air-gapped systeem, gebruik docling-tools models download op een verbonden staging-machine of pre-stage anders goedgekeurde modelartefacten, en wijs de offline omgeving dan naar die lokale artefactenmap.
Actie: voordat je gevoelige documenten verwerkt, blokkeer je uitgaande netwerktoegang op het besturingssysteem- of netwerkniveau en voer je een test uit terwijl je verbindingen bewaakt. Applicatie-instellingen zijn nuttig, maar netwerkcontroles geven je een onafhankelijke verificatielaag.
Wat lokale AI niet oplost
Lokaal draaien verbetert de opties voor gegevensbeheer, maar maakt de extractie niet automatisch correct, compliant of veilig. Lokale bestanden kunnen nog steeds lekken via debug-logs, tijdelijke mappen, back-ups, gedeelde mappen, te permissieve services of gekopieerde exports. Een lokaal model kan ook net zo goed waarden hallucineren als een gehost model.
Gebruik het model niet als de enige verificateur voor hoogimpactvelden zoals bankrekeningnummers, betalingsinstructies, contractdatums, medische waarden of regelgevende identificatiecodes. Voor die velden, vergelijk met de brontekst, pas deterministische validatie toe en vereis menselijke review wanneer het vertrouwen onvoldoende is.
Hoe te testen voordat je een hele map automatiseert
Bouw een kleine gelabelde evaluatieset met de gevallen die je daadwerkelijk ontvangt:
schone digitale PDF;
scan met lage resolutie;
gedraaide of scheve pagina;
factuur met meerdere pagina's;
tabel die over pagina's loopt;
ontbrekende optionele velden;
verschillende datum- en getalformaten;
minstens één bewust moeilijk document.
Vergelijk voor elk doelveld de geëxtraheerde waarde met de ground truth. Meet exacte overeenkomst voor identificatiecodes, numerieke tolerantie voor bedragen en rijnauwkeurigheid voor regelitems. Registreer ook verwerkingstijd en het percentage documenten dat naar handmatige review wordt gestuurd.
Als een eenvoudigere PyMuPDF-plus-LLM-route je vereiste nauwkeurigheid bereikt, houd die dan aan. Als scans de belangrijkste faaloorzaak zijn, verbeter dan OCR. Als tabelrelaties het probleem zijn, test dan Docling. Als visueel gepositioneerde velden moeilijk blijven, routeer die subset dan via een lokaal vision-model. Deze gefaseerde escalatie geeft je meestal betere controle over snelheid en hardwaregebruik dan het zwaarste model op elke pagina toepassen.
Conclusie
Een goed lokaal PDF-extractiesysteem scheidt documentlezen van semantische extractie. Gebruik PyMuPDF wanneer de PDF al goede tekst bevat; OCRmyPDF/Tesseract wanneer de pagina gescand is; Docling wanneer structuur en tabellen ertoe doen; en een lokaal Ollama- of llama.cpp-model wanneer je flexibele afbeelding naar een business-schema nodig hebt. Gebruik lokale vision alleen waar visuele lay-out informatie toevoegt die de tekstpijplijn niet betrouwbaar kan behouden.
De laatste vereiste is validatie. JSON Schema kan de vorm van een modelrespons beperken, maar kan niet bewijzen dat het bedrag, de datum, de naam of het rekeningnummer overeenkomt met de bron. Als je de pijplijn zo ontwerpt dat onzekere documenten zichtbaar en reviewbaar zijn, kun je een groot deel van de PDF-gegevensextractie automatiseren zonder de documenten aan een cloud-API te geven—en zonder te doen alsof lokale AI de behoefte aan kwaliteitscontrole wegneemt.