Docling - Convertir PDF, Word, PowerPoint, Excel et HTML en Markdown, accéléré par GPU
Une image Docker batteries-included pour Docling, la bibliothèque de conversion de documents d'IBM : PDF, Word, PowerPoint, Excel et HTML transformés en Markdown propre, avec accélération GPU pour les machines qui ont de la VRAM en rab. Un complément à mon article Markitdown — même idée, un moteur plus lourd en dessous.
Traduction automatique
Journal des modifications

Cet article fait pour Docling exactement ce que mon article sur Markitdown faisait pour Markitdown : une image Docker batteries-included et une fonction shell docling-convert pour zsh ou bash, afin que convertir un document en Markdown propre tienne en une commande depuis n'importe quel dossier. La différence est sous le capot — Docling utilise des modèles dédiés de layout, de structure de tableaux et d'OCR plutôt que des parsers spécifiques à chaque format, tourne sur GPU si vous en avez un, et est conçu dès le départ exactement pour le scénario « document sensible, qui doit rester en local » auquel ce blog revient sans cesse.
Un ami qui lisait mon article sur Markitdown m'a suggéré d'essayer Docling à la place — projet open source, du côté d'IBM cette fois, même promesse « convertir des documents bureautiques en Markdown », mais construit autour de vrais modèles de compréhension de mise en page plutôt que de parsers par format. J'ai 24 Go de VRAM qui dorment sur mon serveur IA ; si un outil peut les mettre au travail pour transformer un PDF mal scanné en quelque chose de lisible, ça vaut dix minutes de test.
Convertir cinq formats
Une fois l'image et la fonction docling-convert en place (on voit ça plus bas), convertir un document tient en une commande :
PDF, DOCX, PPTX, XLSX et HTML, cinq appels distincts à docling-convert, cinq fichiers .md propres posés à côté de leurs originaux — pas d'export-vers-Markdown manuel dans Word ou PowerPoint, pas de convertisseur en ligne à qui confier le contenu.
Ce que Docling fait différemment
Même sortie, un moteur très différent
Pour tous les formats de cet article sauf le PDF — .docx, .xlsx, .pptx et .html — Docling fait ce que fait tout autre convertisseur : il lit le fichier avec une bibliothèque Python dédiée au format et parcourt le résultat. Rien d'exotique, aucun modèle chargé, et rien qui nécessite un GPU — --pipeline vlm est simplement ignoré sur ces quatre-là.
C'est sur le chemin PDF que ça diverge. Un PDF n'a aucune structure à parcourir : c'est un sac de glyphes à des coordonnées, et chaque convertisseur doit deviner où se trouvaient les paragraphes, les titres et les tableaux. Docling le déduit avec des modèles — un pour la mise en page, un pour la structure des tableaux, un pour l'OCR, et en option un modèle vision-langage qui lit la page rendue comme le ferait un humain. C'est ce dernier qui justifie la présence d'un GPU dans cet article.
Comme toujours, je vais d'abord construire une image Docker — pas de Python, pas de pip, rien d'installé globalement sur ma machine.
Installation
Créer notre image Docker
Deux fichiers obtiennent un emplacement permanent, ~/tools/docling, pour que l'image puisse être reconstruite à tout moment (nouvelle machine, docker image prune, nouvelle version de Docling) : le Dockerfile, et docling-convert.sh, le script qui pilote une conversion (détaillé plus bas) :
Besoin d'aide ? Cliquez sur le bouton « Aide » ci-dessus pour les instructions de mise en place.
ARG DOCLING_VERSION fige la release exacte au lieu de laisser pip attraper la plus récente au moment du build — Docling sort une nouvelle version tous les quelques jours, et un build non figé donne une image différente à chaque reconstruction. Montez cet ARG quand vous voulez réellement la plus récente.
Un nom de package, toute une liste de courses derrière
Depuis le printemps 2026, docling sur PyPI est un metapackage léger : l'installer tire docling-slim[standard], et c'est ça qui amène les backends PDF, DOCX, PPTX, XLSX et HTML, PyTorch et les modèles de layout. Donc un simple pip install docling couvre toujours les cinq formats dont parle cet article, sans extras à retenir — mais c'est aussi pour ça que l'image est lourde. Si vous ne convertissez jamais que du .docx, par exemple, pip install "docling-slim[cli,format-docx,models-local]" vous donne une image beaucoup plus petite ; la liste complète des extras est sur la page PyPI du projet.
Construire l'image
Pas de compose.yaml ici : les conversions passent par une fonction shell qui monte le répertoire dans lequel vous vous trouvez, ce qu'un fichier Compose posé dans un dossier fixe ne peut pas faire. Un simple build suffit donc :
Attendez-vous à ce que celui-ci soit nettement plus long que celui de Markitdown : PyTorch, ses bibliothèques CUDA embarquées et les quatre modèles intégrés montent à une image de 8,3 Go ici. Ces modèles sont la partie qui mérite l'attention — ils sont téléchargés une seule fois, au build, et ils vivent dans l'image, donc un container --rm démarre avec tout ce qu'il lui faut et ne télécharge rien.
Optionnellement, si vous voulez vérifier que l'image est correcte, lancez simplement docker run --rm docling --help — la documentation couvre chaque flag listé.
Rendre docling-convert disponible partout
Même principe que md-convert, adapté à la forme réelle de la CLI de Docling. Le vrai travail est fait par ~/tools/docling/docling-convert.sh, le script que vous venez de créer à côté du Dockerfile :
#!/usr/bin/env bash# Converts documents to Markdown using the isolated docling Docker image, with# GPU acceleration when the NVIDIA container runtime is available. Unlike# md-convert, docling writes "<basename>.md" directly into the current directory# rather than to stdout — the source format is auto-detected from the extension.## The image already carries its layout, table, OCR and VLM models, so there is# nothing to download here and nothing to persist between runs.## --pipeline vlm is the slow, accurate path: it reads the page the way a human# would instead of stitching text fragments, which is what keeps paragraphs and# titles intact. Pass "--pipeline standard" as an extra argument for the fast# one. --pdf-backend only applies to the standard pipeline, where the default# ("threaded_docling_parse") drops the last line of every paragraph; pypdfium2# rebuilds the text correctly and gives the cleanest spacing of the backends.## --image-export-mode referenced overrides docling's own default ("embedded"),# which inlines every picture as a base64 data: URI and bloats the Markdown.# "referenced" writes them as PNG files in "<basename>_artifacts/" instead, and# the links stay relative because of "--output ." below.set -euo pipefail
if [[ $# -eq 0 ]]; then echo "Usage: docling-convert <file> [extra docling options]" >&2 exit 1fi
# True when "$1" is already among the extra options, either bare or as "--opt=value".has_arg() { local needle="$1" arg shift for arg in "$@"; do [[ "${arg}" == "${needle}" || "${arg}" == "${needle}="* ]] && return 0 done return 1}
# Printed under the result of every PDF conversion, because the moment you want# the flag list is the moment you have just read a disappointing file and are# about to run the command again. Options already on the command line drop off# the list, so a second attempt never suggests what it is already doing. PDFs# only: on the other four formats none of these flags changes anything.print_tip() { [[ "${DOCLING_CONVERT_NO_TIP:-}" == "1" ]] && return 0 [[ "${1,,}" == *.pdf ]] || return 0
local -a tips=() has_arg --pipeline "${@:2}" || tips+=("--pipeline standard (faster, rougher on titles)") has_arg --image-export-mode "${@:2}" || tips+=("--image-export-mode placeholder|embedded (drop the images, or inline them)") has_arg -v "${@:2}" || tips+=("-v (the full log)") ((${#tips[@]} == 0)) && return 0
local joined joined="$(printf '%s, ' "${tips[@]}")" echo "💡 Not happy with the result? Run it again with ${joined%, }." >&2 echo "💡 Hide this hint with DOCLING_CONVERT_NO_TIP=1." >&2}
# Without the NVIDIA container runtime, "docker run --gpus all" fails outright;# skip the flag and let "--device auto" settle on the CPU instead.gpu_args=()if docker info --format '{{json .Runtimes}}' 2>/dev/null | grep -q '"nvidia"'; then gpu_args+=(--gpus all)else echo "docling-convert: no NVIDIA container runtime detected, converting on CPU" >&2fi
# Triton compiles a shared library on first use and then has to load it, which a# noexec filesystem forbids. Rather than loosen /tmp, give it 256 MB of its own# that allows execution — and nothing else.## That tmpfs doubles as HOME. The container runs under the caller's UID, which# has no entry in /etc/passwd, so HOME would otherwise be empty: PyTorch then# resolves its kernel cache to "//.cache/torch/kernels", fails to create it, and# recompiles its CUDA kernels on every single run.## --quiet drops the two dozen INFO lines Docling logs per run, leaving warnings# and errors. It is not a dead end: Docling ignores --quiet as soon as -v is# given, so "docling-convert file.pdf -v" still brings the whole log back.## The awk filter handles what --quiet cannot. In 2.127.0, VlmConvertModel.__del__# logs through a module global that Python has already torn down by the time it# runs, so every VLM conversion ends on an "Exception ignored in" traceback —# after the Markdown has been written, and with the exit code still 0. It is# noise, not a failure. The rule below drops that one block, keyed on its exact# first line, and passes everything else through. Delete it when upstream fixes# __del__; it is pinned to a version for exactly that reason.start=${SECONDS}set +edocker run --rm \ "${gpu_args[@]}" \ -v "${PWD}:/workspace:cached" \ --read-only \ --tmpfs /tmp:size=512m,noexec,nosuid \ --tmpfs /run:size=16m \ --tmpfs /cache:size=256m,exec,nosuid \ -e HOME=/cache \ -e TRITON_CACHE_DIR=/cache/triton \ --cap-drop ALL \ --security-opt no-new-privileges:true \ -u "$(id -u):$(id -g)" \ docling convert "$1" \ --to md \ --device auto \ --pipeline vlm \ --pdf-backend pypdfium2 \ --image-export-mode referenced \ --output . \ --quiet \ "${@:2}" 2>&1 | awk ' /^Exception ignored in: <function VlmConvertModel\.__del__/ { skip = 1; n = 0; next } skip { n++; if (/^AttributeError: / || n >= 8) skip = 0; next } { print } ' >&2status=${PIPESTATUS[0]}set -e
# In referenced mode docling creates "<basename>_artifacts/" for every run, even# for a document without a single picture in it. rmdir only succeeds on an empty# directory, so this clears the stray folders and can never touch one that holds# actual images.artifacts="$(basename "${1%.*}")_artifacts"if [[ -d "${artifacts}" ]]; then rmdir "${artifacts}" 2>/dev/null || truefi
# Docling no longer announces what it produced, so the wrapper does — one line,# with the elapsed time, because the whole point of the pipeline choice above is# the trade it makes against the clock.if [[ ${status} -eq 0 ]]; then echo "docling-convert: $(basename "${1%.*}").md written in $((SECONDS - start))s" >&2fi
print_tip "$@"
exit "${status}"Ce script encapsule l'outil docling dans un conteneur Docker isolé pour convertir des documents en Markdown, en activant l'accélération GPU si disponible et en nettoyant les artefacts inutiles après la conversion. Il gère les options de conversion de manière intelligente, affiche des conseils contextuels pour améliorer les résultats, et filtre les messages de log parasites spécifiques à la version.
Il reste un script bash volontairement : votre shell ne charge qu'une courte fonction qui vérifie que le script et l'image sont là, puis lance le script avec bash, que votre propre shell soit zsh ou bash :
# docling-convert: convert a document of the current folder to Markdown with# the docling Docker image. Works in zsh and bash: save it as# ~/.zsh/fns/docling-convert.zsh or ~/.bash/fns/docling-convert.sh.## docling-convert report.pdf -> report.md, next to report.pdf## The real work (GPU probe, docling options, log filtering) is done by# ~/tools/docling/docling-convert.sh, a bash script kept next to the# Dockerfile; this function only checks that everything is in place.docling-convert() { local image="docling" local build_dir="${HOME}/tools/docling" # Shown as is in the messages, so the command can be copied for any user. # shellcheck disable=SC2016 local build_dir_shown='${HOME}/tools/docling' local script="${build_dir}/docling-convert.sh" local script_shown="${build_dir_shown}/docling-convert.sh"
if ! command -v docker >/dev/null 2>&1; then printf '\e[31mError: docker is not installed or not in your PATH.\e[0m\n' >&2 return 1 fi
if [[ ! -f "${script}" ]] || ! docker image inspect "${image}" >/dev/null 2>&1; then if [[ ! -f "${script}" ]]; then printf '\e[31mError: %s does not exist.\e[0m\n\n' "${script_shown}" >&2 else printf '\e[31mError: the Docker image "%s" does not exist on this machine.\e[0m\n\n' "${image}" >&2 fi printf 'How to continue:\n' >&2 if [[ -f "${build_dir}/Dockerfile" && -f "${script}" ]]; then printf ' 1. docker build -t %s "%s"\n' "${image}" "${build_dir_shown}" >&2 printf ' 2. Run your docling-convert command again.\n' >&2 else printf ' 1. Get the Dockerfile and docling-convert.sh from\n' >&2 printf ' https://www.avonture.be/blog/docling and save them in %s\n' "${build_dir_shown}" >&2 printf ' 2. docker build -t %s "%s"\n' "${image}" "${build_dir_shown}" >&2 printf ' 3. Run your docling-convert command again.\n' >&2 fi return 1 fi
bash "${script}" "$@"}Cette fonction bash enveloppe l'outil docling en vérifiant d'abord que Docker est installé et que l'image Docker docling ainsi que le script de conversion existent sur la machine. Si tout est en place, elle exécute le vrai script de conversion; sinon, elle affiche les étapes pour configurer l'environnement.
- zsh
- bash
1. Créez le fichier dans ~/.zsh/fns/ :
Besoin d'aide ? Cliquez sur le bouton « Aide » ci-dessus pour les instructions de mise en place.
2. Chargez le dossier depuis ~/.zshrc. Déjà fait si vous avez suivi un de mes articles « Ollama au quotidien ». Sinon, ajoutez à la fin de ~/.zshrc :
for fn_file in ~/.zsh/fns/*.zsh; do
source "$fn_file"
done
3. Ouvrez un nouveau terminal (ou lancez exec zsh).
1. Créez le fichier dans ~/.bash/fns/ :
Besoin d'aide ? Cliquez sur le bouton « Aide » ci-dessus pour les instructions de mise en place.
2. Chargez le dossier depuis ~/.bashrc. Ajoutez à la fin de ~/.bashrc (le test -r évite qu'un dossier vide n'affiche une erreur) :
for fn_file in ~/.bash/fns/*.sh; do
[[ -r "$fn_file" ]] && source "$fn_file"
done
3. Ouvrez un nouveau terminal (ou lancez exec bash).
Vérifiez que le shell connaît la fonction : type docling-convert doit répondre docling-convert is a shell function.
Si l'image ou le script manque, docling-convert affiche la commande docker build exacte à lancer, ou renvoie vers cet article quand ~/tools/docling a disparu aussi.
Vous venez de la version précédente de cet article ?
Elle installait docling-convert comme script dans /usr/local/bin/. Supprimez-le (sudo rm /usr/local/bin/docling-convert) : la fonction prend le relais, et l'ancien script traînerait sinon sur votre disque.
Pourquoi un wrapper ?
Le script interroge docker info pour détecter le runtime NVIDIA avant d'ajouter --gpus all. Cette vérification n'est pas décorative : docker run --gpus all ne se dégrade pas poliment sur une machine sans le toolkit, il refuse carrément de démarrer le container. Avec la sonde en place, le même script fonctionne sur mon serveur GPU et sur mon portable — plus lentement sur le portable, c'est tout, et rien à configurer dans les deux cas. Mettre ce runtime en place est optionnel et arrive à la fin de cet article.
Laissé tranquille, Docling raconte chaque exécution — choix du moteur, chargement des modèles, comptage des tokens, une vingtaine de lignes INFO pour convertir une seule page — d'où le --quiet passé par le wrapper. Ce n'est pas une impasse : Docling ignore --quiet dès que -v est présent, donc docling-convert report.pdf -v ramène tout le log le jour où quelque chose tourne mal. Les deux variables TRANSFORMERS_* et HF_HUB_* du Dockerfile finissent le travail, en faisant taire la couche de modèles en dessous, qui a ses propres opinions sur les barres de progression.
Première conversion
Il est temps de vérifier que toute la chaîne tient. Les cinq fichiers utilisés tout au long de cet article sont ici — un document, un court bon de livraison, exprimé de cinq façons, pour que vous voyiez ce que chaque format coûte sur le chemin du Markdown plutôt que de comparer cinq choses sans rapport :
samples.zip — les cinq fichiersVous préférez rester dans le terminal ? L'archive est à une URL fixe, donc curl la récupère directement dans un dossier temporaire, /tmp/docling, dézippée dans un sous-dossier samples :
report.md atterrit à côté de report.pdf, titre et paragraphes intacts — pas de dossier de sortie à nommer, pas de redirection à retenir.
Deux choses méritent attention ici. La première, c'est que docling-convert report.pdf a pris quatorze secondes. La seconde, c'est la liste de flags affichée sous le résultat : elle apparaît sous chaque conversion PDF, les options que vous avez déjà passées en disparaissent, les quatre autres formats n'ont droit à aucune suggestion, et DOCLING_CONVERT_NO_TIP=1 la coupe définitivement.
Reste la question évidente : qu'est-ce qu'on achète avec ces quatorze secondes ?
Pourquoi le pipeline lent est celui par défaut
Docling peut lire un PDF de deux manières. Le pipeline standard détecte les régions, en extrait le texte, puis réassemble le tout. Le pipeline vlm confie la page rendue à un petit modèle vision-langage — GraniteDocling, 258M de paramètres — et lui demande d'en décrire la structure, comme le ferait une personne qui lit la page. C'est celui qu'utilise le wrapper, et voici report.pdf — quatre paragraphes justifiés sous un titre en police display — passé par les deux :
$ export DOCLING_CONVERT_NO_TIP=1 $ docling-convert report.pdf --pipeline standard docling-convert: report.md written in 8s $ cat report.md ## Quarterly Delivery Note d titiitl iltil y y Scope, milestones and termination — internal circulation only Following the quarterly review held on 3 September, this note records the agreed scope, [...] the payment schedule set out in section three, which is intended to replace it entirely. The supplier shall deliver the first increment within six weeks of signature, [...] $ docling-convert report.pdf docling-convert: report.md written in 14s $ cat report.md ## Quarterly Delivery Note Scope, milestones and termination - internal circulation only Following the quarterly review held on 3 September, this note records the agreed scope, [...] the payment schedule set out in section three, which is intended to replace it entirely. The supplier shall deliver the first increment within six weeks of signature, [...]
Regardez la première ligne du pipeline standard. Quarterly Delivery Note d titiitl iltil, suivi d'un yy égaré — l'étape OCR s'est déclenchée sur le grand titre et a halluciné des lettres qui n'existent dans aucune version de ce document. Puis elle a coupé la première proposition en deux, laissant which is intended to replace it entirely. seule sur sa ligne. Le VLM n'a produit ni le texte inventé ni l'orpheline. Quatorze secondes contre huit, c'est le prix, et ça achète un fichier que vous pouvez transmettre à quelqu'un sans l'avoir relu.
Le chemin rapide n'échoue pas bruyamment : il invente, et le texte inventé ne se détecte qu'en relisant la sortie.
Une vraie différence avec md-convert
Markitdown écrit le Markdown sur stdout, donc md-convert file.docx > file.md est la façon de le capturer. La CLI de Docling écrit au contraire <basename>.md directement dans le répertoire de sortie — il n'y a pas de mode stdout. docling-convert file.docx produit file.md juste à côté ; aucune redirection > n'est nécessaire, et aucune ne fonctionnera.
Un mot sur les images
Docling rend tout ce que le modèle de layout classe comme image — et sur un titre composé dans une police display, ça peut être le titre lui-même. Laissé tranquille, il intègre ensuite chacune d'elles dans le Markdown sous forme d'URI data: en base64, ce qui garde le fichier autonome et le gonfle énormément. Le wrapper passe --image-export-mode referenced à la place : les images atterrissent en vrais fichiers PNG dans un dossier budget_artifacts/ à côté de budget.md, liées en relatif, pour que les deux voyagent ensemble.
Les deux autres modes sont à un flag de distance. --image-export-mode placeholder supprime les images et laisse un marqueur <!-- image --> à la place de chacune — le bon choix quand le Markdown va alimenter un modèle plutôt qu'une personne. --image-export-mode embedded ramène le base64, quand vous voulez un document unique et autonome. Une chose à savoir si vous appelez un jour Docling sans le wrapper : ces liens sont relatifs grâce à --output ., et un --output absolu écrit les chemins internes au container, qui ne résolvent vers rien à l'extérieur.
Optionnel — Mettre un GPU derrière le pipeline PDF
Tout ce qui précède fonctionne sans GPU, et cette section est sautable — deux fois plutôt qu'une :
- Vous ne convertissez que du
.docx,.xlsx,.pptxou.html? Alors ça ne vous apporte strictement rien. Ces quatre formats ne chargent jamais de modèle, il n'y a donc rien à accélérer ;--gpusne change ni la vitesse ni la sortie. - Vous convertissez des PDF sur une machine sans carte NVIDIA ? Alors ça fonctionne quand même.
--device autose rabat sur le CPU, le même pipeline VLM tourne, et le même Markdown en sort — c'est juste plus long. Le wrapper affiche le temps écoulé à chaque exécution, votre propre matériel vous dira donc de combien.
Recommandé pour les PDF, inutile pour les quatre autres, obligatoire pour personne.
Pourquoi un toolkit est nécessaire
Un container ne voit pas votre carte graphique. La carte, sa VRAM et le driver NVIDIA vivent sur l'host ; un container n'obtient ni /dev/nvidia* dans sa liste de périphériques, ni les bibliothèques du driver dans son système de fichiers. Les bibliothèques CUDA que pip a installées dans notre image — la wheel torch embarque les siennes, raison pour laquelle le Dockerfile part d'un simple python:3.12-slim-trixie et non d'une base nvidia/cuda — ne sont que la moitié supérieure de cette pile : elles parlent au driver, elles ne le remplacent pas. La moitié inférieure manquant, PyTorch ne signale aucun périphérique CUDA et calcule sur le CPU.
Le NVIDIA Container Toolkit est la pièce qui réunit les deux moitiés : il enregistre un hook dans le daemon Docker qui, à chaque démarrage de container avec --gpus, y injecte les nœuds de périphériques GPU et les bibliothèques du driver de l'host. C'est toute la raison de sa présence dans cet article — pas de toolkit, pas de VRAM. Installez-le sur l'host Docker, jamais dans l'image, puis confirmez que le GPU est visible depuis l'intérieur d'un container :
Ce tableau, c'est la carte de l'host lue depuis l'intérieur d'un container : 24 Go de VRAM, version du driver, ce qui l'utilise actuellement. L'image nvidia/cuda n'est là que comme véhicule pratique pour nvidia-smi — notre propre image n'en a pas besoin.
Si ce tableau n'apparaît pas
Rien n'est cassé : docling-convert continue de convertir, sur le CPU, exactement comme il l'a fait tout au long de l'article. Si vous voulez vraiment le GPU, trois pannes couvrent quasiment tous les cas :
| Ce que vous obtenez à la place | Ce que ça veut dire | Quoi faire |
|---|---|---|
could not select device driver "" with capabilities: [[gpu]] | Docker n'a pas de hook GPU : le toolkit n'est pas installé, ou bien installé mais jamais branché au daemon | Installez le toolkit depuis le dépôt de packages NVIDIA, puis lancez les deux commandes ci-dessous |
nvidia-smi échoue sur l'host aussi, en dehors de tout container | Le driver lui-même manque ou est cassé — Docker n'est pas encore en jeu | Installez le driver et redémarrez jusqu'à ce que nvidia-smi fonctionne sur l'host. Sous WSL2, ce driver est un driver Windows : installez-le sur Windows, jamais dans la distribution |
Failed to initialize NVML: Unknown Error | Le hook s'est exécuté, mais le périphérique a été refusé au container — un daemon qui tourne encore avec sa configuration d'avant le toolkit | Les deux commandes ci-dessous |
Deux de ces trois cas ont le même correctif, parce que le package ne fait que poser le hook sur le disque — il faut encore en informer le daemon :
$ sudo nvidia-ctk runtime configure --runtime=docker
$ sudo systemctl restart docker
$ docker info --format '{{json .Runtimes}}'
{"io.containerd.runc.v2":{"path":"runc"},"nvidia":{"path":"nvidia-container-runtime"},"runc":{"path":"runc"}}
Cette dernière commande est exactement la sonde que le script wrapper exécute avant d'ajouter --gpus all : dès que nvidia apparaît parmi les runtimes de Docker, le prochain PDF passe par le GPU sans rien d'autre à changer.
Ce que coûtent les cinq fichiers
Chaque chiffre de cet article a été mesuré sur les fichiers que vous avez dézippés plus haut, et les cinq commandes du tout premier terminal tournent dessus telles quelles. Sur ma machine, les quatre formats bureautiques tiennent en quatre à cinq secondes chacun, presque entièrement du démarrage de processus, et report.pdf prend quatorze secondes avec le GPU en jeu. Cet écart résume tout : seul le PDF a besoin des modèles.
Ce que montre réellement le tableur
Les cellules fusionnées ne sont pas réduites, elles sont répétées : le titre ressort une fois par colonne qu'il couvrait, et chaque ligne de section aussi. Rien n'est perdu, mais n'attendez pas du Markdown qu'il reproduise la fusion visuelle. Et Docling lit les formules, pas leurs résultats — un tableur écrit par un script et jamais ouvert dans Excel se convertit avec tous les totaux vides. C'est pour cette raison que budget.xlsx stocke les valeurs calculées.
À retenir
docling-convert en bref
- Le GPU est optionnel —
--device autoretombe proprement sur le CPU si le passthrough n'est pas configuré - Un package, cinq formats —
pip install doclingtiredocling-slim[standard], qui couvre PDF, DOCX, PPTX, XLSX et HTML - Les modèles sont intégrés — téléchargés au build, donc un container non privilégié en lecture seule n'a jamais rien à récupérer
- Écrit des fichiers, pas sur stdout —
docling-convert file.pdfproduitfile.mddirectement, pas de redirection> - Lent volontairement —
--pipeline vlmgarde paragraphes et titres intacts ; ajoutez--pipeline standardquand la vitesse compte plus - Seuls les PDF ont besoin des modèles —
.docx/.xlsx/.pptx/.htmlpassent par un simple parser, sans GPU ni modèle
Conclusion
Entre celui-ci et Markitdown, j'ai maintenant deux images Docker qui transforment des documents bureautiques en Markdown sans qu'un seul octet ne quitte ma machine — une légère que j'utilise par réflexe, et celle-ci, plus lourde, pour quand la structure d'un PDF mérite qu'on y passe vingt secondes et un GPU. Et comme les deux produisent du Markdown brut, l'une comme l'autre s'intègre directement dans le genre de pipeline que je décrivais dans Discutez avec vos documents grâce à AnythingLLM — ou dans le prochain article de la série « Ollama au quotidien », où ce Markdown devient l'entrée d'un pipeline local de traduction et de résumé pour des documents qui n'ont jamais eu vocation à toucher le cloud.






