IAHDF
Tutoriel

Créer un RAG en Python avec LlamaIndex (ou LangChain) et Qdrant

ÉI Équipe IAHDF 20 min de lecture Mis à jour le 27 septembre 2026 Avancé

Quand Open WebUI ne suffit plus, coder son RAG donne le contrôle : quels fichiers entrer, comment découper, où stocker les vecteurs, quelle consigne imposer au modèle. Ce tutoriel dessine une architecture LlamaIndex (avec un clin d’œil LangChain), un Qdrant local via Docker, et un LLM servi par Ollama. Fil rouge : la documentation interne d’une TPE logistique à Dunkerque. Prérequis : Python à l’aise, Docker disponible, et des documents déjà en texte (sinon [[ta09|OCRisez d’abord]]).

Plan du tutoriel

Huit blocs : architecture, installation, ingestion, index Qdrant, requêtes, évaluation, esquisse d’API, scène HdF. Pour la qualité, évaluer son RAG. Pour un chemin sans code, Flowise / Langflow. Pour le glossaire, RAG.

Architecture minimale

Quatre briques : (1) des documents texte ou PDF textuels, (2) un modèle d’embedding, (3) une base vectorielle Qdrant, (4) un LLM qui rédige à partir des passages. LlamaIndex orchestre souvent l’ingestion et la requête ; LangChain joue un rôle voisin avec d’autres abstractions. Vous pouvez mélanger plus tard, mais commencez simple : un script d’indexation, un script de question.

Ollama fournit le LLM (et parfois l’embedding) en local. Qdrant stocke les vecteurs. Docker Compose relie les services. Un GPU aide pour le confort sur des modèles plus larges, mais n’est pas une obligation théorique pour un prototype pédagogique : parlez en ordre de grandeur et testez sur votre machine. IAHDF ne publie pas de mesures de débit.

Rôles des composants
ComposantRôlePiège
Dossier docs/Source de vérité textuelleScans non OCRisés
EmbeddingVecteurs de similaritéModèle mal adapté au français
QdrantStockage et rechercheCollection mal nommée / non versionnée
LLM (Ollama)Rédaction à partir des passagesConsigne trop créative
Script evalNon-régressionCorpus modifié en silence

Installation de principe

Créez un répertoire de projet, un environnement virtuel Python, et un fichier docker-compose pour Qdrant. Installez Ollama selon la documentation officielle de votre OS, puis tirez un modèle en copiant le tag exact depuis la bibliothèque Ollama le jour J. Les versions de LlamaIndex et des clients Qdrant évoluent : épinglez des versions dans requirements.txt après un essai réussi.

Commandes de principe (à adapter)
# Qdrant local (principe — vérifiez l’image et les ports dans la doc Qdrant)
docker compose up -d

# Environnement Python
python -m venv .venv
# Windows PowerShell :
.\.venv\Scripts\Activate.ps1
pip install -U pip
# Puis packages du jour : llama-index, client qdrant, etc. (lisez la doc)

# Ollama : tirer un modèle (remplacez TAG par le tag officiel du jour)
ollama pull TAG

# Lancer l’indexation puis une question (vos scripts)
python ingest.py
python ask.py "Quelle est la procédure d'expédition fragile ?"

Ingestion et découpage

Placez dans docs/ uniquement des fichiers que vous avez le droit d’indexer. Pour la TPE de Dunkerque : modes opératoires export PDF texte, consignes sécurité, FAQ client interne. Excluez les fichiers RH nominatifs et les contrats clients complets. Si un PDF est scanné, passez par OCR avant.

Le découpage (chunking) doit respecter les titres de procédure quand c’est possible. Un chunk qui coupe au milieu d’une liste d’EPI produit des réponses bancales. Commencez avec des tailles modestes et un chevauchement raisonnable, puis ajustez après évaluation. Loggez le nombre de chunks par document.

Indexer dans Qdrant

Six étapes d’un RAG Python utile

1

Préparer le corpus et le .gitignore

Créez docs/, data/, scripts/. Ignorez .venv, clés, dumps Qdrant et fichiers clients. Ajoutez un README qui décrit le droit d’usage des documents. Sans cette hygiène, le plus bel index devient une fuite. Faites valider la liste des fichiers par un responsable métier à Dunkerque avant la première ingestion. Faites signer ou valider par écrit la liste des fichiers par le responsable métier avant le premier ingest sur le serveur de Dunkerque. Documentez le résultat et passez à l’étape suivante sans empiler d’autres changements le même jour.

2

Démarrer Qdrant et vérifier la santé

Lancez docker compose, ouvrez l’interface ou l’API de santé documentée, créez une collection dédiée au projet (nom stable, ex. tpe-dunkerque-mo). Notez le port. Un Qdrant partagé sans convention de nommage finit en collections fantômes. Documentez comment tout effacer proprement pour un ré-index. Ajoutez un healthcheck dans le compose et refusez de lancer ingest.py si Qdrant ne répond pas : vous éviterez des index fantômes. Documentez le résultat et passez à l’étape suivante sans empiler d’autres changements le même jour. Documentez le résultat et passez à l’étape suivante sans empiler d’autres changements le même jour.

