Mémoire sourcée

RAG sourcé à la ligne, serveur MCP, injections mises en quarantaine

Rôle
Conception, développement, évaluation, sécurité
Outils
  • Python
  • BM25
  • MiniLM multilingue
  • Cross-encodeur mmarco
  • RRF
  • SQLite
  • FastAPI
  • MCP
Statut
Fonctionnel
L’interface : chaque passage cité avec son fichier, ses lignes, son niveau de confiance et sa pertinence.
L’interface : chaque passage cité avec son fichier, ses lignes, son niveau de confiance et sa pertinence.
précision / rappel d’abstention sur 90 questions de test gelées (0,81 / 0,45 avant)
0,95 / 0,79
de rappel sur 40 questions sans réponse jamais vues, sans abstention à tort
0,83
de latence p50 (1 012 ms avant), 6 ms en cache
618 ms
pièges d’injection signalés, 16 / 30 injections paraphrasées
6/6
Le problème
Un assistant documentaire qui invente est pire qu’un assistant muet, et un document piégé ne doit jamais lui dicter sa conduite.
Pour qui
Un assistant compatible MCP (Claude Desktop ou autre) et une interface web, sur 190 documents découpés en 1 496 passages, hors ligne.
Le résultat
Sur 90 questions de test gelées : abstention précision / rappel de 0,81 / 0,45 à 0,95 / 0,79, rappel@3 de 0,76 à 0,81, latence p50 de 1 012 à 618 ms ; pièges signalés 6/6.

Contexte

Une douzaine de projets, 190 documents en français et en anglais qui évoluent chaque jour. Un assistant doit y répondre avec la source exacte, sans halluciner, et sans obéir à un document qui contiendrait des consignes cachées.

Ce que j’ai construit

  • Découpage qui respecte la structure (titres, tableaux, blocs de code jamais coupés) et numéros de lignes exacts ; indexation incrémentale par empreinte SHA-256.
  • Recherche hybride : BM25 et embeddings multilingues fusionnés (RRF), puis cross-encodeur qui reclasse ; abstention sur seuil gelé et règle d’ancrage.
  • Scanner d’injection à l’ingestion, motifs et détection sémantique : chaque passage est fiable, suspect ou en quarantaine ; la quarantaine n’est jamais servie, seulement signalée. 16 injections paraphrasées sur 30 signalées (0 avec les motifs seuls), 0 faux positif en quarantaine sur 931 passages réels.
  • Détecteur d’abstention appris et gelé : précision / rappel 0,95 / 0,79 sur 90 questions de test, abstentions à tort de 5 à 2.
  • Trois accès : interface web, API et serveur MCP (recherche, passage exact, source, inventaire), avec une configuration Claude Desktop prête à coller.
  • Protocole figé avant mesure : 90 questions de test (40 de la v2, 50 nouvelles dont 40 sans réponse), mesurées une seule fois ; l’ancienne version rejouée sur les mêmes questions ; 60 tests.

Architecture 7 briques

  1. 01 · EntréeIngestionDécoupage structuré, lignes exactes, empreintes SHA-256
  2. 02 · OutilScannerMotifs et sémantique : fiable, suspect ou quarantaine, par passage
  3. 03 · DonnéesIndex SQLitePassages, vecteurs, confiance
  4. 04 · OutilRappel hybrideBM25 et MiniLM multilingue, fusion RRF
  5. 05 · ModèleReclassementCross-encodeur mmarco sur 24 candidats
  6. 06 · OutilDécisionCiter la ligne, ou s’abstenir (détecteur gelé)
  7. 07 · SortieServiceInterface web, API, serveur MCP

Fabrication 5 étapes

  1. IngestionDécoupage structuré, scan d’injection.
  2. RappelBM25 et dense, fusion RRF.
  3. ReclassementCross-encodeur sur 24 candidats.
  4. DécisionCiter la ligne, ou s’abstenir.
  5. ServiceWeb, API, MCP.

