mirror of
https://github.com/Alkatrazz24/Funk-lab.git
synced 2026-07-09 01:04:43 +02:00
569 lines
22 KiB
Markdown
569 lines
22 KiB
Markdown
# 2026-05-11 — Hermes opérationnel sur Qwen3.5-9B
|
||
|
||
## Résumé
|
||
|
||
Hermes Agent pleinement fonctionnel sur storage-01 avec le modèle Qwen3.5-9B sur
|
||
gpu-01. Chemin parcouru : 6 blocages techniques résolus dans la même session.
|
||
|
||
---
|
||
|
||
## Blocages rencontrés et résolus
|
||
|
||
### 1. `auxiliary.compression.context_length` manquant dans config.yaml
|
||
|
||
**Symptôme** : `Failed to initialize agent: Auxiliary compression model
|
||
google/gemma-4-e4b has a context window of 4,096 tokens, which is below the
|
||
minimum 64,000 required.`
|
||
|
||
**Cause** : Hermes a deux vérifications de contexte distinctes — le modèle
|
||
principal (`model.context_length`) et le modèle de compression auxiliaire
|
||
(`auxiliary.compression.context_length`). Seule la première était surchargée.
|
||
|
||
**Fix** : Ajout dans `roles/hermes_agent/templates/config.yaml.j2` :
|
||
```yaml
|
||
auxiliary:
|
||
compression:
|
||
context_length: {{ hermes_context_length }}
|
||
```
|
||
|
||
---
|
||
|
||
### 2. Crash GPU Vulkan sur Gemma 4 E4B avec long prompt (>800 tokens)
|
||
|
||
**Symptôme** : `The model has crashed without additional information. (Exit code: null)`
|
||
dès le premier appel Hermes (system prompt ~15 000 tokens). Modèle rechargé avec
|
||
n_ctx=4096 par défaut, puis erreur de contexte en cascade.
|
||
|
||
**Cause** : Bug dans le backend Vulkan de llama.cpp avec l'architecture Gemma 4.
|
||
Gemma 4 utilise une attention interleaved global/local avec sliding window de 512
|
||
tokens. Quand le prompt dépasse 800 tokens (juste au-delà du sliding window), les
|
||
layers d'attention globale crashent dans l'implémentation Vulkan. Confirmé par
|
||
test binaire : OK à 500 tokens, crash à ~900 tokens.
|
||
|
||
**Note** : Le crash n'est pas lié à la VRAM — Gemma 4 utilise GQA aggressif, le
|
||
KV cache réel à 65536 tokens est ~2 GB seulement (7 global layers × 65536 × 4096
|
||
bytes). La VRAM ne serait pas le facteur limitant.
|
||
|
||
**Fix** : Passage sur Qwen3.5-9B qui utilise une attention GQA standard, sans
|
||
problème Vulkan connu. Fichiers modifiés :
|
||
- `host_vars/gpu-01/vars.yml` : `lm_studio_default_model: "qwen/qwen3.5-9b"`
|
||
- `roles/hermes_agent/defaults/main.yml` : `hermes_model: "qwen/qwen3.5-9b"`
|
||
|
||
---
|
||
|
||
### 3. dnsmasq crash au boot (interface USB ethernet non disponible)
|
||
|
||
**Symptôme** : Après reboot de storage-01, gpu-01 ne peut plus télécharger
|
||
de paquets (`yum makecache` bloque). DNS timeout vers 192.168.10.1.
|
||
|
||
**Cause** : dnsmasq démarre avec `After=network.target` mais l'interface USB
|
||
ethernet `enp6s0f3u2c2` prend plus de temps à apparaître. dnsmasq log :
|
||
`dnsmasq: unknown interface enp6s0f3u2c2` → crash.
|
||
|
||
**Fix** :
|
||
- Immédiat : `systemctl reset-failed dnsmasq && systemctl start dnsmasq`
|
||
- Permanent : override systemd dans `roles/dnsmasq/tasks/main.yml` qui crée
|
||
`/etc/systemd/system/dnsmasq.service.d/wait-for-network.conf` :
|
||
```ini
|
||
[Unit]
|
||
After=network-online.target
|
||
Wants=network-online.target
|
||
```
|
||
|
||
---
|
||
|
||
### 4. `LM_API_KEY=qwen/qwen3.5-9b` dans le .env de Hermes
|
||
|
||
**Symptôme** : `Failed to initialize agent: Failed to initialize OpenAI client:
|
||
bad marshal data (invalid reference)` — erreur trompeuse, masque le vrai problème.
|
||
|
||
**Cause** : La commande `hermes model` avait écrit le nom du modèle à la place
|
||
de la clé API dans `/srv/data/hermes/.env`. La clé API pour LM Studio doit être
|
||
une chaîne arbitraire (`lm-studio`), pas le nom du modèle.
|
||
|
||
**Fix** : `sed -i 's/^LM_API_KEY=.*/LM_API_KEY=lm-studio/' /srv/data/hermes/.env`
|
||
|
||
---
|
||
|
||
### 5. Fichiers `.pyc` pydantic corrompus sur le RAID5
|
||
|
||
**Symptôme** : `Failed to initialize OpenAI client: bad marshal data (invalid
|
||
reference)` persistait même après fix du .env.
|
||
|
||
**Cause** : Le reboot du RAID5 a laissé des fichiers `.pyc` Python partiellement
|
||
écrits dans le venv de Hermes. Spécifiquement `pydantic/fields` et ses
|
||
dépendances. Python essaie de charger le bytecode compilé → `ValueError: bad
|
||
marshal data (invalid reference)`.
|
||
|
||
**Traceback exact** :
|
||
```
|
||
File ".../openai/_models.py", line 39, in <module>
|
||
from pydantic.fields import FieldInfo
|
||
File "<frozen importlib._bootstrap_external>", line 729, in _compile_bytecode
|
||
ValueError: bad marshal data (invalid reference)
|
||
```
|
||
|
||
**Fix** :
|
||
```bash
|
||
find /srv/data/hermes/hermes-agent/venv/lib/python3.11/site-packages \
|
||
-name '*.pyc' -delete
|
||
```
|
||
Python recompile les `.pyc` au prochain import depuis les `.py` sources (intacts).
|
||
|
||
**Leçon** : Données applicatives sur RAID5 = écriture partielle possible sur
|
||
reboot non-propre. Les fichiers `.pyc` ne sont pas critiques (régénérables) mais
|
||
peuvent bloquer l'application entièrement.
|
||
|
||
---
|
||
|
||
## Changements ansible
|
||
|
||
| Fichier | Changement |
|
||
|---|---|
|
||
| `roles/common/tasks/main.yml` | Ajout tâche `Upgrade all packages` (tag `update`) |
|
||
| `roles/common/handlers/main.yml` | Ajout handler `Reboot if kernel updated` |
|
||
| `roles/lm_studio/tasks/main.yml` | Ajout `socat` dans les dépendances dnf |
|
||
| `roles/lm_studio/files/run-llmster.sh` | Ajout `lms unload --all` avant le chargement du modèle |
|
||
| `roles/hermes_agent/templates/config.yaml.j2` | Ajout `auxiliary.compression.context_length` |
|
||
| `roles/hermes_agent/defaults/main.yml` | Modèle passé à `qwen/qwen3.5-9b` |
|
||
| `roles/dnsmasq/tasks/main.yml` | Ajout override systemd `wait-for-network.conf` |
|
||
| `roles/dnsmasq/handlers/main.yml` | Ajout handler `Reload systemd` |
|
||
| `host_vars/gpu-01/vars.yml` | `lm_studio_default_model: "qwen/qwen3.5-9b"` |
|
||
|
||
---
|
||
|
||
## État final
|
||
|
||
- Hermes Agent opérationnel sur storage-01 (`hermes chat` fonctionne)
|
||
- Modèle Qwen3.5-9B chargé sur gpu-01 avec contexte 65 536 tokens via Vulkan
|
||
- Proxy socat actif : `192.168.10.20:1234` → `127.0.0.1:1234` (contourne le
|
||
rebind llmster post-Vulkan)
|
||
- DNS résolu après reboot grâce à l'override `network-online.target`
|
||
- Mises à jour système effectuées sur storage-01 et gpu-01
|
||
|
||
## Prochaines étapes (après session matin)
|
||
|
||
- Configurer Claude (API Anthropic) comme second modèle dans Hermes
|
||
- Route statique Freebox : `192.168.10.0/24` → `192.168.1.200`
|
||
- Premier commit GitHub (repo privé)
|
||
- Stubs rôles : `postgresql`, `qdrant`, `minio`
|
||
|
||
---
|
||
|
||
# 2026-05-11 — Session après-midi : llama-server ROCm (remplacement LM Studio)
|
||
|
||
## Résumé
|
||
|
||
Remplacement complet de LM Studio pour l'inférence par **llama-server** compilé from
|
||
source avec ROCm 7.x. Gain de performance ×5 (15 → 70 tok/s génération). Résolution
|
||
du bug de contexte `--parallel 4` qui limitait chaque slot à 8192 tokens.
|
||
|
||
---
|
||
|
||
## Blocages rencontrés et résolus
|
||
|
||
### 6. Hermes — temps de réponse de 2 minutes
|
||
|
||
**Symptôme** : Hermes met ~2 minutes pour répondre, même sur des requêtes courtes.
|
||
|
||
**Investigation** :
|
||
- `nvtop` : GPU à 90% pendant les 2 minutes → le GPU est utilisé, pas d'idle
|
||
- `journalctl -u lm-studio` : backend = **Vulkan** (pas ROCm)
|
||
- Comparaison : Vulkan ~100 tok/s prefill / ~15 tok/s génération ; Hermes system
|
||
prompt ≈ 15 000 tokens → ~2 min juste pour le prefill (15 000 ÷ 100 ≈ 150s)
|
||
|
||
**Tentative 1 — activer le backend ROCm de LM Studio** :
|
||
- `lms runtime get lmstudio-community/gguf-parser --release latest` : backends
|
||
dans `.lmstudio/extensions/backends/` (Node.js addons + libs partagées)
|
||
- Backend ROCm compilé pour ROCm 6.x : `libhipblas.so.2`, `librocblas.so.4`,
|
||
`libamdhip64.so.6` — ROCm 7.2.3 installé expose `.so.3`, `.so.5`, `.so.7`
|
||
- Tentative patchelf pour corriger les SONAME : fixe les DT_NEEDED entries
|
||
mais incompatibilité ABI profonde (structs, signatures de fonctions changées
|
||
entre ROCm 6 et 7 — SONAME seul n'est pas suffisant)
|
||
- Résultat : crash GPU au warmup (`Exit code: null` = SIGSEGV) pour tous les modèles
|
||
|
||
**Fix final — llama.cpp compilé from source avec ROCm 7.x** (option B) :
|
||
|
||
---
|
||
|
||
### 7. Build llama.cpp from source (ROCm 7.x)
|
||
|
||
**Packages requis** (non installés initialement) :
|
||
```bash
|
||
sudo dnf install -y hipblas-devel rocblas-devel hip-devel hipcc cmake gcc-c++ git patchelf
|
||
```
|
||
|
||
**Problème cmake — HIP compiler** :
|
||
- `cmake -DCMAKE_HIP_COMPILER=hipcc` → rejeté (pas dans PATH, cmake ne trouve pas)
|
||
- Fix : utiliser le chemin absolu `{{ rocm_path }}/llvm/bin/clang++`
|
||
|
||
**Commande de build finale** :
|
||
```bash
|
||
cd /opt/llama.cpp
|
||
cmake -B build \
|
||
-DGGML_HIP=ON \
|
||
-DAMDGPU_TARGETS=gfx1030 \
|
||
-DCMAKE_BUILD_TYPE=Release \
|
||
-DROCM_PATH=/opt/rocm \
|
||
-DCMAKE_PREFIX_PATH=/opt/rocm \
|
||
-DCMAKE_HIP_COMPILER=/opt/rocm/llvm/bin/clang++
|
||
cmake --build build --target llama-server -j$(nproc)
|
||
```
|
||
|
||
**Note gfx1031 → gfx1030** : RX 6700XT = gfx1031 (non officiel). Target cmake =
|
||
`gfx1030` (compatible) + `HSA_OVERRIDE_GFX_VERSION=10.3.0` dans le service systemd.
|
||
|
||
**Autre problème** : après `systemctl stop lm-studio`, le processus `llmster`
|
||
survivait (double-fork) et tenait le port 1234.
|
||
Fix : `sudo kill $(pgrep llmster) && sudo kill $(pgrep socat)`
|
||
|
||
---
|
||
|
||
### 8. Tentative Qwen3.5-9B sur llama-server — crash ROCm
|
||
|
||
**Symptôme** : `llama-server` crash au warmup avec Qwen3.5-9B (`ggml_cuda_op_mul_mat`
|
||
assertion failure).
|
||
|
||
**Cause** : Qwen3.5-9B utilise l'architecture **Gated Delta Net** (hybride SSM +
|
||
attention) — non supportée par le backend ROCm de llama.cpp. Confirmé : crash
|
||
identique avec plusieurs versions GGUF de ce modèle.
|
||
|
||
**Fix** : Passage sur **Qwen2.5-7B-Instruct** (transformer standard, GQA classique,
|
||
aucun problème ROCm). Modèle déjà présent sur le NFS.
|
||
|
||
---
|
||
|
||
### 9. Bug `--parallel 4` — contexte insuffisant pour Hermes
|
||
|
||
**Symptôme** : Hermes renvoie HTTP 400 `context window exceeded` même avec
|
||
`--ctx-size 32768`. System prompt Hermes = 14 579 tokens.
|
||
|
||
**Cause** : `--parallel N` divise le ctx-size *total* en N slots égaux.
|
||
Avec `--parallel 4 --ctx-size 32768` → chaque slot = 8192 tokens.
|
||
14 579 > 8192 → dépassement dès le premier appel Hermes.
|
||
|
||
**Fix** :
|
||
```bash
|
||
sudo sed -i 's/--parallel 4/--parallel 1/' /etc/systemd/system/llama-server.service
|
||
sudo systemctl daemon-reload && sudo systemctl restart llama-server
|
||
```
|
||
|
||
Corrigé aussi dans `roles/llama_server/defaults/main.yml` : `llama_parallel: 1`.
|
||
|
||
---
|
||
|
||
## Performances finales (RX 6700XT, ROCm 7.x natif)
|
||
|
||
| Backend | Prefill | Génération | TTFT Hermes (15k tokens) |
|
||
|---|---|---|---|
|
||
| LM Studio Vulkan | ~100 tok/s | ~15 tok/s | ~150s |
|
||
| llama-server ROCm 7.x | ~400 tok/s | ~70 tok/s | ~35s |
|
||
|
||
Gain ×4 prefill, ×4.5 génération — gain ×4 sur le TTFT Hermes.
|
||
|
||
---
|
||
|
||
## Changements ansible
|
||
|
||
| Fichier | Changement |
|
||
|---|---|
|
||
| `roles/llama_server/tasks/main.yml` | Création — build ROCm, service systemd, firewall, désactive lm-studio |
|
||
| `roles/llama_server/defaults/main.yml` | Création — `llama_parallel: 1` (critique : 4 → context bug) |
|
||
| `roles/llama_server/templates/llama-server.service.j2` | Création — template service systemd |
|
||
| `roles/rocm/defaults/main.yml` | Ajout `rocm_build_packages` (hipblas-devel, rocblas-devel, hip-devel, hipcc) |
|
||
| `roles/hermes_agent/defaults/main.yml` | Modèle → `qwen2.5-7b-instruct` |
|
||
| `playbooks/gpu-01.yml` | Remplacement rôle `lm_studio` → `llama_server` |
|
||
| `host_vars/gpu-01/vars.yml` | Suppression vars lm_studio, ajout `llama_model_path` + `llama_model_alias` |
|
||
| `group_vars/gpu_hosts/vars.yml` | Suppression vars lm_studio (port, host, context) |
|
||
| `admin/llama_server.md` | Création — doc ops complète |
|
||
| `admin/lm_studio.md` | Refonte — gestion modèles uniquement, service désactivé |
|
||
| `admin/hermes.md` | Mise à jour — modèle, config.yaml, endpoint llama-server |
|
||
| `admin/systeme.md` | Table services gpu-01 : lm-studio → llama-server |
|
||
| `admin/incidents.md` | Création — incident storage-01 XFS + résolution |
|
||
| `admin/README.md` | Ajout entrées llama_server.md et incidents.md |
|
||
|
||
---
|
||
|
||
## État final
|
||
|
||
- **llama-server** opérationnel sur gpu-01 (`192.168.10.20:1234`) — API OpenAI-compatible
|
||
- **Modèle** : Qwen2.5-7B-Instruct Q4_K_S — 32768 tokens ctx, 1 slot (requis pour Hermes)
|
||
- **Hermes** : fonctionne correctement, réponse en ~35s (vs 2 min avant)
|
||
- **LM Studio** : désactivé pour l'inférence, reste installé pour `lms get` / `lms ls`
|
||
|
||
## Prochaines étapes (après session matin, avant session LiteLLM)
|
||
|
||
- ~~Configurer Claude (API Anthropic) comme second modèle dans Hermes~~ ✅ fait
|
||
- Route statique Freebox : `192.168.10.0/24` → `192.168.1.200`
|
||
- Premier commit GitHub (repo privé)
|
||
- Stubs rôles : `postgresql`, `qdrant`, `minio`
|
||
|
||
---
|
||
|
||
# 2026-05-11 — Session soir : LiteLLM proxy + intégration Claude API
|
||
|
||
## Résumé
|
||
|
||
Déploiement de LiteLLM comme proxy unifié sur storage-01. Hermes passe désormais
|
||
par LiteLLM pour toute inférence — Qwen local par défaut, Claude API switchable
|
||
sans toucher à la configuration de Hermes.
|
||
|
||
---
|
||
|
||
## Blocages rencontrés et résolus
|
||
|
||
### 10. Hermes ne résout pas le provider LiteLLM
|
||
|
||
**Symptôme** : `hermes -z` échoue avec `AuthError: No inference provider configured`
|
||
même avec `LM_BASE_URL=http://127.0.0.1:4000/v1` dans le `.env`.
|
||
|
||
**Investigation** :
|
||
- `hermes doctor` avec `LM_API_KEY=lm-studio` → "✓ API key or custom endpoint configured"
|
||
- `hermes doctor` avec `LM_API_KEY=funk-litellm` → pas reconnu
|
||
|
||
**Cause 1** : `LM_API_KEY` doit valoir `lm-studio` **exactement** — c'est la valeur
|
||
magic qui active le provider "LM Studio" (OpenAI-compatible custom endpoint) dans Hermes.
|
||
Toute autre valeur n'est pas reconnue.
|
||
|
||
**Cause 2** : `config.yaml` manquait `model.provider: lmstudio` et `model.base_url`.
|
||
Sans ces champs, Hermes ne sait pas quel provider utiliser même si `.env` est correct.
|
||
|
||
**Format config.yaml correct** :
|
||
```yaml
|
||
model:
|
||
provider: lmstudio
|
||
base_url: "http://127.0.0.1:4000/v1"
|
||
default: "hermes-default"
|
||
context_length: 65536
|
||
```
|
||
|
||
**Fix** :
|
||
- `LM_API_KEY=lm-studio` dans `.env` (géré par `lineinfile` Ansible)
|
||
- `litellm_master_key: lm-studio` pour que LiteLLM accepte les requêtes Hermes
|
||
- Ajout de `provider` et `base_url` dans le template `config.yaml.j2`
|
||
|
||
---
|
||
|
||
### 11. PermissionError hermes -z depuis le mauvais répertoire
|
||
|
||
**Symptôme** : `PermissionError: [Errno 13] Permission denied: '/home/ansible/.git'`
|
||
|
||
**Cause** : `hermes -z` remonte l'arborescence pour trouver un `.git`. Lancé depuis
|
||
`/home/ansible`, l'utilisateur hermes n'a pas accès.
|
||
|
||
**Fix** : Toujours lancer depuis `/srv/data/hermes` :
|
||
```bash
|
||
cd /srv/data/hermes && hermes -z "question"
|
||
```
|
||
|
||
---
|
||
|
||
### 12. 404 sur /api/v1/models à l'init Hermes
|
||
|
||
**Symptôme** : Logs LiteLLM montrent des `GET /api/v1/models HTTP/1.1" 404`.
|
||
|
||
**Cause** : Hermes appelle `/api/v1/models` lors de l'initialisation — LiteLLM
|
||
n'expose que `/v1/models`. Ce 404 n'est pas bloquant, les requêtes
|
||
`POST /v1/chat/completions` fonctionnent normalement.
|
||
|
||
**Fix** : Aucun — comportement Hermes attendu, sans impact fonctionnel.
|
||
|
||
---
|
||
|
||
## Architecture finale LiteLLM
|
||
|
||
```
|
||
Hermes (hermes-default)
|
||
│ LM_API_KEY=lm-studio
|
||
│ LM_BASE_URL=http://127.0.0.1:4000/v1
|
||
▼
|
||
LiteLLM (:4000) master_key=lm-studio
|
||
│
|
||
├── hermes-default → qwen2.5-7b-instruct → llama-server gpu-01 (défaut)
|
||
├── hermes-default → claude-sonnet-4-6 → api.anthropic.com (switch)
|
||
└── [autres modèles accessibles par nom direct]
|
||
```
|
||
|
||
**Switch sans toucher Hermes** : modifier uniquement le bloc `hermes-default`
|
||
dans `/etc/litellm/config.yaml` + `sudo systemctl restart litellm`.
|
||
|
||
**Proof** : Qwen répond "Je suis Claude" (hallucination sur l'identité — comportement
|
||
normal des 7B). La GPU qui chauffe sur gpu-01 est la vraie source de vérité.
|
||
|
||
---
|
||
|
||
## Changements ansible
|
||
|
||
| Fichier | Changement |
|
||
|---|---|
|
||
| `roles/litellm/` | Création complète du rôle (defaults, tasks, handlers, templates) |
|
||
| `roles/litellm/templates/config.yaml.j2` | Alias `hermes-default` + 3 modèles |
|
||
| `roles/litellm/defaults/main.yml` | `master_key: lm-studio`, `host: 127.0.0.1` |
|
||
| `roles/hermes_agent/defaults/main.yml` | `hermes_lm_base_url: 127.0.0.1:4000`, `api_key: lm-studio` |
|
||
| `roles/hermes_agent/templates/config.yaml.j2` | Ajout `provider: lmstudio`, `base_url`, `model.default` |
|
||
| `roles/hermes_agent/templates/hermes-agent.service.j2` | `LM_BASE_URL`/`LM_API_KEY` (pas HERMES_LLM_*), `gateway run` |
|
||
| `roles/hermes_agent/tasks/main.yml` | Tâches `lineinfile` pour `.env` (LM_BASE_URL, LM_API_KEY) |
|
||
| `playbooks/storage-01.yml` | Rôle `litellm` ajouté avant `hermes_agent` |
|
||
| `group_vars/all/vault.yml` | `vault_anthropic_api_key` (clé Anthropic chiffrée) |
|
||
| `admin/hermes.md` | Refonte complète — architecture LiteLLM, config correcte, switch |
|
||
| `admin/litellm.md` | Correction master_key, procédure switch, points d'attention |
|
||
|
||
---
|
||
|
||
## État final
|
||
|
||
- **LiteLLM** opérationnel sur storage-01 (:4000), 4 modèles enregistrés
|
||
- **Hermes** utilise Qwen local via LiteLLM — ~70 tok/s, gratuit
|
||
- **Claude Sonnet/Opus** disponibles via switch LiteLLM uniquement (clé API Anthropic en vault)
|
||
- **Vault Ansible** : `vault_anthropic_api_key` chiffré dans `group_vars/all/vault.yml`
|
||
|
||
## Prochaines étapes
|
||
|
||
- Route statique Freebox : `192.168.10.0/24` → `192.168.1.200`
|
||
- Premier commit GitHub (repo privé)
|
||
- **Mémoire Hermes sur cluster** : Qdrant (vectoriel) + PostgreSQL sur storage-01,
|
||
embeddings via Qwen, retrieval via Claude API pour les tâches complexes
|
||
- Stubs rôles : `postgresql`, `qdrant`, `minio`
|
||
|
||
---
|
||
|
||
# 2026-05-11 — Session nuit : Qdrant + PostgreSQL + embeddings + upgrade 14B
|
||
|
||
## Résumé
|
||
|
||
Déploiement de la stack mémoire vectorielle complète pour Hermes : PostgreSQL 16 et
|
||
Qdrant v1.13.4 sur storage-01 (RAID5). Activation des embeddings sur llama-server.
|
||
Installation du skill qdrant-vector-search dans Hermes. Indexation de 17 chunks de
|
||
connaissance dans Qdrant. Upgrade modèle Qwen2.5-7B → 14B.
|
||
|
||
---
|
||
|
||
## Blocages rencontrés et résolus
|
||
|
||
### 13. Embeddings llama-server — erreur 400 pooling
|
||
|
||
**Symptôme** : `curl /v1/embeddings` → `400 Pooling type 'none' is not OAI compatible`
|
||
|
||
**Cause** : Sur les LLM causaux (Qwen2.5), le pooling par défaut de llama-server est
|
||
`none` (pas de agrégation des token embeddings). Le format OAI attend un vecteur unique.
|
||
|
||
**Fix** : Ajout du flag `--pooling mean` dans le template service llama-server.
|
||
Variables Ansible : `llama_embeddings: true` + `llama_pooling: "mean"`.
|
||
|
||
---
|
||
|
||
### 14. qdrant-client non installé dans le venv Hermes
|
||
|
||
**Symptôme** : `ModuleNotFoundError: No module named 'qdrant_client'` lors des tests Python.
|
||
|
||
**Cause** : Le skill qdrant-vector-search fournit la documentation API à Hermes mais
|
||
n'installe pas automatiquement qdrant-client dans tous les environnements.
|
||
|
||
**Fix** : Installation manuelle + ajout dans le rôle Ansible :
|
||
```bash
|
||
/srv/data/hermes/hermes-agent/venv/bin/pip install "qdrant-client>=1.12.0"
|
||
```
|
||
Tâche `ansible.builtin.pip` ajoutée dans `roles/hermes_agent/tasks/main.yml`.
|
||
|
||
---
|
||
|
||
### 15. Hermes utilise execute_code (mauvais env Python) au lieu du terminal
|
||
|
||
**Symptôme** : Hermes échoue en boucle quand on lui demande d'utiliser qdrant-client.
|
||
Il utilise l'outil `🐍 execute_code` qui tourne dans son propre env Python sans qdrant-client.
|
||
|
||
**Cause** : Qwen 7B ne sait pas distinguer quand utiliser `execute_code` vs `terminal`.
|
||
Sur les tâches avec imports externes, il faut forcer l'approche "écrire un script + terminal".
|
||
|
||
**Workaround** : Écrire le script dans `/tmp/script.py` puis exécuter via terminal avec
|
||
le chemin complet `/srv/data/hermes/hermes-agent/venv/bin/python /tmp/script.py`.
|
||
|
||
**Fix structurel** : PATH du venv ajouté dans le service systemd hermes-agent et
|
||
dans `~/.bashrc` de l'utilisateur hermes.
|
||
|
||
---
|
||
|
||
### 16. Segfault llama-server avec Qwen2.5-14B à 32k contexte
|
||
|
||
**Symptôme** : `code=dumped, signal=SEGV` au démarrage du service après upgrade 14B.
|
||
|
||
**Cause** : VRAM insuffisante. Qwen2.5-14B Q4_K_M ≈ 8 GB + KV cache 32k ≈ 6 GB = ~14 GB
|
||
→ dépasse les 12 GB de la RX 6700XT.
|
||
|
||
**Fix** : Réduction du contexte à 16384 tokens dans `host_vars/gpu-01/vars.yml` :
|
||
```yaml
|
||
llama_ctx_size: 16384
|
||
```
|
||
Budget VRAM résultant : ~8 GB (modèle) + ~3 GB (KV cache) = ~11 GB ✅
|
||
|
||
---
|
||
|
||
### 17. qdrant-client API : client.search() supprimé en v1.14+
|
||
|
||
**Découverte** : qdrant-client v1.18 (installé dans le venv) vs serveur Qdrant v1.13.4.
|
||
La méthode `client.search()` a été supprimée en v1.14 — utiliser `client.query_points()`.
|
||
|
||
**Note** : Warning de compatibilité de version (majeure OK, mineure diff > 1) affiché
|
||
au démarrage du client mais sans impact fonctionnel sur les opérations de base.
|
||
|
||
---
|
||
|
||
## Réalisations
|
||
|
||
### Qdrant opérationnel
|
||
- Collection `hermes_memory` créée : dim=5120 (14B), distance=COSINE
|
||
- 17 chunks de connaissance indexés (architecture, Hermes, LiteLLM, ROCm, PostgreSQL, Ansible)
|
||
- Recherche sémantique validée : score 0.82-0.85 sur requêtes pertinentes
|
||
- Script d'indexation : `admin/index_knowledge.py`
|
||
|
||
### Skill Hermes
|
||
- `mlops/qdrant` (qdrant-vector-search) installé et actif
|
||
- qdrant-client v1.18 dans le venv Hermes
|
||
- PATH venv dans service systemd et bashrc
|
||
|
||
### Script hermes-switch
|
||
- `/usr/local/bin/hermes-switch [qwen|claude|status]`
|
||
- Switch LiteLLM + restart automatique
|
||
- Déployé via `roles/litellm/files/hermes-switch`
|
||
|
||
### Upgrade modèle
|
||
- Qwen2.5-7B → Qwen2.5-14B Q4_K_M
|
||
- Contexte : 32768 → 16384 (contrainte VRAM)
|
||
- Alias API : `qwen2.5-14b-instruct`
|
||
|
||
---
|
||
|
||
## Changements ansible
|
||
|
||
| Fichier | Changement |
|
||
|---|---|
|
||
| `roles/llama_server/defaults/main.yml` | Ajout `llama_embeddings: true`, `llama_pooling: mean` |
|
||
| `roles/llama_server/templates/llama-server.service.j2` | Flags `--embeddings --pooling mean` conditionnels |
|
||
| `roles/hermes_agent/tasks/main.yml` | pip install qdrant-client, PATH venv dans bashrc |
|
||
| `roles/hermes_agent/templates/hermes-agent.service.j2` | `Environment=PATH` avec venv en premier |
|
||
| `roles/litellm/files/hermes-switch` | Création script switch modèle |
|
||
| `roles/litellm/tasks/main.yml` | Déploiement hermes-switch |
|
||
| `roles/litellm/templates/config.yaml.j2` | Alias `qwen2.5-14b-instruct` (remplace 7b) |
|
||
| `host_vars/gpu-01/vars.yml` | Modèle 14B, `llama_ctx_size: 16384` |
|
||
| `admin/index_knowledge.py` | Script indexation Qdrant (17 chunks) |
|
||
| `admin/llama_server.md` | Modèle 14B, embeddings, contrainte VRAM documentés |
|
||
| `admin/litellm.md` | hermes-switch documenté, alias mis à jour |
|
||
| `admin/hermes.md` | Section skill Qdrant ajoutée |
|
||
|
||
---
|
||
|
||
## État final
|
||
|
||
- **PostgreSQL 16** : opérationnel sur storage-01 (RAID5 `/srv/data/postgres`)
|
||
- **Qdrant v1.13.4** : opérationnel sur storage-01 (RAID5 `/srv/data/qdrant`)
|
||
- **llama-server** : Qwen2.5-14B, 16384 ctx, embeddings activés
|
||
- **Hermes** : skill qdrant actif, 17 chunks indexés dans `hermes_memory`
|
||
- **hermes-switch** : déployé et fonctionnel
|
||
|
||
## Prochaines étapes
|
||
|
||
- Route statique Freebox : `192.168.10.0/24` → `192.168.1.200`
|
||
- Premier commit GitHub (repo privé)
|
||
- Tester Hermes 14B sur les tâches agent complexes (Qdrant queries)
|
||
- Mettre à jour la dimension des vecteurs dans index_knowledge.py (5120 pour 14B vs 3584 pour 7B)
|
||
- MinIO : rôle à déployer
|