backup: snapshot post-démo GHT 2026-05-19
Some checks failed
tests / Lint (ruff + black) (push) Successful in 1m50s
tests / Tests unitaires (sans GPU) (push) Failing after 1m50s
tests / Tests sécurité (critique) (push) Has been skipped

Backup état complet après enregistrement vidéo démo de bout en bout.
À utiliser comme point de référence pour la consolidation post-démo.

Changements majeurs de la session 18-19 mai :
- AIVA-URGENCE : page autonome avec preset URL + auto-focus chain
- Workflow Demo_urgence_3_db : merge linux_db + steps AIVA + pause humaine NoMachine
- Bypass LLM (static_result / static_text) dans replay_engine
  pour démos déterministes sans appel Ollama
- Fix api_stream:3013 — replay_paused au premier polling /next
- dag_execute : lift duration_ms vers top-level pour wait runtime
- NPM bypass auth /aiva-urgence/ via location ^~ (proxy_host/10.conf hors git)
- scripts/cancel-replays.sh — workaround Stop VWB qui ne purge pas la queue

Anchors visuels (468) forcés dans le commit pour garantir restorabilité.
DB workflows actuelle + ~12 .bak DB de la journée incluses.

Sujets identifiés pour consolidation post-démo (TODO) :
1. Bug VWB recapture anchor ne régénère pas le PNG
2. Léa client accumule état mémoire (restart périodique requis)
3. Stop VWB ne purge pas la queue serveur (lien manquant vers /replay/cancel)
4. Bug coord client mss tronqué 2560x60 → mapping Y cassé
5. delay_before/delay_after ignorés au runtime (fix partiel duration_ms)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Dom
2026-05-19 14:55:06 +02:00
parent f2212e77e3
commit 5ea4960e65
627 changed files with 211348 additions and 169 deletions

130
deploy/VRAM_BUDGET.md Normal file
View File