Décisions le choix, la raison, l’alternative écartée

  1. D1
    Geler la répartition des questions et leurs empreintes avant toute mesure de la v2.

    L’évaluateur refuse de mesurer si une question a changé : le chiffre de test n’est pas sur-ajusté.

    ÉcartéAjuster les seuils en regardant le test.

  2. D2
    Rejouer l’ancienne version sur les mêmes questions de test.

    Le gain se lit sur le même jeu, métrique par métrique, sans changer de référence.

  3. D3
    Traiter le contenu des documents comme une donnée non fiable dès l’ingestion.

    Les passages en quarantaine ne sont jamais servis ; le texte rendu est échappé et précédé d’un avertissement « données, pas instructions ».

  4. D4
    CPU uniquement, vérifié au chargement.

    Le service tourne à côté des travaux GPU sans les gêner ; environ 0,8 Go de mémoire résidente pour une session MCP.

Résultats

Détecteur v3 contre règle v2, même exécution de recherche (CPU)

MesureAvantAprès
Abstention précision / rappel (90 questions)0,81 / 0,450,95 / 0,79
Rappel d’abstention, 40 questions sans réponse inédites0,480,83
Abstentions à tort52
Rappel@3 (90 questions)0,760,81
Rappel@3, 15 questions d’origine0,750,83
Injections paraphrasées signalées0 / 3016 / 30
Faux positifs en quarantaine (931 passages réels)00
Latence p50 (banc de 80 requêtes)1 012 ms618 ms (6 ms en cache)

Seuils choisis uniquement sur le jeu de mise au point, puis gelés. Protocole strict : une abstention à tort est comptée comme une erreur.

Jeu de test gelé (40 questions, CPU) : v0 du 18/10 contre v2 du 20/10

Mesurev0v2
Rappel@10,330,67
Source dans le top 5 (sans abstention)0,440,93
MRR0,360,70
Pièges d’injection signalés0/66/6
Passages en quarantaine servis00

Livrables 4

  • Interface web (recherche, évaluation), API et serveur MCP stdio en lecture seule.
  • Configuration Claude Desktop prête à coller.
  • Protocole gelé (90 questions de test, dont 40 sans réponse jamais vues), résultats et analyse par question.
  • 60 tests ; scanner : 0 faux positif en quarantaine sur 931 passages réels, 16 / 30 injections paraphrasées signalées.

Environnement

Matériel et conditions de mesure

  • Tout tourne sur CPU, modèles en cache local, environ 0,8 Go de mémoire résidente par session MCP : le service cohabite avec les travaux GPU.
  • Latence p50 de 618 ms avec reclassement sur CPU, 6 ms pour une requête en cache ; plus rapide sur GPU.

Reproduire commandes du README

Code privé : accès en lecture sous accord de confidentialité, ou démo en direct de 30 minutes. Demander l’accès →

.venv/bin/atelier index
.venv/bin/atelier search "Comment RELAIS revient-il en arrière ?" -k 3
.venv/bin/atelier eval verifier
.venv/bin/atelier eval tester
.venv/bin/atelier serve
.venv/bin/atelier mcp
.venv/bin/python -m pytest
  • Interface sur 127.0.0.1:8341 ; tout tourne sur CPU, modèles en cache local.
  • Si le corpus change, les seuils se recalibrent sur le jeu de mise au point.

Galerie 3

Abstention : un terme absent de tout le corpus, pas d’invention ; les passages les plus proches restent visibles pour inspection.
Trois documents piégés correspondent à la question : signalés, jamais servis comme réponse.
La page d’évaluation : avant et après sur le même jeu de test gelé.

Ce que ce projet change pour vous

Le même savoir-faire, sur votre sujet.

01

Une base de connaissances qui cite

Vos procédures et documents interrogeables par vos assistants, chaque réponse avec fichier et lignes, et une abstention plutôt qu’une invention.

02

Résister aux documents piégés

Un document qui contient des consignes cachées est mis de côté et signalé, jamais servi à l’assistant.

03

Mesurer avant de déployer

Un jeu de questions écrit avec vos équipes et gelé : vous connaissez l’effet de chaque version avant la mise en service.