OCR für sensible Daten auf eigener GPU
Veröffentlicht 16. Dezember 2025
Foto von Sear Greyson auf Unsplash
Einleitung
Nachdem wir im ersten Teil, Wie LLMs die OCR-basierte Dokumentenanalyse revolutionieren, die Robustheit und die strukturellen Analysefähigkeiten von Vision-Language Models (VLM) wie Dots.OCR im direkten Vergleich zur klassischen OCR (Tesseract) belegt haben, steht nun die alles entscheidende Frage im Raum: Wie setzen wir diese Technologie DSGVO-konform und hochperformant ein?
Die Verarbeitung von sensiblen Kundendaten oder internen Dokumenten über externe Cloud-Dienste ist oft aus Datenschutzgründen ausgeschlossen. Ein Teil der Lösung kann, in der eigenen, kontrollierten Infrastruktur liegen.
In diesem zweiten Teil widmen wir uns der praktischen Implementierung dieser hochperformanten Pipeline. Wir zeigen Schritt für Schritt, wie man mithilfe von Podman (auf Rocky Linux) und der Inferenz-Engine vLLM einen dedizierten, schnellen Verarbeitungsserver auf Ihrer eigenen NVIDIA-GPU aufsetzen. Anschließend bauen wir einen asynchronen Python-Client, um die volle Leistung der GPU auszuschöpfen und so selbst große Dokumentenstapel zu verarbeiten.
Alle besprochenen Codebeispiele, einschließlich der fertigen main.py und der docker-compose.yml, finden Sie im dazugehörigen GitHub repository.
Einrichtung der Serverseite
Um die hochperformante VLM-Pipeline zu realisieren, ist eine dedizierte Serverumgebung erforderlich. Die Entscheidung, das Vision-Language Model (rednote-hilab/Dots.OCR) auf der eigenen Hardware zu betreiben, ermöglicht DSGVO-Konformität, erfordert jedoch spezifische Ressourcen:
Hardware-Voraussetzungen für vLLM-Inferenz
Da wir eine Architektur nutzen, die auf Large Language Models (LLMs) basiert, ist eine GPU-Beschleunigung unerlässlich, um einen wirtschaftlichen Durchsatz (Throughput) zu erzielen.
Grafikkarte (GPU): Zwingend erforderlich ist eine NVIDIA-GPU mit CUDA-Unterstützung.
Videospeicher (VRAM): Obwohl das Dots.OCR-Modell mit 1.7 Milliarden Parametern relativ kompakt ist, empfehlen wir für das Laden des Modells und die Durchführung von effizientem Inference mit vLLM mindestens 24 GB VRAM. In unseren Tests kam eine NVIDIA RTX 3090 zum Einsatz. Diese lief stabil, wenn auf ihr eine Balance zwischen Modellgröße, Batch-Größe und Dokumentenlänge gefunden wurde.
Hinweis: Der Betrieb auf reiner CPU-Hardware ist theoretisch möglich, aber der Durchsatz (Throughput) ist im Vergleich zur GPU-Beschleunigung stark eingeschränkt.
Ist keine lokale Hardware vorhanden, können dedizierte deutsche Cloud-Server (z. B. bei IONIS, StackIT oder Hetzner) eine DSGVO-konforme und sogar ISO 27001 zertifizierte Alternative darstellen.
Die Wahl der Inferenz-Engine: vLLM
Um die Rechenlast des VLM auf der GPU optimal zu verwalten und so neben schnellen Antwortzeiten auch einen hohen Durchsatz zu gewährleisten, setzen wir auf die Open-Source-Inferenz-Engine **vLLM** (**Dokumentation**).
vLLM ist bekannt für seinen hohen Durchsatz und bietet eine **OpenAI-kompatible API**, was die Integration in unseren Client (und in bestehende Lösungen) erheblich vereinfacht.
Bereitstellung via Podman (Rocky Linux)
Um sicherzustellen, dass unser Setup reproduzierbar ist und ohne Root-Rechte (Rootless) sicher betrieben werden kann, setzen wir auf Podman,alternativ Docker, den Standard auf RHEL-basierten Systemen wie Rocky Linux.
Um die Containerlösung nutzen zu können, müssen wir als Erstes Podman sowie das NVIDIA Container Toolkit installieren und konfigurieren.
1. Podman und Tools installieren
2. NVIDIA Container Toolkit & CDI
Im Gegensatz zu Docker nutzt Podman modern das CDI (Container Device Interface) für den GPU-Zugriff.
Hinweis: Das var/run/* Verzeichnis wird bei jedem Neustart geleert, daher muss die nvidia.yaml Datei bei jedem Systemstart neu generiert werden.
Auf dem Server erstellen wir zuerst ein neues Verzeichnis und bewegen uns hinein mit dem Befehl:
Dort erstellen wir eine neue Datei mit dem Namen docker-compose.yml via VIM:
Diese Datei füllen wir mit dem folgenden Inhalt. Wir nutzen hier die CDI-Syntax für Devices und das :z Flag für SELinux-Kompatibilität unter Rocky Linux.
Im nächsten Schritt erstellen wir eine weitere Datei auf die selbe Art mit dem Namen .env, in der wir die notwenigen Umgebungsvariablen einstellen:
Nun können wir den Container starten und uns dem Skript widmen. Dafür geben wir einfach den folgenden Befehl in das Terminal ein:
Automatisierung und Autostart via Systemd
Damit unser Inferenz-Server auch nach einem Neustart des Systems automatisch hochfährt und robust im Hintergrund läuft, richten wir einen Systemd-Service ein. Dies ersetzt den manuellen Startbefehl.
Dazu erstellt man die Service-Datei unter /etc/systemd/system/vllm.service:
Danach fügt man den folgenden Inhalt ein
Wichtig:Man passt den Pfad in ExecStart und ExecStop an den Ort an, an dem man zuvor den Ordner dotsOCR erstellt haben (im Beispiel unten wird /root/dotsOCR angenommen).
Im Anschluss setzen wir die korrekten Berechtigungen für die Datei (Root-User, Leserechte für alle) und aktivieren den Dienst.
Um sicherzustellen, dass der Container korrekt läuft, überprüfen wir den Status:
Erscheint hier ein grünes "active (running)", ist der Server einsatzbereit.
Pipeline
Client-Einrichtung und Abhängigkeiten
Um Anfragen an unseren vLLM-Server zu senden und die komplexen PDF-Dokumente vorzuverarbeiten, benötigen wir auf der Client-Seite die folgenden Python-Bibliotheken. Wir nutzen pdf2image zur Umwandlung von PDF-Seiten in Bilder und die openai-Bibliothek zur Kommunikation mit dem vLLM-Endpunkt.
Man installiert alle notwendigen Pakete in der lokalen (oder Client-)Umgebung.
und erstellt die Datei main.py.
1. PDF-Dateien laden
Als erstes brauchen wir eine Funktion um .pdf Dateien zu lesen, dafür schreiben wir in unsere main.py:
Diese Funktion nimmt einen Pfad zu einer .pdf und gibt eine Liste von PIL.Images zurück, diese Images können wir allerdings noch nicht für die Anfragen an unseren Server verwenden, dazu müssen wir sie erst in einen Base64 String umwandeln.
2. PIL.Image zu Base64
Hier sind zwei weitere Imports notwenidig, also fügen wir den Imports am Anfang unserer Datei die folgenden Zeilen hinzu:
Am Ende der Datei definieren wir die folgende neue Funktion:
3. Client-Initialisierung & Anfrage Logik
Um Anfrage an unseren Server senden zu können, benötigen wir einen OpenAI Client, hier sind wieder zusätzliche Imports notwendig also fügen wir am Anfang unserer Datei diese Zeilen hinzu.
und vor die Definition der Funktionen schreiben wir:
Hier würden wir nun typischerweise eine Schleife schreiben, die die Bilder einzeln an den Server sendet (sequenziell). Doch das ist oft zu langsam.
Beschleunigung
Eine sequenzielle Bearbeitung (Bild für Bild) nutzt das Potential des vLLM-Endpunkts nicht aus. Unser Skript würde warten, bis eine Antwort kommt, bevor das nächste Bild gesendet wird. Um die GPU wirklich auszulasten, sollten wir die Anfragen parallel senden. Außerdem ist es unpraktisch, den Pfad und die Prompt im Code zu hinterlegen, daher nehmen wir Verbesserungen an der main.py vor.
1. Parallele Anfragen mit asyncio
Um die Wartezeit zu überbrücken, ersetzen wir den synchronen Client durch den asynchronen openai.AsyncOpenAI und nutzen das asyncio-Framework.
Wir definieren die Verarbeitungslogik neu und führen eine Konstante MAX_CONCURRENT_REQUESTS ein, um die Serverlast zu steuern:
2. Integration von argparse
Um das Skript flexibel über das Terminal steuern zu können, fügen wir argparse hinzu. Dies ermöglicht den Aufruf wie folgt:
Zusammengefasst
Unsere fertige main.py vereint nun alle Schritte: Sie lädt das PDF, konvertiert die Seiten und sendet sie hocheffizient und parallel an unseren lokalen Podman-Container:
Diese finale Version der Pipeline ermöglicht es, innerhalb ihreres eigenen Netzwerks Dokumente zu verabeiten, allerdings sollte sie in dieser Form und Weise nicht über das Internet zur Verfügung gestellt werden, dazu sind weitere Sicherheitsmaßnahmen notwendig, beispielsweise sollten Anfragen via https abgesichtert werden und entsprechende Firewall-Regeln gesetzt werden.
Performance
Die Geschwindigkeit der Verarbeitung hängt neben der eingesetzen Hardware und der Anzahl der Parallel-Anfragen auch stark von der Komplexität und Qualität der Dokumente ab. In mehreren Tests mit historischen Dokumenten aus den letzten Weltkriegsjahren und der frühen Nachkriegszeit (stark verblasster Text, handschriftliche Notizen, verschiedene Schriftarten, tablellarische Strukturen), konnten wir mit einer NVIDIA RTX 3090 (24 GB VRAM) einen durchschnittlichen Durchsatz (Throughput) von ca. 180 Seiten pro Stunde erreichen, bei einer Batch-Größe von 5 parallelen Anfragen. Weniger komplexe, moderne Dokumente (z. B. Rechnungen, Formulare) lassen sich deutlich schneller verarbeiten, aber schon das gewählte Testsenario zeigt, dass selbst schwierige Dokumente in akzeptabler Zeit analysiert werden können.
Weiter Schritte zur Enterprise-Lösung
Das oben beschriebene Setup stellt eine robuste Basis dar, um VLM-basierte Dokumentenanalysen auf eigener Hardware durchzuführen. Um diese Architektur jedoch nahtlos in eine komplexe Enterprise-IT-Landschaft zu integrieren, sollten folgende Aspekte berücksichtigt werden:
- Orchestrierung statt Einzelserver: Während podman-compose ideal für Einzelinstanzen ist, erfordert der Produktivbetrieb oft Hochverfügbarkeit. Hier empfiehlt sich der Einsatz von Kubernetes oder – passend zu Rocky Linux – Red Hat OpenShift. Damit lassen sich VLLM-Inferenz-Pods dynamisch je nach Last skalieren und über mehrere GPU-Nodes verteilen.
- API Gateway & Security: Der direkte Zugriff auf den vLLM-Container sollte vermieden werden. Ein vorgeschaltetes API Gateway (z. B. LiteLLM) kann Aufgaben wie Rate Limiting, zentrales Logging, das Verwalten von Nutzergruppen und Fallbacklösungen sowie caching übernehmen.
- Observability: Um Engpässe frühzeitig zu erkennen, ist ein detailliertes Monitoring unerlässlich. Metriken wie GPU-Auslastung (via DCGM Exporter), VRAM-Belegung und Request-Latenzen sollten in Systemen wie Prometheus gesammelt und in Grafana visualisiert werden.
Mit dieser Architektur wird die Verarbeitung Tausender von Dokumenten nicht mehr in Tagen, sondern in Minuten gemessen – und das unter voller eigener Datenkontrolle.
Gerne unterstützen wir auch bei der Umsetzung eigener Projekte im OCR-Bereich und besprechen weitere Details im persönlichen Kontakt.