Zum Inhalt

Formate

Welche Dateiendung welche Engine bedient und wo die Engines sich unterscheiden, steht hier.

Die Matrix

Die Reihenfolge ist die Präferenz: Bei engine=auto bekommt die Datei die erste Engine, die gerade bereit ist. Diese Liste steht im Code (backend/app/converters/registry.py) und nicht in der Konfiguration — sie beschreibt, was die Bibliotheken können, und das ändert sich mit den Abhängigkeiten, nicht mit dem Deployment.

Endung Präferenz (erste Wahl zuerst)
.pdf docling, markitdown
.docx markitdown, docling, pandoc
.epub pandoc, markitdown
.pptx, .xlsx markitdown, docling
.html, .htm markitdown, pandoc, docling
.odt, .rtf, .tex, .rst, .org pandoc
.csv, .json, .xml, .txt markitdown
.png, .jpg, .jpeg, .tiff docling (mit OCR), markitdown
.md, .markdown durchreichen, keine Engine

Pandoc fehlt bei .pdf, weil Pandoc PDF nicht liest. Markdown reicht der Dienst durch: Er liest die Datei und gibt sie zurück, wie sie ist — solange sie UTF-8 ist. Jedes ungültige Byte ersetzt er durch � und meldet in einer Warnung, wie viele Zeichen er ersetzt hat. Steht � schon in einer gültigen Datei, gibt es nichts zu melden.

Für POST /api/convert/url gilt dieselbe Tabelle. Welche Zeile greift, entscheidet der Inhaltstyp, den der ferne Server liefert — text/html führt auf .html, application/pdf auf .pdf —, und erst wenn der nichts hergibt, die Endung im Pfad. Eine Adresse, die auf ein PDF zeigt, landet also in der Zeile .pdf und bekommt dieselbe Engine und dieselben Warnungen wie ein hochgeladenes PDF: Solange Docling lädt, wandelt MarkItDown, und die Antwort sagt in warnings, dass dabei die Bilder verlorengehen.

Was von dieser Tabelle im Betrieb übrig bleibt, meldet GET /api/capabilities. Wählbar und in formats ist dabei nicht dasselbe: Eine Engine, die gerade ihre Modelle lädt, steht mit dem Zustand warming in engines und lässt sich ausdrücklich wählen — die Anfrage wartet dann, bis die Modelle geladen sind —, aus formats fällt sie aber heraus wie eine nicht installierte, und deshalb nimmt engine=auto für ein PDF solange die nächste Engine der Liste.

Auswahl und Rückfall

Eine ausdrücklich genannte Engine wird nie durch eine andere ersetzt. Kann sie das Format nicht, antwortet der Dienst mit 400 (engine_unsuitable), statt stillschweigend etwas anderes zu nehmen.

Bei engine=auto nimmt der Dienst die nächste Engine der Liste, wenn die erste scheitert. Der Grund des Fehlschlags steht danach in warnings des Ergebnisses. KAIMARKIT_ENABLE_FALLBACK=false schaltet diesen Rückfall ab. KAIMARKIT_DEFAULT_ENGINE=<name> zieht eine Engine in allen Listen nach vorn, sofern sie die Endung überhaupt bedient.

Eine Endung außerhalb der Tabelle lehnt der Dienst mit 415 (unsupported_format) ab.

Docling: Modelle und OCR

Docling lädt beim Start Layout- und Tabellenmodelle in den Speicher. Das dauert und geschieht deshalb im Hintergrund: GET /api/health antwortet sofort, während Docling noch lädt. Solange gilt die Engine als warming: GET /api/capabilities nennt sie unter engines mit diesem Zustand, in formats steht sie noch nicht, und engine=auto nimmt für ein PDF die nächste Engine der Präferenzliste. Wer Docling ausdrücklich verlangt, wartet stattdessen, bis die Modelle da sind.

Fehlen die Modelle oder ist die Bibliothek nicht installiert, meldet der Dienst 400 (engine_unavailable), sobald jemand Docling ausdrücklich verlangt. Bei engine=auto bleibt Docling einfach aus der Liste.

KAIMARKIT_OCR_ENABLED legt fest, ob Docling gescannte Seiten und Bilder durch die Texterkennung schickt; eine einzelne Anfrage überschreibt das mit dem Feld ocr. Für jede der beiden Einstellungen hält der Dienst einen eigenen Konverter, den er wiederverwendet — der erste Aufruf mit umgeschaltetem OCR ist deshalb langsamer als die folgenden. Die Sprachen kommen aus KAIMARKIT_OCR_LANGS; ihre Kürzel müssen zu der Texterkennung passen, die Docling benutzt.

