feat(stt-server): grounding RAG — le cerveau répond depuis la doc Funk (#27)

Sans contexte, le modèle (qwen3-8b) hallucinait sur le homelab (« stockage
décentralisé », « worker nodes »…) car il ignore tout du cluster réel. Le
cerveau interroge désormais la collection funk-docs (la doc admin/ indexée) et
injecte les passages pertinents au prompt → il répond à partir de la vraie doc.

Coût ~nul : funk-docs et stt-memory partagent le même embedder nomic (:1238,
768 dim) → le vecteur de requête calculé pour le recall mémoire est réutilisé
pour la recherche doc (une embed, deux recherches). Dégrade en silence si
Qdrant/embed down (réponse sans doc plutôt qu'échec).

Module knowledge.py (STT_DOCS_RAG, TOPK=6, MIN_SCORE=0.45). Log /v1/ask
expose docs=<n>. Serveur 0.2.1 → 0.3.0.

Validé : « c'est quoi le nom des nœuds ? » → avant « worker/master nodes »
(inventé) ; après « Kubernetes ; nœuds storage-01, compute-01, compute-02 »
(tiré de la doc).

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
ALI YESILKAYA 2026-06-19 21:53:30 +02:00 committed by GitHub
parent 767a94b1d0
commit 1db84e9041
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 132 additions and 6 deletions

View file

@ -120,6 +120,20 @@ au prompt système (`STT_DISABLE_THINKING`, défaut `true` ; inoffensif hors Qwe
espace). Aucun drop manuel — la collection est reconstruite à la première requête après bascule.
- **Réparation Qdrant (5c, fait)** : crash-loop depuis 05/06 (segment `funk-docs` corrompu).
Réparé le 17/06 sur s01 : `systemctl stop qdrant && rm -rf /srv/data/qdrant/storage/collections/funk-docs && systemctl start qdrant`.
- **RAG documentaire / grounding (5f, fait)** : le cerveau interroge aussi la collection
**`funk-docs`** (la doc `admin/` indexée) et injecte les passages pertinents au prompt → il
répond **à partir de la vraie doc du homelab** au lieu d'halluciner des généralités (« stockage
décentralisé », « worker nodes »…). Module `stt_server/knowledge.py`, activé par `STT_DOCS_RAG`.
- **Coût ~nul** : `funk-docs` et `stt-memory` partagent le **même embedder** (`nomic-embed-text`
`:1238`, dim 768) → le vecteur de requête calculé pour le recall mémoire est **réutilisé** pour
la recherche doc (une seule embed, deux recherches Qdrant). Dégrade en silence (réponse sans
doc si Qdrant/embed down).
- **Réglages** : `STT_DOCS_TOPK` (6), `STT_DOCS_MIN_SCORE` (0.45), `STT_DOCS_TIMEOUT` (4 s),
`STT_DOCS_COLLECTION` (`funk-docs`). Le `funk-docs` doit être ingéré (`rag-ingest`) **avec le
même modèle** nomic — sinon dimensions incompatibles (cf. rôle `rag`).
- **Validé** : « c'est quoi le nom des nœuds ? » → sans RAG « worker/master nodes » (inventé) ;
avec RAG « Kubernetes ; nœuds storage-01, compute-01, compute-02 » (tiré de la doc). Le log
`/v1/ask` expose `docs=<n>` (nb d'extraits injectés).
> ⚠️ **Vie privée** : seule la mémoire distillée serait committée. Repo privé impératif.
@ -242,6 +256,7 @@ optionnel — son absence n'empêche rien.
| **5c — Réparation Qdrant** | drop `funk-docs` corrompu + restart (s01) | ✅ (17/06) |
| **5d — Embeddings dédiés** | `nomic-embed-text` (dim 768) sur gpu-01 `:1238` → recherche plus précise | ✅ (rôle llama_server + migration auto collection) |
| **5e — Fix thinking Qwen3** | `/no_think` (content vide / timeout 502) + fallback reasoning_content | ✅ (17/06) |
| **5f — RAG documentaire (grounding)** | le cerveau interroge `funk-docs` (doc `admin/`) et injecte les passages au prompt → répond depuis la vraie doc au lieu d'halluciner ; réutilise le vecteur nomic du recall | ✅ (`knowledge.py`, `STT_DOCS_RAG`) |
| **6 — Auto-start client** | `stt --install-service` (systemd --user, `graphical-session.target`) + kiosk | ✅ (à tester sur poste) |
| **7 — Outils Hermes** | « agir sur Funk » via gateway `:8080` (API à spécifier) | ⏳ |