Dokumentförståelse: OCR, layout, tabeller
Kunna extrahera strukturerad information ur dokumentbilder och mäta kvalitet.
Förkunskaper
Intuition
Ett dokument är inte en textsträng. Layouten bär betydelse: vad som står i vilken kolumn, vilken rad i en tabell, vilket fält en siffra hör till. Läser du bara av texten uppifrån och ner tappar du just det som gör dokumentet begripligt.
Två vägar, och de är verkligen olika:
| OCR-pipeline | VLM direkt | |
|---|---|---|
| Steg | avbild → OCR → layoutanalys → fältmatchning | avbild → modell → JSON |
| Ger | textkoordinater, spårbarhet till pixel | direkt strukturerat svar |
| Bra på | höga volymer, fasta mallar, revision | varierande layouter, handskrift, få dokument |
| Fel uppstår | i OCR:en och i regelverket | tyst, som påhittade fältvärden |
| Kostnad | låg per sida | hög per sida |
Den avgörande skillnaden är var felen syns. En OCR-pipeline som misslyckas ger tomt eller uppenbart skräp. En VLM som misslyckas ger ett trovärdigt men fel organisationsnummer.
Formellt
Mät fältvis, aldrig som en helhet. Ett dokumentextraktionssystem med «94 % träffsäkerhet» är en meningslös siffra. Fälten skiljer sig enormt:
| Fält | Typisk exakt träff | Varför |
|---|---|---|
| Fakturanummer | 0,98 | välavgränsat, tecken lätt lästa |
| Datum | 0,95 | format varierar men går att normalisera |
| Totalbelopp | 0,93 | förväxlas med delsummor |
| Leverantörsnamn | 0,85 | logotyper, förkortningar, juridiskt namn ≠ varumärke |
| Radposter (tabell) | 0,70 | flersidiga tabeller, sammanslagna celler |
Normalisera före jämförelse: «1 234,50 kr», «1234.50» och «1 234,50» är samma belopp. Annars mäter du formatering.
Konfidens och mänsklig granskning. Nyttan ligger i att skicka rätt dokument till människa. Det kräver en kalibrerad konfidens:
- Låt modellen ange konfidens per fält — eller använd OCR-konfidens och överensstämmelse mellan två metoder.
- Kalibrera mot en märkt mängd: när modellen säger 0,9, hur ofta har den rätt?
- Sätt tröskeln utifrån vad ett fel kostar jämfört med vad granskningen kostar.
- Mät täckningen — andelen dokument som går igenom automatiskt. Det är det tal som avgör affärsnyttan.
Kryssvalidering är billig och effektiv: kör både OCR-pipeline och VLM, och flagga varje fält där de är oense. Två oberoende fel som sammanfaller är sällsynta, och det du får är en konfidenssignal som inte kommer från modellen själv.
Två saker att hantera från början: flersidiga dokument (radposter som fortsätter över sidbrytning) och personuppgifter (dokumentbilder innehåller nästan alltid sådana — samma gallringsregler gäller som för all annan persondata).
Kod
import json, re
from pydantic import BaseModel, Field
class Radpost(BaseModel):
beskrivning: str
antal: float
styckpris: float
belopp: float
class Faktura(BaseModel):
fakturanummer: str | None = None
fakturadatum: str | None = Field(default=None, description="ÅÅÅÅ-MM-DD")
leverantor: str | None = None
organisationsnummer: str | None = None
totalbelopp: float | None = None
valuta: str = "SEK"
radposter: list[Radpost] = []
osakra_falt: list[str] = []
PROMPT = ("Extrahera fakturan som JSON enligt schemat. Läs ENDAST det som står i bilden. "
"Sätt null för fält du inte kan läsa och lista dem i osakra_falt. Hitta aldrig på värden.")
def belopp(s):
if s is None:
return None
return float(re.sub(r"[^\d,.-]", "", str(s)).replace(" ", "").replace(",", "."))
def faltvis_matt(facit: list[dict], pred: list[dict], falt: list[str]):
ut = {}
for f in falt:
traff = sum(1 for a, b in zip(facit, pred)
if (belopp(a[f]) if f.endswith("belopp") else a[f]) ==
(belopp(b.get(f)) if f.endswith("belopp") else b.get(f)))
ut[f] = round(traff / len(facit), 3)
return ut
# Kryssvalidering: två oberoende vägar, flagga oenighet
def kryss(ocr_resultat: dict, vlm_resultat: dict, falt: list[str]):
return [f for f in falt if ocr_resultat.get(f) != vlm_resultat.get(f)]
print(faltvis_matt(facit, pred, ["fakturanummer", "fakturadatum", "totalbelopp", "leverantor"]))
# {'fakturanummer': 0.98, 'fakturadatum': 0.95, 'totalbelopp': 0.93, 'leverantor': 0.85}
osakra_falt i schemat är billigt och underskattat: det ger modellen ett sätt att säga «jag vet inte» som är strukturerat nog att agera på i koden.
Behärskning innebär
- Väljer mellan OCR-pipeline och VLM
- Extraherar fält och tabeller med schema
- Mäter fältvis träffsäkerhet och kalibrerar konfidens
Logga in för att göra övningarna och bygga upp din behärskning.
Källor
- arXiv — LayoutLMv3: Pre-training for Document AI — arXiv (öppen åtkomst; licens per artikel)
- arXiv — OCR-free Document Understanding Transformer (Donut) — arXiv (öppen åtkomst; licens per artikel)
- Hugging Face — dokumentation (Apache-2.0) — Apache-2.0