Zum Inhalt

OCR — Dokumentenerkennung

Uebersicht

Der OCR-Service bietet universelle Dokumentenerkennung mit austauschbaren Providern.

Verfuegbare Provider:

Provider Typ Default Strukturierte Extraktion Beschreibung
Surya OCR Lokal (GPU) Ja Nein GPU-beschleunigte lokale OCR — kein Cloud-Dienst, keine API-Kosten
Mistral OCR 3 Cloud-API Nein Ja (JSON-Schema) Mistral AI Cloud OCR mit strukturierter Datenextraktion
  • Prefix: /api/v1/ocr/
  • Permissions: ocr.read, ocr.process
  • Provider-Architektur: Abstract Factory — neue Provider ohne API-Aenderung ergaenzbar

Unterstuetzte Formate

Format Surya Mistral
PDF
PNG
JPEG
WebP
GIF
BMP
TIFF
AVIF
DOCX
PPTX

Max. Dateigroesse: 50 MB

Endpoints

Provider auflisten

GET /api/v1/ocr/providers

Permission: ocr.read

Gibt alle registrierten OCR-Provider mit Verfuegbarkeitsstatus zurueck.

Response:

[
  {
    "type": "surya",
    "name": "Surya OCR (Lokal)",
    "description": "Lokale Dokumentenerkennung mit GPU-Beschleunigung — kein Cloud-Dienst",
    "supported_formats": ["pdf", "png", "jpg", "jpeg", "webp", "gif", "bmp", "tiff"],
    "supports_structured": false,
    "available": true,
    "is_default": true
  },
  {
    "type": "mistral",
    "name": "Mistral OCR 3 (Cloud)",
    "description": "Mistral AI Dokumentenerkennung — Cloud-API, strukturierte Extraktion",
    "supported_formats": ["pdf", "png", "jpg", "jpeg", "webp", "gif", "bmp", "tiff", "avif", "docx", "pptx"],
    "supports_structured": true,
    "available": true,
    "is_default": false
  }
]

Dokument verarbeiten

POST /api/v1/ocr/process

Permission: ocr.process

OCR-Verarbeitung eines Dokuments. Gibt Markdown pro Seite zurueck.

Request Body:

{
  "document": {
    "type": "url",
    "data": "https://example.com/rechnung.pdf",
    "filename": "rechnung.pdf",
    "mime_type": "application/pdf"
  },
  "provider": "surya",
  "pages": [0, 1],
  "table_format": "markdown",
  "include_images": false,
  "extract_headers": true,
  "extract_footers": true,
  "language_hint": "de"
}

Eingabe-Typen (document.type):

Typ Beschreibung data-Feld
url Dokument-URL HTTPS-URL zum Dokument
base64 Base64-kodiert Base64-String des Dokuments
file_id Mistral File-ID ID einer hochgeladenen Datei (nur Mistral)

Optionen:

Feld Typ Default Beschreibung
provider string surya OCR-Provider (surya oder mistral)
pages int[] alle Bestimmte Seiten (0-basiert)
table_format string null markdown oder html
include_images bool false Bilder als Base64 extrahieren (nur Mistral)
extract_headers bool false Kopfzeilen extrahieren (nur Mistral)
extract_footers bool false Fusszeilen extrahieren (nur Mistral)
language_hint string null Sprachhinweis (z.B. de)

Response:

{
  "pages": [
    {
      "index": 0,
      "markdown": "# Rechnung Nr. 2025-001\n\n| Position | Betrag |\n|---|---|\n| Hosting | 29,90 EUR |",
      "images": [],
      "header": null,
      "footer": null,
      "dimensions": {
        "dpi": 300,
        "height": 3507,
        "width": 2480
      }
    }
  ],
  "usage": {
    "pages_processed": 1,
    "provider": "surya",
    "model": "surya"
  },
  "document_annotation": null,
  "processed_at": "2026-03-12T14:30:00Z"
}

Strukturierte Extraktion

POST /api/v1/ocr/process/structured

Permission: ocr.process

Extrahiert strukturierte Daten anhand eines JSON-Schemas (z.B. Rechnungsdaten).

Nur Mistral

