Onze online krantencollectie omvat 500.000 pagina's. Ze zijn doorzoekbaar met Elasticsearch. De tekst is uit de scan geëxtraheerd met behulp van tesseract OCR, en opgeslagen als alto.xml.
De kwaliteit van die OCR-tekst is aardig, maar voor verbetering vatbaar. In een poging de vindbaarheid te verbeteren hebben we het volgende experiment gedaan: de OCR-tekst uit de alto.xml hebben we naar een lokale LLM gestuurd (gemma4) met deze prompt:
Dat werkt best goed. Idee is om deze gecorrigeerde tekst te gebruiken om nieuwe trefwoorden aan de zoekindex toe te voegen (door een 'delta' of diff te doen tov de OCR-tekst). We willen vooralsnog niet de alto.xml aanpassen.
Deze aanpak lijkt veelbelovend alleen te traag. De machine die wij er voor beschikbaar hebben zou een jaar continu moeten werken, ongeveer 1 pagina per minuut. Dit was na optimalisatie van de tekstgrootte / batches (eerste pogingen 5 minuten per pagina).
Ik vraag me daarin af of anderen een dergelijke aanpak hebben gevolgd om met AI de vindbaarheid van OCR teksten te verbeteren, op zo'n manier dat 500.000 pagina's in maximaal een paar maanden te verwerken zijn?
Dank!
Reacties
Ik heb hier zelf ook over nagedacht, omdat tesseract OCR soms net niet perfect is, maar met een soort spellingscontrolle dat wel nagenoeg zou kunnen worden. Een LLM kon dit in mijn ervaring idd ook goed, maar ik heb dat nooit op schaal gedaan. Iets anders dan tesseract was toen (1.5 jaar geleden) ook niet echt een optie, omdat de meeste gratis OCR programma's — zelfs degene die gebruikt maakte van state-of-the-art machine learning — tov tesseract niet zo goed waren op oud Nederlandse teksten (1700-1930).
Uiteindelijk heb ik het resultaat toen verbeterd door het bestaande tesseract model te hertrainen ("finetunen") op wat handmatig verbeterde data (training set had geloof ik een paar honderd samples). Dat was niet extreem veel werk, en maakte een merkbaar verschil. Zie https://github.com/tesseract-ocr/tesstrain voor de hertrain procedure.
Ik denk niet dat het zo goed word als een LLM alles laten corrigeren, maar je zou het Nederlandse tesseract model kunnen finetunen op wat perfect geannoteerde samples. Bijvoorbeeld de verbeterde teksten die de LLM heeft gemaakt.
Dan heb je nog steeds het woord afbreek probleem, maar misschien kun je dat gedeelte met een script oplossen?
Aangepast op 15 april
In ieder geval benieuwd naar hoe je dit oplost, mogelijk is er een wat snellere/minder zware LLM die je kunt gebruiken? Eentje met bijv. minder parameters, zodat je er een aantal tegelijk op je GPU kan draaien?
Heb je de denkmodus uitgezet? Bij Gemma 4 kost dit namelijk enorm veel tijd, maar als je een nothink-parameter meestuurt, is het binnen een seconde klaar. Je zou ook kunnen overstappen op een kleiner model van Qwen, of de MoE-versie van Gemma 4 overwegen. Die laatste is doorgaans iets sneller, terwijl de kwaliteit vrijwel gelijk is aan het dense model. Werk je overigens met batches of doe je het per woord? Als je nog geen batches gebruikt, valt daar sowieso nog winst te behalen. Eventueel kun je de library Instructor (of PydanticAI) gebruiken om direct structured output terug te krijgen.
Zelf heb ik meer succes met Surya, olmOCR, PaddleOCR (VL) en DocTR. Het nadeel van deze pakketten is wel dat ze geen ALTO XML aanleveren. Volgens mij is DocTR overigens de enige die bounding boxes op woordniveau geeft; de andere pakketten doen dit op zinsniveau. Ik heb helaas nog geen degelijke manier gevonden om de bounding boxes van DocTR om te zetten naar ALTO XML (in ieder geval niet met pixelprecisie). De layout parsing van tesseract vind ik persoonlijk niet heel goed. Als het puur om OCR gaat heb je geen LLM meer nodig om de tekst beter te maken, deze zijn tegenwoordig ruim boven de 90% accuraat. Zet tesseract in voor de ALTO XML en gebruik een van de meeste recente oplossingen om puur de tekst te genereren. Ik denk dat je dan met een seconde of 2/3 klaar bent.
Voor oude teksten blijft Kraken geweldig. Ik gebruik een VL-model dat bepaalt uit welke tijd een document komt en het soort tekst, waarna het automatisch het juiste model uit Kraken kiest. Op basis van transcripties die we bij kunnen werken, kunnen we vervolgens relatief makkelijk zelf bijtrainen. Wij hebben software ontwikkeld die particuliere archieven automatisch archiveert en van metadata voorziet, en OCR is hier logischerwijs een onderdeel van, voor het OCR'en en genereren van ALTO XML (specifiek voor kranten) had ik ook software gebouwd maar dit heb ik ondertussen helaas verwijderd maar is nog wel een project dat ik moet afronden dus dit zal ik later waarschijnlijk weer bouwen.
Ter vergelijking; het volledig verwerken van één document in onze software kost ongeveer 5 a 6 seconden op een RTX 5090 (is nog niet geoptimaliseerd), dan is de OCR gedaan, embeddings gemaakt, classificatie gedaan (op basis van eigen instellingen), de entiteiten geëxtraheerd, metadata aangemaakt en nog veel meer. Ik denk niet dat alleen het aanpassen van tekst langer dan 2 seconden per pagina zou moeten duren. (eerste run is uiteraard langer omdat het model nog moet laden). Nog steeds een dag of 12 werk maar toch zeker geen maanden.
Ten slot nog twee waarschuwingen; zet geen LLM in om hele zinnen aan te passen, dan krijg je gegarandeerd hallucinaties in je teksten. En zorg dat je per pagina werkt, KV-cache explodeert bij meerdere paginas en als de context te groot wordt krijg je een overloop in je werkgeheugen en daarna je HD. Bij de overloop naar je geheugen krijg je al bizarre vertragingen, bij een overloop naar je HD is het einde verhaal en simpelweg onwerkbaar.
Mocht je vragen hebben dan hoor ik dat uiteraard graag!