@@ -0,0 +1,130 @@
# Budget VRAM — RPA Vision V3
GPU cible : **NVIDIA RTX 5070, 12 GB VRAM**.
Ce document fige les choix d'allocation pour éviter les chevauchements et crashs CUDA quand plusieurs services tournent en parallèle. À jour au 26 avril 2026 (Phase 1A — service grounding persistant).
## Hypothèse d'usage
Dom fait soit du **RECORD** (création de workflow dans le VWB), soit du **REPLAY** (exécution d'un workflow), mais pas les deux en même temps. C'est cette hypothèse qui rend les modes ci-dessous compatibles.
## Modèles résidents permanents (3.6 GB)
Ces modèles restent en VRAM en permanence pour éviter le coût de chargement à chaque appel.
| Modèle | VRAM | Hébergement | Pourquoi permanent |
|---|---|---|---|
| **InfiGUI-G1-3B** (4-bit NF4) | 2.4 GB | `rpa-grounding.service` (Unix socket) | Sinon ~15 s de chargement par clic. |
| **CLIP ViT-B/32** | 0.7 GB | Singleton in-process (`core/gpu/clip_manager.py`) | Appelé sur chaque frame du pipeline. |
| **EasyOCR fr+en** | 0.5 GB | Singleton in-process (DialogHandler, TitleVerifier, input_handler) | Polling 500 ms, CPU = 510× plus lent. |
**Note** : CLIP et EasyOCR ne sont PAS mutualisés dans le service. Le gain serait nul tant qu'un seul processus consommateur tourne à la fois (record OU replay). À envisager en Phase 1B si on mesure une vraie contention multi-process.
## VLM Ollama — un seul à la fois (config `ollama-vram-policy.conf`)
`OLLAMA_MAX_LOADED_MODELS=1` force Ollama à ne garder qu'un VLM en VRAM. Le swap a lieu au changement de mode (~5 s, une fois).
| Mode | VLM Ollama | VRAM Ollama | Usage |
|---|---|---|---|
| **REPLAY** | `qwen2.5vl:7b` | ~5.5 GB | Raisonnement haut niveau (`observe_reason_act`) |
| **RECORD** | `qwen2.5vl:3b` | ~3.0 GB | Description d'ancres (`capture.py`) |
Modèles référencés mais NON résidents (chargés à la demande, soumis au `MAX_LOADED_MODELS=1`) : `qwen3-vl:8b`, `gemma4:e4b`, `gemma4:latest`.
## Matrice VRAM totale
| Mode | Résidents | Ollama | **Total** | **Marge sur 12 GB** |
|---|---|---|---|---|
| Idle (lazy) | 2.4 (InfiGUI seul) | 0 | **2.4 GB** | 9.6 GB |
| RECORD actif | 3.6 | 3.0 (qwen 3b) | **6.6 GB** | 5.4 GB ✅ |
| REPLAY actif | 3.6 | 5.5 (qwen 7b) | **9.1 GB** | 2.9 GB ✅ |
La marge couvre les pics CUDA et la fragmentation VRAM observée à long run.
## Configuration systemd
### 1. Service grounding (déjà créé)
```
deploy/systemd/rpa-grounding.service
```
Crée le `RuntimeDirectory=rpa` (= `/run/rpa/`) qui héberge :
- `grounding.sock` — socket de communication
- `infigui_screen.png`, `infigui_anchor.png` — images d'inférence (passées par fichier, pas par socket)
### 2. Services consommateurs
Patchés pour pointer sur le socket et partager `/run/rpa/` :
```ini
Environment="RPA_GROUNDING_SOCKET=/run/rpa/grounding.sock"
Environment="RPA_GROUNDING_IMG_DIR=/run/rpa"
RuntimeDirectory=rpa
RuntimeDirectoryMode=0755
RuntimeDirectoryPreserve=yes
```
Units patchées : `rpa-vision-v3-api.service`, `rpa-vision-v3-worker.service`, `rpa-streaming.service`.
### 3. Drop-in Ollama
```
deploy/systemd/ollama-vram-policy.conf
```
Installation :
```bash
sudo mkdir -p /etc/systemd/system/ollama.service.d/
sudo cp deploy/systemd/ollama-vram-policy.conf /etc/systemd/system/ollama.service.d/vram-policy.conf
sudo systemctl daemon-reload
sudo systemctl restart ollama
```
## Activation complète
```bash
# 1. Service grounding
sudo cp deploy/systemd/rpa-grounding.service /etc/systemd/system/
# 2. Drop-in Ollama
sudo mkdir -p /etc/systemd/system/ollama.service.d/
sudo cp deploy/systemd/ollama-vram-policy.conf /etc/systemd/system/ollama.service.d/vram-policy.conf
# 3. Recharger les units patchées (api, worker, streaming)
sudo cp deploy/systemd/rpa-vision-v3-api.service /etc/systemd/system/
sudo cp deploy/systemd/rpa-vision-v3-worker.service /etc/systemd/system/
sudo cp deploy/systemd/rpa-streaming.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now rpa-grounding
sudo systemctl restart ollama
sudo systemctl restart rpa-vision-v3-api rpa-vision-v3-worker rpa-streaming
```
## Vérification
```bash
# 1. Service grounding actif et socket en place
systemctl status rpa-grounding
ls -la /run/rpa/grounding.sock
# 2. VRAM réelle après warm-up
nvidia-smi --query-gpu=memory.used,memory.free --format=csv,noheader
# 3. Test d'un ground via socket
python -c "
from core.grounding.ui_tars_grounder import UITarsGrounder
from PIL import Image
g = UITarsGrounder.get_instance()
# Devrait afficher [InfiGUI/server/...] (et non [InfiGUI/subprocess/...])
print(g.ground(target_text='Save', screen_pil=Image.new('RGB', (800, 600))))
"
```
Si tu vois `[InfiGUI/subprocess/...]` dans les logs, c'est que le client est tombé en fallback — vérifier `journalctl -u rpa-grounding`.
## Garde-fous
- **Pas de chevauchement** : InfiGUI tourne dans son process, Ollama dans le sien. Aucun ne peut écraser l'autre.
- **Pas de double VLM** : `OLLAMA_MAX_LOADED_MODELS=1` empêche qu'un appel qwen 3b traîne pendant qu'on demande qwen 7b.
- **Pas de crash CUDA héritage parent** : l'unit `rpa-grounding` force `CUDA_VISIBLE_DEVICES=0` explicitement et démarre dans son propre process tree (pas hérité de systemd directement).
- **Fallback subprocess** : si `rpa-grounding` n'est pas démarré ou crash, le code client retombe sur l'ancien subprocess one-shot (cf. `ui_tars_grounder.py`). Aucune régression possible.