Chatboard RAG pour les questions-réponses scientifiques
Posez une question sur un corpus d'articles de recherche et recevez une réponse avec ses sources. Elle tourne en deux services Docker sur une machine équipée d'un GPU.
L'énoncé du problème
La littérature scientifique grossit plus vite qu'un chercheur ne peut la lire, et les questions qui comptent traversent un corpus entier plutôt qu'un seul article. La recherche par mots-clés rend une liste classée et laisse au lecteur le soin d'ouvrir, de parcourir, de comparer et d'assembler la réponse. Ce système renvoie directement la réponse citée, en flux, sur un corpus d'articles de recherche en traitement automatique des langues (TAL), servie par deux services Docker.
La tâche est la réponse à des questions en domaine ouvert sur un corpus préindexé. À partir d'une requête en langage naturel, le système retrouve les 7 meilleurs passages dans un index d'environ 47 800 fragments bâti sur FAISS et BM25 (à partir des 888 articles du jeu d'entraînement de QASPER, qui compte 5 049 questions sur 1 585 articles de TAL), puis rédige une réponse ancrée et citée avec un modèle local.
L'architecture de l'application
La pile compte 2 services sous Docker Compose : un serveur FastAPI sur le port 8080 et une interface de discussion Chainlit sur le port 8001. Les deux conteneurs tournent en network_mode: host, ce qui donne au serveur un accès direct à Ollama sur la machine hôte. L'interface attend un serveur validé par sa sonde de santé (condition: service_healthy), en interrogeant /health toutes les 30 secondes avec une période de démarrage de 300 secondes, pour que le téléchargement des artefacts au premier démarrage ait le temps de finir.
Les index FAISS pèsent environ 230 Mo (dense.index à 147 Mo, les métadonnées à 31 Mo, sparse.pkl à 51 Mo). gdown les récupère depuis Google Drive au premier démarrage. compose.yml ne monte aucun volume pour eux, donc ils se téléchargent de nouveau chaque fois que le conteneur est recréé. Le serveur détecte CUDA et choisit HuggingFace Transformers sur GPU ou Ollama sur processeur, sans que l'utilisateur change quoi que ce soit à la configuration.
La chaîne RAG, en 4 étapes
Étape 1. La recherche hybride. La recherche dense FAISS (plongements SPECTER2, 768 dimensions, un index plat à produit scalaire) fusionne avec la recherche creuse BM25 par fusion de rang réciproque (k=60). L'application garde les 50 meilleurs candidats.
Étape 2. Le reclassement ColBERT v2. Les plongements de tokens des documents sont calculés hors ligne, donc le temps de requête ne coûte qu'un MaxSim sur des plongements de tokens. Cela achète la précision d'un encodeur croisé à l'échelle de la recherche, et ramène les 50 meilleurs candidats aux 7 meilleurs.
Étape 3. La porte CRAG. La vérification CRAG (Yan et al., 2024) étiquette chaque passage Correct, Ambigu ou Incorrect. Si aucun passage ne la franchit, le serveur se replie sur les 3 premiers passages et répond quand même, au lieu de refuser.
Étape 4. La génération en flux. Sur GPU, HuggingFace Transformers fait tourner Llama-3.1-8B-Instruct. Sans GPU, Ollama fait tourner Llama 3. Le modèle rédige un bref raisonnement, puis une réponse finale avec des citations [Doc N] en ligne et 6 tours de mémoire de conversation. Une file asynchrone pousse les jetons vers un point de terminaison de diffusion NDJSON.
La chaîne d'intégration et de déploiement continus
Chaque envoi sur master déclenche un flux GitHub Actions qui s'authentifie auprès de GHCR avec le GITHUB_TOKEN automatique, donc sans aucun secret à gérer, puis construit et envoie les deux images Docker sous 2 étiquettes : :latest et :sha-<commit>. L'image du serveur clone la chaîne de recherche à un commit épinglé. compose.yml récupère l'image de l'interface depuis GHCR et construit le serveur en local.
L'évaluation
L'évaluation se trouve dans le dépôt de recherche, sur 150 questions QASPER vérifiées contre des preuves annotées par des humains. Lors de l'exécution de référence du 2026-09-02, la précision des citations ALCE valait 0,654 et le rappel 0,674, avec 128 questions sur 150 traitées. Corriger le code de notation a compté autant que la chaîne elle-même : la précision et le rappel partageaient un même dénominateur, donc ils coïncidaient sur chaque ligne notée. L'étude complète, avec les gains de rappel des preuves obtenus en indexant les tableaux, figure sur la page du projet RAG hybride.
L'effet obtenu
- Des images prêtes à l'emploi. L'intégration continue publie les images du serveur et de l'interface sur GHCR à chaque envoi. compose.yml récupère l'image de l'interface et construit le serveur, qui télécharge ses index depuis Google Drive au premier démarrage, donc aucun environnement Python à créer et aucun index à télécharger à la main. Le mode processeur demande Ollama installé sur la machine hôte.
- Le système tourne sur processeur. Le moteur Ollama fonctionne sur du matériel courant, à environ 2 à 5 jetons par seconde.
- Un raisonnement auditable. Chaque réponse montre son bloc de raisonnement avant la réponse finale, pour qu'un lecteur vérifie la logique qui l'a produite.
- Les questions de suite fonctionnent. 6 tours de mémoire évitent à l'utilisateur de redonner le contexte.