docs: add jean-router architecture and session journal

- Add SESSION-2026-07-20-JEAN-ROUTER.md (complete session journal)
- Add ARCHITECTURE-JEAN-ROUTER.md (new architecture documentation)
- Remove ARCHITECTURE-LITELLM.md (replaced by jean-router)
- Update README.md with jean-router, Jean backend, and VRAM management
- Document dynamic preset discovery and VRAM switching logic
This commit is contained in:
Folzo
2026-07-20 11:22:47 +02:00
parent babe4ee621
commit e9cd1edbff
4 changed files with 639 additions and 189 deletions
+313
View File
@@ -0,0 +1,313 @@
# Architecture LLM — jean-router (routing dynamique + gestion VRAM)
## Vue d'ensemble
```
┌─────────────────────────────────────────────────────────────────┐
│ OpenWebUI (:3000) │
│ http://192.168.1.27:3000 │
└────────────────────────┬────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ jean-router (:3014) │
│ Routing dynamique + Gestion VRAM automatique │
│ │
│ • Interroge Jean /api/presets (découverte dynamique) │
│ • Interroge Ollama /api/tags (modèles vision) │
│ • Switch automatique de preset Jean │
│ • Arrête Jean quand on passe sur Ollama (libère VRAM) │
│ • Garde Ollama 5 min en mémoire avant déchargement │
└────────┬──────────────────────────────────────┬────────────────┘
│ │
▼ ▼
┌────────────────────────┐ ┌────────────────────────┐
│ jean-proxy (:3012) │ │ wol-proxy (:3011) │
│ + WOL si PC éteint │ │ + WOL si PC éteint │
└────────┬───────────────┘ └────────┬───────────────┘
│ │
▼ ▼
┌────────────────────────┐ ┌────────────────────────┐
│ Jean (.11:8080) │ │ Ollama (.11:11434) │
│ llama.cpp server │ │ Modèles vision │
│ Presets dynamiques │ │ mistral, qwen3.5 │
│ Ornith, Qwen3.6... │ │ │
└────────────────────────┘ └────────────────────────┘
```
## Composants
### jean-router (`/jean-router/`) — Proxy dynamique
**Rôle :** Router intelligemment entre Jean et Ollama avec gestion VRAM
**Fonctionnalités :**
1. **Découverte dynamique** : Interroge `/api/presets` (Jean) et `/api/tags` (Ollama)
2. **Routing intelligent** : Route vers Jean ou Ollama selon le modèle demandé
3. **Switch automatique** : Change de preset Jean si nécessaire
4. **Gestion VRAM** : Évite la contention mémoire entre Jean et Ollama
**Endpoints :**
- `GET /v1/models` : Liste tous les modèles (Jean + Ollama)
- `POST /v1/chat/completions` : Route vers le bon backend
**Configuration :**
```bash
JEAN_WEB_HOST=192.168.1.11 # Jean Web UI (API presets)
JEAN_WEB_PORT=8090
JEAN_PROXY_HOST=localhost # jean-proxy (backend Jean)
JEAN_PROXY_PORT=3012
OLLAMA_PROXY_HOST=localhost # wol-proxy (backend Ollama)
OLLAMA_PROXY_PORT=3011
OLLAMA_DIRECT_HOST=192.168.1.11 # Ollama direct (pour unload)
OLLAMA_DIRECT_PORT=11434
ENABLE_OLLAMA=true
ENABLE_VRAM_MANAGEMENT=true
OLLAMA_KEEP_ALIVE_MINUTES=5 # Ollama reste 5 min en mémoire
SWITCH_TIMEOUT=90 # Timeout chargement Jean (s)
JEAN_STOP_TIMEOUT=30 # Timeout arrêt Jean (s)
LISTEN_PORT=3014
```
### jean-proxy (`/jean-proxy/`) — Reverse-proxy Jean + WOL
**Rôle :** Proxy vers Jean avec Wake-on-LAN si le PC gaming est éteint
**Fonctionnalités :**
- Écoute `:3012` sur le host (`network_mode: host`)
- Health-check : `GET /health` sur Jean
- Si cible DOWN → envoi paquets WOL vers `TARGET_MAC`
- Attente jusqu'à `WAKE_TIMEOUT` (60s)
- Route toutes les requêtes vers `http://${OLLAMA_HOST}:8080`
**Configuration :**
```bash
TARGET_HOST=192.168.1.11
TARGET_PORT=8080
TARGET_MAC=04:D9:F5:D1:EC:DF
LISTEN_PORT=3012
WAKE_TIMEOUT=60
CHECK_INTERVAL=5
BROADCAST_IP=192.168.1.255
HEALTH_PATH=/health
```
### wol-proxy (`/wol-proxy/`) — Reverse-proxy Ollama + WOL
**Rôle :** Proxy vers Ollama avec Wake-on-LAN
**Fonctionnalités :**
- Écoute `:3011` sur le host
- Health-check : `GET /api/version` sur Ollama
- Si cible DOWN → envoi paquets WOL
- Route toutes les requêtes vers `http://${OLLAMA_HOST}:11434`
**Configuration :**
```bash
TARGET_HOST=192.168.1.11
TARGET_PORT=11434
TARGET_MAC=04:D9:F5:D1:EC:DF
LISTEN_PORT=3011
WAKE_TIMEOUT=180
CHECK_INTERVAL=5
BROADCAST_IP=192.168.1.255
```
## Gestion VRAM
### Problème
Jean et Ollama partagent la même carte graphique (RX 7800 XT, 16GB VRAM). Charger les deux simultanément cause une contention mémoire.
| Backend | Modèle typique | VRAM utilisée |
|---------|---------------|---------------|
| Jean | Ornith 35B Q6_K | ~28.5GB (déborde en RAM) |
| Ollama | mistral 7B Q4_K_M | ~4GB |
| Ollama | qwen3.5:9b Q4_K_M | ~6GB |
### Solution : Switch automatique
**Switch Jean → Ollama :**
```
1. Arrêt de Jean via API web (/api/stop)
2. Attente confirmation (max 30s)
3. Route requête vers Ollama
```
**Switch Ollama → Jean :**
```
1. Programme déchargement Ollama dans 5 min (timer)
2. Démarrage de Jean via API web (/api/start)
3. Attente chargement modèle (max 90s)
4. Route requête vers Jean
```
**Timer Ollama :**
- Ollama reste en mémoire pendant **5 minutes** après le dernier usage
- Chaque requête vers Ollama annule le timer
- Si retour sur Ollama avant expiration → déchargement annulé
- Après 5 min d'inactivité → déchargement automatique
### Logs observés
**Switch Jean → Ollama :**
```
[VRAM] Switch Jean → Ollama
[VRAM] Arrêt de Jean pour libérer la VRAM...
[VRAM] Jean arrêté via API web
[VRAM] Jean confirmé arrêté
[Router] → Ollama (gemma4:e4b)
```
**Switch Ollama → Jean :**
```
[VRAM] Switch Ollama → Jean
[VRAM] Déchargement Ollama programmé dans 5 minutes
[VRAM] Démarrage de Jean...
[VRAM] Jean prêt après 45s
[Router] → Jean (ornith-35b-q6)
```
**Timer Ollama :**
```
[VRAM] Timer écoulé (5min), déchargement Ollama...
[VRAM] Ollama déchargé via API
```
## Modèles disponibles
### Jean (presets dynamiques)
Les presets sont découverts automatiquement via `/api/presets` :
- **ornith-35b-q6** (actif, Q6_K, reasoning)
- **qwen3.6-27b-mtp** (IQ4_XS, reasoning)
- **qwen3.6-35b-moe-compact**
- **qwen3.6-35b-moe-compact-reason** (reasoning)
- **qwen3.6-35b-moe-nano**
**Note :** Nouveaux presets Jean apparaissent automatiquement dans OpenWebUI sans configuration.
### Ollama (modèles vision)
- **mistral** (7.2B, Q4_K_M, tools)
- **qwen3.5:9b** (9.7B, Q4_K_M, vision, thinking)
**Note :** Ollama sert principalement pour les modèles avec vision que Jean ne supporte pas.
## Déploiement
### Commandes (sur effi-server .27)
```bash
cd /home/effi/effi
git pull
# Build et démarrage jean-router
docker compose -f docker-compose.yml -f docker-compose.litellm.yml up -d --build jean-router
# Recréer open-webui avec nouvelle config
docker compose -f docker-compose.yml -f docker-compose.litellm.yml up -d --force-recreate open-webui
# Vérifier
docker logs jean-router --tail 20
curl -s http://localhost:3014/v1/models | jq
```
### Tests
**1. Liste des modèles :**
```bash
curl -s http://localhost:3014/v1/models | python3 -m json.tool
```
**2. Requête Jean :**
```bash
curl -X POST http://localhost:3014/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "ornith-35b-q6",
"messages": [{"role": "user", "content": "Bonjour"}],
"max_tokens": 50
}'
```
**3. Requête Ollama :**
```bash
curl -X POST http://localhost:3014/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "mistral",
"messages": [{"role": "user", "content": "Hello"}],
"max_tokens": 30
}'
```
**4. Vérifier logs VRAM :**
```bash
docker logs jean-router -f | grep -E "VRAM|Router"
```
## Avantages vs LiteLLM
| Aspect | LiteLLM | jean-router |
|--------|---------|-------------|
| Configuration | Statique (config.yaml) | Dynamique (API Jean) |
| Nouveaux presets | Modifier config + restart | Automatique |
| Pass-through /v1/models | Non | Oui |
| Gestion VRAM | Aucune | Automatique |
| Couches | 2 (LiteLLM + jean-proxy) | 1 (jean-router) |
| Complexité | Élevée | Faible |
## Limitations
### 1. Latence de switch
- Jean → Ollama : ~3s (arrêt Jean)
- Ollama → Jean : ~45-90s (démarrage + chargement modèle)
- **Impact** : Première requête après switch plus lente
### 2. Timer Ollama non-persistant
- Si jean-router redémarre, le timer est perdu
- Ollama restera en mémoire indéfiniment (jusqu'à son propre timeout)
- **Acceptable** : Ollama gère son propre `keep_alive`
### 3. Pas de failover
- Si Jean échoue (timeout, erreur), pas de fallback automatique vers Ollama
- **À considérer** : Ajouter un fallback dans jean-router si besoin
### 4. Jean n'a pas d'auto-unload natif
- Ollama décharge automatiquement après `OLLAMA_KEEP_ALIVE` (défaut 5min)
- Jean garde son modèle chargé tant que le service tourne
- **Solution actuelle** : Arrêt complet de Jean via API web
## Évolution possible
### Court terme
- **Monitorer** : Vérifier que la gestion VRAM fonctionne bien en production
- **Ajuster** : Modifier `OLLAMA_KEEP_ALIVE_MINUTES` selon l'usage réel
- **Tester** : Valider que les nouveaux presets Jean apparaissent bien automatiquement
### Moyen terme
- **VRAM monitoring** : jean-router pourrait vérifier la VRAM disponible avant de router
- **Fallback automatique** : Si Jean échoue, router vers Ollama
- **Metrics** : Exposer des statistiques (temps de switch, VRAM utilisée, etc.)
### Long terme
- **JeanOrchestrator** : Jean pourrait gérer lui-même le switch entre presets
- **Multi-GPU** : Si plusieurs GPU, router vers celui avec le plus de VRAM libre
- **Load balancing** : Si plusieurs instances Jean/Ollama, répartir la charge
## Historique
**2026-06-27** : Architecture initiale avec LiteLLM
- Routing statique par nom de modèle
- Configuration codée en dur dans `litellm/config.yaml`
**2026-07-20** : Migration vers jean-router
- Routing dynamique basé sur les presets Jean
- Gestion automatique de la VRAM
- Suppression de LiteLLM (une couche de moins)
- Nouveaux modèles automatiquement disponibles
## Références
- **Code jean-router** : `/jean-router/app.py`
- **Docker compose** : `/docker-compose.litellm.yml`
- **Journal de session** : `/docs/05-journal/SESSION-2026-07-20-JEAN-ROUTER.md`
- **Repo Gitea** : https://gitea.folzocorp.fr/Folzo/Effi