Strukturierte Extraktion ist nur mit dem Mistral-Provider verfuegbar. Surya gibt null als document_annotation zurueck.

Request Body:

{
  "document": {
    "type": "url",
    "data": "https://example.com/rechnung.pdf"
  },
  "provider": "mistral",
  "schema_definition": {
    "name": "invoice",
    "schema": {
      "type": "object",
      "properties": {
        "invoice_number": {"type": "string"},
        "date": {"type": "string"},
        "total": {"type": "number"},
        "line_items": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "description": {"type": "string"},
              "amount": {"type": "number"}
            }
          }
        }
      }
    }
  },
  "extraction_prompt": "Extrahiere alle Rechnungsdaten"
}

Datei hochladen + OCR

POST /api/v1/ocr/upload

Permission: ocr.process

Datei direkt hochladen (Multipart) und OCR verarbeiten. Ideal fuer Frontend-Integration.

Form-Parameter:

Feld Typ Pflicht Beschreibung
file File ja Dokument (max. 50 MB)
provider string nein Provider (default: surya)
table_format string nein markdown oder html
include_images bool nein Bilder extrahieren

cURL Beispiel:

# Surya (lokal, Default)
curl -X POST https://platform.xynap.tech/api/v1/ocr/upload \
  -H "Authorization: Bearer <token>" \
  -F "file=@rechnung.pdf"

# Mistral (Cloud)
curl -X POST https://platform.xynap.tech/api/v1/ocr/upload \
  -H "Authorization: Bearer <token>" \
  -F "file=@rechnung.pdf" \
  -F "provider=mistral" \
  -F "table_format=markdown"

Architektur

Provider-Pattern

BaseOcrProvider (Abstract)
  |
  +-- SuryaOcrProvider        (lokal, GPU — Default)
  +-- MistralOcrProvider      (mistral-ocr-latest, Cloud)
  +-- [Kuenftige Provider]    (z.B. Google Document AI, PaddleOCR)

Neue Provider implementieren BaseOcrProvider mit zwei Methoden:

  • process() — Standard-OCR (Markdown-Ausgabe)
  • process_structured() — OCR mit JSON-Schema-Extraktion

Dateien

Datei Beschreibung
app/core/ocr/base.py Abstrakte Provider-Schnittstelle
app/core/ocr/factory.py Provider-Factory
app/core/ocr/surya.py Surya OCR (lokal, GPU)
app/core/ocr/mistral.py Mistral OCR 3 (Cloud)
app/core/ocr/schemas.py Pydantic Request/Response Modelle
app/core/ocr/router.py FastAPI Endpoints

Konfiguration

Surya (Lokal)

Surya benoetigt keinen API-Key. GPU-Einstellungen:

TORCH_DEVICE=cuda              # GPU-Backend (cuda/cpu)
RECOGNITION_BATCH_SIZE=128     # Batch-Groesse OCR (RTX 4000: 128)
DETECTOR_BATCH_SIZE=18         # Batch-Groesse Detektion

Modelle werden beim ersten Aufruf automatisch heruntergeladen (~1.5 GB) und unter /root/.cache/datalab gecacht. Im Docker-Container wird /var/lib/xynap/surya-models als persistentes Volume gemountet.

Mistral (Cloud)

Der Mistral API-Key wird ueber eine der folgenden Quellen geladen (Prioritaet):

  1. Secret Store: ocr.mistral_api_key
  2. Umgebungsvariable: MISTRAL_API_KEY

Berechtigungen

Permission Rollen Beschreibung
ocr.read admin, reseller, customer, user Provider-Liste abrufen
ocr.process admin, reseller, customer, user Dokumente verarbeiten

super_admin

Super-Admins haben implizit Zugriff auf alle Permissions.

Neuen Provider hinzufuegen

  1. Provider-Klasse erstellen (erbt von BaseOcrProvider)
  2. OcrProviderType Enum erweitern in schemas.py
  3. Factory in factory.py erweitern
  4. API-Key ueber Secret Store oder Env-Var bereitstellen (falls Cloud-Provider)
  5. Provider-Info in list_providers() ergaenzen
  6. Tests erweitern
  7. Service-Register aktualisieren (/home/admin/docs/services/ocr.md)