Un pipeline RAG découpe son fonds documentaire PDF tous les cinq cents caractères, sans se soucier de ce que chaque fragment contient réellement. Ça fonctionne, jusqu’au jour où une requête sur le montant total d’une facture ramène une réponse incohérente. Le fragment concerné contient bien une ligne de tableau, mais plus aucune trace de l’en-tête de colonne à laquelle cette ligne appartenait. Le nombre est là, isolé de tout contexte : impossible de savoir s’il s’agit d’un prix unitaire, d’une quantité ou d’un total. Le modèle de langage répond quand même — avec assurance, et à côté.
Le chunking par caractères : simple, jusqu’à ce qu’il coûte cher
Découper un texte tous les N caractères est la première approche que rencontre à peu près toute équipe qui construit un pipeline RAG, et ce n’est pas un hasard. Elle ne demande aucune compréhension du document : ni titre, ni paragraphe, ni tableau à identifier, juste un compteur qui avance et coupe où il s’arrête. Elle s’applique identiquement à un contrat, une notice technique ou un rapport financier. Sur un corpus de quelques dizaines de pages de texte continu, sans mise en page complexe, le résultat reste souvent acceptable : les coupures tombent au hasard, mais rarement au pire endroit.
Le problème n’est pas que cette approche échoue immédiatement. C’est qu’elle fonctionne juste assez bien, au début, pour devenir la valeur par défaut d’un pipeline entier — et que ses failles n’apparaissent qu’après, une fois le corpus étendu à des documents que personne n’a relus un par un.
La facture s’alourdit à mesure que le corpus grossit
Sur un rapport structuré en sections, un compteur de caractères ignore superbement les titres : un fragment peut commencer au milieu d’un paragraphe, se terminer au milieu du suivant, et mélanger la fin d’un sujet avec le début d’un autre. Un modèle d’embedding qui reçoit ce fragment mixte produit une représentation vectorielle qui ne correspond plus clairement à rien — ni au premier sujet, ni au second, un peu aux deux, jamais avec précision. Résultat : ce fragment remonte pour des requêtes qui n’ont rien à voir avec son contenu réel, ou au contraire n’est jamais retrouvé pour la question à laquelle il pouvait pourtant répondre.
Sur un document contenant des tableaux — bilan comptable, grille tarifaire, tableau de conformité — le compteur de caractères ne sait pas qu’il traverse un tableau. Il coupe une ligne au milieu, sépare une valeur de sa colonne, ou pire, laisse un fragment ne contenir qu’une poignée de cellules sans l’en-tête qui leur donnait un sens. Une fois ce fragment extrait de son contexte visuel et indexé isolément, aucune information ne permet plus de savoir à quelle colonne appartenait chaque chiffre.
Sur une mise en page à plusieurs colonnes, la difficulté change de nature mais s’ajoute aux précédentes : un compteur qui avance dans l’ordre brut des caractères du fichier peut interclasser la fin d’une colonne avec le début de la suivante, produisant un fragment qui mélange deux passages qui ne se suivaient jamais visuellement. Le texte extrait reste exact, caractère par caractère — c’est son assemblage en fragments qui devient trompeur.
La conséquence, pour l’utilisateur final d’un pipeline RAG, se voit directement dans les réponses générées : des réponses qui mélangent deux informations sans rapport entre elles, ou qui manquent une donnée pourtant présente dans le corpus, simplement parce qu’elle a été fragmentée au mauvais endroit et n’a jamais formé un fragment exploitable à l’indexation.
Trois manières de découper un document qui respecte son sens
Un découpage qui respecte la structure d’un document repose sur une idée simple : un fragment doit correspondre à une unité de sens, pas à une longueur fixe. Trois approches concrètes s’en approchent, chacune avec un compromis différent.
La première découpe par élément sémantique : un paragraphe forme un fragment, un titre un autre, une liste un troisième. Chaque fragment reste petit et précis, ce qui aide un modèle d’embedding à produire une représentation nette — mais un fragment isolé peut manquer de contexte si son sens dépend fortement du titre ou du paragraphe qui le précède.
La deuxième découpe par section : tout le contenu qui suit un titre, jusqu’au titre suivant, forme un seul fragment. Un fragment correspond alors à un sujet complet plutôt qu’à une phrase isolée, ce qui aide un modèle à répondre à des questions qui demandent le contexte entier d’une section — au prix de fragments parfois plus longs, moins ciblés sur un détail précis.
La troisième n’est pas une découpe mais une fusion : les fragments trop courts pour porter un sens exploitable en embedding — un titre isolé de trois mots, une phrase de rupture — sont regroupés avec un fragment voisin, jusqu’à atteindre un seuil indicatif de l’ordre de deux cents caractères. En dessous, un fragment porte trop peu d’information pour qu’un modèle d’embedding le distingue utilement d’un autre fragment tout aussi pauvre.
Une règle traverse les trois approches, sans exception : un tableau n’est jamais fractionné entre deux fragments. Il reste une unité indivisible, quelle que soit la stratégie retenue, parce qu’un tableau coupé en deux perd son sens — une ligne sans l’en-tête de colonne à laquelle elle appartient ne veut plus rien dire, même parfaitement extraite caractère par caractère.
Ces trois stratégies ont cependant un préalable commun, souvent passé sous silence : elles ne sont applicables proprement que sur un document déjà structuré, où chaque zone porte un type (titre, paragraphe, tableau, liste) et où l’ordre de lecture réel est connu — pas simplement l’ordre d’apparition des caractères dans le fichier. Sur un flux de texte brut sans cette information, aucune des trois n’est même possible à mettre en œuvre correctement : ni un titre à repérer, ni une section à délimiter, ni un tableau à protéger d’une coupure. On revient alors, faute de mieux, au découpage par caractères — pas par choix, mais par absence d’alternative.
Ce que l’export structuré de Vigie PDF fournit réellement
C’est précisément ce préalable que couvre l’export structuré de Vigie PDF, sans pour autant se substituer au travail de découpage lui-même. Chaque document déposé, natif ou scanné, ressort de son traitement automatique sous la forme d’une collection de zones typées — titre, paragraphe, liste, tableau, image, en-tête, pied de page — positionnées par leurs coordonnées exactes sur la page, et ordonnées selon un ordre de lecture réellement détecté. Cet ordre s’appuie sur une analyse de la position géométrique des blocs sur la page plutôt que sur leur simple ordre d’apparition dans le fichier, ce qui le rend fiable même sur des mises en page à plusieurs colonnes. Les en-têtes et pieds de page répétitifs, ainsi que les filigranes, sont écartés automatiquement de cette structure : ils n’apportent aucune information utile à un fragment destiné à l’indexation.