Die Texterkennung greift dabei nur in PDF und in den Bildformaten .png, .jpg, .jpeg und .tiff. In .docx, .pptx, .xlsx, .html und .epub bleibt sie aus, und daran ändert weder das Feld ocr noch KAIMARKIT_OCR_ENABLED etwas: Docling schickt diese Formate durch eine Pipeline, die do_ocr nicht kennt (gemessen im Container-Abbild mit docling 2.124.0). Wer den Text eines abfotografierten Absatzes aus einem Word-Dokument braucht, speichert das Dokument als PDF und gibt dieses ab. In PDF reicht die Erkennung auch in eingebettete Bilder hinein; die Einzelheiten stehen unter Grenzen.

Bilder übernimmt Docling nicht, es setzt den Platzhalter <!-- image --> an ihre Stelle — auch dort, wo gar kein Bild stand, sondern eine breite Tabelle, die das Modell als Bild eingeordnet hat. Die Antwort sagt das in warnings und nennt die Zahl: „Docling hat in breit.pdf 14 Bilder durch Platzhalter ersetzt. Ihr Inhalt fehlt im Markdown." Bei einem einzigen Platzhalter steht dort „ein Bild durch einen Platzhalter". Danach nennt dieselbe Warnung, warum an dieser Stelle nichts steht und was hilft: In einem Word-, PowerPoint-, Excel- oder HTML-Dokument der Weg über PDF, bei ausgeschalteter Texterkennung der Schalter selbst, und bei schon eingeschalteter Texterkennung ein Blick ins Original.

Wo die vorgebackenen Modelle liegen, sagt DOCLING_ARTIFACTS_PATH. Die Variable gehört Docling, nicht kaimarkit; das Container-Abbild setzt sie, damit zur Laufzeit nichts aus dem Netz nachgeladen wird.

MarkItDown

MarkItDown kommt ohne Modelle und ohne OCR aus und ist deshalb die schnelle Engine. Einen LLM-Client setzt der Dienst bewusst nicht ein: In .docx, .html und .epub steht von einem Bild nur der Alt-Text im Markdown, nicht sein Inhalt.

Aus einem PDF übernimmt MarkItDown Bilder gar nicht. Die Engine liest dort nur die Textebene; ein Bild hinterlässt weder Marke noch Alt-Text, und ein PDF mit Bildern ergibt Zeichen für Zeichen dasselbe Markdown wie dasselbe PDF ohne. Deshalb warnt der Dienst bei jedem PDF, das durch MarkItDown läuft — auch bei einem ohne Bilder: Er liest die Datei kein zweites Mal, um nachzuzählen. Wer die Stellen sehen will, an denen ein Bild stand, wählt Docling.

Findet MarkItDown in einer Datei keinen Text — bei einem gescannten PDF etwa —, ist das kein Fehler. Das Ergebnis bleibt leer und die Antwort nennt den Grund in warnings. Wer aus solchen Dateien Text braucht, wählt Docling mit OCR.

Pandoc

Pandoc ist kein Python-Modul, sondern ein Programm im Container. Es bedient die Formate, die sonst niemand liest: .odt, .rtf, .tex, .rst und .org. Für .epub ist es die erste Wahl. PDF liest Pandoc nicht.

Jeder Aufruf läuft mit --sandbox. Damit liest und schreibt Pandoc nur die Datei, die auf der Kommandozeile steht. Ein ePub oder eine LaTeX-Datei kann sonst auf beliebige Pfade des Servers zeigen — dieser Schalter ist der Grund, warum der Dienst fremde Dateien überhaupt durch Pandoc schicken darf.

KAIMARKIT_PANDOC_TIMEOUT begrenzt den Unterprozess. Läuft die Zeit ab, beendet der Dienst den Prozess und antwortet mit 504 (conversion_timeout). Meldungen, die Pandoc auf stderr schreibt und trotzdem weiterarbeitet, stehen danach in warnings.

Fehlt das Programm im PATH, meldet GET /api/capabilities die Engine als unavailable; wer sie ausdrücklich verlangt, bekommt 400 (engine_unavailable).

Weiter

Wie man eine Engine im Aufruf verlangt und was die Auskunft im Einzelnen enthält, steht unter API. Wo diese Engines an ihre Grenze kommen — gescannte Seiten, Bilder, Speicher —, steht unter Grenzen.