Funk-lab/README.md
ALI YESILKAYA af98b47018
docs(cluster): aligne la doc sur l'état réel + re-ingest RAG + fix ubatch embed (#44)
* fix(rag): ubatch=2048 pour llama-embed + retry rag-ingest + nettoie defaults rag

L'instance llama-embed (:1238) tournait avec l'ubatch llama.cpp par défaut (512).
En mode --embeddings + pooling, toute l'entrée doit tenir dans un seul ubatch →
tout chunk > 512 tokens échouait en HTTP 500 « input too large to process.
increase the physical batch size ». ~46 chunks du RAG (CHUNK_MAX=2000 chars ≈
700 tokens) n'étaient pas indexés.

- llama_server : ajoute llama_embed_ubatch_size (2048 = ctx) + flags
  --batch-size/--ubatch-size dans le template llama-embed.service.
- rag-ingest : retry (5×, backoff) sur erreurs transitoires 5xx/réseau de l'embed.
- rag/defaults : aligne embed_url/embed_model sur nomic :1238 (étaient des vars
  mortes pointant encore qwen3-8b :1234 — trompeuses).

Résultat : ré-ingestion 436/436 chunks, 0 erreur.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* 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>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 23:29:05 +02:00

266 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Funk Lab
> Homelab IA — Kubernetes (Talos) + GPU AMD + Agent autonome (Hermes)
![Funk Lab](docs/funk-lab.jpg)
## Vue d'ensemble
**Funk** est un homelab orienté IA composé de 5 machines physiques :
- un nœud de stockage/passerelle qui héberge tous les services de données et l'agent IA
- un nœud GPU dédié à l'inférence LLM local (AMD RX 6700XT)
- trois nœuds qui forment un cluster Kubernetes (Talos Linux)
L'ensemble est géré en Infrastructure-as-Code : **Ansible** pour les hôtes AlmaLinux, **talhelper** pour Talos, **ArgoCD** pour les workloads Kubernetes.
---
## Architecture
```
Internet
[ Freebox ] 192.168.1.254
│ port 1 · VLAN 1
┌───────────────┴────────────────────────────┐
│ Switch Netgear GS308EV4 │ 8 ports Gigabit · managé Plus
│ 8 ports Access (sans trunk) │ VLAN 1 (Default) + VLAN 10 (cluster-funk)
└───┬───┬─────────────────────────────┬───────┘
VLAN 1 │ │ VLAN 10 │ ports 3-6 · VLAN 10 (cluster 192.168.10.0/24)
enp4s0 │ │ enp6s0f3u2c2 ┌──────────┴───────────────────────┐
(port 2) │ │ (port 7) │ │
┌──┴───┴──┐ [ compute-01 ] [ compute-02 ] [ compute-03 ] [ gpu-01 ]
│storage-01│ 192.168.10.11 192.168.10.12 192.168.10.13 192.168.10.20
│AlmaLinux │ control-plane worker worker llama-server
│Gateway· │ Talos Linux · Kubernetes AMD RX 6700XT
│NAT·DNS· │
│NFS·PG· │
│Qdrant· │
│LiteLLM· │
│Hermes │
└──────────┘
```
**Câblage du switch (Netgear GS308EV4)** — tous les ports en mode **Access** (pas de trunk). storage-01 utilise **deux NIC physiques**, une par VLAN (pas de sous-interface taguée) :
| Port | Connecté à | IP | VLAN |
|---|---|---|---|
| 1 | Freebox | — | 1 · Default |
| 2 | storage-01 — NIC1 `enp4s0` (WAN) | `192.168.1.200` | 1 · Default |
| 3 | gpu-01 | `192.168.10.20` | 10 · cluster-funk |
| 4 | compute-01 (control-plane) | `192.168.10.11` | 10 · cluster-funk |
| 5 | compute-02 (worker) | `192.168.10.12` | 10 · cluster-funk |
| 6 | compute-03 (worker) | `192.168.10.13` | 10 · cluster-funk |
| 7 | storage-01 — NIC2 `enp6s0f3u2c2` (LAN cluster) | `192.168.10.1` | 10 · cluster-funk |
| 8 | PC perso (poste admin) | `192.168.1.x` | 1 · Default |
> storage-01 fait **passerelle / NAT** entre la VLAN 1 (LAN domestique `192.168.1.0/24`, côté Freebox) et la VLAN 10 (cluster `192.168.10.0/24`).
---
## Stack IA
```
┌─────────────────────────────────────┐
│ Hermes Agent (storage-01) │
│ │
│ profil funk-ai (Qwen3-8B GPU) │
│ │ ask-agent system/monitor │
│ ▼ │
│ profil system (Qwen3-1.7B CPU) │
│ profil monitor (Qwen3-1.7B CPU) │
│ profil brain (Claude Sonnet API) │
└──────────────┬──────────────────────┘
LiteLLM Proxy :4000
┌────────────────────┼────────────────────┐
│ │ │
qwen3-8b GPU qwen3-1.7b CPU Claude API
gpu-01 :1234 :1236 system / :1237 monitor Anthropic
```
| Composant | Rôle | Hôte |
|---|---|---|
| **llama-server** | Inférence GPU (:1234, qwen3-8b — ROCm 7.x) + embeddings dédiés nomic-embed-text (:1238, CPU) + watchdog/heartbeat. Instances CPU :1236/:1237 (profils `system`/`monitor`) **manuelles, souvent éteintes** | gpu-01 |
| **LiteLLM** | Proxy API — routing local/cloud transparent | storage-01 |
| **Hermes Agent** | Agent IA multi-profils avec mémoire vectorielle | storage-01 |
| **ask-agent** | Délégation inter-agents (system / monitor / brain) | storage-01 |
| **STT** | Assistant vocal « Jarvis » — client `stt` (poste) + STT-server in-cluster | k8s (`ai`) |
| **Qdrant** | Base vectorielle — RAG (`funk-docs`) + mémoire STT (`stt-memory`) | storage-01 |
| **PostgreSQL 16** | Persistance Hermes, LiteLLM, n8n, Open WebUI, Ghostfolio | storage-01 |
### Profils Hermes
| Profil | Modèle | Usage |
|---|---|---|
| `funk-ai` | Qwen3-8B GPU (~35 tok/s) | Agent principal — par défaut |
| `system` | Qwen3-1.7B CPU (~21 tok/s) | Calculs rapides, formatage, résumés |
| `monitor` | Qwen3-1.7B CPU (~21 tok/s) | Analyse logs, métriques, santé système |
| `brain` | Claude Sonnet 4.6 (API) | Raisonnement complexe, architecture |
---
## Infrastructure
### Machines
| Machine | IP | OS | RAM | Rôle |
|---|---|---|---|---|
| storage-01 | 192.168.10.1 | AlmaLinux 9.8 | 32 GB | Gateway · NFS · Services IA |
| gpu-01 | 192.168.10.20 | AlmaLinux 9.8 | 32 GB | Inférence LLM (RX 6700XT) |
| compute-01 | 192.168.10.11 | Talos v1.13 (k8s v1.33.1) | 16 GB | k8s control-plane |
| compute-02 | 192.168.10.12 | Talos v1.13 (k8s v1.33.1) | 8 GB | k8s worker |
| compute-03 | 192.168.10.13 | Talos v1.13 (k8s v1.33.1) | 8 GB | k8s worker |
### Stockage
- NVMe système (`/home/data`, ~845 GB XFS) — bind-monté sur `/srv/data` depuis 2026-05-29
- RAID5 logiciel (`md0`) — 4 × 1 TB SATA, actif mais plus monté (sdb ATA errors + sdd retiré)
- Point de montage `/srv/data` — héberge modèles LLM, bases de données, données Hermes
---
## Organisation du repo
```
├── ansible/ # Gestion storage-01 + gpu-01 (AlmaLinux)
│ ├── inventory.yml
│ ├── playbooks/
│ │ ├── storage-01.yml
│ │ └── gpu-01.yml
│ ├── group_vars/ # Variables globales + vault chiffré
│ ├── host_vars/ # Variables par machine
│ └── roles/
│ ├── common # Paquets, sécurité, NTP
│ ├── gateway # nftables + NAT
│ ├── dnsmasq # DNS local (lab.local)
│ ├── nfs_server # Exports NFS (modèles, k8s)
│ ├── nfs_client # Montages NFS sur gpu-01
│ ├── rocm # Stack GPU AMD (ROCm 7.x)
│ ├── llama_server # Inférence LLM + embeddings
│ ├── litellm # Proxy LLM + script ask-agent
│ ├── hermes_agent # Agent IA autonome
│ ├── hermes_user # User hermes + SSH partagé entre hosts
│ ├── rag # RAG : scripts rag-ingest/rag-query + skill Hermes
│ ├── alertmanager_webhook # Pont AlertManager → ask-agent
│ ├── postfix_relay # SMTP sortant via Gmail
│ ├── node_exporter # Métriques Prometheus
│ ├── minio # ⚠️ placeholder vide — service non déployé
│ ├── postgresql # Base de données
│ ├── qdrant # Base vectorielle
│ └── hermes_auto_improve # Worker analyse doc + trigger server :9095
├── hermes-skills/ # Skills Hermes versionnés
│ ├── funk/
│ │ ├── agent-delegation/ # Délégation ask-agent (system/monitor/brain)
│ │ └── rag-docs/ # Usage de rag-query
│ └── souls/ # Prompts système par profil (funk-ai, system, monitor, brain)
├── tools/ # Sources des outils déployés
│ ├── hermes-auto-improve/ # auto-improve.py + trigger-server.py
│ └── hermes-voice/ # Client vocal Hermes (CLI faster-whisper + Piper)
├── stt/ # Assistant vocal « Jarvis » — client `stt` (pipx) + STT-server (conteneur)
├── admin/ # Base de connaissance (indexée dans le RAG)
├── progress/ # Journaux de session (référencés par PROGRESS.md)
├── archive/ # Documents historiques obsolètes (conception d'origine) — ne fait pas foi
├── talos/ # Cluster Kubernetes (talhelper)
└── k8s/ # Workloads ArgoCD
├── infra/ # monitoring, nfs-provisioner (Traefik + MetalLB via helm au bootstrap)
└── apps/ # Open WebUI, n8n, STT, Ghostfolio, external-services
```
---
## Démarrage rapide
### Pré-requis
```bash
pip install ansible
ansible-galaxy collection install ansible.posix community.general community.postgresql
```
### Déployer storage-01
```bash
cd ansible/
ansible-playbook -i inventory.yml playbooks/storage-01.yml
```
### Déployer gpu-01
```bash
ansible-playbook -i inventory.yml playbooks/gpu-01.yml
```
### Déployer un rôle spécifique
```bash
ansible-playbook -i inventory.yml playbooks/storage-01.yml --tags litellm
ansible-playbook -i inventory.yml playbooks/gpu-01.yml --tags llama_server
```
### Gestion du cluster
```bash
funk-start # Allume gpu-01 (WOL) + démarre tous les services
funk-start --k8s # Idem + démarre les nœuds k8s
funk-stop # Arrêt propre
funk-stop --k8s # Arrêt propre + éteint k8s avant
funk-status # État de tous les services (13 checks)
```
> Détail complet des procédures : [admin/ops/cluster.md](admin/ops/cluster.md)
---
## Secrets
Les secrets sont gérés via **Ansible Vault** (chiffrement AES256).
```bash
# Chiffrer le vault
ansible-vault encrypt ansible/group_vars/all/vault.yml
# Editer les secrets
ansible-vault edit ansible/group_vars/all/vault.yml
```
Variables stockées dans le vault : `vault_anthropic_api_key`, `vault_pg_hermes_password`, `vault_pg_litellm_password`, `vault_pg_n8n_password`, `vault_pg_openwebui_password`, `vault_pg_ghostfolio_password`, `vault_postfix_relay_password`, `vault_n8n_api_key`.
---
## Contrainte GPU
La RX 6700XT (gfx1031) n'est pas officiellement supportée par ROCm. La variable suivante est obligatoire dans tous les services GPU :
```
HSA_OVERRIDE_GFX_VERSION=10.3.0
```
Elle est gérée automatiquement par le rôle Ansible `llama_server`.
---
## Roadmap
- [x] Ansible — storage-01 (gateway, NFS, PostgreSQL, Qdrant, LiteLLM, Hermes, postfix, AlertManager webhook)
- [x] Ansible — gpu-01 (ROCm, llama-server : GPU :1234 + embeddings :1238 via le rôle ; 2× CPU manuels)
- [x] Stack IA opérationnelle (Hermes multi-profils + Qwen3 + Claude API)
- [x] Délégation inter-agents (`ask-agent` + skill `agent-delegation`)
- [x] RAG opérationnel — Qdrant ~436 chunks (embeddings nomic-embed-text `:1238`, dim 768), `rag-query` / `rag-ingest`
- [x] User `hermes` avec SSH partagé entre storage-01 et gpu-01
- [x] Cluster Kubernetes opérationnel (Talos v1.13 + talhelper)
- [x] MetalLB + Traefik + wildcard DNS `lab.local`
- [x] Monitoring complet (kube-prometheus-stack + AlertManager → Hermes + n8n)
- [x] Open WebUI (`openwebui.lab.local`, namespace `ai`)
- [x] n8n (`n8n.lab.local`, namespace `ai`, 3 workflows actifs)
- [x] Email sortant — Postfix relay → Gmail SMTP
- [x] hermes-auto-improve — analyse quotidienne de la doc par Hermes (n8n 22h → PR `hermes/daily-work`)
- [x] Ghostfolio — suivi de portefeuille (`ghostfolio.lab.local`, PostgreSQL s01 + Redis)
- [x] STT — assistant vocal « Jarvis » (client `stt` + STT-server in-cluster, mémoire Qdrant `stt-memory`)
- [x] Modèle d'embedding dédié — nomic-embed-text sur gpu-01 `:1238` (utilisé par la mémoire STT **et le RAG**)
- [x] Réparer Qdrant — crash-loop résolu 2026-06-17 ; collection `funk-docs` **reconstruite** depuis (436 chunks)
- [x] Re-ingérer le RAG (`rag-ingest`) **basculé sur l'embedding dédié `:1238`** (dim 768)
- [ ] WOL compute nodes (configuration BIOS)
- [ ] Route statique Freebox