Funk-lab/admin/ia/llama_server.md
ALI YESILKAYA 870c28b43d
docs(stt): fix /no_think Qwen3 + instance embeddings :1238 (doc complète) (#14)
* feat(stt): mémoire long-terme sémantique via Qdrant (5b)

Serveur : longterm.py — collection Qdrant stt-memory (embeddings Qwen3 gpu-01, dim auto,
Cosine), recall top-k injecté au prompt, remember des tours user. Tout dégrade proprement
si Qdrant/embeddings injoignables (la mémoire court-terme tient). Env STT_MEMORY_LONGTERM,
STT_QDRANT_URL, STT_EMBED_URL, STT_MEMORY_TOPK.

Testé en process : dégradation OK (Qdrant down → mem=0, pas de crash, court-terme tient).
Qdrant réparé le 17/06 (5c). Recherche sémantique réelle à valider sur cluster.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013FmcxGsyXZXogiAHQLjnZT

* feat(stt): endpoint /v1/memory/health + upsert Qdrant synchrone

- /v1/memory/health sonde activement embeddings + Qdrant + collection et
  expose les erreurs (recall/remember dégradent en silence → indébogables).
  Permet de diagnostiquer la mémoire long-terme sans kubectl exec.
- remember() : upsert avec ?wait=true → le souvenir est immédiatement
  cherchable (sans wait, Qdrant met l'écriture en file → un recall
  cross-session immédiat pouvait le rater).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013FmcxGsyXZXogiAHQLjnZT

* docs(stt): 5b mémoire long-terme validée en prod + backlog nomic-embed-text

- Rappel cross-session confirmé (« Felix » retrouvé dans une nouvelle session),
  points_count vérifié via /v1/memory/health.
- Note du fix upsert ?wait=true et de l'endpoint de diagnostic.
- Roadmap : 5d (nomic-embed-text dim 768) en backlog qualité ; états haut/bas
  du doc mis à jour (déployé + validé sur cible).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013FmcxGsyXZXogiAHQLjnZT

* feat(stt): embeddings dédiés nomic-embed-text sur gpu-01 (:1238) + migration auto

Remplace Qwen3 (chat réutilisé, dim 4096, peu discriminant) par un modèle
d'embedding spécialisé nomic-embed-text (dim 768) pour la mémoire long-terme.

Ansible (rôle llama_server) :
- nouvelle instance optionnelle `llama-embed` (llama_embed_enabled) servant un
  modèle d'embedding dédié sur :1238, GPU ; télécharge le GGUF si absent.
- activée sur gpu-01 (host_vars) : nomic-embed-text-v1.5 f16.

STT-server :
- STT_EMBED_URL → :1238, STT_EMBED_MODEL → nomic-embed-text (deployment + config).
- _ensure_collection détecte le changement de dimension (4096→768) et recrée
  automatiquement la collection stt-memory (anciens vecteurs incomparables) —
  pas de drop manuel.

Docs : llama_server README, rag.md, stt.md (5d ), CLAUDE.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013FmcxGsyXZXogiAHQLjnZT

* fix(stt): désactiver le mode thinking de Qwen3 (/no_think) — content vide / 502

Qwen3 est un modèle « thinking » : il dépensait tout le budget max_tokens en
reasoning_content → content vide, ou partait en raisonnement long → timeout (502
"upstream LiteLLM : " avec message vide). Diagnostic : appel direct LiteLLM en
0.87s mais content="" et tout dans reasoning_content.

- brain.py : ajoute le token de contrôle `/no_think` au system prompt
  (configurable STT_DISABLE_THINKING, défaut true ; inoffensif pour non-Qwen).
- brain.py : filet de sécurité — si content vide, récupère reasoning_content
  au lieu de renvoyer "".

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013FmcxGsyXZXogiAHQLjnZT

* docs(stt): documenter le fix /no_think Qwen3 + instance embeddings :1238

- admin/ia/stt.md : caveat « thinking » Qwen3 (content vide / timeout 502) +
  fix /no_think + fallback reasoning_content ; roadmap 5e ; bannière.
- stt/server/README.md : env STT_DISABLE_THINKING + section caveat Qwen3.
- admin/ia/llama_server.md : 4e instance llama-embed :1238 (nomic, dim 768),
  double source d'embeddings (1234 Qwen3 / 1238 nomic), caveat thinking,
  correction dim Qwen3 (3584 → 4096).
- admin/ia/litellm.md : cross-ref caveat thinking (concerne tous les
  consommateurs de hermes-default/qwen3).
- ci : exclure **/*.md du trigger build-stt-server (doc-only ne rebuild plus).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013FmcxGsyXZXogiAHQLjnZT

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-06-17 22:32:43 +02:00

232 lines
8.5 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.

# llama-server — Inférence LLM (gpu-01)
llama-server (llama.cpp compilé with ROCm 7.x) tourne en **quatre instances systemd** sur **gpu-01** (`192.168.10.20`).
API 100% compatible OpenAI — remplace LM Studio pour l'inférence.
---
## Quatre instances
| Service systemd | Port | Modèle | Backend | Usage |
|---|---|---|---|---|
| `llama-server` | 1234 | Qwen3-8B Q4_K_M | GPU (RX 6700XT) | Inférence principale — Hermes + LiteLLM |
| `llama-server-system` | 1236 | Qwen3-1.7B Q4_K_M | CPU | Profil Hermes `system` (tâches légères) |
| `llama-server-monitor` | 1237 | Qwen3-1.7B Q4_K_M | CPU | Profil Hermes `monitor` (supervision) |
| `llama-embed` | 1238 | nomic-embed-text-v1.5 f16 | GPU | Embeddings dédiés (mémoire STT, dim 768) |
Les instances CPU (`system`, `monitor`) partagent le même binaire mais des configs distinctes.
Les modèles sont sur NFS monté depuis storage-01 (`/mnt/models`).
> `llama-embed` (`:1238`) est **géré par Ansible** (rôle `llama_server`, `llama_embed_enabled`) —
> contrairement aux instances CPU (gap IaC, voir plus bas). Sert un modèle d'embedding **dédié**
> (`nomic-embed-text`, dim 768), bien plus discriminant que Qwen3-8B réutilisé. Partage le GPU
> avec `:1234` (~300 Mo VRAM).
---
## Service systemd
```bash
# Instance GPU (principale)
sudo systemctl status llama-server
sudo systemctl restart llama-server
sudo journalctl -u llama-server -f
# Instance CPU — profil system
sudo systemctl status llama-server-system
sudo systemctl restart llama-server-system
sudo journalctl -u llama-server-system -f
# Instance CPU — profil monitor
sudo systemctl status llama-server-monitor
sudo systemctl restart llama-server-monitor
sudo journalctl -u llama-server-monitor -f
# Instance GPU — embeddings dédiés (nomic-embed-text :1238)
sudo systemctl status llama-embed
sudo systemctl restart llama-embed
sudo journalctl -u llama-embed -f
```
---
## Modèle actuel (GPU)
| Paramètre | Valeur |
|---|---|
| Modèle | Qwen3-8B Q4_K_M |
| Alias API | `qwen3-8b` |
| Chemin | `/mnt/models/bartowski/Qwen3-8B-GGUF/Qwen3-8B-Q4_K_M.gguf` |
| Contexte | 32768 tokens |
| GPU offload | 99 layers (tout sur GPU) |
| Parallélisme | 1 slot (requis pour Hermes — voir bug parallel) |
| Embeddings | activés (`--embeddings --pooling mean`) |
### Contrainte VRAM (12 GB RX 6700XT)
| Élément | VRAM |
|---|---|
| Modèle Q4_K_M 8B | ~5 GB |
| KV cache à 32768 ctx | ~4 GB |
| **Total** | **~9 GB** ✅ |
---
## Embeddings
llama-server expose `/v1/embeddings` avec `--embeddings --pooling mean`.
Le flag `--pooling mean` est obligatoire pour les LLM causaux (sinon : erreur 400
`Pooling type 'none' is not OAI compatible`).
**Deux sources d'embeddings :**
| Endpoint | Modèle | Dim | Usage |
|---|---|---|---|
| `:1234/v1/embeddings` | Qwen3-8B (chat réutilisé) | 4096 | RAG (`funk-docs`) — peu discriminant |
| `:1238/v1/embeddings` | nomic-embed-text (dédié) | 768 | Mémoire STT (`stt-memory`) — précis |
> Qwen3-8B n'est **pas** un modèle d'embedding dédié (cosinus uniformément hauts → recherche
> peu discriminante). L'instance `llama-embed` (`:1238`) sert `nomic-embed-text`, spécialisé.
> Le RAG pourra y basculer quand il sera réparé (voir `admin/ia/rag.md`).
```bash
# Test embeddings dédiés nomic (:1238) — depuis le LAN cluster
curl -s -X POST http://192.168.10.20:1238/v1/embeddings \
-H "Content-Type: application/json" \
-d '{"model":"nomic-embed-text","input":["test"]}' | jq '.data[0].embedding | length'
# → 768 (dimension nomic-embed-text-v1.5)
# Test embeddings Qwen3 (:1234) — RAG
curl -s -X POST http://192.168.10.20:1234/v1/embeddings \
-H "Content-Type: application/json" \
-d '{"model":"qwen3-8b","input":["test"]}' | jq '.data[0].embedding | length'
# → 4096 (dimension Qwen3-8B)
```
---
## Performances (RX 6700XT, ROCm 7.x)
| Métrique | Qwen3-1.7B (CPU) | Qwen3-8B (GPU) |
|---|---|---|
| Prefill | ~50 tok/s | ~300 tok/s |
| Génération | ~15 tok/s | ~60 tok/s |
| TTFT Hermes (15k tokens) | ~300s | ~50s |
| VRAM modèle | — (CPU only) | ~5 GB |
---
## Validation API
```bash
# Depuis storage-01 ou n'importe quelle machine du LAN cluster
curl -s http://192.168.10.20:1234/v1/models | jq '.data[].id'
# Test inférence rapide (GPU)
curl http://192.168.10.20:1234/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "qwen3-8b",
"messages": [{"role": "user", "content": "Dis bonjour"}],
"max_tokens": 50
}'
# Test instances CPU
curl -s http://192.168.10.20:1236/v1/models | jq '.data[].id'
curl -s http://192.168.10.20:1237/v1/models | jq '.data[].id'
```
---
## Métriques Prometheus
Le flag `--metrics` est requis dans le service systemd pour activer l'endpoint `/metrics`.
Sans lui, llama-server retourne `501 Not Implemented`.
```bash
# Vérifier que les métriques sont disponibles
curl -s http://192.168.10.20:1234/metrics | grep llamacpp
# Métriques clés exposées
curl -s http://192.168.10.20:1234/metrics | grep -E \
"llamacpp:prompt_tokens_total|llamacpp:tokens_predicted_total|llamacpp:requests_deferred|llamacpp:kv_cache_usage_ratio"
```
| Métrique | Description |
|---|---|
| `llamacpp:prompt_tokens_total` | Tokens de prompt traités (cumul) |
| `llamacpp:tokens_predicted_total` | Tokens générés (cumul) |
| `llamacpp:prompt_tokens_seconds` | Débit prefill (tok/s) |
| `llamacpp:predicted_tokens_seconds` | Débit génération (tok/s) |
| `llamacpp:requests_deferred` | Requêtes en file d'attente (backpressure) |
| `llamacpp:kv_cache_usage_ratio` | Occupation KV cache (01) |
| `llamacpp:kv_cache_tokens` | Tokens actuellement en KV cache |
Ces métriques sont scrapées par Prometheus via les jobs `llama-server-gpu`, `llama-server-system`, `llama-server-monitor` définis dans `k8s/infra/monitoring/values.yaml`.
---
## Changer de modèle
1. Modifier `host_vars/gpu-01/vars.yml` :
```yaml
llama_model_path: "/mnt/models/bartowski/NouveauModele.gguf"
llama_model_alias: "nouveau-alias"
llama_ctx_size: 32768 # ajuster selon VRAM disponible
```
2. Redéployer :
```bash
ansible-playbook -i inventory.yml playbooks/gpu-01.yml --tags llama_server
```
3. Mettre à jour LiteLLM (alias `hermes-default`) :
```bash
ansible-playbook -i inventory.yml playbooks/storage-01.yml --tags litellm
```
---
## Build (source)
```bash
# Sur gpu-01 — rebuild si besoin
cd /opt/llama.cpp
git pull
cmake -B build \
-DGGML_HIP=ON \
-DAMDGPU_TARGETS=gfx1030 \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_HIP_COMPILER=/opt/rocm/llvm/bin/clang++ \
-DCMAKE_PREFIX_PATH=/opt/rocm
cmake --build build --target llama-server -j$(nproc)
sudo systemctl restart llama-server
```
---
## ⚠️ Gap IaC — instances CPU non couvertes par Ansible
Le rôle `ansible/roles/llama_server/` ne déploie que l'instance **GPU** (`llama-server.service` sur :1234).
Les instances CPU (`llama-server-system` :1236 et `llama-server-monitor` :1237) ont été créées **manuellement** et ne sont pas encore dans le code Ansible.
Conséquence : un `make apply-gpu` complet sur un hôte vierge ne déploierait PAS les instances CPU.
**Axe d'amélioration** : étendre le rôle `llama_server` pour déployer les 3 instances via une boucle (`with_items` ou `loop` Ansible), avec des variables dédiées dans `host_vars/gpu-01/vars.yml`.
---
## Points d'attention
| Sujet | Détail |
|---|---|
| GPU non officiel | RX 6700XT (gfx1031) — `HSA_OVERRIDE_GFX_VERSION=10.3.0` dans le service |
| ROCm version | 7.2.3 — libs dans `/opt/rocm` |
| --metrics obligatoire | Sans ce flag, `/metrics` retourne `501 Not Implemented` — Prometheus ne scrappe rien |
| parallel=1 obligatoire | `--parallel 4` divise le ctx en slots → contexte insuffisant pour Hermes |
| pooling mean obligatoire | Sans `--pooling mean`, l'endpoint `/v1/embeddings` retourne erreur 400 |
| Qwen3 = modèle « thinking » | Par défaut Qwen3 raisonne avant de répondre → consomme le budget `max_tokens` en `reasoning_content` (`content` vide) ou réfléchit longtemps (timeout). Ajouter **`/no_think`** au prompt système pour le désactiver. STT le fait (`STT_DISABLE_THINKING`) ; à considérer pour tout consommateur de Qwen3 à `max_tokens` faible (ask-agent, profils Hermes). |
| Gemma 4 interdit | Crash ROCm sur prompts >800 tokens |
| Modèles sur NFS | `/mnt/models` monté depuis storage-01 (NFS) — si NFS down, les 3 services échouent au démarrage |
| 3 services indépendants | Chaque instance a son propre service systemd — redémarrer l'un n'affecte pas les autres |
| Instances CPU hors Ansible | llama-server-system et llama-server-monitor créés manuellement — voir section Gap IaC ci-dessus |