3

Choisir embedding et LLM (tags officiels)

Sur la doc Ollama ou Hugging Face, copiez les tags du jour pour l’embedding et le modèle de chat. Testez une phrase française métier (« bon de livraison », « consignation ») et regardez si des documents proches se retrouvent. Si le français administratif est mal traité, changez d’embedding plutôt que d’accuser le LLM. Voir embeddings français. Conservez dans le README la date et l’URL exacte où le tag a été copié, pour rejouer l’installation six mois plus tard. Documentez le résultat et passez à l’étape suivante sans empiler d’autres changements le même jour.

4

Écrire ingest.py

Le script charge les fichiers, découpe, calcule les embeddings, upsert dans Qdrant avec métadonnées (chemin, titre, date de fichier). Idempotence : pouvoir ré-ingérer sans doubler aveuglément. Affichez un résumé (nb docs, nb chunks). En cas d’erreur sur un fichier, continuez avec journal — ne laissez pas un PDF corrompu tuer tout le lot. Idempotence oblige : un second ingest du même hash ne doit pas doubler les points ; sinon l’évaluation devient absurde. Documentez le résultat et passez à l’étape suivante sans empiler d’autres changements le même jour.

5

Écrire ask.py avec consigne stricte

Récupérez les k passages les plus proches, construisez un prompt qui impose : répondre uniquement à partir des extraits, citer le fichier source, dire « information absente du corpus » sinon. Appelez Ollama. Affichez passages + réponse pour debug. Cette transparence accélère le diagnostic plus que n’importe quelle interface opaque. Affichez toujours les passages avant la prose : le methods de la TPE débugggera plus vite qu’avec une belle réponse orpheline. Documentez le résultat et passez à l’étape suivante sans empiler d’autres changements le même jour.

6

Brancher une mini évaluation

Rejouez cinq à dix questions du jeu de test qualité RAG. Stockez les sorties dans evaluations/avec horodatage. Ne passez en « API interne » que lorsque les procédures critiques tiennent. Une API rapide sur un mauvais index industrialise l’erreur. Bloquez la bascule API tant qu’une question de sécurité échoue ; industrialiser l’erreur est pire que rester en script. Documentez le résultat et passez à l’étape suivante sans empiler d’autres changements le même jour. Documentez le résultat et passez à l’étape suivante sans empiler d’autres changements le même jour.

Requêtes et consigne système

La qualité de ask.py dépend autant de la consigne que du modèle. Exigez le refus poli hors corpus. Demandez des extraits courts. Interdisez d’inventer des numéros de procédure. Pour une TPE, mieux vaut une réponse courte vérifiable qu’un roman. Si vous exposez plus tard une API HTTP, gardez la même consigne côté serveur.

Exemple fictif de mauvaise réponse : « Selon l’article 18 du code interne Dunkerque Port Authority Act 2019, toute palette fragile… » — formulation inventée pour la pédagogie. Si vous voyez ce genre de précision absente du corpus, votre consigne ou votre retrieval échoue.

Exemple fictif IAHDF — ne pas citer comme source

Esquisse d’API et alternatives LangChain

Une fois ask.py stable, encapsuler dans une petite API (FastAPI ou autre) permet de brancher un front interne. Ajoutez authentification, journalisation, et limitation d’accès réseau. LangChain peut remplacer LlamaIndex sur le même Qdrant : le geste reste ingestion → vecteurs → retrieval → LLM. Choisissez l’écosystème que votre équipe lira dans six mois, pas la mode du fil Twitter.

Pour un assemblage visuel sans tout coder, Flowise / Langflow peut prototyper. Pour un chatbot sur site public, chatbot RAG site ajoute widget, mentions et cadre données.

Scène : TPE logistique à Dunkerque

L’équipe a trente modes opératoires PDF. Le premier index sans OCR sur deux scans échoue. Après OCR et un jeu de dix questions, le script Python répond correctement sur l’emballage fragile, s’abstient sur une question RH, et cite le bon fichier. Le dirigeant voit les passages : la confiance monte. Le GPU du poste de CAO reste hors sujet : le prototype tourne d’abord sur un PC dédié correctement dimensionné selon la doc des modèles choisis.

Checklist avant de parler « prod »

  • Corpus textuel validé, scans traités.
  • Secrets et dumps exclus du git.
  • Tags modèles documentés.
  • Jeu de test rejoué après ingest.
  • Consigne d’abstention vérifiée.
  • Plan de ré-index et de sauvegarde Qdrant.

Détails d’implémentation qui évitent les nuits blanches

Nommez les collections Qdrant avec un suffixe de version. Quand vous changez d’embedding, créez une nouvelle collection plutôt que de mélanger des vecteurs incompatibles. Gardez un script de reconstruction documenté. Stockez dans chaque point le chemin fichier, un hash de contenu, et le titre de section si vous l’avez. Au moment de la réponse, affichez ces métadonnées : le debug devient humain et partageable avec le métier.

