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:
@@ -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
|
||||
Reference in New Issue
Block a user