From 9ef74547ce0904cc3508bcfa6baa41ce9047cb25 Mon Sep 17 00:00:00 2001 From: grgmro Date: Thu, 17 Sep 2026 10:02:14 +0200 Subject: [PATCH] Docs: condense model = qwen3:30b MoE + section 'why a MoE on a modest iGPU' --- docs/rag/DESIGN.md | 7 ++++--- docs/rag/PIPELINE.md | 21 ++++++++++++++++++++- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/docs/rag/DESIGN.md b/docs/rag/DESIGN.md index b435837..ade2e7b 100644 --- a/docs/rag/DESIGN.md +++ b/docs/rag/DESIGN.md @@ -186,7 +186,7 @@ d'entrée embed (1024 vs 4096), seuil de filtre titre, taille fenêtre. | D7 | 14/09/2026 | G (routing par taille) rejeté | Mesuré à l'échelle (796) : dégrade MRR vs fusion libre | | D8 | 14/09/2026 | Abstention/scope : zone graduée sur score CE (pas de seuil dur) + gate d'entrée déterministe + clause de refus dans le prompt | Aucun seuil ne sépare proprement in-domain/hors-sujet (distributions qui se chevauchent) — voir SAFETY.md | | D9 | 17/09/2026 | **Pas de LangChain** — patterns repris sans la dépendance | Voir §9 | -| D10 | 17/09/2026 | Réécriture de requête multi-tour via modèle dédié léger (`condense_query`, llama3.1:8b) — repli sur le message brut si indispo | Retrieval ne voyait que le dernier message ; bug réel observé en usage (17/09). Modèle non-thinking choisi exprès (qwen3:4b engloutit son budget dans le champ `reasoning`) | +| D10 | 17/09/2026, **révisée même jour** | Réécriture de requête multi-tour (`condense_query`) via **`qwen3:30b-a3b-q6k`** — le LLM principal, pas un modèle dédié | Retrieval ne voyait que le dernier message ; bug réel observé en usage. Première mouture `llama3.1:8b` (qwen3:4b engloutissait son budget dans `reasoning`) ; test comparatif → le MoE (~3B actifs) condense en ~1.0s vs 1.6s, qualité égale, **un modèle résident de moins** en RAM. `think:false` forcé dans la requête (garde-fou thinking, ignoré sans erreur par les non-thinking) | ## 9. Stack : pourquoi pas LangChain (et ce qu'on en retient) @@ -213,8 +213,9 @@ concept : **Ce qu'on a quand même repris de ce monde** : la **réécriture de requête conversationnelle** (pattern *condense question* / *history-aware retriever* de LangChain, et littérature QReCC/CANARD) — implémentée dans -`Retrieval.condense_query` avec un petit modèle dédié : le dernier message + -les 3 tours précédents → une requête autonome avant embedding. +`Retrieval.condense_query` : le dernier message + les 3 tours précédents → +une requête autonome avant embedding. Le modèle qui réécrit est **le même +Qwen3-30B que la génération** (D10) — voir PIPELINE.md « pourquoi un MoE ». ## 8. Questions ouvertes — état diff --git a/docs/rag/PIPELINE.md b/docs/rag/PIPELINE.md index e971aa5..7df7252 100644 --- a/docs/rag/PIPELINE.md +++ b/docs/rag/PIPELINE.md @@ -52,9 +52,28 @@ Sanitizer serveur : [[n]] → URLs /t/slug/id ← liens générés côté serve |---|---|---|---| | **bge-m3** | bi-encoder (embedding) | texte → vecteur 1024-dim. Encode chaque post **une fois** (backfill) et chaque question **à la volée** | Ollama — RTX 2060 laptop en dev ; Ollama mini PC `:32134` en prod | | **cross-encoder mmarco-mMiniLMv2-L12-H384** | cross-encoder | score de pertinence d'une **paire** (question, candidat) — lit les deux ensemble | dev : `sentence-transformers` CPU laptop ; **prod : TEI `/rerank` sur le mini PC** (pod k3s `reranker`, NodePort 32136, Tailscale only) | -| **LLM chat** | génératif | rédige la réponse à partir des 6 sources fournies | mini PC | +| **LLM chat `qwen3:30b-a3b-q6k`** | génératif (MoE ~3B actifs) | rédige la réponse à partir des 6 sources fournies **+** réécriture de requête multi-tour (`condense_query`, `think:false`) | mini PC (Ollama `:32134`) — **un seul modèle résident** pour les deux rôles | | Postgres/pgvector | — | stockage + distance cosine/hamming | conteneur Discourse (VPS en prod) | +### Pourquoi un MoE 30B sur un iGPU modeste — le choix structurel + +La iGPU 780M du mini PC n'a **pas de VRAM dédiée** : les poids vivent dans +la RAM unifiée (GTT, plusieurs dizaines de Gio). Deux conséquences : + +- **Capacité** : un 30B quantifié (~20+ Gio) tient là où une dGPU du même + format plafonnerait à 8-16 Go de VRAM — le facteur limitant n'est pas la + VRAM mais la RAM système, dont on a 48 Go. +- **Vitesse** : l'inférence sur iGPU est **bound par la bande passante + mémoire** (chaque token relit les poids actifs). Un MoE n'active que + ~3B paramètres par token → le débit reste élevé malgré la taille totale + du modèle. Mesuré : réécriture de requête en **~1.0 s** à chaud vs 1.6 s + pour un llama3.1:8B dense — le « gros » modèle est plus rapide que le + petit, **parce qu'il est MoE**. + +C'est pourquoi la réécriture de requête a basculé de `llama3.1:8b` vers le +LLM principal (D10, 17/09) : plus rapide, qualité égale ou meilleure, et un +modèle résident de moins à garder chaud en RAM. + ### Bi-encoder vs cross-encoder — pourquoi les deux Ce ne sont **pas des concurrents** mais deux étages complémentaires :