Funk-lab/admin/ia/rag.md
alkatrazz 34b235305b docs(cluster): aligne la doc sur l'état réel (relevé 2026-06-21) + snapshot
Passe de vérification terrain (SSH s01/g01 + kubectl) pour corriger les écarts
doc↔réalité, et ajout d'un document de référence vérifié.

- admin/ops/etat-cluster.md (nouveau) : snapshot daté — machines, services+ports
  par hôte, workloads k8s, namespaces, IngressRoute, bases PG, modèles LiteLLM,
  RAG/Qdrant, + procédure pour régénérer le relevé.
- OS AlmaLinux 9.7 → 9.8 (s01/g01) ; précise k8s v1.33.1 (CLAUDE/README/install/talos).
- RAG funk-docs : retire le warning périmé « supprimée 2026-06-17 / à re-ingérer » →
  reconstruite (436 chunks, nomic-embed-text :1238 dim 768, CPU). Maj rag.md,
  incidents.md, stt.md.
- Namespace sacrifice (hors-repo, hors ArgoCD) + bases PG grafana/sacrifice +
  services ai via IngressRoute + registry in-cluster (CLAUDE.md, k9s.md).
- Services de résilience (llm-heartbeat, llama-watchdog/embed) et instances CPU
  manuelles :1236/:1237 (souvent éteintes) documentés.
- Journal progress/2026-06-21.md : section relevé + RAG.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 22:47:33 +02:00

6.6 KiB
Raw Blame History

RAG — Documentation Funk

Opérationnel (relevé 2026-06-21) — funk-docs reconstruite après l'incident Qdrant du 2026-06-17 : 436 chunks, statut 🟢 green, embeddings nomic-embed-text (:1238, dim 768). rag-query fonctionne. Détails de l'incident : admin/incidents.md (entrée 2026-06-05).

Le RAG (Retrieval-Augmented Generation) permet à Hermes de répondre en s'appuyant sur la documentation du repo (admin/) plutôt que sur sa seule mémoire de modèle.


Architecture

Hermes (funk-ai)
  │  terminal: rag-query "comment relancer dnsmasq ?"
  ▼
/usr/local/bin/rag-query  (storage-01)
  │  1. Embed la question → POST http://192.168.10.20:1238/v1/embeddings (nomic-embed-text)
  │  2. Recherche vectorielle → POST http://127.0.0.1:6333/collections/funk-docs/points/search
  ▼
Qdrant  (storage-01:6333)
  │  Retourne les N chunks les plus proches sémantiquement
  ▼
rag-query affiche les extraits + fichier source + score
  │
  ▼
Hermes formule sa réponse en citant les sources

Composants déployés

Composant Emplacement Rôle
Qdrant storage-01:6333/6334 Base vectorielle — stocke les embeddings
rag-ingest /usr/local/bin/rag-ingest Indexe les docs dans Qdrant
rag-query /usr/local/bin/rag-query Interroge Qdrant depuis la ligne de commande
Skill rag-docs Profil funk-ai Hermes Enseigne à Hermes comment utiliser rag-query
Docs indexées /srv/data/rag/docs/ (NVMe) Copie locale du dossier admin/
Collection Qdrant funk-docs 436 chunks, 🟢 green, dim 768 Cosine (nomic-embed-text)

Modèle d'embedding utilisé

nomic-embed-text via l'instance dédiée llama-server llama-embed sur gpu-01 (:1238, CPU, dim 768). C'est un vrai modèle d'embedding — les scripts déployés rag-ingest et rag-query le hardcodent (EMBED_URL=http://192.168.10.20:1238/v1/embeddings, EMBED_MODEL=nomic-embed-text).

Historique : le RAG utilisait au départ Qwen3-8B (modèle de chat, :1234, dim 4096) réutilisé pour les embeddings → scores cosinus saturés (0.900.95), peu discriminants. La migration vers nomic (dim 768) étale les scores → tri par pertinence réel. La collection a été recréée à dim 768.

