mirror of
https://github.com/Alkatrazz24/Funk-lab.git
synced 2026-07-08 07:34:43 +02:00
feat(llama_server): heartbeat embed — garde chaud le slot nomic :1238 (#28)
Le grounding RAG du STT ratait par intermittence (docs=0 → réponses génériques) parce que l'instance d'embedding :1238 partait à froid après une pause : la 1ʳᵉ requête mettait 5-8 s et dépassait le timeout 4 s du STT-server (recall + RAG doc). llama-embed-heartbeat : service systemd local sur gpu-01 qui envoie un petit embed à :1238 toutes les 20 s → le slot reste résident/chaud → la 1ʳᵉ vraie requête est rapide → docs>0 fiable. Pendant du llm-heartbeat (slot chat :1234), pour le slot embed. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
11693e2abf
commit
1b85d4ee65
7 changed files with 140 additions and 0 deletions
|
|
@ -168,3 +168,42 @@ vrac, et sonde au plus près du serveur figé.
|
||||||
1. `llm-heartbeat` (storage-01, rôle `litellm`) — garde la connexion chaude (anti-péremption).
|
1. `llm-heartbeat` (storage-01, rôle `litellm`) — garde la connexion chaude (anti-péremption).
|
||||||
2. `request_timeout: 20` + `num_retries: 2` (LiteLLM) + retry STT-server — bornent le blip.
|
2. `request_timeout: 20` + `num_retries: 2` (LiteLLM) + retry STT-server — bornent le blip.
|
||||||
3. `llama-watchdog` (gpu-01, rôle `llama_server`) — répare le wedge ROCm à la source.
|
3. `llama-watchdog` (gpu-01, rôle `llama_server`) — répare le wedge ROCm à la source.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2026-06-19 (suite) — slot d'embedding `:1238` froid → RAG du STT raté (`docs=0`)
|
||||||
|
|
||||||
|
### Symptôme
|
||||||
|
|
||||||
|
Après déploiement du grounding RAG du STT-server (le cerveau interroge `funk-docs`), les
|
||||||
|
réponses sur le homelab étaient **intermittentes** : parfois ancrées dans la doc, parfois
|
||||||
|
génériques (« serveur XMPP », « worker nodes »…). Log du pod `stt-server` :
|
||||||
|
|
||||||
|
```
|
||||||
|
ask … recall=5471ms … docs=6 ← embed OK → 6 extraits doc injectés → réponse ancrée
|
||||||
|
ask … recall=8330ms … docs=0 ← embed à 8 s → timeout → 0 extrait → réponse générique
|
||||||
|
```
|
||||||
|
|
||||||
|
### Cause
|
||||||
|
|
||||||
|
L'instance d'embedding dédiée (`nomic-embed-text`, gpu-01 `:1238`) part **à froid** après une
|
||||||
|
pause : le slot GPU devient inactif, la 1ʳᵉ requête met 5-8 s (réchauffe + VRAM). Or le
|
||||||
|
STT-server borne le recall mémoire **et** la recherche doc à `4 s` (chemin de réponse). Au-delà :
|
||||||
|
`recall` renvoie `([], None)` → `knowledge.search` ré-embed (2ᵉ timeout) → `docs=0` → le cerveau
|
||||||
|
répond sans contexte. Même famille que le wedge chat, sur l'**autre slot** GPU — mais ici pas de
|
||||||
|
freeze, juste une latence à froid. Le slot chat `:1234` est gardé chaud par `llm-heartbeat`,
|
||||||
|
l'embed `:1238` ne l'était **pas**.
|
||||||
|
|
||||||
|
### Correctif — heartbeat embed (rôle `llama_server`)
|
||||||
|
|
||||||
|
`llama-embed-heartbeat` : service systemd local sur gpu-01 qui envoie un petit embed à `:1238`
|
||||||
|
toutes les `llama_embed_heartbeat_interval` s (défaut 20). Le slot reste **résident/chaud** → la
|
||||||
|
1ʳᵉ vraie requête est rapide → recall + RAG doc tiennent dans les 4 s → `docs>0` fiable.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ansible-playbook -i inventory.yml playbooks/gpu-01.yml --tags llama_server # déploie le heartbeat embed
|
||||||
|
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.
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,20 @@ Compile llama.cpp (backend HIP/ROCm) et déploie le service **llama-server GPU**
|
||||||
`llama-embed` servant un modèle d'embedding spécialisé (ex. `nomic-embed-text`) sur
|
`llama-embed` servant un modèle d'embedding spécialisé (ex. `nomic-embed-text`) sur
|
||||||
`:1238`, GPU. Télécharge le GGUF depuis `llama_embed_model_url` si absent. Partage le
|
`:1238`, GPU. Télécharge le GGUF depuis `llama_embed_model_url` si absent. Partage le
|
||||||
binaire et le GPU avec `:1234` (modèle ~300 Mo VRAM).
|
binaire et le GPU avec `:1234` (modèle ~300 Mo VRAM).
|
||||||
|
- **Heartbeat embed** (optionnel, `llama_embed_heartbeat_enabled`, défaut `true`) : service
|
||||||
|
systemd `llama-embed-heartbeat` qui envoie un petit embed à `:1238` toutes les
|
||||||
|
`llama_embed_heartbeat_interval` s → garde le **slot d'embedding chaud**. Sans ça, la 1ʳᵉ
|
||||||
|
requête après une pause part à froid (5-8 s) et dépasse le timeout du STT-server (4 s) →
|
||||||
|
recall mémoire vide **et** RAG documentaire raté (`docs=0`, cf. `admin/ia/stt.md`). Pendant
|
||||||
|
du `llm-heartbeat` (rôle `litellm`) côté chat. Logs : `journalctl -u llama-embed-heartbeat`.
|
||||||
|
|
||||||
|
## Heartbeat embed — variables
|
||||||
|
|
||||||
|
| Variable | Défaut |
|
||||||
|
|---|---|
|
||||||
|
| `llama_embed_heartbeat_enabled` | `true` (si `llama_embed_enabled`) |
|
||||||
|
| `llama_embed_heartbeat_interval` | `20` (s entre deux pings) |
|
||||||
|
| `llama_embed_heartbeat_timeout` | `15` (s max par ping) |
|
||||||
- **Watchdog** (optionnel, `llama_watchdog_enabled`, défaut `true`) : service systemd
|
- **Watchdog** (optionnel, `llama_watchdog_enabled`, défaut `true`) : service systemd
|
||||||
`llama-watchdog` qui sonde une **vraie génération** sur `:1234` toutes les
|
`llama-watchdog` qui sonde une **vraie génération** sur `:1234` toutes les
|
||||||
`llama_watchdog_interval` s. Sur `llama_watchdog_failures` échecs consécutifs →
|
`llama_watchdog_interval` s. Sur `llama_watchdog_failures` échecs consécutifs →
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,14 @@ llama_embed_ctx_size: 2048
|
||||||
llama_embed_n_gpu_layers: 99
|
llama_embed_n_gpu_layers: 99
|
||||||
llama_embed_pooling: "mean"
|
llama_embed_pooling: "mean"
|
||||||
|
|
||||||
|
# Heartbeat embed — garde CHAUD le slot d'embedding (:1238). Sans ça, la 1ʳᵉ requête
|
||||||
|
# après une pause part à froid (slot GPU inactif) → latence qui dépassait le timeout 4 s
|
||||||
|
# du STT-server → recall mémoire vide ET RAG doc raté (docs=0). Petit embed périodique
|
||||||
|
# (modèle minuscule, ~10-50 ms GPU) → le slot reste résident. Cf. admin/ia/stt.md.
|
||||||
|
llama_embed_heartbeat_enabled: true
|
||||||
|
llama_embed_heartbeat_interval: 20 # s entre deux pings (< idle avant refroidissement)
|
||||||
|
llama_embed_heartbeat_timeout: 15 # s max par ping
|
||||||
|
|
||||||
# Watchdog — auto-réparation du llama-server figé (wedge ROCm gfx1031).
|
# Watchdog — auto-réparation du llama-server figé (wedge ROCm gfx1031).
|
||||||
# Sonde une VRAIE génération sur :1234 (pas seulement /health, qui ment quand le
|
# Sonde une VRAIE génération sur :1234 (pas seulement /health, qui ment quand le
|
||||||
# slot d'inférence est bloqué — cf. admin/incidents-llm-gpu.md). Sur N échecs
|
# slot d'inférence est bloqué — cf. admin/incidents-llm-gpu.md). Sur N échecs
|
||||||
|
|
|
||||||
|
|
@ -17,3 +17,8 @@
|
||||||
ansible.builtin.systemd:
|
ansible.builtin.systemd:
|
||||||
name: llama-watchdog
|
name: llama-watchdog
|
||||||
state: restarted
|
state: restarted
|
||||||
|
|
||||||
|
- name: Restart llama-embed-heartbeat
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: llama-embed-heartbeat
|
||||||
|
state: restarted
|
||||||
|
|
|
||||||
|
|
@ -124,6 +124,34 @@
|
||||||
immediate: true
|
immediate: true
|
||||||
when: llama_embed_enabled
|
when: llama_embed_enabled
|
||||||
|
|
||||||
|
# --- Heartbeat embed (garde chaud le slot :1238) — optionnel ------------------
|
||||||
|
|
||||||
|
- name: Deploy llama-embed-heartbeat script
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: llama-embed-heartbeat.sh.j2
|
||||||
|
dest: /usr/local/bin/llama-embed-heartbeat
|
||||||
|
mode: '0755'
|
||||||
|
notify: Restart llama-embed-heartbeat
|
||||||
|
when: llama_embed_enabled and llama_embed_heartbeat_enabled
|
||||||
|
|
||||||
|
- name: Deploy llama-embed-heartbeat service
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: llama-embed-heartbeat.service.j2
|
||||||
|
dest: /etc/systemd/system/llama-embed-heartbeat.service
|
||||||
|
mode: '0644'
|
||||||
|
notify:
|
||||||
|
- Reload systemd
|
||||||
|
- Restart llama-embed-heartbeat
|
||||||
|
when: llama_embed_enabled and llama_embed_heartbeat_enabled
|
||||||
|
|
||||||
|
- name: Enable llama-embed-heartbeat service
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: llama-embed-heartbeat
|
||||||
|
enabled: true
|
||||||
|
daemon_reload: true
|
||||||
|
state: started
|
||||||
|
when: llama_embed_enabled and llama_embed_heartbeat_enabled
|
||||||
|
|
||||||
# --- Watchdog auto-réparation (wedge ROCm) — optionnel ------------------------
|
# --- Watchdog auto-réparation (wedge ROCm) — optionnel ------------------------
|
||||||
|
|
||||||
- name: Deploy llama-watchdog script
|
- name: Deploy llama-watchdog script
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
[Unit]
|
||||||
|
Description=llama-embed-heartbeat (garde chaud le slot d'embedding nomic :1238)
|
||||||
|
After=llama-embed.service
|
||||||
|
Wants=llama-embed.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
User=root
|
||||||
|
ExecStart=/usr/local/bin/llama-embed-heartbeat
|
||||||
|
Restart=always
|
||||||
|
RestartSec=10
|
||||||
|
SyslogIdentifier=llama-embed-heartbeat
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# llama-embed-heartbeat — garde chaud le slot d'embedding nomic (:1238).
|
||||||
|
#
|
||||||
|
# Le piège (cf. admin/ia/stt.md) : l'instance d'embedding part à froid après une pause
|
||||||
|
# (slot GPU inactif) → la 1ʳᵉ requête est lente (5-8 s) et dépasse le timeout du STT-server
|
||||||
|
# (4 s) → recall mémoire vide ET RAG documentaire raté (`docs=0`) → réponses non ancrées.
|
||||||
|
#
|
||||||
|
# Un petit embed périodique (modèle minuscule, ~10-50 ms GPU) garde le slot résident → la
|
||||||
|
# 1ʳᵉ vraie requête tombe sur un slot chaud. Pendant logique au `llm-heartbeat` (rôle litellm)
|
||||||
|
# qui garde chaud le slot de CHAT. Logge les échecs → sert aussi de sonde de l'instance embed.
|
||||||
|
set -u
|
||||||
|
|
||||||
|
URL="http://127.0.0.1:{{ llama_embed_port }}/v1/embeddings"
|
||||||
|
MODEL="{{ llama_embed_model_alias }}"
|
||||||
|
INTERVAL="{{ llama_embed_heartbeat_interval }}"
|
||||||
|
TIMEOUT="{{ llama_embed_heartbeat_timeout }}"
|
||||||
|
|
||||||
|
payload="{\"model\":\"${MODEL}\",\"input\":\"ping\"}"
|
||||||
|
|
||||||
|
fails=0
|
||||||
|
while true; do
|
||||||
|
code=$(curl -s -m "$TIMEOUT" -o /dev/null -w '%{http_code}' \
|
||||||
|
"$URL" -H 'Content-Type: application/json' -d "$payload" 2>/dev/null || echo "000")
|
||||||
|
if [ "$code" = "200" ]; then
|
||||||
|
fails=0
|
||||||
|
else
|
||||||
|
fails=$((fails + 1))
|
||||||
|
echo "embed-heartbeat: KO (HTTP ${code}) — ${fails} échec(s) consécutif(s)"
|
||||||
|
fi
|
||||||
|
sleep "$INTERVAL"
|
||||||
|
done
|
||||||
Loading…
Add table
Add a link
Reference in a new issue