fix(llama_server): embed nomic sur CPU — supprime la contention GPU (docs=0) (#30)

Le heartbeat embed (#28) gardait le slot :1238 chargé mais docs=0 revenait :
latence bimodale 16ms / 9-12s. Cause = contention GPU, pas cold-start. nomic
(:1238, --n-gpu-layers 99) partageait la RX 6700XT avec le chat qwen3-8b (:1234) ;
ROCm sérialise → un embed lancé pendant une génération chat attend ~10s → dépasse
le budget recall 4s du STT-server → docs=0 intermittent.

- llama_embed_n_gpu_layers: 99 → 0 (CPU). nomic = 137M → ~100ms déterministe,
  découplé du slot chat. Le template lit déjà la variable.
- heartbeat embed conservé comme sonde de vivacité (commentaire ajusté).
- incidents-llm-gpu.md : section dédiée + README rôle mis à jour.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
ALI YESILKAYA 2026-06-20 12:38:08 +02:00 committed by GitHub
parent 1d3e1e6eb8
commit ef15ba25e0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 61 additions and 7 deletions

View file

@ -207,3 +207,49 @@ systemctl status llama-embed-heartbeat ; journalctl -u llama-embed-heartbeat -f
> Variante moins bonne envisagée : remonter `STT_DOCS_TIMEOUT`/`recall` à ~8 s → couvre le froid
> mais **ajoute** la latence à chaque requête froide. Le warming l'**élimine** à la source.
---
## 2026-06-20 — embed `:1238` lent par intermittence MALGRÉ le heartbeat → vraie cause : contention GPU
### Symptôme
Le heartbeat embed (`#28`) déployé et `active`, mais `docs=0` revenait quand même par
intermittence. Mesures directes sur `:1238` (5 pings espacés) :
```
embed 9.68s (HTTP 200)
embed 0.017s (HTTP 200)
embed 0.016s (HTTP 200)
embed 12.0s (HTTP 000) ← timeout total
embed 0.016s (HTTP 200)
```
Latence **bimodale** : 16 ms (chaud) ou 9-12 s (bloqué). Le heartbeat lui-même loggait
`KO (HTTP 000000)`. Donc le slot n'était **pas froid** (le heartbeat le gardait chargé) —
il **stallait**.
### Cause
`llama-embed` (`:1238`, nomic) tournait avec `--n-gpu-layers 99` → il **partageait la
RX 6700XT** avec le chat `qwen3-8b` (`:1234`, lui aussi `99`). ROCm sérialise l'accès GPU :
un embed lancé pendant une génération chat (~10 s) tombe dans la file et attend ~10 s. Le
heartbeat ne pouvait rien — le slot n'est pas inactif, il est **derrière le chat dans la
queue GPU**. D'où le `recall=8290ms` côté STT-server → timeout 4 s → `docs=0` → réponse
non ancrée.
### Correctif — embed sur CPU (découplage)
`llama_embed_n_gpu_layers: 0` (défaut du rôle `llama_server`). nomic-embed-text est
minuscule (137M) → ~100 ms en CPU, **déterministe**, et surtout **ne touche plus le GPU**
zéro contention avec le chat. 100 ms fiable >> 16 ms/10 s bimodal pour le budget recall 4 s.
```bash
ansible-playbook -i inventory.yml playbooks/gpu-01.yml --tags llama_server # redéploie :1238 en CPU
for i in 1 2 3 4 5; do ssh gpu-01 'curl -s -m12 -o/dev/null -w "%{time_total}s\n" \
http://127.0.0.1:1238/v1/embeddings -d "{\"model\":\"nomic-embed-text\",\"input\":\"x\"}"'; done
# attendu : ~0,1 s stable (plus de 9-12 s)
```
> Le heartbeat embed reste en place comme **sonde de vivacité** (il logge les KO), mais il
> n'est plus le mécanisme qui garantit la latence — c'est le CPU qui la garantit.