1) Cadrage & KPIs — RAG
Objectifs métier, périmètre des sources, KPIs & critères d’acceptation, conformité (GDPR/PII), livrables de cadrage.
Objectifs & périmètre KPIs & acceptation GDPR/PII Livrables
Mise en Œuvre des Outils
Choix techniques, paramétrage et pipeline de référence pour construire le RAG.
1) Cadrage (Jours 1–3)
Objectifs métier (à saisir)
- Use cases : FAQ RH, support IT, docs techniques, juridique…
- Types de questions : factuelles, procédures, “how-to”, code.
- Langues : fr, en (détection + réponse dans la langue).
- Latence cible : P95 ≤ 1.5 s (retrieval + génération).
- Coûts : ≤ €0.01 / requête (RAG + LLM compact de base).
- Périmètre des sources : PDF/HTML, Confluence/Notion, S3, DB.
- Contraintes : on-prem / cloud, PII, logs 90j, RBAC.
Formulaire (exemples de champs)
| Champ | Exemple |
|---|---|
| Use cases prioritaires | Support interne IT, politiques RH, guide SSO |
| Utilisateurs | Employés (RBAC BU/Role), partenaires |
| Volumétrie | 30k docs, 200 req/h, pics 30 rps |
| Langues | fr, en |
| Contraintes | On-prem, pas de PII en clair, rétention 90j |
Tip : consigner les décisions clés en ADR (Architecture Decision Records).
Backlog initial (EPICs → US)
- EPIC Ingestion : connecteurs, nettoyage, OCR, chunking.
- EPIC Index : embeddings, vector DB, hybrid BM25.
- EPIC RAG API : retrieve→rerank→context→LLM→post-process.
- EPIC Observabilité : traces, coûts, qualité.
- EPIC Sécurité/Conformité : RBAC, PII, purge.
ADR à rédiger
- Choix Vector DB (pgvector vs FAISS vs service managé).
- Modèle d’embeddings (open-source vs API).
- Reranker (cross-encoder) vs top-k plus large.
Retrieval (qualité)
| Mesure | Seuil cible | Notes |
|---|---|---|
| hit@5 | ≥ 0.85 | Rappel initial (hybride BM25 + dense) |
| MRR | ≥ 0.65 | Qualité du ranking |
| nDCG@10 | ≥ 0.80 | Pertinence globale top-10 |
Performance
| Mesure | Seuil |
|---|---|
| Latence P50 | ≤ 700 ms |
| Latence P95 | ≤ 1.5 s |
| Coût / 1k req | ≤ €8 (RAG + LLM compact) |
Q&A (réponse)
| Mesure | Seuil | Notes |
|---|---|---|
| Exact-Match | ≥ 0.75 | FAQ / QCM |
| F1 | ≥ 0.80 | Réponses libres courtes |
| Faithfulness | ≥ 95% | Pas de contenu hors contexte |
Acceptation : passage si toutes les métriques ≥ seuils et aucun critère “bloquant”.
GDPR – Base légale & minimisation
- Documenter la base légale (contrat, intérêt légitime, consentement).
- Minimisation : champs strictement nécessaires.
- Cartographier sources & catégories de données.
PII – Masquage & rétention
- Masquage à l’ingestion (hash email, pseudonymisation).
- Rétention : logs 90j, index 365j (à adapter).
- Droit à l’oubli : purge document + chunks + embeddings.
Traçabilité & audit
- Journaliser : source_id, version, hash, last_modified, user_id.
- Filtrage RBAC au retrieval (claims utilisateur en métadonnées).
- DPA fournisseurs, registre des traitements.
Liste des livrables
- Document de cadrage (objectifs, périmètre, risques, jalons).
- Backlog EPICs/US (ingestion, index, RAG API, observabilité, sécurité).
- Protocole d’évaluation (golden set, métriques, seuils, procédure).
- Plan de conformité (GDPR/PII, rétention, purge, registre).
Contrat JSON (exportable)
{
"project":"RAG - Projet",
"objectives":{
"question_types":["FAQ","procédures","code"],
"precision":{"EM":0.75,"F1":0.80},
"languages":["fr","en"],
"latency_ms":{"p50":700,"p95":1500},
"cost_eur_per_req_max":0.01,
"sources":["PDF","HTML","Confluence","DB","S3"]
},
"kpis":{
"retrieval":{"hit@5":0.85,"mrr":0.65,"ndcg@10":0.80},
"qa":{"exact_match":0.75,"f1":0.80,"faithfulness":0.95},
"performance":{"p50_ms":700,"p95_ms":1500,"cost_per_1k_req_eur":8}
},
"compliance":{
"gdpr_legal_basis":"contract",
"pii_masking":true,
"retention":{"logs_days":90,"index_days":365},
"rbac_filters":["business_unit","role"]
},
"deliverables":["doc_cadrage","backlog_epics_us","eval_protocol","compliance_plan"]
}Utilise “Copier JSON” (en haut) pour récupérer ce contrat.
Checklist d’entrée (DoR)
- Sources listées + accès validés (lecture seule).
- Langues cibles décidées + stratégie de fallback.
- Seuils KPIs validés par le métier.
- Contraintes infra (on-prem/cloud) figées.
Checklist de sortie (DoD)
- Document de cadrage signé.
- Backlog EPICs/US priorisé (S1→S4).
- Golden set v1 versionné.
- Plan GDPR/PII approuvé + DPA si SaaS.
Risques & parades (exemples)
| Risque | Impact | Parade |
|---|---|---|
| Accès sources retardé | Moyen | Mock datasets + connecteurs offline |
| PII non maîtrisées | Élevé | Masquage ingestion + revue légale |
| KPIs trop ambitieux | Moyen | Ablations rapides + itérations seuils |
| Coûts LLM | Moyen | Modèles compacts + cache + streaming |
Mise en Œuvre des Outils (Jours 2–7)
Connecteurs & normalisation
- PDF/Office/HTML : parseur + nettoyage (titles, H1–H3, tables).
- OCR (si besoin) : Tesseract/PaddleOCR (qualité > 90%).
- Metadata : source_id lang tags[] rbac last_modified hash
- Lang detect + normalisation Unicode + trim espaces.
Chunking (réglages initiaux)
- Taille : 600–900 tokens • Overlap : 80–120 • Hiérarchie H1–H3 en contexte parent.
- Compression “passage” optionnelle (réécriture courte pour index).
Exemple (pseudo-code Python)
# ingest.py
for doc in scan_sources():
text, meta = parse(doc) # PDF/HTML/Confluence/DB...
lang = detect_lang(text)
for chunk in chunker(text, size=800, overlap=100, titles=meta.hierarchy):
yield {
"id": hash(chunk), "text": chunk,
"meta": {**meta, "lang": lang, "rbac": meta.get("rbac", [])}
}Embeddings (choix)
- API / hébergé : modèle “small/medium” multilingue pour coûts & latence.
- Open-source : encoders type bge-small / e5-base selon langues.
- Dimension 384–1024 ; L2-norm conseillée.
Vector DB
- pgvector (PostgreSQL) : simple, RBAC SQL, back-up natif.
- FAISS : rapide on-disk/memory pour PoC, simple à servir.
Schéma (pgvector)
-- PostgreSQL
CREATE EXTENSION IF NOT EXISTS vector;
CREATE TABLE rag_chunks(
id TEXT PRIMARY KEY,
text TEXT,
lang TEXT,
meta JSONB,
embedding VECTOR(768) -- adapter à la dimension réelle
);
CREATE INDEX ON rag_chunks USING ivfflat (embedding vector_l2_ops) WITH (lists = 200);
CREATE INDEX ON rag_chunks ((meta->>'rbac'));
CREATE INDEX ON rag_chunks ((meta->>'source_id'));Ingestion → embeddings → upsert
# index.py
from db import upsert_chunk, embed
for item in ingest():
vec = embed(item["text"]) # retourne une liste[float]
upsert_chunk(id=item["id"], text=item["text"], meta=item["meta"], emb=vec)Paramètres clés
- k initial = 50 (hybride), 200 si corpus hétérogène.
- lists (IVF) = 200–400 (selon taille corpus).
- Quantization (INT8/OPQ) si > 5M chunks.
Hybrid Retrieval
- BM25 (Full-text) ∪ Vecteur (kNN) → union & dédup.
- Filtres : lang == user.lang rbac ∈ user.claims date >= cutoff
- Rerank cross-encoder si top-k > 20 pour augmenter la précision.
Ex. requête (pgvector + fulltext)
-- pseudo-SQL
WITH dense AS (
SELECT id, text, meta,
1 - (embedding <=> :qvec) AS score_d
FROM rag_chunks
WHERE (meta->>'lang') = :lang
AND (meta->>'rbac') ?| :claims
ORDER BY embedding <=> :qvec
LIMIT 50
),
sparse AS (
SELECT id, text, meta,
ts_rank_cd(to_tsvector(text), plainto_tsquery(:q)) AS score_s
FROM rag_chunks
WHERE to_tsvector(text) @@ plainto_tsquery(:q)
LIMIT 50
)
SELECT * FROM (
SELECT *, score_d * 0.6 AS s FROM dense
UNION
SELECT *, score_s * 0.6 AS s FROM sparse
) u
ORDER BY s DESC
LIMIT 24;Rerank (cross-encoder)
# rerank.py (pseudo)
candidates = retrieve_hybrid(q, qvec)
scored = reranker.score_pairs([(q, c["text"]) for c in candidates])
top = [c for _, c in sorted(zip(scored, candidates), reverse=True)][:8]Context builder
- Fenêtrage par proximité (H1–H3) + dé-duplication par source.
- Citations (source_id, page, ancre) injectées dans la réponse.
Gabarit de prompt (RAG)
System:
Tu es un assistant qui répond UNIQUEMENT à partir du contexte fourni.
Si l'info manque, réponds "Je ne sais pas" + propose une piste.
User:
Question: {{question}}
Contexte (passages citables):
{{#each passages}}
- [{{this.source_id}}] {{this.text}}
{{/each}}
Réponse attendue:
- Brève, exacte, avec citations [source_id] si possible.
- Langue: {{lang}}
Post-process
- Validation JSON (si format structuré).
- Filtre “answer or I don’t know”.
- Ajout des citations & scores.
Paramètres
- temperature : 0.1–0.3 (réponses précises).
- max_tokens : 300–800 selon use case.
- top_p : 0.9 ; presence / frequency penalty = 0.
Citations obligatoires
Refuser poliment si aucune source fiable n’est trouvée dans le contexte.
Traces & métriques
- OpenTelemetry : spans par étape (ingest, embed, kNN, rerank, LLM).
- KPIs : hit@k, MRR, nDCG, P50/P95, coût/req, rate “I don’t know”.
- Feedback UI : up/downvote + champ libre (stockage structuré).
Ex. payload de trace
{
"trace_id":"...",
"spans":[
{"name":"retrieve_hybrid","duration_ms":120,"k":24,"filters":["rbac","lang"]},
{"name":"rerank","duration_ms":65,"model":"cross-encoder"},
{"name":"llm","duration_ms":540,"prompt_tokens":680,"completion_tokens":190}
],
"cost_eur": 0.0064,
"answer":{"has_citations": true, "dont_know": false}
}RBAC & filtrage
- Stocker rbac (claims) dans métadonnées chunk.
- Filtrage au retrieval + au moment de l’affichage (défense en profondeur).
PII & secrets
- Masquage ingestion (regex/NER) + re-validation en sortie.
- Journaux signés & chiffrés pour accès sensible.
Garde-fous (guardrails)
- Policies “Input/Output/Tool/Context” (strict vs gracieux).
- Limites : max_ctx_len, max_passages, timeout_ms.
- Sanitisation SQL / URL / code avant outils.
