coffreobsidian/inbox/Documentation méthode traitement Normes.md
2025-03-27 16:48:21 +01:00

373 lines
57 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
- Extraire et préparer les schémas depuis les PDF
- Traduire les légendes et contextualiser les images pour LLM vision
- Utiliser les bons LLM aux bonnes étapes (Vision, Traduction, Résumé, Rerank, etc.)
- Intégrer efficacement les chunks enrichis dans Ragflow (structure, métadonnées, lien logique avec les autres chunks)
- Fournir un tutoriel détaillé étape par étape, avec du code Python lorsque pertinent
# Traitement Multimodal de PDFs Réglementaires avec Ragflow
## Contexte et Enjeux
Les documents PDF complexes, mêlant texte réglementaire en français et schémas annotés, posent un défi pour les pipelines RAG (Retrieval-Augmented Generation). Il sagit dextraire fidèlement le contenu textuel **et** visuel afin dalimenter un moteur de recherche sémantique et de permettre à un LLM de répondre aux questions de lutilisateur de manière précise et sourcée. Nous allons explorer toutes les méthodes pour **extraire et contextualiser les schémas** dans de tels PDF, puis détailler le choix des modèles dIA (vision, résumé, traduction, rerank, etc.) à chaque étape, en précisant la langue de travail appropriée (anglais vs français). Nous fournirons ensuite un **tutoriel pas-à-pas** illustré de code Python pour mettre en œuvre ces étapes dans un pipeline RAGFlow. Enfin, nous proposerons des **conseils de structuration** de la base de connaissances Ragflow et de lorchestration des assistants afin de maximiser la qualité des réponses.
## Extraction et Contextualisation des Schémas dans un PDF
Traiter les schémas (diagrammes, figures, graphiques) dun PDF nécessite de combiner plusieurs techniques. Lobjectif est de **capturer linformation visuelle** contenue dans ces schémas et de la lier au texte environnant (ex. légendes, références dans le corps du texte). Voici les stratégies principales :
- **Extraction directe dimages intégrées** : Si le PDF comporte des images matricielles intégrées (formats JPEG/PNG), on peut les extraire via une bibliothèque PDF. Par exemple, avec PyMuPDF on peut parcourir chaque page et extraire les blocs de type _image_ via `page.get_text("dict")` (qui renvoie un dict contenant texte et images) ([Images - PyMuPDF 1.25.4 documentation](https://pymupdf.readthedocs.io/en/latest/recipes-images.html#:~:text=2,images%20shown%20on%20a%20page)). Chaque bloc image fournit le _binary_ de limage (quon peut sauvegarder) et sa position (_bbox_) dans la page ([Images - PyMuPDF 1.25.4 documentation](https://pymupdf.readthedocs.io/en/latest/recipes-images.html#:~:text=,0.0%2C%20228.2460174560547%2C%20100.0)). Cette approche est rapide et conserve la résolution originale de limage.
- **Capture raster des zones graphiques** : Si le schéma nest pas une image distincte (par ex., un dessin vectoriel dans le PDF), on peut **rasteriser la page ou la zone** correspondante. PyMuPDF permet de rendre une page ou un _rectangle_ de page en image via `page.get_pixmap(matrix=..., clip=...)`. On peut dabord identifier la zone du schéma (par ex. via la position de la légende ou par une analyse de la mise en page), puis générer une image de cette zone. Des outils comme pdf2image (basé sur Poppler) peuvent aussi convertir chaque page en image haute résolution à analyser.
- **Détection automatique de la mise en page** : Pour localiser les figures et leurs légendes de manière fiable, on peut utiliser des modèles de _Document Layout Analysis_. Par exemple, Ragflow intègre un module de reconnaissance de layout qui classifie les éléments dune page en catégories (texte courant, titre, **figure**, **légende de figure**, table, etc.) ([ragflow/deepdoc/README.md at main · infiniflow/ragflow · GitHub](https://github.com/infiniflow/ragflow/blob/main/deepdoc/README.md#:~:text=,components%20which%20covers%20most%20cases)) ([ragflow/deepdoc/README.md at main · infiniflow/ragflow · GitHub](https://github.com/infiniflow/ragflow/blob/main/deepdoc/README.md#:~:text=,Equation)). Ce type de modèle (semblable à LayoutParser ou PubLayNet) peut détecter quune zone est une _figure_ et la zone en dessous comme _Figure caption_. En combinant ces informations, on peut automatiquement **découper** chaque schéma et lassocier à sa légende. Ragflow DeepDoc fournit par exemple 10 composants de base dont _Figure_ et _Figure caption_, ce qui permet de savoir qu“une image X est décrite par telle légende Y” ([ragflow/deepdoc/README.md at main · infiniflow/ragflow · GitHub](https://github.com/infiniflow/ragflow/blob/main/deepdoc/README.md#:~:text=Recognition,components%20which%20covers%20most%20cases)).
- **OCR des textes dans limage** : Les schémas « annotés » contiennent souvent du texte (labels, commentaires dans le diagramme). Un OCR est nécessaire pour extraire ces textes **imbriqués dans limage**. On peut utiliser Tesseract (via `pytesseract`) en spécifiant la langue française (`lang='fra'`) pour reconnaître les mots en français sur le schéma. Par exemple : ```python texte_image = pytesseract.image_to_string(Image.open("schema.png"), lang="fra")```
- **Contextualisation manuelle ou semi-automatique** : Dans certains cas complexes, un **découpage manuel** peut être nécessaire. Par exemple, si le PDF est très hétérogène, lintervenant peut ouvrir le PDF, repérer les pages contenant des schémas dimportance, et définir manuellement des zones de capture. Cela peut être fait via un outil ou en coordonnant des *bounding boxes* à passer à la fonction de rasterisation (PyMuPDF ou autre). Cette méthode garantit de capturer exactement ce qui est pertinent, mais elle demande un effort humain. Idéalement, on la combine avec les méthodes automatiques (layout/OCR) pour gagner du temps par exemple, vérifier et ajuster les zones détectées automatiquement.
**Association au texte réglementaire** : Une fois limage du schéma extraite et son texte OCRisé, il faut la **lier au contexte textuel**. Cela se fait en récupérant la légende (souvent présente juste en-dessous ou au-dessus du schéma dans le PDF) et/ou en repérant les renvois dans le texte principal (ex. “voir Figure 5”). En pratique :
- La **légende** (caption) est généralement extraite par le parser PDF comme un bloc de texte à part. Il convient de lisoler. Par exemple, Ragflow indique extraire pour chaque figure *“la figure elle-même avec sa légende et le texte inclus dans la figure”* ([ragflow/deepdoc/README.md at main · infiniflow/ragflow · GitHub](https://github.com/infiniflow/ragflow/blob/main/deepdoc/README.md#:~:text=,and%20text%20in%20the%20figures)). Si loutil ne la pas fait, on peut rechercher dans le texte brut des motifs du type “Figure X : …” ou bien utiliser la détection de layout mentionnée plus haut.
- Le **texte environnant** qui fait référence à la figure peut être utile. Par exemple, un paragraphe qui introduit le schéma (“Le schéma ci-dessous illustre…”). On peut décider dinclure ce paragraphe dans le même *chunk* que la description du schéma, ou au moins de sy référer via des métadonnées (ex : “related_to=Figure 5”).
En résumé, lextraction efficace des schémas combine **outils PDF** (pour isoler images et textes), **OCR** (pour lire le contenu interne des images) et éventuellement **analyse de layout** (pour automatiser lidentification des figures et légendes). Lobjectif final est de produire pour chaque schéma une **description textuelle riche** (contenant la légende originale, les textes OCR, et une explication globale) qui pourra être indexée et utilisée par le LLM.
## Choix des Modèles LLM à Chaque Étape
Un pipeline RAG multimodal sappuie sur divers modèles spécialisés. Voici les types de modèles intervenant et lesquels choisir pour ce cas dusage, en précisant la langue dentrée/sortie optimale pour chacun :
- **Modèle de Vision (LLM Vision)** : Cest le cœur de linterprétation des schémas. Un LLM vision combine un encodeur dimage et un grand modèle de langue pour **décrire limage** ou répondre à des questions sur celle-ci. Exemples appropriés : *LLaVA* (Large Language and Vision Assistant) ou *LLaMA-3 Vision*. LLaVA est un modèle open-source entraîné en instruction-following visuel (Vicuna + encodeur CLIP) apte à fournir des descriptions détaillées dimages ([Analyzing Images with LLaVA - Medium](https://medium.com/@natsunoyuki/analyzing-images-with-llava-f3ac169cbecf#:~:text=Analyzing%20Images%20with%20LLaVA%20,source%20chatbot%20to%20create)) ([Vision models · Ollama Blog](https://ollama.com/blog/vision-models#:~:text=Vision%20models%20%C2%B7%20Ollama%20Blog,support%20higher%20resolution%20images%2C)). Les LLMs vision actuels ont été majoritairement entraînés en anglais, et **ont tendance à répondre en anglais** par défaut. En effet, des études ont montré quavec une image en entrée, même si la question est en français, un modèle LLaVA a de fortes chances de répondre en anglais ([](https://aclanthology.org/2024.findings-emnlp.783.pdf#:~:text=We%20uncover%20a%20surprising%20multilingual,a%20mechanistic%20analysis%20of%20the)) ([](https://aclanthology.org/2024.findings-emnlp.783.pdf#:~:text=to%20the%20query%20to%20a,First%20we)). Pour exploiter au mieux ces modèles, il est donc conseillé de **travailler en anglais pendant létape vision** (décrire limage en anglais) puis de traduire en français le résultat. Nous aborderons ce point de langue plus loin. En termes de choix, *LLaVA 1.5/1.6* en 7B ou 13B de paramètres (disponible via Ollama par ex.) fait partie des meilleurs candidats open-source. La version 1.6 a amélioré la **lecture de texte dans les images** et la compréhension de diagrammes ([Vision models · Ollama Blog](https://ollama.com/blog/vision-models#:~:text=The%20LLaVA%20%28Large%20Language,supporting)), ce qui est précieux pour nos schémas annotés. Dautres alternatives comme *MiniGPT-4*, *BLIP-2* (pour du captioning plus simple) ou *Pix2Struct/Pixtral* (modèles récents de Mistral AI avec 12B+ paramètres) pourraient être considérées, mais LLaVA offre un bon compromis maturité/poids. **Langue dutilisation** : fournir les consignes en anglais (par ex. “Describe this diagram…”) et sattendre à une réponse en anglais (que lon traduira ensuite).
- **Modèle de Résumé (LLM de résumé)** : Un modèle de résumé nest pas toujours indispensable, mais il peut intervenir pour **condenser des textes longs** ou structurer linformation. Dans notre pipeline, on pourrait lutiliser pour : (1) résumer un long passage réglementaire en un chunk plus synthétique (si on craint de dépasser les limites de tokens ou de diluer la pertinence), ou (2) reformuler la description brute générée par lOCR + LLM vision en un texte plus concis. Un LLM de résumé en français serait ici indiqué si lon souhaite une sortie en français directement. Par exemple, on pourrait utiliser *GPT-3.5* ou *GPT-4* via API pour une grande qualité de résumé multilingue, ou opter pour un modèle open-source instruct finetuned, tel que *Mistral 7B* (ou sa déclinaison fine-tunée sur des données FR, ex. *Claire-Mistral-7B* ([OpenLLM-France/Claire-Mistral-7B-0.1 - Hugging Face](https://huggingface.co/OpenLLM-France/Claire-Mistral-7B-0.1#:~:text=Claire,7B%20on%20French%20conversational%20data))). Mistral 7B, bien que plus petit, a été salué pour ses capacités multilingues (notamment en français) et peut être utilisé localement. On pourrait lui demander :  Résume le texte suivant en gardant les points clés… »*. **Langue** : si on résume du texte réglementaire français, rester en français pour ne pas perdre les nuances juridiques dans une traduction inutile. En revanche, si on résume une description dimage générée en anglais par LLaVA, on pourrait en profiter pour directement la traduire/résumer en français via un prompt (de type  Traduits et résume ... »*).
- **Traducteur (LLM ou API de traduction)** : La traduction est un composant crucial pour concilier langlais et le français dans le pipeline. Deux besoins : **FR → EN** (pour fournir au LLM vision un contexte compréhensible le cas échéant) et **EN → FR** (pour réinjecter les résultats dans la base en français). La solution de haute qualité est dutiliser lAPI DeepL, reconnue pour ses traductions précises y compris dans le domaine technique/réglementaire. Par exemple, lendpoint `/translate` de DeepL permet de traduire un texte fourni en spécifiant la langue source et cible ([Translate text | DeepL API Documentation](https://developers.deepl.com/docs/api-reference/translate#:~:text=Example%20request%3A%20text%20translation%20,glossary)) ([Translate text | DeepL API Documentation](https://developers.deepl.com/docs/api-reference/translate#:~:text=,)). Un appel POST avec `text="Schéma de l'architecture logicielle"` et `target_lang="EN"` renverra *“Diagram of the software architecture”*. Inversement, on peut traduire la description anglaise dune figure vers le français (*target_lang="FR"*). DeepL assure une **haute fidélité sémantique**, ce qui est essentiel dans un contexte réglementaire. En alternative open-source, on pourrait utiliser un modèle comme *NLLB (No Language Left Behind)* ou *M2M100* de Facebook pour la traduction automatique, ou même solliciter un LLM généraliste (par ex. *GPT-4*, ou *Mistral 7B* avec un prompt de traduction). Cependant, la consistance terminologique offerte par DeepL Pro est souvent un atout dans ce type de documents. **Langue** : on traduit bien sûr vers la langue requise par létape suivante (vers langlais pour létape vision, vers le français pour enrichir la KB).
- **Reranker (Modèle de re-classement)** : Un reranker sert à **affiner lordre des résultats de recherche** en évaluant la pertinence contextualisée. Dans Ragflow, la recherche initiale se fait via les **vecteurs dembedding** (similarité cosinus), mais on peut activer un modèle de rerank pour re-trier les top résultats selon un critère plus précis ([HTTP API | RAGFlow](https://ragflow.io/docs/dev/http_api_reference#:~:text=match%20at%20L1565%20%2A%20%60,Default%20to%201024)) ([HTTP API | RAGFlow](https://ragflow.io/docs/dev/http_api_reference#:~:text=%2A%20%60,Default%20to%201024)). Typiquement, un reranker est un modèle de type *cross-encoder* qui prend la requête et un chunk en entrée et produit un score de pertinence. Par exemple, on pourrait utiliser un modèle **multilingue** comme `camembert/msmarco` (spécialisé QA FR) ou un modèle anglais multilingue comme `sentence-transformers/paraphrase-multilingual-mpnet-base-v2` en cross-encodage. Si on conserve tout en français, un modèle *french cross-encoder* serait idéal, sinon on pourrait traduire la requête et les chunks en anglais et utiliser un reranker anglais (mais cest lourd). Ragflow propose un champ *rerank_model* dans la config de lassistant ([HTTP API | RAGFlow](https://ragflow.io/docs/dev/http_api_reference#:~:text=%2A%20%60,Default%20to%201024)), on pourrait y brancher un modèle comme **OpenAI re-rank** ou un modèle local. En pratique, on choisira un reranker si lon constate que de nombreux chunks bruités remontent et que le LLM final peine à choisir. Ce modèle na pas besoin dêtre gros; même un MiniLM ou E5-large en cross-encoder peut suffire. **Langue** : à adapter selon le modèle choisi idéalement français natif pour éviter de devoir tout traduire pendant la phase de retrieval.
- **Modèle QA final (Assistant Ragflow)** : Bien que non listé explicitement, il faut rappeler que dans le chat Ragflow, lassistant lui-même est un LLM qui exploite les documents retrouvés. Ce modèle doit **bien maîtriser le français** et le style de réponse attendu (p. ex., rédiger de manière professionnelle et justifier par les sources). On peut configurer lassistant Ragflow pour utiliser un modèle open-source hébergé localement (*via* Ollama ou autre). Par exemple, on pourrait utiliser *Llama-2 13B Chat* (qui a une bonne compréhension du français), ou une variante fine-tunée sur du français juridique. Mistral 7B peut également être utilisé sil a été affiné sur des instructions (des initiatives comme Mistral/INRIA ont probablement amélioré la sortie française ([OpenLLM-France/Claire-Mistral-7B-0.1 - Hugging Face](https://huggingface.co/OpenLLM-France/Claire-Mistral-7B-0.1#:~:text=Claire,7B%20on%20French%20conversational%20data))). Limportant est que ce modèle final saura **intégrer les extraits** (texte réglementaire et descriptions de schémas) pour formuler une réponse pertinente. On veillera à ce que la **sortie soit en français** (on peut le garantir via le prompt système de lassistant). Ragflow permet de configurer ces paramètres dans linterface Chat (description du rôle, ouverture de conversation, etc.) ([RAGFlow an Open-Source Retrieval-Augmented Generation (RAG) Engine | by Omar Santos | Medium](https://becomingahacker.org/ragflow-an-open-source-retrieval-augmented-generation-rag-engine-6b903005a032#:~:text=The%20figure%20above%20shows%20the,configure%20the%20assistant%E2%80%99s%20settings%2C%20including)) ([RAGFlow an Open-Source Retrieval-Augmented Generation (RAG) Engine | by Omar Santos | Medium](https://becomingahacker.org/ragflow-an-open-source-retrieval-augmented-generation-rag-engine-6b903005a032#:~:text=5,base%20that%20I%20created%20earlier)). Notamment, en activant *“Show Quote”* lassistant pourra inclure les citations des documents dans sa réponse ([RAGFlow an Open-Source Retrieval-Augmented Generation (RAG) Engine | by Omar Santos | Medium](https://becomingahacker.org/ragflow-an-open-source-retrieval-augmented-generation-rag-engine-6b903005a032#:~:text=5,base%20that%20I%20created%20earlier)), ce qui est souhaitable ici pour appuyer les réponses par des extraits du PDF (page, figure, etc.). **Langue** : français impératif en sortie, avec potentiellement langlais compris en entrée aussi (si lutilisateur posait une question en anglais ou sur du contenu anglais, ce qui est peu probable ici).
En synthèse, chaque tâche du pipeline utilise le meilleur de lIA spécialisé : Vision en anglais avec LLaVA (exploité via Ollama localement), résumé/traduction éventuellement via des services ou LLM dédiés, et un LLM final aligné sur le français. Cette combinaison garantit performance et cohérence linguistique.
## Langue de Traitement : Anglais vs Français
Il est crucial de **distinguer les contenus à traiter en anglais ou en français** afin dutiliser chaque modèle de façon optimale tout en maintenant une base de connaissance homogène. Résumons comment gérer la langue à chaque étape du flux :
- **Extraction du texte brut du PDF** : Ici, pas de question de langue, on extrait tel quel. Le texte réglementaire est en français et le reste en létat.
- **Traitement des schémas par le LLM Vision** : Comme expliqué, ces modèles sont plus fiables en anglais. Il est donc recommandé de **convertir en amont tout ce qui peut les aider en anglais**. Cela inclut : la légende du schéma (si elle est en français, la traduire en anglais), ainsi que les éventuels textes OCRisés de limage en français. En pratique, on peut construire une *prompt* pour le LLM vision du style : *“Here is an image. Legend: <légende traduite>. Please describe the image in detail.”*. Le LLM vision (LLaVA par ex.) va comprendre la légende car elle est en anglais, et produire une description cohérente en anglais. Cette astuce évite quil “bute” sur des mots français non vus pendant son entraînement (même si LLaVA 1.6 a fait des progrès en lecture de texte multilingue ([Vision models · Ollama Blog](https://ollama.com/blog/vision-models#:~:text=model%20to%20grasp%20more%20details,the%20LLaMA%202%20Community%20License))).
- **Indexation et stockage dans la base Ragflow** : **Français privilégié**. Toutes les données textuelles que lon va indexer pour la recherche sémantique devraient idéalement être en français, puisque les questions utilisateurs le seront. Cela concerne le texte réglementaire lui-même (déjà en français), **enrichi éventuellement des descriptions de schémas que lon ajoutera en français**. Autrement dit, après avoir obtenu la description dun schéma en anglais (via lLLM vision), on la **traduit en français** pour lintégrer au chunk correspondant. De même, si on ajoute des métadonnées ou titres, on peut les laisser en français pour cohérence. Lobjectif est que lespace sémantique de la base soit uniforme : un vecteur de requête en français devra être comparé à des vecteurs de documents en français. (📌 *Remarque*: si pour une raison quelconque on indexait des morceaux en anglais, il faudrait alors soit traduire la requête de lutilisateur en anglais avant recherche, soit utiliser un embedder cross-langue solutions moins simples que de tout garder en français).
- **Enrichissement et métadonnées** : Les opérations denrichissement (ajout de résumés, de mots-clés, de catégories) doivent aussi suivre la logique de langue. Par exemple, si on tagge un chunk avec des mots-clés thématiques, autant les mettre en français pour pouvoir filtrer ou booster avec des termes que lutilisateur pourrait employer. Si on utilise un LLM pour générer un résumé de section, autant quil le fasse en français directement (on peut configurer un LLM open-source en français pour cela, ou GPT-3.5 avec `“Please summarize this French text in French:”`). En revanche, pour la partie *vision*, lenrichissement se fait en anglais puis est converti.
- **Phase de questions/réponses utilisateur** : Lutilisateur pose ses questions en français (étant donné le contexte). Le système de retrieval de Ragflow cherchera donc les chunks pertinents en français. Les réponses générées par lassistant final seront en français. Si par extraordinaire un utilisateur posait une question en anglais, on pourrait détecter la langue et la traduire vers le français pour la recherche (puis traduire la réponse finale en anglais si on voulait répondre dans la langue de la question). Mais dans notre usage, on peut supposer le français uniquement.
En somme, la règle est : **anglais uniquement là où les modèles lexigent** (principalement pour la vision et éventuellement pour le rerank si on utilisait un modèle non francophone), **français partout ailleurs**. Cette séparation garantit dune part des performances optimales (chaque modèle opère dans la langue où il est le plus compétent), et dautre part une cohérence de la connaissance (tous les contenus indexés et fournis à lutilisateur final sont en français).
Notons que cette stratégie est confirmée par lexpérience : par exemple, *Pamela Fox* (Microsoft) a souligné ce biais des modèles multimodaux à répondre en anglais et limportance de le gérer en amont dans un pipeline RA ([](https://aclanthology.org/2024.findings-emnlp.783.pdf#:~:text=We%20uncover%20a%20surprising%20multilingual,a%20mechanistic%20analysis%20of%20the)) ([](https://aclanthology.org/2024.findings-emnlp.783.pdf#:~:text=to%20the%20query%20to%20a,First%20we))】. Il est plus simple de **post-traduire** une bonne description anglaise que de forcer un modèle vision à tout sortir directement en français (ce qui souvent aboutirait à un texte de moindre qualité ou à un mélange de langues).
## Tutoriel Étape par Étape du Pipeline Ragflow
Passons à la pratique : comment mettre en place ce pipeline de traitement de PDF avec schémas, depuis la préparation du document jusquà lingestion dans Ragflow. Nous détaillerons chaque étape avec des exemples de code Python et des outils concrets.
### 1. Préparation du PDF et extraction initiale
**But** : Obtenir le texte et les images brutes du PDF. Pour cela, on utilise des bibliothèques Python de parsing PDF.
- **Installation des outils requis** : Assurez-vous davoir installé `PyMuPDF` (alias `fitz`), `pdfplumber`, `pytesseract` (et le binaire Tesseract + le data fr), ainsi que éventuellement `pdf2image` si vous comptez convertir les pages en images. Par exemple :
```bash
pip install pymupdf pdfplumber pytesseract pdf2image Pillow
sudo apt-get install tesseract-ocr-fra # installation du pack langue française
````
- **Extraction du texte avec PyMuPDF ou pdfplumber** : Vous pouvez opter pour lune ou lautre. PyMuPDF a lavantage doffrir à la fois texte et images. Pdfplumber excelle pour le texte (et tables) mais nextrait pas les images incorporées facilemen ([How to extract image · jsvine pdfplumber · Discussion #496 - GitHub](https://github.com/jsvine/pdfplumber/discussions/496#:~:text=GitHub%20github,with%20the%20pdfminer%20object))】. Nous utiliserons ici PyMuPDF.
Exemple de code pour parcourir les pages et extraire contenu textuel et images :
```python
import fitz # PyMuPDF
doc = fitz.open("mon_document.pdf")
for page in doc:
# Extraire texte
texte = page.get_text("text")
# Extraire images
blocks = page.get_text("dict")["blocks"]
images = [b for b in blocks if b["type"] == 1] # type 1 => imag ([Images - PyMuPDF 1.25.4 documentation](https://pymupdf.readthedocs.io/en/latest/recipes-images.html#:~:text=%3E%3E%3E%20d%20%3D%20page.get_text%28,3%2C%20%27ext%27%3A%20%27jpeg%27%2C%20%27height%27%3A%20501))】
for img in images:
xref = img.get("xref") # identifiant d'objet de l'image
pix = fitz.Pixmap(doc, xref) # extraire l'image
pix.save(f"page{page.number+1}_img{xref}.png")
# stocker aussi la position si besoin:
bbox = img["bbox"]
# ... éventuellement enregistrer texte OCR plus tard
```
Ici, `page.get_text("dict")` fournit un dictionnaire où chaque _block_ a un champ `"type"` (0 pour texte, 1 pour image ([Images - PyMuPDF 1.25.4 documentation](https://pymupdf.readthedocs.io/en/latest/recipes-images.html#:~:text=%3E%3E%3E%20d%20%3D%20page.get_text%28,8%2C%20%27colorspace%27%3A%203%2C%20%27ext%27%3A%20%27jpeg))】. On filtre les images et on les sauvegarde sur le disque avec `Pixmap`. On conserve aussi `bbox` (x,y de coin haut gauche et bas droite) au cas où on souhaite associer limage à une portion de texte par la position. Le texte de la page est récupéré simplement en format brut.
- **Extraction des légendes et repérage des figures** : Dans le texte extrait, on peut chercher des motifs de légende. Souvent, les PDF scientifiques/réglementaires ont des légendes qui commencent par “Figure” ou “Fig.” suivi dun numéro. Par exemple:
```python
import re
legendes = re.findall(r'Figure\s*\d+[^.:]*?:\s*([^\.]+)\.', texte)
```
Cela peut capturer des phrases descriptives. Une autre approche consiste à repérer que la légende est souvent un block de texte court situé juste en dessous dune image. Si on a les `bbox`, on peut imaginer que la légende est le block texte dont y est juste plus grand que ly max de limage. Toutefois, cela devient complexe à coder entièrement. On peut se contenter de lapproche regex manuelle et vérifier les résultats.
- **OCR sur les images** : Pour chaque image extraite, on applique Tesseract afin de lire déventuels textes. On peut utiliser pytesseract ainsi:
```python
from PIL import Image
import pytesseract
pytesseract.pytesseract.tesseract_cmd = r'/usr/bin/tesseract' # chemin vers binaire si nécessaire
for img_path in extracted_images_paths:
text_in_img = pytesseract.image_to_string(Image.open(img_path), lang="fra")
print(f"Texte détecté dans {img_path}: {text_in_img}")
```
Veillez à bien préciser `lang="fra"` (ou `"fra+eng"` si le schéma contient un mélange de français et danglais). LOCR permettra par exemple de récupérer des mots clés du schéma (titres de boîtes, etc.). Ces termes pourront être ajoutés à la description du schéma pour améliorer la recherche (ils agiront comme des _keywords_ très pertinents).
À ce stade, on dispose potentiellement pour chaque page du PDF :
- du **texte principal** en français (`texte`),
- dune ou plusieurs **images de schémas** (fichiers PNG extraits),
- du **texte OCR** de chaque image (`text_in_img`),
- des **légendes** identifiées (`legendes`).
Il faut maintenant associer ces éléments entre eux. Par exemple, si page 5 contient une image et quon a trouvé “Figure 3: Schéma du processus X.” dans le texte, on peut lier limage extraite de la page 5 à cette légende. On peut créer une structure Python pour représenter un _schéma_ avec : son image, son texte OCR, sa légende.
### 2. Traduction des légendes et textes utiles en anglais
Avant dappeler le modèle visuel, on prépare son _input_. Comme discuté, on veut fournir une **description de contexte en anglais**.
Pour chaque schéma identifié, construisons un _prompt_ qui inclura (si disponibles) : la légende traduite et le texte OCR traduit. Par exemple :
```python
import deepl
translator = deepl.Translator("YOUR_DEEPL_API_KEY") # utiliser votre clé API DeepL
for schema in schemas: # supposons une liste d'objets schéma avec properties
legende_fr = schema.legende # ex: "Schéma du processus X..."
ocr_fr = schema.ocr_text # texte détecté dans limage
content_to_translate = legende_fr
if ocr_fr:
content_to_translate += " " + ocr_fr
result = translator.translate_text(content_to_translate, target_lang="EN-US")
schema.context_en = result.text
print(f"Légende FR: {legende_fr}\nLégende+OCR EN: {schema.context_en}")
```
Ici on utilise lAPI DeepL via son SDK Pytho ([Translate text | DeepL API Documentation](https://developers.deepl.com/docs/api-reference/translate#:~:text=curl%20,DE))】. On envoie la légende (et éventuellement le texte OCR concaténé) et on récupère `schema.context_en`, une phrase ou deux en anglais. _Note_: On peut aussi traduire séparément la légende et le texte OCR, et les garder distincts dans le prompt (par ex: _Legend: ..._ / _Labels: ..._).
Si on na pas accès à DeepL, on pourrait utiliser un modèle local de traduction. Par exemple, avec HuggingFace Transformers :
```python
from transformers import AutoTokenizer, AutoModelForSeq2SeqLM
tokenizer = AutoTokenizer.from_pretrained("Helsinki-NLP/opus-mt-fr-en")
model = AutoModelForSeq2SeqLM.from_pretrained("Helsinki-NLP/opus-mt-fr-en")
inputs = tokenizer(legende_fr, return_tensors="pt")
outputs = model.generate(**inputs)
english = tokenizer.decode(outputs[0], skip_special_tokens=True)
```
Ce modèle _opus-mt_ est basique mais peut faire laffaire pour de courtes légendes.
Quoiquil en soit, on obtient en sortie une chaîne anglaise du style : _“Diagram of the X process illustrating step A, B, C…”_. Cela servira de complément contextuel pour le LLM vision.
### 3. Appel dun LLM Vision pour générer une description du schéma
On peut maintenant interroger un modèle vision et lui fournir : limage du schéma + le contexte en anglais produit à létape 2.
**Choix du déploiement** : Supposons que nous utilisions _Ollama_ pour déployer localement LLaVA 1.5/1.6. Ollama permet de charger des modèles multimodaux (par ex. `ollama pull llava:13b`) et expose une API locale. On a deux moyens dappeler le modèle : via lAPI HTTP ou via le SDK Python dOllama.
- **Via lAPI HTTP** : Faire un POST sur `http://localhost:11434/api/generate` avec un JSON contenant `"model": "llava"` et `"prompt": "Describe this image: <chemin>"`. Daprès la doc, on peut passer le chemin dune image dans le prompt CL ([Vision models · Ollama Blog](https://ollama.com/blog/vision-models#:~:text=To%20use%20a%20vision%20model,files%20using%20file%20paths))】, mais en JSON on envoie plutôt limage encodée en base64 dans un champ `"images" ([Vision models · Ollama Blog](https://ollama.com/blog/vision-models#:~:text=console)) ([ollama/docs/api.md at main · ollama/ollama · GitHub](https://github.com/jmorganca/ollama/blob/main/docs/api.md#:~:text=))】.
- **Via le SDK Python** (plus simple ici) : On utilise la librairie `ollama` pour Python. Par exemple :
```python
import ollama
image_path = "./page5_img17.png"
prompt = f"Here is an image.\n{schema.context_en}\nDescribe this image in detail."
response = ollama.chat(model="llava", messages=[
{"role": "user", "content": prompt, "images": [image_path]}
])
description_en = response['message']['content']
print("Description générée (EN):", description_en)
```
Ce snippet utilise `ollama.chat` en spécifiant le modèle LLaVA et en fournissant la requête utilisateur contenant du texte et limag ([Vision models · Ollama Blog](https://ollama.com/blog/vision-models#:~:text=import%20ollama)) ([Vision models · Ollama Blog](https://ollama.com/blog/vision-models#:~:text=))】. Concrètement, la librairie va lire le fichier image, lencoder en base64 et lenvoyer à lAPI Ollama en arrière-pla ([Vision models · Ollama Blog](https://ollama.com/blog/vision-models#:~:text=console))】. Le modèle retourne une réponse textuelle que lon récupère.
Veillez à ce que _schema.context_en_ (la légende traduite) soit bien incluse pour guider le modèle. On pourrait formater le prompt différemment selon les préférences du modèle (certains modèles attendent un token `<image>` dans le texte, mais daprès la doc Ollama ce nest pas nécessaire car on passe limage dans un param séparé).
**Exemple de résultat** : Le modèle LLaVA pourrait répondre (en anglais) quelque chose comme : _“The diagram shows a three-step process. Step 1 (Initialization) leads to Step 2 (Processing), followed by Step 3 (Verification). Each step is represented by a box with a label... The arrows indicate the flow from one step to the next.”_. Ce texte correspond à la description détaillée du schéma. Lavantage est quil formule linformation visuelle de manière fluide et exhaustive (incluant probablement le contenu OCRisé quil aura détecté aussi de son côté, confirmant nos données).
Si on constate que la réponse est partielle ou confuse, on peut affiner le prompt (par ex. poser une question spécifique: _“What does the diagram illustrate? Describe all labeled components.”_). Avec un bon modèle vision, généralement un prompt générique _“Describe the image”_ suffit.
Répétez cette étape pour chaque schéma identifié. On associera chaque _description_en_ à lobjet _schema_ correspondant.
### 4. Réinjection de la description dans le chunk original (en français)
Nous avons maintenant pour chaque schéma une description en anglais. Il faut la convertir en français et lintégrer au contenu indexé.
- **Traduire la description en français** : On peut réutiliser lAPI DeepL pour cela, ou un LLM. Cest lopération inverse de létape 2. Par exemple :
```python
description_fr = translator.translate_text(description_en, target_lang="FR").text
schema.description_fr = description_fr
```
Après traduction, on obtient par ex. : _“Le schéma montre un processus en trois étapes. Létape 1 (Initialisation) conduit à létape 2 (Traitement), suivie de létape 3 (Vérification)...”_. On vérifie rapidement que les termes techniques sont bien traduits (DeepL est généralement fiable sur ce point).
- **Construire le chunk fusionné** : Lidée est dintégrer cette _description_fr_ au côté du texte original du PDF de manière cohérente. Deux approches possibles :
1. **Insérer la description dans le texte à lemplacement du schéma** Par exemple, remplacer la légende dorigine par une version augmentée : _“Figure 3 : Schéma du processus X (Description générée : Ce schéma montre que… )”_. Cette méthode garde tout dans un même bloc, pratique pour que le LLM final ait tout dun coup.
2. **Créer un chunk séparé dédié à la figure** Par exemple, un chunk qui contient uniquement _“[Figure 3] Schéma du processus X Ce schéma illustre…”_, distinct du chunk de texte principal. On relie ce chunk via métadonnées (même page, même figure number) à la partie texte. Cette méthode permet de cibler spécifiquement la figure lors de la recherche.
La seconde est souvent plus propre, car elle isole bien la description dimage. Ragflow, lors du parsing, segmente souvent par type de contenu (il a des _chunk templates_ spécifiques _“picture”_ pour images, _“table”_ pour tableaux, etc. ([HTTP API | RAGFlow](https://ragflow.io/docs/dev/http_api_reference#:~:text=match%20at%20L308%20,object%20contains%20the%20following%20attributes))】). **Nous pouvons imiter ce fonctionnement** : créer manuellement un chunk de type “picture” pour chaque schéma.
Concrètement, on peut construire un petit JSON ou Markdown pour chaque chunk. Par exemple, supposons quon décide de faire un format JSON avec champs: _id_, _page_, _type_, _content_, _metadata_. Un chunk image pourrait ressembler à :
```json
{
"id": "fig3",
"page": 5,
"type": "figure",
"content": "Figure 3 : Schéma du processus X.\nCe schéma illustre un processus en trois étapes : ... (notre description_fr)...",
"metadata": {
"source": "MonDocument.pdf",
"figure_id": 3,
"titre": "Processus X"
}
}
```
Le _content_ ici comprend la légende originale suivie de la description détaillée en français. On peut la formater avec un saut de ligne ou une phrase distincte introduite par _“Description : …”_ pour bien la démarquer.
Le chunk texte environnant, lui, reste inchangé sauf quon pourrait éventuellement supprimer la légende pour éviter la redondance. Ou le laisser, ce nest pas bien grave davoir la légende en double. Limportant est davoir la description dans au moins un chunk.
- **Ajout des métadonnées adéquates** : Utilisez les métadonnées pour conserver la provenance et faciliter la requête. Les métadonnées utiles pourraient être :
- _page_ (numéro de page du PDF) Ragflow le fait déjà pour les chunks extraits, donc indiquez la page du schéma.
- _figure_id_ ou un identifiant interne utile si on veut plus tard filtrer ou manipuler spécifiquement les figures.
- _source_ (le nom du document, ou son ID) permet à lassistant de formuler la citation.
- éventuellement _type=figure_ dans Ragflow il ny a pas forcément un champ type explicite dans lindex, mais on peut lajouter en mot-clé dans le contenu ou en tag si lAPI le permet. Au minimum, inclure le mot “Figure” dans le content garantit quune requête cherchant “figure” le remontera.
À ce stade, nous avons enrichi le contenu. Par exemple, là où initialement on navait que le texte réglementaire brut, on a maintenant en plus, pour chaque figure, un paragraphe explicatif en français qui sera **indexé**.
### 5. Intégration des chunks dans Ragflow (interface ou API)
La dernière étape consiste à **charger ces données enrichies dans Ragflow** pour quelles soient utilisées lors des questions/réponses. Il y a deux façons principales : via linterface web (Knowledge Base) de Ragflow, ou via les APIs (HTTP/Python).
**Option A Interface graphique** :
1. Démarrez le serveur Ragflow (Docker ou local) et accédez à lUI. Créez une **Knowledge Base** dédiée (par exemple nommée “Docs Réglementaires”). Configurez-la avec un _chunking method_ approprié, par exemple _“Laws”_ si disponible (template optimisé pour documents juridiques ([Configure knowledge base | RAGFlow](https://ragflow.io/docs/dev/configure_knowledge_base#:~:text=Paper%20PDF%20Book%20DOCX%2C%20PDF%2C,XLSX%2C%20CSV%2FTXT))】 ou _“Manual”_ si on veut contrôler nous-même. Pour éviter que Ragflow ne segmente tout automatiquement, vous pouvez choisir _Manual_ pour le PDF en questio ([Configure knowledge base | RAGFlow](https://ragflow.io/docs/dev/configure_knowledge_base#:~:text=Resume%20Enterprise%20edition%20only,JPEG%2C%20JPG%2C%20PNG%2C%20TIF%2C%20GIF))】 cela signifie quil ne coupera pas le fichier en chunks tout seul.
2. **Upload du PDF** via _Add file_. Une fois uploadé, cliquez sur _Parse_ (le bouton _Play_). Comme on est en Manual, il va peut-être créer un chunk par page ou tout mettre en un seul chunk (daprès la doc _Manual PDF_ est un template qui semble garder la structure page par page ([Configure knowledge base | RAGFlow](https://ragflow.io/docs/dev/configure_knowledge_base#:~:text=Resume%20Enterprise%20edition%20only,JPEG%2C%20JPG%2C%20PNG%2C%20TIF%2C%20GIF))】.
3. Allez dans la vue _Chunks_ du document (en cliquant sur le fichier puis _View chunks_ ([Get started | RAGFlow](https://ragflow.io/docs/dev/#:~:text=match%20at%20L347%201,to%20view%20the%20chunking%20results))】. Là vous verrez la liste des chunks extraits. Cest ici quon peut **intervenir** (d_Intervene with file parsing_) pour éditer le conten ([Get started | RAGFlow](https://ragflow.io/docs/dev/#:~:text=1,to%20view%20the%20chunking%20results))】. Vous pouvez soit modifier un chunk existant, soit en ajouter un nouveau. Par exemple, créez un nouveau chunk pour la figure 3, copiez-collez le contenu _content_ que vous avez préparé (légende + description française). Assurez-vous de remplir les champs de métadonnées (il y a souvent un champ “title” ou similaire où on peut mettre “Figure 3”). Si Ragflow noffre pas de champ spécifique, vous pouvez simplement inclure en début de chunk “Figure 3 : ...” comme on a fait.
4. Enregistrez les modifications. Vous verrez alors vos chunks mis à jour. Si on avait supprimé la légende du chunk principal, on peut coller notre description au bon endroit, etc. **En résumé, via lUI, on utilise la fonction dédition pour injecter nos descriptions de schémas.**
**Option B API/Automatisation** :
Si vous avez de nombreux documents à traiter, il est préférable dautomatiser lingestion. Ragflow propose une API REST (et SDK Python). Quelques points clés :
- Vous pouvez créer une Knowledge Base via lAPI ou trouver son `dataset_id` depuis lUI.
- Ensuite, utilisez lendpoint **Upload documents** (`POST /api/v1/datasets/{dataset_id}/documents`) pour envoyer le fichier PD ([HTTP API | RAGFlow](https://ragflow.io/docs/dev/http_api_reference#:~:text=match%20at%20L610%20The%20ID,A%20document%20to%20upload))】. Cela créera une entrée de document.
- Lancez le parsing via `POST /api/v1/documents/{doc_id}/parse` (vérifiez la doc exacte, il y a possiblement un appel ou un flag).
- Une fois parsé, vous pouvez récupérer la liste des chunks avec `GET /api/v1/documents/{doc_id}/chunks` ou similaire.
- Pour **mettre à jour un chunk**, lAPI propose peut-être un endpoint (les erreurs 1001/1002 font référence à *Invalid Chunk ID / Chunk Update Failed ([Python API | RAGFlow](https://ragflow.io/docs/dev/python_api_reference#:~:text=Code%20Message%20Description%20400%20Bad,Update%20Failed%20Chunk%20update%20failed))】, ce qui suggère quon peut appeler une méthode PUT/PATCH sur un chunk spécifique). Vérifiez la documentation _Python SDK_ : par exemple, `ragflow_sdk.Document.update_chunk(chunk_id, content="new content", metadata={...})`. Si lAPI directe nest pas évidente, une alternative est de **supprimer tous les chunks** de ce document (il y a un appel DELETE dataset maybe) puis de **réinsérer nos propres chunks**. On peut en effet créer un document de type JSON et luploader comme si cétait un texte. Une astuce serait de **convertir notre PDF en un fichier Markdown** contenant toutes les parties enrichies, puis de le faire ingérer par Ragflow comme un document texte normal.
Pour illustrer, imaginons quon veuille tout faire par code avec le SDK Python (après `pip install ragflow-sdk`). On pourrait avoir :
```python
from ragflow_sdk import Client
client = Client(api_key="YOUR_API_KEY")
kb = client.create_knowledge_base("DocsRegl", embedding_model="sentence-transformers/all-MiniLM-L6-v2")
ds = kb.create_dataset("Doc1", chunk_method="manual") # create dataset with manual chunking
doc = ds.upload_file("mon_document.pdf")
doc.parse() # trigger parsing
chunks = doc.get_chunks()
# Find the chunk corresponding to figure 3's original legend, or decide where to insert
doc.add_chunk(content=new_content, metadata={"page":5, "figure":3})
doc.delete_chunk(chunk_id=...) # if needed to remove duplicates
```
(Les noms de méthodes sont imaginés, lidée est quon pilote la KB via le SDK.)
Pour les besoins de documentation, on ne détaillera pas toute lAPI, mais sachez que Ragflow est pensé pour ce genre dintervention programmatique.
**Validation** : Après ingestion, que ce soit via UI ou API, testez dans la section _Retrieval testing_. Tapez quelques mots clés liés au schéma pour voir si la description ressort. Par exemple, si le schéma concerne “processus X”, cherchez _“processus X étapes”_. Vous devriez voir dans les résultats le chunk de la figure avec la descriptio ([RAGFlow an Open-Source Retrieval-Augmented Generation (RAG) Engine | by Omar Santos | Medium](https://becomingahacker.org/ragflow-an-open-source-retrieval-augmented-generation-rag-engine-6b903005a032#:~:text=You%20can%20test%20retrieval%20by,to%20the%20%E2%80%9CRetrieval%20testing%E2%80%9D%20section))】. Si ce nest pas le cas, vérifiez que lembedding a bien été mis à jour (peut-être faut-il re-parsing après modifs manuelles, ou cliquer _Save_ dans lUI).
### 6. Exemples Concrets dUtilisation
Maintenant que tout est en place, interrogez lassistant Ragflow en conditions réelles. Par exemple : _“Quelles sont les différentes étapes du processus X illustré dans le document ?”_. Le système devrait :
- retrouver le chunk texte où sont listées les étapes (dans le réglementaire, ou possiblement dans notre description de figure),
- retrouver le chunk figure qui décrit ces étapes visuellement (car notre description FR contient ces mots clés),
- passer le tout au modèle de chat (par ex. Llama-2 ou autre) configuré en assistant.
Lassistant combinera ces sources. Grâce à loption _Show Quote_, il pourra inclure dans sa réponse des extraits du chunk figure ou du texte origina ([RAGFlow an Open-Source Retrieval-Augmented Generation (RAG) Engine | by Omar Santos | Medium](https://becomingahacker.org/ragflow-an-open-source-retrieval-augmented-generation-rag-engine-6b903005a032#:~:text=5,base%20that%20I%20created%20earlier))】. On pourrait obtenir une réponse du genre : _“Le document décrit un processus en trois étapes (voir Figure 3). **Étape 1** : Initialisation… **Étape 2** : Traitement… **Étape 3** : Vérification ([Vision models · Ollama Blog](https://ollama.com/blog/vision-models#:~:text=,Michel%20Basquiat))】. Ce schéma illustre le flux allant de létape 1 à 3 par des flèches.”_. On remarque que la réponse inclut potentiellement la référence _Figure 3_ et reprend le contenu de notre chunk enrichi (ici mention des flèches par ex provenant de la description de limage).
Pour sassurer de la qualité :
- **Tester plusieurs questions** sur les schémas, mais aussi des questions purement textuelles, pour vérifier que lajout des schémas na pas perturbé lindexation. Normalement non, chaque chunk a son vecteur.
- Si certaines réponses sont hors-sujet, ajuster le _Similarity Threshold_ ou _Top N_ dans la config de lassistan ([RAGFlow an Open-Source Retrieval-Augmented Generation (RAG) Engine | by Omar Santos | Medium](https://becomingahacker.org/ragflow-an-open-source-retrieval-augmented-generation-rag-engine-6b903005a032#:~:text=Similarity%20Threshold%20)) ([RAGFlow an Open-Source Retrieval-Augmented Generation (RAG) Engine | by Omar Santos | Medium](https://becomingahacker.org/ragflow-an-open-source-retrieval-augmented-generation-rag-engine-6b903005a032#:~:text=Top%20N%20))】, ou entraîner le reranker. Un bon réglage est un _similarity_threshold_ assez bas (0.2 par défaut) pour ne pas louper de chunk pertinent, et un _top_n_ modéré (5-6) pour ne pas surcharger le context ([HTTP API | RAGFlow](https://ragflow.io/docs/dev/http_api_reference#:~:text=,)) ([HTTP API | RAGFlow](https://ragflow.io/docs/dev/http_api_reference#:~:text=match%20at%20L1715%20or%20reranking,number%20of%20top%20chunks%20with))】.
## Conseils de Structuration de la Base de Connaissances et de lArchitecture
Pour clôturer, voici quelques recommandations globales afin de tirer le maximum de ce pipeline RAGFlow multimodal :
- **Utilisez des chunk templates adaptés** : Ragflow offre plusieurs modèles de chunking (général, Q&A, laws, presentation, picture, etc. ([Configure knowledge base | RAGFlow](https://ragflow.io/docs/dev/configure_knowledge_base#:~:text=Template%20Description%20File%20format%20General,DOCX%2C%20PDF%2C%20TXT%20Manual%20PDF))】. Dans le cas de documents réglementaires, le template _Laws_ peut améliorer la segmentation (il est conçu pour repérer articles, sections, etc. afin déviter de couper en plein milieu dun article de loi). Vous pouvez aussi utiliser _Manual_ pour tout contrôler, mais cela nécessite alors de fournir soi-même la logique dextraction (ce que nous avons fait manuellement). Une approche hybride : laissez Ragflow parser en _Laws_, puis **intervenez** pour insérer les descriptions de figures là où il faut.
- **Granularité des chunks** : Trouvez le bon équilibre de taille. En général, vise ~100-200 tokens par chun ([HTTP API | RAGFlow](https://ragflow.io/docs/dev/http_api_reference#:~:text=match%20at%20L295%20%2A%20%60,false))】. Pour le texte réglementaire, on peut chunker par paragraphes ou sections numérotées. Pour les figures, comme on la fait, un chunk par figure. Évitez de coller un énorme bloc de plusieurs pages moins précis au retrieva ([Breaking up is hard to do: Chunking in RAG applications - Stack Overflow](https://stackoverflow.blog/2024/12/27/breaking-up-is-hard-to-do-chunking-in-rag-applications/#:~:text=The%20size%20of%20the%20chunked,the%20context%20of%20the%20data)) ([Breaking up is hard to do: Chunking in RAG applications - Stack Overflow](https://stackoverflow.blog/2024/12/27/breaking-up-is-hard-to-do-chunking-in-rag-applications/#:~:text=%E2%80%9CThe%20reason%20to%20start%20thinking,%E2%80%9D))】. A contrario, ne coupez pas trop fin (une phrase isolée peut perdre le contexte). Notre approche de lier légende + description image dans un chunk est idéale : cest concis et autonome sémantiquement.
- **Mise en place des métadonnées** : Profitez des métadonnées pour améliorer la recherche et le filtrage. Par exemple, dans Ragflow vous pourriez tagger tous les chunks de figures avec un mot-clé “figure”. Ainsi, si lassistant détecte que lutilisateur pose une question de type “Montrez-moi un schéma…”, vous pourriez (via un mécanisme plus avancé) filtrer pour ne récupérer que les chunks taggés figure. Ragflow ne supporte pas encore les requêtes booléennes complexes en interface, mais on peut imaginer le faire au niveau de lorchestration (ex : un _tool_ qui dabord identifie si la question concerne une image). Pour linstant, un bon usage des métadonnées sert surtout à **la traçabilité** (source, page) afin que lassistant inclue une référence précise dans sa réponse.
- **Assistants multiples ou spécialisés** : Si votre cas dutilisation le justifie, vous pourriez configurer plusieurs assistants dans Ragflow reliés à la même base. Par exemple, un assistant “Explicateur de schémas” et un assistant “Analyste réglementaire”. Le premier pourrait avoir un prompt système orienté pédagogie visuelle (_“Tu es un expert qui explique des schémas techniques simplement”_), le second un prompt plus juridique. Tous deux utiliseraient la même KB, mais formuleraient les réponses différemment. Ragflow facilite la création de multiples assistants avec des personnalités distinctes, tout en pointant vers la ou les mêmes bases de connaissance ([RAGFlow an Open-Source Retrieval-Augmented Generation (RAG) Engine | by Omar Santos | Medium](https://becomingahacker.org/ragflow-an-open-source-retrieval-augmented-generation-rag-engine-6b903005a032#:~:text=Creating%20Assistants)) ([RAGFlow an Open-Source Retrieval-Augmented Generation (RAG) Engine | by Omar Santos | Medium](https://becomingahacker.org/ragflow-an-open-source-retrieval-augmented-generation-rag-engine-6b903005a032#:~:text=The%20%E2%80%9CPrompt%20Engine%E2%80%9D%20tab%20of,prompts%20and%20configure%20other%20parameters))】.
- **Workflow de traitement automatisé** : Intégrer lextraction de schémas dans votre pipeline dingestion de documents. Si vous avez un grand nombre de PDF, scriptez tout ce quon a décrit (comme dans le tutoriel) pour que chaque nouveau document ajouté passe par : extraction PyMuPDF -> OCR -> LLM vision -> enrichissement -> upload Ragflow. Cela peut être orchestré avec des tâches offline. Ragflow est pensé pour la **mise à jour continue** des connaissances, donc on peut imaginer ré-exécuter le parsing si un document a été enrichi, etc. Utilisez lAPI REST de Ragflow dans vos scripts dingestion pour éviter le travail manuel.
- **Qualité des réponses** : Pour maximiser la qualité, veillez à la **pertinence des données fournies au LLM final**. Nos descriptions de schémas enrichissent la base, mais il faut que lassistant sache les utiliser. Vous pouvez le guider via le prompt système. Par exemple : _“Lorsque des schémas ou figures sont pertinents, intègre leur description dans la réponse.”_. De même, incitez-le à citer la source (_“Cite systématiquement le document et la figure lorsque tu tappuies sur eux.”_). Ainsi, lassistant combinera texte et image de façon transparente dans ses explications.
- **Tests et ajustements** : Enfin, testez le pipeline avec des questions variées, notamment :
- Des questions purement textuelles (pour vérifier que le texte réglementaire seul est bien géré, et que lajout des images na pas introduit de bruit).
- Des questions directement sur un schéma (_“Que montre la figure X ?”_ ou _“Expliquez le schéma du processus X”_).
- Des questions croisées (_“Selon le document, quelle étape suit létape 2 du processus X et quindique le schéma à ce propos ?”_). Ce type de question oblige à utiliser les deux sources (texte et schéma). Idéalement, le LLM va puiser lordre des étapes dans le texte réglementaire, et les détails visuels dans la description du schéma.
En évaluant ces réponses, vous pourrez itérer : par ex., si vous constatez que le LLM ignore la description du schéma, peut-être faut-il ajouter un peu plus de poids (ex. répéter certains termes dans la description pour quelle ressorte plus dans la similarité, ou abaisser _similarity_threshold_). Si au contraire il cite trop limage même quand ce nest pas demandé, assurez-vous que _Show Quote_ noblige pas à tout citer, etc.
En suivant ces étapes et conseils, vous disposerez dune **base de connaissances Ragflow multimodale** bien structurée, où les schémas annotés de vos PDF sont traités efficacement. Cela permettra à lassistant IA de fournir des réponses précises, complètes et appuyées à la fois par le texte réglementaire et par linterprétation des éléments graphiques, offrant ainsi à lutilisateur le meilleur des deux mondes dans ses réponses.
**Sources :** Extraction PDF (PyMuPDF ([Images - PyMuPDF 1.25.4 documentation](https://pymupdf.readthedocs.io/en/latest/recipes-images.html#:~:text=2,images%20shown%20on%20a%20page)) ([Images - PyMuPDF 1.25.4 documentation](https://pymupdf.readthedocs.io/en/latest/recipes-images.html#:~:text=,0.0%2C%20228.2460174560547%2C%20100.0))】, Ragflow DeepDoc (mise en page, figures ([ragflow/deepdoc/README.md at main · infiniflow/ragflow · GitHub](https://github.com/infiniflow/ragflow/blob/main/deepdoc/README.md#:~:text=Recognition,components%20which%20covers%20most%20cases)) ([ragflow/deepdoc/README.md at main · infiniflow/ragflow · GitHub](https://github.com/infiniflow/ragflow/blob/main/deepdoc/README.md#:~:text=,and%20text%20in%20the%20figures))】, Ollama (LLM vision LLaVA ([Vision models · Ollama Blog](https://ollama.com/blog/vision-models#:~:text=To%20use%20a%20vision%20model,files%20using%20file%20paths)) ([Vision models · Ollama Blog](https://ollama.com/blog/vision-models#:~:text=import%20ollama))】, Biais langue LLM visio ([](https://aclanthology.org/2024.findings-emnlp.783.pdf#:~:text=We%20uncover%20a%20surprising%20multilingual,a%20mechanistic%20analysis%20of%20the))】, Config Ragflow & assistant ([RAGFlow an Open-Source Retrieval-Augmented Generation (RAG) Engine | by Omar Santos | Medium](https://becomingahacker.org/ragflow-an-open-source-retrieval-augmented-generation-rag-engine-6b903005a032#:~:text=5,base%20that%20I%20created%20earlier)) ([RAGFlow an Open-Source Retrieval-Augmented Generation (RAG) Engine | by Omar Santos | Medium](https://becomingahacker.org/ragflow-an-open-source-retrieval-augmented-generation-rag-engine-6b903005a032#:~:text=The%20%E2%80%9CPrompt%20Engine%E2%80%9D%20tab%20of,prompts%20and%20configure%20other%20parameters))】, API Deep ([Translate text | DeepL API Documentation](https://developers.deepl.com/docs/api-reference/translate#:~:text=curl%20,DE))】.