Partie 2 : Pipeline RAG
Guides a student through forking, cloning, Dockerizing, and running a RAG chatbot with Streamlit, ChromaDB, and Google Gemini.
What this file does
Guides a student through forking, cloning, Dockerizing, and running a RAG chatbot with Streamlit, ChromaDB, and Google Gemini.
When to use it
- Learning to containerize a RAG application with Docker Compose
- Setting up a local MLOps pipeline with hot reload for document updates
- Practicing DevOps workflows on a pre-built AI project
- Understanding the end-to-end RAG pipeline from ingestion to query
Assumes this stack
Partie 2 : Pipeline RAG
Objectif
Mettre en pratique la conteneurisation et l'orchestration d'une application de Génération Augmentée par Récupération (RAG) à l'aide de Docker. Ce TP vous permettra de comprendre comment déployer une application d'intelligence artificielle moderne en utilisant les meilleures pratiques DevOps.
Structure des dossiers et fichiers
AIops-RAG/
├── app/
│ ├── main.py # Point d'entrée principal de l'application
│ ├── data/ # Dossier des documents sources
│ │ ├── DevOps_cours.txt # Informations sur le cours DevOps
│ │ ├── ensa_about.txt # Description de l'ENSA
│ │ ├── ensa_programs.md # Programmes d'études (format Markdown)
│ │ └── student_life.txt # Vie étudiante et activités
│ ├── chroma_db/ # Base de données vectorielle (générée)
│ │ ├── chroma.sqlite3 # Stockage SQLite des métadonnées
│ │ └── index/ # Index de recherche vectorielle
│ └── utils/ # Modules utilitaires
│ ├── chat_interface.py # Interface utilisateur Streamlit
│ ├── embeddings.py # Gestion des embeddings (vecteurs)
│ └── rag_pipeline.py # Logique du pipeline RAG
├── docker-compose.yml # Configuration d'orchestration Docker
├── Dockerfile # Instructions de construction de l'image
├── requirements.txt # Dépendances Python
├── .env.example # Modèle de fichier d'environnement
├── .env # Variables d'environnement (clé API)
└── TP.md # Documentation du TP
Qu'est-ce que le RAG ?
RAG (Retrieval-Augmented Generation) est une technique d'IA qui combine :
- Récupération : Recherche d'informations pertinentes dans une base de données
- Génération : Utilisation d'un modèle de langage (LLM) pour créer des réponses contextuelles
Avantages du RAG :
- Réduit les hallucinations du modèle
- Permet de travailler avec des données privées/spécifiques
- Plus économique que le fine-tuning complet
- Facilite la mise à jour des connaissances
Pré-requis
- Docker Desktop installé (Télécharger)
- Pourquoi ? Permet de créer des environnements isolés et reproductibles
- Clé API Google Gemini (À obtenir ici)
- Pourquoi ? Accéder au modèle de langage Gemini pour la génération de texte
Étape 1 : Acquérir le Projet
1.1 Fork du dépôt GitHub
Action : Dupliquer le dépôt sur votre profil GitHub
- Rendez-vous sur le dépôt original
- Cliquez sur le bouton "Fork" en haut à droite
- Sélectionnez votre compte GitHub comme destination
Pourquoi forker ?
- Vous obtenez votre propre copie du projet
- Vous pouvez modifier sans affecter l'original
- Facilite la contribution et le suivi de vos modifications
1.2 Cloner le dépôt localement
Outil utilisé : Git (système de contrôle de version)
git clone https://github.com/youssef-elkahlaoui/AIops_tp.git
cd AIops_tp
Explication des commandes :
git clone: Télécharge l'intégralité du dépôt sur votre machinecd AIops_tp: Se déplace dans le répertoire du projet
Qu'est-ce qui est téléchargé ?
- Le code source de l'application
- Les fichiers de configuration Docker
- Les données d'exemple
- L'historique Git complet
1.3 Configuration de la clé API
Étape 1 : Créer le fichier d'environnement
cp .env.example .env
Pourquoi utiliser un fichier .env ?
- Sépare les secrets du code source
- Évite d'exposer les clés API dans Git
- Facilite la configuration pour différents environnements (dev, prod)
Étape 2 : Insérer votre clé API
Ouvrez le fichier .env et modifiez-le :
GOOGLE_API_KEY=AIzaSy... (votre clé obtenue depuis Google AI Studio)
Sécurité :
- ⚠️ Ne commitez JAMAIS le fichier
.envdans Git - Le fichier
.gitignoredoit contenir.envpour éviter cela - Utilisez des variables d'environnement en production
Étape 2 : Conditionnement Docker
2.1 Qu'est-ce que Docker ?
Docker est une plateforme de conteneurisation qui permet de :
- Empaqueter une application avec toutes ses dépendances
- Garantir un fonctionnement identique sur tous les environnements
- Isoler l'application du système hôte
Concepts clés :
- Image Docker : Modèle immuable contenant l'application et ses dépendances
- Conteneur : Instance en cours d'exécution d'une image
- Dockerfile : Fichier de recette pour construire une image
2.2 Analyse du Dockerfile
Le fichier Dockerfile est déjà présent dans le projet. Examinez son contenu ligne par ligne :
| Directive | Fonction | Explication détaillée |
|---|---|---|
FROM python:3.9-slim | Image de base | Utilise Python 3.9 dans une version légère (sans paquets inutiles), réduit la taille de l'image finale |
WORKDIR /app | Répertoire de travail | Définit /app comme dossier principal où toutes les commandes seront exécutées |
RUN apt-get update && apt-get install -y build-essential | Dépendances système | Installe les outils de compilation nécessaires pour ChromaDB (gcc, g++, make) |
COPY requirements.txt . | Transfert des dépendances | Copie uniquement le fichier de dépendances en premier (optimise le cache Docker) |
RUN pip install --no-cache-dir -r requirements.txt | Installation Python | Installe tous les packages Python nécessaires sans garder le cache (réduit la taille) |
COPY . . | Transfert du code source | Copie tout le code de l'application dans le conteneur |
EXPOSE 8501 | Exposition du port | Indique que Streamlit écoute sur le port 8501 (documentation, pas de sécurité réelle) |
CMD ["streamlit", "run", "app/main.py", "--server.address=0.0.0.0"] | Commande de démarrage | Lance l'application Streamlit au démarrage du conteneur |
2.3 Pourquoi cet ordre spécifique ?
Optimisation du cache Docker :
- Les couches qui changent rarement (image de base, dépendances système) sont en premier
requirements.txtest copié avant le code source- Le code source (qui change fréquemment) est copié en dernier
Avantage : Si vous modifiez seulement le code, Docker réutilise les couches précédentes (gain de temps considérable)
2.4 Construction manuelle (optionnelle)
Pour comprendre le processus, vous pouvez construire l'image manuellement :
docker build -t rag-app:latest .
Explication :
docker build: Commande de construction d'image-t rag-app:latest: Nomme l'image "rag-app" avec le tag "latest".: Utilise le Dockerfile du répertoire courant
Processus de construction :
- Docker lit le Dockerfile
- Exécute chaque instruction dans l'ordre
- Crée une couche intermédiaire pour chaque instruction
- Produit l'image finale
Étape 3 : Gestion avec Docker Compose
3.1 Qu'est-ce que Docker Compose ?
Docker Compose est un outil d'orchestration qui permet de :
- Définir des applications multi-conteneurs
- Gérer les configurations via un fichier YAML
- Démarrer tous les services avec une seule commande
- Gérer les réseaux et volumes automatiquement
Pourquoi utiliser Docker Compose ?
- Simplifie la gestion des conteneurs
- Configuration reproductible
- Idéal pour les environnements de développement
- Facilite la collaboration en équipe
3.2 Analyse du docker-compose.yml
Le fichier docker-compose.yml contient la configuration complète de l'application. Éléments typiques :
version: "3.8" # Version du format Compose
services:
rag-app: # Nom du service
build: . # Construit depuis le Dockerfile local
ports:
- "8501:8501" # Mappe le port hôte:conteneur
volumes:
- ./app:/app/app # Monte le code pour hot-reload
env_file:
- .env # Charge les variables d'environnement
restart: unless-stopped # Redémarre automatiquement en cas d'erreur
Explication des paramètres :
- build : Indique où trouver le Dockerfile
- ports : Permet d'accéder à l'application depuis l'hôte
- volumes : Synchronise les fichiers entre hôte et conteneur (permet les modifications à chaud)
- env_file : Charge les variables d'environnement depuis
.env - restart : Politique de redémarrage automatique
3.3 Démarrage de l'application
Commande principale :
docker-compose up --build
Décomposition de la commande :
docker-compose up: Lance tous les services définis--build: Force la reconstruction des images (utile après modification du code)
Processus détaillé :
- Lecture du docker-compose.yml : Docker Compose analyse la configuration
- Construction de l'image : Exécute le Dockerfile
- Téléchargement de l'image Python de base (~50 MB)
- Installation des dépendances système (~100 MB)
- Installation des packages Python (~200 MB)
- Durée totale : 3-5 minutes la première fois
- Création du réseau : Réseau Docker isolé pour le projet
- Montage des volumes : Synchronisation des dossiers
- Démarrage du conteneur : Lance Streamlit
- Affichage des logs : Montre la sortie en temps réel
Indicateurs de réussite :
✓ Network aiops-rag_default Created
✓ Container aiops-rag-app Started
You can now view your Streamlit app in your browser.
Local URL: http://localhost:8501
3.4 Accès à l'interface
URL : http://localhost:8501
Que se passe-t-il ?
- Votre navigateur envoie une requête au port 8501
- Docker redirige vers le conteneur
- Streamlit traite la requête et renvoie l'interface web
Vérifications :
- ✓ La page se charge correctement
- ✓ L'interface Streamlit s'affiche
- ✓ Le panneau latéral est visible
3.5 Commandes Docker Compose utiles
| Commande | Action | Quand l'utiliser |
|---|---|---|
docker-compose up -d | Lance en arrière-plan | Pour continuer à utiliser le terminal |
docker-compose down | Arrête et supprime les conteneurs | Pour nettoyer l'environnement |
docker-compose logs -f | Affiche les logs en temps réel | Pour déboguer |
docker-compose restart | Redémarre les services | Après modification de .env |
docker-compose exec rag-app bash | Ouvre un terminal dans le conteneur | Pour explorer l'intérieur |
Arrêt de l'application :
- Méthode 1 :
Ctrl + Cdans le terminal - Méthode 2 :
docker-compose downdans un autre terminal
Étape 4 : Vérification de la Chaîne MLOps
4.1 Qu'est-ce qu'un pipeline MLOps ?
MLOps (Machine Learning Operations) applique les principes DevOps au machine learning :
- Automatisation du flux de données
- Reproductibilité des résultats
- Déploiement continu des modèles
- Monitoring et maintenance
Notre pipeline RAG comporte 4 phases essentielles qui transforment des documents bruts en un système de question-réponse intelligent.
4.2 Paramétrage Initial
Actions à effectuer :
-
Ouvrir l'interface : http://localhost:8501
-
Localiser le panneau latéral (sidebar à gauche)
- Si masqué, cliquez sur la flèche en haut à gauche
-
Entrer la clé API Google
- Collez votre clé dans le champ prévu
- Format :
AIzaSy...(environ 39 caractères)
-
Lancer la construction : Cliquez sur "Rebuild Vector Store"
Pourquoi ce bouton ?
- Initialise la base de données vectorielle
- Traite tous les documents du dossier
app/data/ - Crée les embeddings nécessaires pour la recherche sémantique
4.3 Phase 1 : Ingestion de Données
Objectif : Charger les documents sources dans le système
Outil utilisé : LangChain Document Loaders
TextLoaderpour les fichiers.txtUnstructuredMarkdownLoaderpour les fichiers.md
Processus détaillé :
- Scan du dossier : Le système parcourt
app/data/ - Détection des fichiers : Identifie les formats supportés
- Lecture du contenu : Charge chaque fichier en mémoire
- Création de documents : Chaque fichier devient un objet Document avec :
page_content: Le texte du fichiermetadata: Nom du fichier, chemin, type
Fichiers traités :
- ✓
DevOps_cours.txt: Informations sur le cours DevOps - ✓
ensa_about.txt: Description de l'ENSA - ✓
ensa_programs.md: Liste des programmes d'études - ✓
student_life.txt: Vie étudiante et activités
Résultat attendu :
Loaded 4 documents from app/data/
Total characters: ~5000
Points de vigilance :
- Les fichiers doivent être en UTF-8
- Les noms de fichiers sans caractères spéciaux
- Taille maximale recommandée : 5 MB par fichier
4.4 Phase 2 : Segmentation de Texte (Chunking)
Objectif : Diviser les documents en fragments gérables
Outil utilisé : RecursiveCharacterTextSplitter de LangChain
Pourquoi segmenter ?
- Les modèles ont des limites de tokens
- Améliore la précision de la recherche
- Réduit le coût des API (moins de tokens traités)
- Permet de retrouver des passages spécifiques
Paramètres de segmentation :
chunk_size=1000 # Taille maximale d'un fragment (en caractères)
chunk_overlap=200 # Chevauchement entre fragments
Pourquoi le chevauchement ?
- Évite de couper des informations importantes
- Maintient le contexte entre les chunks
- Améliore la qualité des réponses
Processus :
-
Découpage intelligent :
- Tente de couper aux sauts de paragraphe
- Sinon aux points
- Sinon aux virgules
- En dernier recours : coupe au caractère
-
Préservation du contexte :
- Les 200 derniers caractères d'un chunk apparaissent dans le suivant
- Les métadonnées sont conservées
Résultat attendu :
Split into 45 chunks
Average chunk size: 850 characters
Exemple de chunk :
Chunk 1: "L'ENSA Al Hoceima a été établie en 2008..."
Chunk 2: "...établie en 2008. Elle offre plusieurs programmes..."
4.5 Phase 3 : Création d'Embeddings
Objectif : Transformer le texte en vecteurs numériques
Qu'est-ce qu'un embedding ?
- Représentation mathématique du sens d'un texte
- Vecteur de nombres (ex: [0.23, -0.45, 0.67, ...])
- Les textes similaires ont des vecteurs proches
Outil utilisé : SentenceTransformers avec le modèle all-MiniLM-L6-v2
Caractéristiques du modèle :
- Dimensions : 384 (taille du vecteur)
- Langue : Multilingue (français, anglais, arabe)
- Taille : ~80 MB
- Performance : Excellent rapport qualité/vitesse
Processus :
- Chargement du modèle : Téléchargé depuis Hugging Face (première fois uniquement)
- Encodage des chunks :
- Chaque chunk est transformé en vecteur de 384 dimensions
- Traitement par batch pour optimiser la vitesse
- Normalisation : Les vecteurs sont normalisés pour la recherche par similarité cosinus
Exemple simplifié :
Texte: "L'ENSA offre des formations en génie informatique"
→ Embedding: [0.234, -0.456, 0.678, ..., 0.123] (384 valeurs)
Pourquoi ce modèle ?
- ✓ Rapide (environ 1000 chunks/seconde)
- ✓ Fonctionne sans connexion internet après téléchargement
- ✓ Gratuit et open-source
- ✓ Bonne qualité pour le français
Résultat attendu :
Generated 45 embeddings
Dimensions: 384
Model: all-MiniLM-L6-v2
4.6 Phase 4 : Sauvegarde Vectorielle
Objectif : Stocker les embeddings dans une base de données optimisée
Outil utilisé : ChromaDB
Qu'est-ce que ChromaDB ?
- Base de données vectorielle open-source
- Optimisée pour la recherche de similarité
- Persistance sur disque
- Interface Python simple
Processus de stockage :
-
Initialisation de ChromaDB :
- Création du dossier
app/chroma_db/si inexistant - Configuration de la collection "rag_collection"
- Création du dossier
-
Insertion des données :
- Chaque chunk est stocké avec :
- Son embedding (vecteur)
- Son contenu textuel
- Ses métadonnées (source, page, etc.)
- Un ID unique
- Chaque chunk est stocké avec :
-
Création d'index :
- ChromaDB construit des index HNSW (Hierarchical Navigable Small World)
- Permet des recherches ultra-rapides (millisecondes)
Structure de stockage :
chroma_db/
├── chroma.sqlite3 # Base de données SQLite
├── index/ # Index de recherche
└── metadata/ # Métadonnées
Avantages de ChromaDB :
- ✓ Recherche rapide même avec des millions de vecteurs
- ✓ Persistance locale (pas besoin de serveur)
- ✓ Mise à jour incrémentale (ajouter sans tout recréer)
- ✓ Gratuit et sans limites
Résultat attendu :
💾 Vector store saved
Location: app/chroma_db/
Total documents: 45
Status: Ready for queries
4.7 Récapitulatif du pipeline complet
Flux de données :
📄 Documents (.txt, .md)
↓ Phase 1: Ingestion
📚 Documents chargés en mémoire
↓ Phase 2: Chunking
✂️ Fragments de texte (1000 chars)
↓ Phase 3: Embeddings
🔢 Vecteurs numériques (384 dimensions)
↓ Phase 4: Stockage
💾 ChromaDB (recherche vectorielle)
↓ Utilisation
💬 Chatbot RAG opérationnel
Temps d'exécution typique :
- Phase 1 : < 1 seconde
- Phase 2 : < 1 seconde
- Phase 3 : 5-10 secondes (selon nombre de chunks)
- Phase 4 : 2-3 secondes
- Total : ~15 secondes pour le jeu de données fourni
4.8 Évaluer le Chatbot
Objectif : Tester la qualité du système RAG avec des questions variées
Comment fonctionne une requête ?
- Saisie de la question : L'utilisateur tape dans le chat
- Embedding de la question : Transformation en vecteur (384D)
- Recherche vectorielle : ChromaDB trouve les chunks les plus similaires
- Sélection du contexte : Les 3 meilleurs chunks sont récupérés
- Construction du prompt : Combinaison du contexte + question
- Appel à Gemini : Le LLM génère la réponse
- Affichage : La réponse apparaît dans l'interface
Tests à effectuer :
Test 1 : Question factuelle simple
Question : "Quand l'ENSA Al Hoceima a-t-elle été établie ?"
Réponse attendue : "L'ENSA Al Hoceima a été établie en 2008."
Ce test valide :
- ✓ La recherche vectorielle fonctionne
- ✓ Le chunk contenant la date est bien retrouvé
- ✓ Gemini extrait correctement l'information
Test 2 : Question nécessitant agrégation
Question : "Quels sont les clubs étudiants répertoriés ?"
Réponse attendue : Une liste des clubs mentionnés dans student_life.txt
Ce test valide :
- ✓ Capacité à retrouver plusieurs informations
- ✓ Structuration de la réponse (liste)
- ✓ Exhaustivité de la recherche
Test 3 : Question en anglais
Question : "What programming languages are taught?"
Réponse attendue : Liste des langages de programmation du cursus
Ce test valide :
- ✓ Support multilingue du modèle d'embeddings
- ✓ Capacité de Gemini à répondre en anglais
- ✓ Recherche cross-lingue (question EN, docs FR)
Analyse de la qualité :
Bon indicateurs :
- ✅ Réponse précise et concise
- ✅ Information directement extraite des documents
- ✅ Pas d'invention d'informations (hallucination)
- ✅ Citation implicite de la source
Mauvais indicateurs :
- ❌ Réponse générique ("Je ne sais pas")
- ❌ Information inventée non présente dans les docs
- ❌ Réponse hors sujet
- ❌ Mélange de sources contradictoires
Comprendre les limites :
Si le chatbot répond "Je n'ai pas cette information" :
- Vérifiez que le document contient bien l'info
- Reformulez la question différemment
- Chunking : L'info est peut-être coupée entre 2 chunks
Panel de test avancé :
| Type de question | Exemple | Difficulté |
|---|---|---|
| Factuelle | "Quelle est la date de fondation ?" | Facile |
| Agrégation | "Liste tous les programmes" | Moyenne |
| Comparaison | "Quelle est la différence entre ..." | Difficile |
| Temporelle | "Quand se déroule le cours X ?" | Facile |
| Négation | "Quels clubs ne sont pas mentionnés ?" | Très difficile |
Étape 5 : Mise à Jour Instantanée (Hot Reload)
5.1 Qu'est-ce que le Hot Reload ?
Hot Reload (rechargement à chaud) est une fonctionnalité DevOps qui permet :
- Mise à jour de l'application sans redémarrage complet
- Synchronisation automatique des fichiers modifiés
- Gain de temps considérable en développement
Comment ça fonctionne ici ?
- Docker monte le dossier
app/local dans le conteneur - Streamlit détecte les changements de fichiers
- Le système recharge automatiquement les données
Pourquoi c'est important ?
- Itération rapide sur les données
- Pas besoin de
docker-compose down/up - La base vectorielle se met à jour automatiquement
- Environnement de développement agile
5.2 Objectif de ce test
Démontrer que la chaîne MLOps peut intégrer de nouvelles données sans nécessiter :
- Reconstruction de l'image Docker
- Redémarrage du conteneur
- Intervention manuelle complexe
Scénario réel : Un professeur ajoute des informations de dernière minute
5.3 Ajout d'un Nouveau Document
Étape 1 : Créer le fichier app/data/DevOps_cours.txt
Emplacement : c:\Users\jozef\OneDrive\Desktop\AIops-RAG\app\data\DevOps_cours.txt
Méthode 1 - Via l'éditeur :
- Ouvrir VS Code
- Naviguer vers
app/data/ - Créer un nouveau fichier :
DevOps_cours.txt - Coller le contenu ci-dessous
- Sauvegarder (
Ctrl+S)
Méthode 2 - Via PowerShell :
cd app\data
New-Item -Path "DevOps_cours.txt" -ItemType File
notepad DevOps_cours.txt
Contenu à insérer :
Le cours de DevOps est dispensé le mercredi matin à 9 h.
Le professeur responsable est Dr. Bahri.
Les étudiants apprennent Docker, Kubernetes et CI/CD.
Le TP pratique couvre la conteneurisation d'applications.
Pourquoi ce contenu ?
- Information factuelle simple (date, heure)
- Nom propre spécifique (Dr. Bahri)
- Termes techniques (Docker, Kubernetes)
- Facilement vérifiable dans les réponses
5.4 Constater la Détection Automatique
Mécanisme de surveillance :
Le système utilise un watchdog (chien de garde) qui :
- Surveille le dossier
app/data/en permanence - Calcule un hash (empreinte numérique) du contenu
- Compare avec le hash précédent
- Déclenche le rebuild si différence détectée
Processus automatique :
📁 Fichier ajouté/modifié
↓
🔍 Détection du changement (hash différent)
↓
⚠️ Alerte "Data folder changes detected!"
↓
🔄 Rebuild automatique du vector store
↓
✅ Système à jour
Indicateurs visuels :
-
Actualisez la page dans le navigateur (
F5) -
Message attendu dans le panneau latéral :
⚠️ Data folder changes detected! The vector store needs to be rebuilt. -
Bouton activé : "Rebuild Vector Store" devient cliquable
-
Cliquez sur le bouton pour lancer le rebuild
-
Progression : Les 4 phases se relancent
- ✓ Phase 1 : Détection de 5 documents (au lieu de 4)
- ✓ Phase 2 : Nouveau nombre de chunks
- ✓ Phase 3 : Embeddings recalculés
- ✓ Phase 4 : ChromaDB mis à jour
Temps de rebuild : 10-20 secondes
Optimisation possible :
- Version avancée : Ne traiter que les nouveaux fichiers (delta update)
- Version actuelle : Rebuild complet (plus simple, plus fiable)
5.5 Vérification technique (optionnelle)
Inspecter les logs Docker :
docker-compose logs -f rag-app
Messages attendus :
[INFO] File watcher detected changes
[INFO] Starting vector store rebuild...
[INFO] Loaded 5 documents (1 new)
[INFO] Generated 52 chunks
[INFO] Vector store updated successfully
5.6 Interroger la Nouvelle Donnée
Test 1 : Question temporelle
Question : "Quand est prévu le cours de DevOps ?"
Réponse attendue : "Le cours de DevOps est prévu le mercredi matin à 9h."
Validation :
- ✅ Le système a bien indexé le nouveau fichier
- ✅ La recherche vectorielle fonctionne sur les nouvelles données
- ✅ L'information temporelle est correctement extraite
Analyse : Si la réponse est incorrecte ou absente :
- Vérifiez que le fichier est bien dans
app/data/ - Confirmez que le rebuild a été effectué
- Regardez les logs pour d'éventuelles erreurs
Test 2 : Question sur personne
Question : "Qui est le professeur responsable du cours de DevOps ?"
Réponse attendue : "Le professeur responsable du cours de DevOps est Dr. Bahri."
Validation :
- ✅ Extraction de nom propre fonctionnelle
- ✅ Association correcte (cours ↔ professeur)
- ✅ Formulation naturelle de la réponse
Test 3 : Question technique
Question : "Quelles technologies sont enseignées dans le cours de DevOps ?"
Réponse attendue : "Docker, Kubernetes et CI/CD"
Validation :
- ✅ Énumération correcte
- ✅ Pas d'ajout d'informations non présentes
- ✅ Formatage lisible
5.7 Comprendre l'avantage du volume Docker
Sans volume Docker :
# Mauvaise pratique
services:
rag-app:
build: .
# Pas de volume
- ❌ Modifications de code non prises en compte
- ❌ Nécessite
docker-compose up --buildà chaque fois - ❌ Perte de temps (3-5 minutes par rebuild)
Avec volume Docker (configuration actuelle) :
# Bonne pratique
services:
rag-app:
build: .
volumes:
- ./app:/app/app # Synchronisation bidirectionnelle
- ✅ Modifications instantanées
- ✅ Workflow de développement fluide
- ✅ Rebuild uniquement si changement de dépendances
Cas d'usage réels :
- Développement : Itération rapide sur les données/code
- Démo : Ajout de données devant le client
- Production : ⚠️ À désactiver (stabilité requise)
5.8 Expérimentations suggérées
Exercice 1 : Modifier un fichier existant
- Éditez
app/data/ensa_about.txt - Ajoutez une phrase
- Observez la détection automatique
- Posez une question sur la nouvelle info
Exercice 2 : Supprimer un document
- Supprimez
app/data/student_life.txt - Rebuild le vector store
- Tentez une question sur les clubs
- Résultat : "Information non disponible"
Exercice 3 : Format Markdown
- Créez
app/data/horaires.md - Utilisez la syntaxe Markdown (titres, listes)
- Vérifiez que le système traite correctement le formatage
Limites à connaître :
- Formats supportés :
.txt,.mduniquement - Encodage : UTF-8 obligatoire
- Taille : Éviter les fichiers > 5 MB
- Noms : Pas de caractères spéciaux (é, à, ç, espaces)
🎯 Récapitulatif et Concepts Clés
Technologies et leur rôle
| Technologie | Rôle | Alternatives possibles |
|---|---|---|
| Docker | Conteneurisation | Podman, LXC |
| Docker Compose | Orchestration | Kubernetes (pour production) |
| Python 3.9 | Langage principal | Python 3.10+, 3.11 |
| Streamlit | Framework web | Gradio, Flask, FastAPI |
| LangChain | Framework RAG | LlamaIndex, Haystack |
| ChromaDB | Base vectorielle | Pinecone, Weaviate, Milvus, FAISS |
| SentenceTransformers | Modèle d'embeddings | OpenAI Ada-002, Cohere |
| Google Gemini | LLM génératif | GPT-4, Claude, Llama |
Concepts DevOps appliqués
- Infrastructure as Code :
Dockerfile+docker-compose.yml - Immutabilité : Conteneurs identiques sur tous les environnements
- Isolation : Application séparée du système hôte
- Reproductibilité : Build identique partout
- Hot Reload : Développement itératif rapide
- Surveillance : Détection automatique des changements
- Logs centralisés :
docker-compose logs
Flux d'une requête utilisateur
1. 💬 Utilisateur : "Quand l'ENSA a-t-elle été créée ?"
↓
2. 🔢 Embedding : [0.23, -0.45, 0.67, ...] (384D)
↓
3. 🔍 ChromaDB : Recherche par similarité cosinus
↓
4. 📄 Top 3 chunks :
- "L'ENSA Al Hoceima établie en 2008..." (score: 0.92)
- "Histoire de l'établissement..." (score: 0.87)
- "Création et développement..." (score: 0.81)
↓
5. 📝 Construction du prompt :
Contexte: [chunks récupérés]
Question: "Quand l'ENSA a-t-elle été créée ?"
Instruction: Réponds précisément basé sur le contexte.
↓
6. 🤖 Gemini API : Génération de la réponse
↓
7. ✅ Réponse : "L'ENSA Al Hoceima a été créée en 2008."
Métriques de performance
Temps de réponse typique :
- Embedding de la question : ~50 ms
- Recherche vectorielle : ~10 ms
- Appel API Gemini : 1-3 secondes
- Total : 1-3 secondes
Coûts :
- Embeddings locaux : Gratuit (SentenceTransformers)
- ChromaDB : Gratuit (open-source)
- Gemini API : ~15 requêtes gratuites/minute
- Coût total pour ce TP : 0 €
Scalabilité :
- Documents : Jusqu'à 10 000 sans problème
- Requêtes simultanées : 10-50 (selon config serveur)
- Pour plus : Passer à une architecture distribuée
🏃 Plan B : Exécution Locale (Sans Docker)
Quand utiliser cette méthode ?
- ❌ Docker Desktop ne fonctionne pas
- ❌ Problèmes de virtualisation (Hyper-V)
- ❌ Ressources système limitées
- ✅ Développement rapide et léger
- ✅ Débogage approfondi nécessaire
Prérequis système
- Python : Version 3.9, 3.10 ou 3.11 installée
- Pip : Gestionnaire de packages Python
- Git : Pour cloner le dépôt
- Espace disque : ~2 GB (modèles + dépendances)
Installation pas à pas
Étape 1 : Vérifier Python
python --version
Résultat attendu : Python 3.9.x ou supérieur
Si Python n'est pas installé :
- Télécharger depuis python.org
- Cocher "Add Python to PATH" pendant l'installation
- Redémarrer PowerShell
Étape 2 : Créer un environnement virtuel
# Se placer dans le dossier du projet
cd c:\Users\jozef\OneDrive\Desktop\AIops-RAG
# Créer l'environnement virtuel
python -m venv venv
# Activer l'environnement (Windows)
.\venv\Scripts\Activate.ps1
Pourquoi un environnement virtuel ?
- Isole les dépendances du projet
- Évite les conflits avec d'autres projets Python
- Facilite la gestion des versions de packages
Étape 3 : Installer les dépendances
# Mettre à jour pip
python -m pip install --upgrade pip
# Installer tous les packages requis
pip install -r requirements.txt
Packages installés (principaux) :
streamlit: Framework weblangchain: Framework RAGchromadb: Base vectoriellesentence-transformers: Modèle d'embeddingsgoogle-generativeai: SDK Gemini
Temps d'installation : 3-5 minutes
Étape 4 : Configurer la clé API
# Copier le fichier d'exemple
copy .env.example .env
# Éditer avec notepad
notepad .env
Insérer votre clé :
GOOGLE_API_KEY=AIzaSy...
Étape 5 : Démarrer l'application
# Lancer Streamlit
python -m streamlit run app/main.py
Alternative :
streamlit run app/main.py
Sortie attendue :
You can now view your Streamlit app in your browser.
Local URL: http://localhost:8501
Network URL: http://192.168.1.x:8501
Étape 6 : Accéder à l'interface
Ouvrir http://localhost:8501 dans votre navigateur
📚 Pour aller plus loin
Documentation officielle :
Tutoriels avancés :
Communautés :
What's inside
5 numbered steps, 15 subsections, 8 code blocks, 3 test scenarios, 1 directory tree
Change this for your project
- Replace
https://github.com/youssef-elkahlaoui/AIops_tp.gitwith your own fork URL - Replace
AIops-RAG/folder name with your project's root directory name - Replace
GOOGLE_API_KEY=AIzaSy...placeholder with your actual Gemini API key
Where it goes
Reference documentation for a retrieval pipeline. Keep with the ingestion or retrieval code it describes.
Worth borrowing
- Mounting
./app:/app/appas a volume for hot reload during development - Using a watchdog hash comparison to auto-rebuild the vector store on data changes
Related Documents
SUMMARY
Proposes three on-prem AI architectures, modular, hybrid, and fully local RAG, with hardware specs and vendor lists.
Retrieval & Prompts
Explains how CharMemory's extraction prompt and Vector Storage settings determine memory retrieval quality in SillyTavern.
App Review Support Guide — Switch2Go
Explains an AAC app's accessibility permissions, hardware needs, and reviewer walkthrough to pass App Store review.
RFC-BLite: High-Performance Embedded Document Database for .NET
Specifies an embedded document database for.NET with zero-allocation I/O, C-BSON format, and ACID transactions.