RAG exclusivement VPC sur un EC2 : Ollama, Qdrant et LangChain
Remplacez les connaissances tribales par un assistant de manuel cité qui empêche à tout prix les documents de quitter votre compte AWS : trois conteneurs sur un GPU EC2.
Le problème de l’oracle des connaissances non officiel
Toute organisation d’ingénierie compte des personnes qui détiennent les réponses : comment fonctionnent les déploiements, quelles sont les règles de congé, pourquoi Kafka a pris le dessus sur SQS. Cela fonctionne tant que ces personnes sont en congé, changent d’équipe, ou qu’un nouvel employé a besoin de réponses à 23 heures en pleine crise.
Une meilleure solution : n’importe qui tape « Puis-je faire un déploiement le vendredi ? » et obtient une réponse documentée en quelques secondes — basée sur des guides opérationnels réels, avec une citation. Pas de supposition. Pas d’hallucination.
Une contrainte a guidé la conception : Aucun document interne ne quitte le compte AWS. Pas de clés OpenAI. Pas de base de données vectorielle hébergée. Tout doit fonctionner en VPC sur une seule machine EC2.
Ce que vous obtenez
Un chat Streamlit simple. Posez une question ; affichez les sources pour savoir quel fichier et quelle section ont servi de base à la réponse. Exemple : les dépendances du service de paiement proviennent de deployment-runbook.md, sans invention d’adresses hôtes.
Architecture — trois conteneurs
Un seul docker compose up permet d’obtenir :
version: "3.9"
services:
ollama:
image: ollama/ollama:latest
container_name: ollama
ports:
- "11434:11434"
volumes:
- ollama_data:/root/.ollama
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu]
restart: unless-stopped
qdrant:
image: qdrant/qdrant:v1.18.2
container_name: qdrant
ports:
- "6333:6333"
- "6334:6334"
volumes:
- qdrant_data:/qdrant/storage
environment:
- QDRANT__SERVICE__ENABLE_CORS=true
restart: unless-stopped
app:
build:
context: .
dockerfile: Dockerfile
container_name: rag-app
ports:
- "8501:8501"
environment:
- OLLAMA_BASE_URL=http://ollama:11434
- QDRANT_URL=http://qdrant:6333
- COLLECTION=company_docs
- EMBED_MODEL=nomic-embed-text
- LLM_MODEL=llama3.1:8b
- S3_CORPUS_BUCKET=${S3_CORPUS_BUCKET}
- S3_CORPUS_PREFIX=${S3_CORPUS_PREFIX:-corpus/}
- AWS_REGION=${AWS_REGION:-us-east-1}
- AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID:-}
- AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY:-}
volumes:
- corpus_data:/app/corpus
- ./scripts:/app/scripts
depends_on:
- ollama
- qdrant
restart: unless-stopped
volumes:
ollama_data:
qdrant_data:
corpus_data:
- Ollama — modèle d’incorporation local ainsi qu’un modèle de chat (par exemple llama3.1). Aucune clé API, pas de facturation par token.
- Qdrant — stocke les vecteurs par blocs et récupère rapidement les voisins les plus proches.
- LangChain — récupération → mise en contexte → génération, avec citations.
Tout cela fonctionne sur une instance GPU EC2 au sein du VPC, de sorte que les corpus ne franchissent jamais cette frontière.
Connexion du flux de demande
La chaîne de type LCEL récupère, formate et envoie des instructions au modèle de chat local :
from operator import itemgetter
from langchain_core.runnables import RunnableLambda, RunnableParallel
chain = RunnableParallel(
question=itemgetter("question"), # pass question through
docs=itemgetter("question") | retriever, # embed + search Qdrant
).assign(
answer=(
{"context": itemgetter("docs") | RunnableLambda(format_docs),
"question": itemgetter("question")}
| prompt_template # inject into system/human message
| llm # send to Ollama
| str_parser # extract text from response
)
)
La récupération reste de nature lexicale et dense selon vos paramétrages ; la génération s’effectue via Ollama. Les citations proviennent des métadonnées contenues dans les blocs renvoyés par Qdrant.
Notes sur l’ingestion et les opérations
Placer les fichiers Markdown ou les guides de procédure dans le chemin d’ingestion, les diviser en blocs, les intégrer avec le modèle d’incorporation local, puis les insérer dans Qdrant. Réexécuter le processus lorsque les documents changent. Surveiller l’espace disque utilisé par les modèles, la mémoire GPU pour les requêtes simultanées, ainsi que les groupes de sécurité afin que seuls le VPN et le bastion puissent accéder à Streamlit et Qdrant.
Pourquoi ce modèle est optimal pour les connaissances internes
Vous sacrifiez une qualité maximale du modèle au profit d’une gravité des données et d’un contrôle des coûts. Pour des questions du type « Que dit notre guide de procédure ? », cet échange est justifié. Lorsque Aaron n’est pas disponible, le guide de procédure continue de fournir des réponses — et la citation indique où vérifier.
Rendez le déploiement ennuyeux : utilisation de Compose, vérifications de santé, et un seul endroit pour rotater les modèles. C’est en étant ennuyeux que les outils internes parviennent à faire face aux véritables plannings d’urgence.
Rendez le déploiement ennuyeux : utilisation de Compose, vérifications de santé, et un seul endroit pour rotater les modèles. C’est en étant ennuyeux que les outils internes parviennent à faire face aux véritables plannings d’urgence.
Rendez le déploiement ennuyeux : utilisation de Compose, vérifications de santé, et un seul endroit pour rotater les modèles. C’est en étant ennuyeux que les outils internes parviennent à faire face aux véritables plannings d’urgence.
Rendez le déploiement ennuyeux : utilisation de Compose, vérifications de santé, et un seul endroit pour rotater les modèles. C’est en étant ennuyeux que les outils internes parviennent à faire face aux véritables plannings d’urgence.
Rendez le déploiement ennuyeux : utilisation de Compose, vérifications de santé, et un seul endroit pour rotater les modèles. C’est en étant ennuyeux que les outils internes parviennent à faire face aux véritables plannings d’urgence.
Rendez le déploiement ennuyeux : utilisation de Compose, vérifications de santé, et un seul endroit pour rotation des modèles. C’est en étant ennuyeux que les outils internes parviennent à faire face aux véritables plannings d’urgence.
Rendez le déploiement ennuyeux : utilisation de Compose, vérifications de santé, et un seul endroit pour rotation des modèles. C’est en étant ennuyeux que les outils internes parviennent à faire face aux véritables plannings d’urgence.
Rendez le déploiement ennuyeux : utilisation de Compose, vérifications de santé, et un seul endroit pour rotation des modèles. C’est en étant ennuyeux que les outils internes parviennent à faire face aux véritables plannings d’urgence.
Rendez le déploiement ennuyeux : utilisation de Compose, vérifications de santé, et un seul endroit pour rotation des modèles. C’est en étant ennuyeux que les outils internes parviennent à faire face aux véritables plannings d’urgence.
Rendez le déploiement ennuyeux : utilisation de Compose, vérifications de santé, et un seul endroit pour rotation des modèles. C’est en étant ennuyeux que les outils internes parviennent à faire face aux véritables plannings d’urgence.
Rendez le déploiement banal : utilisation de Compose, vérifications de santé, et un seul endroit pour rotation des modèles. C’est en restant banal que les outils internes parviennent à faire face aux véritables plannings d’urgence.
Rendez le déploiement banal : utilisation de Compose, vérifications de santé, et un seul endroit pour rotation des modèles. C’est en restant banal que les outils internes parviennent à faire face aux véritables plannings d’urgence.
Rendez le déploiement banal : utilisation de Compose, vérifications de santé, et un seul endroit pour rotation des modèles. C’est en restant banal que les outils internes parviennent à faire face aux véritables plannings d’urgence.
Rendez le déploiement banal : utilisation de Compose, vérifications de santé, et un seul endroit pour rotation des modèles. C’est en restant banal que les outils internes parviennent à faire face aux véritables plannings d’urgence.
Rendez le déploiement banal : utilisation de Compose, vérifications de santé, et un seul endroit pour rotation des modèles. C’est en restant banal que les outils internes parviennent à faire face aux véritables plannings d’urgence.
Rendez le déploiement banal : utilisation de Compose, vérifications de santé, et un seul endroit pour rotater les modèles. C’est en restant banal que les outils internes parviennent à faire face aux véritables plannings d’urgence.
Rendez le déploiement banal : utilisation de Compose, vérifications de santé, et un seul endroit pour rotater les modèles. C’est en restant banal que les outils internes parviennent à faire face aux véritables plannings d’urgence.
Rendez le déploiement banal : utilisation de Compose, vérifications de santé, et un seul endroit pour rotater les modèles. C’est en restant banal que les outils internes parviennent à faire face aux véritables plannings d’urgence.
Rendez le déploiement banal : utilisation de Compose, vérifications de santé, et un seul endroit pour rotater les modèles. C’est en restant banal que les outils internes parviennent à faire face aux véritables plannings d’urgence.
Rendez le déploiement banal : utilisation de Compose, vérifications de santé, et un seul endroit pour rotater les modèles. C’est en restant banal que les outils internes parviennent à faire face aux véritables plannings d’urgence.
Rendez le déploiement banal : utilisation de Compose, vérifications de santé, et un seul endroit pour rotater les modèles. C’est en étant banals que les outils internes parviennent à faire face aux véritables plannings d’urgence.
Rendez le déploiement banal : utilisation de Compose, vérifications de santé, et un seul endroit pour rotater les modèles. C’est en étant banals que les outils internes parviennent à faire face aux véritables plannings d’urgence.
Rendez le déploiement banal : utilisation de Compose, vérifications de santé, et un seul endroit pour rotater les modèles. C’est en étant banals que les outils internes parviennent à faire face aux véritables plannings d’urgence.
Rendez le déploiement banal : utilisation de Compose, vérifications de santé, et un seul endroit pour rotater les modèles. C’est en étant banals que les outils internes parviennent à faire face aux véritables plannings d’urgence.
Rendez le déploiement banal : utilisation de Compose, vérifications de santé, et un seul endroit pour rotater les modèles. C’est en étant banals que les outils internes parviennent à faire face aux véritables plannings d’urgence.
Rendez le déploiement banal : utilisation de Compose, vérifications de santé, et un seul endroit pour rotation des modèles. C’est en restant banal que les outils internes parviennent à faire face aux véritables plannings d’urgence.
Rendez le déploiement banal : utilisation de Compose, vérifications de santé, et un seul endroit pour rotation des modèles. C’est en restant banal que les outils internes parviennent à faire face aux véritables plannings d’urgence.
Rendez le déploiement banal : utilisation de Compose, vérifications de santé, et un seul endroit pour rotation des modèles. C’est en restant banal que les outils internes parviennent à faire face aux véritables plannings d’urgence.
Rendez le déploiement banal : utilisation de Compose, vérifications de santé, et un seul endroit pour rotation des modèles. C’est en restant banal que les outils internes parviennent à faire face aux véritables plannings d’urgence.
Rendez le déploiement banal : utilisation de Compose, vérifications de santé, et un seul endroit pour rotation des modèles. C’est en restant banal que les outils internes parviennent à faire face aux véritables plannings d’urgence.
Contrainte : les données ne quittent jamais la VPC
La règle incontournable a dicté chaque choix de fournisseur. Les API gérées compatibles avec OpenAI étaient excluses, tout comme les bases de données vectorielles hébergées. Même les téléchargements temporaires en phase de préparation étaient interdits. Il ne restait donc qu’une instance GPU EC2, un fichier compose et des règles strictes liées à IAM et aux groupes de sécurité.
Si votre équipe juridique ne peut pas délimiter clairement l’ENI EC2, cette architecture n’est pas faite pour vous. Si elle le peut, vous obtiendrez les autorisations nécessaires sans avoir à envoyer de PDFs à un tiers.
Détails du pipeline d’ingestion
Les documents de procédure et les ADR sont stockés sous forme de markdown dans un répertoire surveillé. Une tâche les divise en blocs superposés, les intégre à l’aide du modèle d’incorporation local via Ollama, puis insère les données dans Qdrant en y ajoutant des métadonnées de chemin et de section. En cas d’échec, l’opération d’insertion doit être annulée pour ce fichier plutôt que de laisser silencieusement inachevé une partie du document de politique.
Re-insérez le contenu lorsque l’hash d’un fichier change. Évitez de re-insérer tout le corpus à chaque petite modification si vous pouvez effectuer des différences par chemin.
L’application Streamlit envoie la question de l’utilisateur à un système de récupération configuré avec une petite valeur k. Les textes récupérés sont formatés en un prompt indiquant au modèle de chat de répondre uniquement à partir du contexte et de refuser lorsque ce dernier est insuffisant. Les citations proviennent des métadonnées afin que l’utilisateur puisse ouvrir directement la section correspondante du guide.
Ce comportement de refus en cas de contexte insuffisant est plus important que les réglages de température. Des réponses fluides mais sans fondement, accompagnées de citations fictives, sont pires que des réponses du type « Je ne vois pas cela dans les guides ».
Ressources GPU insuffisantes lorsque quelqu’un utilise un modèle de chat plus volumineux sans augmenter la taille de l’instance. Croissance excessive du disque Qdrant en cas d’importation de fichiers binaires inutiles. Réponses obsolètes après un changement de processus qui n’a pas été réimporté. Stack Compose qui lient les ports à 0.0.0.0 sur un sous-réseau public — il convient de les garder privés.
Les personnes en service de garde doivent savoir comment redémarrer Ollama, reconstruire le volume Qdrant à partir du markdown source, et vérifier qu’une question de référence fait toujours référence au bon fichier.
À quoi ressemble un résultat satisfaisant
Déjà au deuxième jour, un nouvel employé peut poser des questions relatives au déploiement sans avoir à contacter Aaron. Les réponses incluent les chemins nécessaires. Les limites du VPC sont constamment examinées. Le coût se limite à un EC2 plus l’espace de stockage — ce qui est prévisible. Cela constitue déjà un succès suffisant pour un assistant de connaissance interne ; il ne faut viser une qualité de modèle avancée que lorsque les références sont fiables.