Côté Ollama, séparez mentalement embedding et chat pour comprendre qui sature. Loggez les durées sans en faire un benchmark public. Si une requête paraît longue, regardez d’abord le nombre de chunks renvoyés et la taille du prompt, pas seulement le GPU. Un prompt qui colle vingt pages fatigue n’importe quel modèle, local ou non.

Pour LangChain, le même découpage s’applique : loaders, splitters, vectorstore, retriever, chaîne de génération. Évitez les agents multi-outils tant que le RAG simple n’est pas fiable. Stabilisez documents, vecteurs et réponse fidèle, puis seulement ouvrez d’autres capacités.

Vers une petite API interne

Une petite API protégée par un jeton d’équipe, un endpoint de santé, des logs structurés : le front interne consomme un contrat JSON avec réponse, sources et indicateur d’abstention. Ajoutez une limitation de débit basique. Prévoir trois questions de référence rejouées après chaque ingest. Sauvegardez Qdrant selon sa documentation et testez une restauration. Documentez le temps de reprise acceptable pour la TPE afin d’éviter la suringénierie.

Questions fréquentes

LlamaIndex ou LangChain ?

Les deux peuvent monter un RAG avec Qdrant et Ollama. LlamaIndex est souvent confortable pour l’index documentaire ; LangChain brille dans les chaînes d’agents et intégrations larges. Pour un premier pipeline HdF, choisissez celui que vous arriverez à maintenir. Vous pourrez migrer l’idée (pas forcément le code) plus tard. Lisez les docs actuelles avant d’arquitecturer pour dix ans. Vous pourrez migrer d’écosystème plus tard si le contrat documents-vecteurs-LLM reste clair et documenté pour le prestataire. Documentez le résultat et passez à l’étape suivante sans empiler d’autres changements le même jour.

Puis-je tout faire sans GPU ?

Un prototype modeste avec un modèle adapté à votre machine est possible, surtout pour valider le pipeline. Pour un usage équipe concurrent, dimensionnez selon la documentation des modèles et un essai réel. Parlez en ordres de grandeur, pas en chiffres de labo IAHDF. Le goulot est parfois l’embedding sur gros corpus, parfois la génération. Le prototype pédagogique n’exige pas un cluster : validez d’abord la fidélité des réponses sur un PC dédié correctement choisi. Documentez le résultat et passez à l’étape suivante sans empiler d’autres changements le même jour.

Qdrant est-il obligatoire ?

Non. D’autres bases vectorielles existent. Qdrant est un choix courant, bien documenté, pratique en Docker. L’important est la séparation claire documents / vecteurs / LLM, et la capacité à tout reconstruire. Évitez de multiplier les moteurs sans besoin. Choisir un moteur, le maîtriser, valoir mieux que trois bases vectorielles « au cas où » sans procédure de restore. Documentez le résultat et passez à l’étape suivante sans empiler d’autres changements le même jour. Documentez le résultat et passez à l’étape suivante sans empiler d’autres changements le même jour.

Comment éviter d’indexer des données personnels ?

Revue humaine de la liste des fichiers, règles d’exclusion (RH, clients nominatifs), et éventuellement un script de détection de motifs évidents (emails, téléphones) comme filet — imparfait. Cadrez l’usage avec les données à ne pas confier. Un RAG local n’autorise pas tout. Un script de détection de motifs n’est qu’un filet : la revue humaine de la liste des fichiers reste le vrai contrôle. Documentez le résultat et passez à l’étape suivante sans empiler d’autres changements le même jour. Documentez le résultat et passez à l’étape suivante sans empiler d’autres changements le même jour.

Que livrer à mon équipe après ce tuto ?

Un dépôt avec ingest/ask, un docker-compose Qdrant, un README, un jeu de test minimal, et un compte rendu des questions réussies/échouées. Pas un notebook unique illisible. Ensuite seulement, discutez d’une API ou d’un widget site. La pédagogie IAHDF privilégie ce livrable auditable. Ce paquet livrable permet à un stagiaire de repartir sans séance mystérieuse devant un notebook unique non versionné. Documentez le résultat et passez à l’étape suivante sans empiler d’autres changements le même jour. Documentez le résultat et passez à l’étape suivante sans empiler d’autres changements le même jour.

Pour continuer

AgendaAgenda des ateliers IAHDFInscriptionCréer un compte communautéTutorielRAG en glisser-déposer avec Flowise / Langflow
Cette ressource vous a-t-elle aidé ?

Pour aller plus loin

Tutoriel Évaluer la qualité de son RAG : jeu de questions, métriques et outils 20 min · Équipe IAHDF Tutoriel RAG sur des PDF scannés : ajouter l'OCR avant l'indexation 20 min · Équipe IAHDF Tutoriel RAG dans Open WebUI : régler chunks, embeddings, recherche hybride et reranker 30 min · Équipe IAHDF