2) Architecture de référence (production)
Chaîne de valeur complète : Sources → Ingestion → Chunking → Embeddings → Index → Retrieval → Rerank → Contexte → LLM avec Guardrails, Citations, Observabilité et Cache.
Ingestion/OCR Chunking structurel Embeddings Index vecteur + BM25 Retrieval filtré Rerank Guardrails Observabilité Cache
Vue d’ensemble — architecture de référence
Schéma (ASCII)
[Sources] → [Ingestion & Parsing] → [Chunking] → [Embeddings] → [Vector DB]
↑ (OCR, PDF, HTML, DOCX) ↓
└─────────────── enrich. métadonnées ────────────→ [BM25 Index]
User Q → [Rewrite/Decompose] → [Retrieve (k)] → [Re-rank] → [Context Builder] → [LLM]
↑
[Policies/Guardrails]
↓
[Citations/Attributions]
↓
[Eval · Telemetry · Cache]🚦 Latence cible (p95)
- Rewrite + Retrieval (k ≤ 20) : 300–800 ms
- Rerank (3–6 passages) : 200–600 ms
- LLM génération (200–600 tok) : 1–3 s
📏 KPIs essentiels
- Hit@k, nDCG@k (pertinence)
- Taux de citation valide
- Latency p95, coût/req
⛔ Anti-patterns
- Chunking fixe sans structure → contexte hors-sujet.
- Index vecteur seul sans BM25 pour les mots rares.
- Pas de guardrails (fuites PII / hors périmètre).
Ingestion & OCR — extracteurs fiables
📥 Formats
- PDF (text + images), HTML, DOCX, MD, PPTX
- Confluence, SharePoint, GDrive
- OCR pour scans (Tesseract, cloud OCR)
🧹 Nettoyage
- Supprimer pieds de page, entêtes, numéros
- Détecter langue, extraire titres H1–H3
- Normaliser espaces, listes, tableaux
🏷️ Métadonnées
- app, produit, version, auteur, date, langue
- confidentialité (public/interne/secret)
- url_source, checksum, timestamp
Contrat d’extraction (extrait)
{
"doc_id":"uuid", "lang":"fr", "title":"Guide SSO",
"sections":[{"h":"H2","title":"Prerequis","text":"..."}, ...],
"meta":{"product":"WebApp","version":"4.2","conf":"internal"}
}Chunking structurel — pas “bête”
🔪 Principes
- 400–1 200 tokens, overlap 10–20 %
- Scinder par titres/sections/tableaux
- Garder les légendes/équations avec le texte
🧭 Heuristiques
- Éviter de couper une liste numérotée
- Inclure le parent (H2/H3) en header
- Encoder les méta dans le chunk (lang, conf, produit)
📦 Exemple de chunk
CHUNK#42 (lang=fr, product=WebApp, section="SSO/Prerequis")
"Pour activer SSO, configurez OpenID avec scopes: email, profile..."
Citations: ["guide_sso.pdf#p3", "oidc.md#prerequis"]Embeddings — projection vectorielle
🎯 Choix
- Multilingue vs mono-langue
- Coût/latence vs qualité
- Dimension (384–1 536+)
🧪 Bonnes pratiques
- Normaliser (L2) si l’index l’exige
- Batcher et paralléliser
- Cache des embeddings par
hash(chunk)
🔐 Métadonnées stockées
- doc_id, section, langue, conf
- timestamp, version d’index
- score qualité (optionnel)
Index — HNSW / IVF + BM25 (hybride)
🗃️ Vecteur
- HNSW (m, efConstruction, efSearch)
- IVF-PQ (nlist, nprobe, codebook)
- Filtres: post-filtering par méta
🔤 Lexical (BM25)
- Gère mots rares / codes / numéros
- Fusion scores:
α·score_vect + (1-α)·score_bm25 - Poids α typique: 0.6–0.8
Config (extrait)
{"index":"hnsw","dim":768,"ef_search":64,"m":32,"hybrid":{"bm25":true,"alpha":0.7}}Retrieval — top-k & filtres de métadonnées
🔎 Paramètres
- k = 10–20 (selon densité des chunks)
- Filtres: langue, date, produit, version, conf
- Boost récence (decay) optionnel
🎛️ Requête
{
"q": "Activer SSO Azure AD",
"filters": {"lang":"fr","product":"WebApp"},
"k": 16, "hybrid": true
}Rewrite & Decomposition — améliorer la requête
✍️ Rewrite
- Expandir abréviations (“AD” → “Active Directory”)
- Ajouter contraintes implicites (langue, version)
- Supprimer bruit (“stp”, “urgent”)
🔪 Decomposition
- Diviser question complexe en sous-questions
- Multi-hop retrieval (séquentiel)
- Composer les réponses partielles
Re-ranking — cross-encoder
🎯 Rôle
- Ré-ordonner les passages candidats
- Garder top 3–6 de haute qualité
- Améliorer précision des citations
⚙️ Paramètres
- max_len passage (ex. 512–1024 tok)
- batch 8–32, parallélisme
- timeout (p95) 200–600 ms
Context Builder & Prompting
🧱 Construction du contexte
- Assembler 3–6 passages rerankés
- Inclure titres, liens, sources
- Dé-dupliquer & compresser
🧩 Format sortie
{"context":[{"title":"SSO","url":"...#p3","text":"..."}],
"must_cite": true, "style":"concise", "language":"fr"}🗞️ Prompt
SYSTEM: Réponds uniquement avec les passages fournis. Cite les sources.
USER:
CONTEXT:
Guardrails & Policies — sécurité, PII, périmètre
🔐 Filtrage
- RBAC sur les métadonnées (confidentialité)
- Redaction PII (masking, hashing)
- Domaines autorisés (whitelist)
🧯 Refus utiles
- Hors périmètre documentaire
- Questions personnelles/PII interdites
- Absence d’info → “je ne sais pas” + liens
📚 Citations
- Afficher titre, URL, horodatage
- Score de pertinence & passage surligné
- Permet la vérification humaine
Observabilité — logs, traces, qualité
📊 Télémétrie
- Events : rewrite, retrieve, rerank, llm, cite
- Latence, tokens, coûts, erreurs
- Traces corrélées (trace_id)
🧪 Évaluation
- Golden set (questions → docs attendus)
- Hit@k, nDCG, factualité/citation rate
- Feedback humain (👍/👎 + commentaire)
Événement (extrait)
{"event":"rerank","k_in":20,"k_out":5,"lat_ms":220,"model":"cross-encoder-v1","trace_id":"..."} Cache — réponses & embeddings
🧠 Caches
- Embeddings : clé =
hash(chunk)+ ver d’encodeur - Réponse : clé = (
q_norm, filtres, ver_index) - Expiration par TTL & invalidation par version
⚙️ Exemple clé
key = sha1(f"{norm(q)}|{sorted(filters)}|{index_ver}|{prompt_ver}").hexdigest()Astuce : stocker aussi le trace_id pour rejouer une réponse.
