Bot WhatsApp
RAG par matière (10 x)
Voici un module RAG par matière prêt à implémenter (10 matières). Je détaille le pipeline, les paramètres conseillés, les schémas, et un pseudo-code minimal.
1) Ingestion → Normalisation → Chunking → Embeddings → Index
A. Ingestion & normalisation
- Formats : PDF, DOCX/PPTX, HTML, YouTube (transcriptions), MOOC (chapitrage), images (OCR).
- Nettoyage : suppression en-têtes/pieds, numéros de page, menus, bruit OCR, figures → légendes.
- Structuration : détection titres (H1–H3), paragraphes, listes, tableaux → JSON hiérarchique.
- Langues : FR/MG détectées et taguées (lang: fr|mg).
Schéma document (niveau fichier)
doc_id, matiere_id, titre, auteurs, source, type_doc (fiche_TP|video|mooc|faq), chapitre, niveau(L1/L2/L3), date_pub, version, lang, url_source, droits
B. Chunking (granularité contextuelle)
- Stratégie : titre → section → paragraphe avec chevauchement.
- Taille : 500–1 200 tokens (conseil : 800 de base, overlap 120).
- Fenêtres hiérarchiques : concat des titres parents (breadcrumb) en prefix.
- Tables : extraire en texte structuré (CSV-style) + joindre au chunk parent.
Schéma chunk
chunk_id, doc_id, matiere_id, chapitre, lang, text, tokens, breadcrumb("TP Irrigation > Pose des lignes"), position(section_idx, para_idx), quality_flags(ocr_ok|table_extracted|code_snippet), ts_video_start, ts_video_end # si vidéo
C. Embeddings
- Modèle : multilingue FR/MG (dimension 768–1024).
- Normalisation : L2 sur vecteurs, lowercasing, strip accents (pour BM25 hybride).
- Stockage : embedding (float[]), norm (float), text compressé (zstd).
D. Index vectoriel (1 collection par matière)
- 10 collections : vec_irr, vec_mar, vec_sol, …
- Moteur : pgvector / Qdrant / Weaviate (au choix).
- Clés : (matiere_id, chunk_id) + index HNSW (M=32, ef_construction=200).
- Hybridation : champ BM25 (ou tsvector) pour lexico-sémantique.
2) Recherche : Retriever (top-k) → Re-ranker → Contexte
A. Retriever (candidat initial)
- Requête : embedding(question) + filtres (matiere_id, chapitre/semaine, langue).
- Top-k : k=30 (vectoriel cosine) + k_lex=20 (BM25).
- Fusion : Reciprocal Rank Fusion (RRF) → liste 40 ±.
B. Re-ranker (cross-encoder)
- Modèle léger (≤110M) multilingue.
- Entrée : (question, passage).
- Sortie : score de pertinence.
- Garde-fous : priorité aux chunks avec citabilité (présence de page/ts vidéo).
C. Contexte final
- Top-n pour LLM : n=6 (≈ 3 000–4 500 tokens cumulé).
- Dé-dupliquer par doc_id.
- Diversité : OdoLearn + YouTube + MOOC si possible (au moins 2 sources).
3) LLM génératif → Réponse structurée + citations
A. Gabarit de prompt (résumé)
- Rôle “Prof de TP agricole”, pas de théorie, étapes actionnables.
-
Structure de sortie :
- Objectif du TP (1 phrase)
- Matériel (liste courte)
- Étapes pas-à-pas (numérotées)
- Contrôles/erreurs fréquentes
- Sécurité (1–2 points)
- Sources (citations ancrées)
- Pour aller plus loin (1 vidéo, 1 séquence MOOC)
B. Citations (obligatoires)
-
2–5 références minimum, format ancré :
- OdoLearn : OdoLearn: <titre_fiche>, p. X
- YouTube : YouTube: <chaîne>, mm:ss
- MOOC : MOOC: <cours>, chap. X.Y
- Rejeter la génération si 0 source trouvée (demander reformulation).
C. Style & langues
- FR simple; option MG via traduction contrôlée (glossaire).
- Limiter température (0.2–0.4) pour stabilité.
4) Performance & Cache
- Latence cible : Retriever ≤ 120 ms, Re-ranker ≤ 350 ms, LLM ≤ 2.5 s (p95 ≤ 4–6 s global).
-
Caches :
- Embedding de requêtes fréquentes (LRU 2 000).
- Réponses FAQ par matière (clé = hash(question_norm)).
- Chunks chauds (top hits hebdo).
5) Qualité & Sûreté
- Vérifs automatiques : anti-hallucination (vérifier que chaque fait clé a une source parmi les passages).
- Règles examen : si détecté, fournir méthode sans solution complète.
- Versionnage : doc_id@v dans citation pour traçabilité.
6) Évaluation continue
- RAGAS / Faithfulness : ≥ 0.85.
- Citation hit-rate : la source citée ∈ top-k retriever ≥ 0.95.
- Coverage chapitre : questions → chapitres actifs.
- Human-in-the-loop : revue enseignant sur 2% des interactions.
7) Tables (format texte simple)
docs_matiere
doc_id | matiere_id | type_doc | titre | chapitre | version | lang | url | date_pub
chunks_matiere
chunk_id | doc_id | matiere_id | text | tokens | breadcrumb | pos | ts_start | ts_end | emb_vector
index_params
matiere_id | engine | metric | M | ef_const | ef_runtime | bm25_enabled IRR | HNSW | cosine | 32| 200 | 128 | true
8) Pseudo-code (Python-like)
def build_index(matiere_id, docs): for doc in docs: clean = normalize(doc) sections = segment(clean) # titres H1-H3, tableaux -> texte chunks = chunk(sections, size=800, overlap=120) for ch in chunks: emb = embed(ch.text) upsert_vector(matiere_id, ch, emb) optimize_index(matiere_id) # HNSW params, bm25 def retrieve(question, matiere_id, filters=None): q_emb = embed(question) v_hits = knn_search(matiere_id, q_emb, k=30, filters=filters) l_hits = bm25_search(matiere_id, question, k=20, filters=filters) candidates = rrf_merge(v_hits, l_hits) reranked = cross_encoder_rank(question, candidates) # top-40 → top-12 context = diversify_by_doc(reranked, n=6) # OdoLearn/YouTube/MOOC return context def generate_answer(question, context, lang='fr'): prompt = compose_prompt_prof_TP(question, context) answer = llm(prompt, temperature=0.3) if not has_min_citations(answer): return ask_clarify() if lang == 'mg': answer = translate_fr_to_mg(answer, glossary='agri') return answer
9) Paramètres par défaut (départ)
- Chunk size 800 tokens (overlap 120)
- Top-k 30 (vec) + 20 (BM25) → re-rank top-40 → garder 6
- HNSW M=32, ef_build=200, ef_search=128
- Re-ranker cross-encoder petit, seuil confiance 0.55
- LLM temp 0.3, longueur max 700–900 tokens (WhatsApp-friendly)
10) Bonnes pratiques
- Toujours inclure l’ID de version dans la citation.
- Forcer diversité des sources (au moins 2 types).
- Breadcrumb dans chaque chunk pour contextualiser les étapes de TP.
- Sur vidéo, timestamp précis (±5 s) dans la réponse.
- Journaliser requête → passages → citations pour audit pédagogique.
exemple d’implémentation FastAPI (endpoints /ingest, /query) et un gabarit de prompt “Prof de TP agricole”
je peux vous livrer un exemple d’implémentation FastAPI (endpoints /ingest, /query) et un gabarit de prompt “Prof de TP agricole” prêt à copier-coller.