Une zone de type tableau conserve, dans cet export, ses lignes et ses colonnes organisées comme telles — pas une suite de lignes de texte interclassées comme le ferait une extraction brute. C’est exactement cette matière qui rend possible la règle du tableau jamais fractionné : une équipe RAG qui applique l’une des trois stratégies précédentes s’appuie sur ce typage pour identifier sans ambiguïté où commence et où finit un tableau, quelle que soit la stratégie retenue par ailleurs pour le reste du document.
Vigie PDF ne choisit pas cette stratégie à la place de l’équipe qui exploite les données. Ce n’est pas son rôle, et ce n’est pas ce que fournit le produit : par élément, par section, ou une combinaison des deux avec seuil de fusion, le choix reste entièrement celui du pipeline RAG en place, en fonction de la nature de ses documents et des questions qu’il doit couvrir. Ce que l’export structuré apporte, c’est la matière fiable — zones typées, position exacte, ordre de lecture réel — sur laquelle cette stratégie s’applique correctement, sans qu’une équipe data doive d’abord redétecter elle-même la structure du document à partir de rien, avec les heuristiques fragiles que ça suppose habituellement.
Concrètement, une zone de tableau extraite garde son en-tête de colonne associé à chacune de ses lignes, une zone de titre reste liée au paragraphe qui la suit dans l’ordre de lecture réel de la page, et un bloc de texte réparti sur deux colonnes visuelles ne se retrouve jamais recomposé dans le mauvais ordre. C’est cette même matière — zones, coordonnées, ordre de lecture — qui s’affiche à l’écran, page par page, dans le Studio de visualisation des zones taguées : l’export consommé par un pipeline RAG n’est rien d’autre que la version machine-lisible de ce que le Studio donne déjà à voir visuellement. Le détail exact des formats disponibles pour récupérer cet export — pensé pour s’intégrer sans réécrire un pipeline de chunking déjà en place — figure dans la documentation, accessible depuis le tableau de bord une fois le compte créé, comme détaillé dans l’article sur les données structurées pour un pipeline RAG.
Ce que ça change pour les réponses générées par un RAG
Le passage d’un découpage par caractères à un découpage qui respecte la structure du document ne demande pas de réécrire la logique de détection existante d’un pipeline RAG — seulement de la nourrir avec une entrée déjà fiable plutôt que du texte plat. Les fragments produits correspondent alors à des unités de sens réelles plutôt qu’à des tranches arbitraires : un paragraphe reste un paragraphe, une section reste un sujet, un tableau reste intact du premier en-tête à la dernière ligne. Sur une mise en page à plusieurs colonnes, l’ordre de lecture ne fausse plus le découpage, puisqu’il reflète la position réelle des blocs sur la page plutôt que l’ordre brut des caractères dans le fichier.
Pour l’utilisateur final, la différence se voit directement dans la qualité des réponses générées : moins de réponses qui mélangent deux informations sans rapport, moins de données présentes dans le corpus mais introuvables parce que fragmentées au mauvais endroit. Le fragment qui remonte à une requête correspond à ce qu’il prétend être — et reste, en plus, traçable jusqu’à sa zone d’origine sur la page source.