⚠️ Drift IaC : ansible/roles/rag/defaults/main.yml a longtemps gardé embed_url: :1234 / embed_model: qwen3-8b — variables mortes (le handler lance rag-ingest sans passer d'env → le défaut hardcodé nomic du script gagne). Aligné sur nomic dans le même lot que ce relevé.

L'instance llama-embed est gérée par le rôle llama_server (llama_embed_enabled, voir son README).

# (re)déployer l'instance embeddings sur gpu-01
ansible-playbook -i inventory.yml playbooks/gpu-01.yml --tags llama_server

Alternative envisagée

Modèle Taille Dimension Notes
nomic-embed-text ~274 MB 768 En service — rapide, bon équilibre qualité/taille
bge-m3 ~1.2 GB 1024 Multilingue (français natif) — option si la qualité FR doit monter

Utilisation

Via Hermes (funk-ai)

Le skill rag-docs est chargé dans le profil funk-ai. Hermes l'utilise automatiquement pour les questions sur le cluster :

# Dans le TUI Hermes :
"Comment je relance dnsmasq ?"
→ Hermes appelle rag-query en interne et cite les sources

En ligne de commande

# Depuis storage-01
rag-query "ma question"
rag-query "ma question" --top 3   # limiter les résultats (défaut: 5)

# Exemples
rag-query "comment relancer llama-server gpu"
rag-query "nftables firewall port cluster"
rag-query "hermes profils configuration"
rag-query "alertmanager webhook pipeline"
rag-query "monitoring grafana dashboard"

Mise à jour de l'index

L'index doit être re-généré après chaque modification de la doc admin/.

Via Ansible (recommandé)

cd ansible/
../.venv/bin/ansible-playbook -i inventory.yml playbooks/storage-01.yml --tags rag

Ansible synchronise admin/ vers /srv/data/rag/docs/ puis relance automatiquement rag-ingest (handler Ansible).

Manuellement

# Synchroniser les docs (depuis le poste perso)
rsync -av --delete admin/ storage-01:/srv/data/rag/docs/

# Ré-indexer (depuis storage-01)
ssh storage-01 "rag-ingest /srv/data/rag/docs/"

L'ingestion prend quelques minutes pour ~436 chunks (embeddings via l'instance nomic :1238, CPU). Elle est idempotente — re-lancer ne crée pas de doublons (IDs stables basés sur MD5 du fichier+section).


Administration Qdrant

# Collections existantes
curl -s http://storage-01:6333/collections | python3 -m json.tool

# Stats de la collection funk-docs
curl -s http://storage-01:6333/collections/funk-docs | python3 -m json.tool

# Nombre de points indexés
curl -s http://storage-01:6333/collections/funk-docs \
  | python3 -c "import sys,json; print(json.load(sys.stdin)['result']['points_count'])"

# Vider et re-créer la collection (si re-indexation propre nécessaire)
curl -s -X DELETE http://storage-01:6333/collections/funk-docs
rag-ingest /srv/data/rag/docs/

# Statut du service
ssh storage-01 "systemctl status qdrant --no-pager"

Structure des fichiers

ansible/roles/rag/
├── defaults/main.yml          # URLs Qdrant/embed, collection, répertoires
├── tasks/main.yml             # Déploiement scripts + docs + skill Hermes
├── handlers/main.yml          # Handler : Run rag-ingest + Restart hermes-agent
└── files/
    ├── rag-ingest             # Script Python d'ingestion
    ├── rag-query              # Script Python de requête
    └── rag-docs/SKILL.md      # Skill Hermes

hermes-skills/funk/rag-docs/
└── SKILL.md                   # Source versionnée du skill (copié dans files/)

/srv/data/rag/           (NVMe storage-01 — bind-mount /home/data)
├── docs/                      # Copie de admin/ — source des chunks
└── (Qdrant stocke dans /srv/data/qdrant/)

Points d'attention

Sujet Détail
Qualité embeddings nomic-embed-text (modèle dédié) — scores cosinus discriminants, tri par pertinence réel
Embeddings CPU llama-embed (:1238) tourne en CPU (découplé du slot chat GPU) — rag-ingest ne contend pas le GPU. ubatch=2048 requis (sinon 500 sur chunks > 512 tokens)
Re-indexation Obligatoire après modification de admin/ — pas de sync automatique
Qdrant persistance Données dans /srv/data/qdrant/ sur NVMe — survivent aux redémarrages
Score minimum MIN_SCORE dans rag-query ajusté pour nomic (scores plus étalés que qwen3-8b)