Some checks failed
security-audit / Bandit (scan statique) (push) Successful in 12s
security-audit / pip-audit (CVE dépendances) (push) Successful in 10s
security-audit / Scan secrets (grep) (push) Successful in 8s
tests / Lint (ruff + black) (push) Successful in 13s
tests / Tests unitaires (sans GPU) (push) Failing after 14s
tests / Tests sécurité (critique) (push) Has been skipped
Point de sauvegarde incluant les fichiers non committés des sessions précédentes (systemd, docs, agents, GPU manager). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
193 lines
6.6 KiB
Markdown
193 lines
6.6 KiB
Markdown
# Flags d'exécution vision-aware (C1) — ExecutionLoop
|
||
|
||
> Introduit dans la série de correctifs **C1** (avril 2026).
|
||
> Référence code : [`core/execution/execution_loop.py`](../core/execution/execution_loop.py) (classe `ExecutionLoop`, constructeur lignes ~177-237).
|
||
|
||
Cette page décrit les quatre flags ajoutés à `ExecutionLoop` pour piloter
|
||
finement la construction de `ScreenState` pendant le replay. Ils permettent de
|
||
dégrader volontairement le pipeline de perception quand un composant est en
|
||
panne ou quand on veut gagner de la latence.
|
||
|
||
## Contexte
|
||
|
||
Depuis C1, chaque itération de la boucle d'exécution construit un
|
||
`ScreenState` enrichi via `ScreenAnalyzer` (OCR + détection UI + embedding),
|
||
avec un cache perceptuel pour éviter de recalculer deux fois sur le même
|
||
screenshot.
|
||
|
||
Cela coûte cher (~200 ms – 2 s selon la machine). Les flags ci-dessous
|
||
permettent de désactiver ou contraindre ces étapes.
|
||
|
||
Le `StepResult` expose désormais :
|
||
|
||
| Champ | Type | Sens |
|
||
|---|---|---|
|
||
| `ocr_ms` | float | Temps OCR pour ce step |
|
||
| `ui_ms` | float | Temps détection UI pour ce step |
|
||
| `analyze_ms` | float | Temps total analyse ScreenState |
|
||
| `total_ms` | float | Temps total du step (alias `duration_ms`) |
|
||
| `cache_hit` | bool | True si le ScreenState vient du cache perceptuel |
|
||
| `degraded` | bool | True si on est retombé en mode dégradé |
|
||
|
||
Ces champs remontent automatiquement dans le module analytics
|
||
(table SQLite `step_metrics`, voir
|
||
[`core/analytics/storage/timeseries_store.py`](../core/analytics/storage/timeseries_store.py)).
|
||
|
||
## Flags
|
||
|
||
### `enable_ui_detection: bool = True`
|
||
|
||
Active/désactive la détection UI (YOLO + SomEngine + VLM de grounding).
|
||
|
||
**Pourquoi le désactiver** :
|
||
- Le serveur VLM (Ollama) est down ou surchargé
|
||
- On cible un workflow très simple où seul l'OCR suffit
|
||
- On debugge un problème de détection et on veut isoler la cause
|
||
|
||
**Impact performance** : gain ~100-1500 ms par step selon modèle VLM.
|
||
|
||
**Exemple** :
|
||
|
||
```python
|
||
from core.execution.execution_loop import ExecutionLoop, ExecutionMode
|
||
|
||
loop = ExecutionLoop(
|
||
pipeline=pipeline,
|
||
enable_ui_detection=False, # VLM down → on coupe la détection UI
|
||
)
|
||
loop.start(workflow_id="wf_notepad", mode=ExecutionMode.AUTOMATIC)
|
||
```
|
||
|
||
### `enable_ocr: bool = True`
|
||
|
||
Active/désactive l'OCR (Tesseract/docTR).
|
||
|
||
**Pourquoi le désactiver** :
|
||
- Gains de performance sur un workflow piloté uniquement par templates/embeddings
|
||
- Environnement CPU-only où l'OCR est trop lent
|
||
- Les textes ne sont pas utilisés par la stratégie de matching
|
||
|
||
**Impact performance** : gain ~80-500 ms par step.
|
||
|
||
**Exemple** :
|
||
|
||
```python
|
||
loop = ExecutionLoop(
|
||
pipeline=pipeline,
|
||
enable_ocr=False,
|
||
)
|
||
```
|
||
|
||
> Note : si `enable_ui_detection=False` **et** `enable_ocr=False`, la boucle
|
||
> renvoie un `ScreenState` stub (sans texte ni éléments) et force
|
||
> `degraded=True`. Le matching retombera sur les embeddings CLIP seuls.
|
||
|
||
### `analyze_timeout_ms: int = 8000`
|
||
|
||
Seuil soft en millisecondes au-delà duquel on considère que l'analyse a été
|
||
trop lente et on bascule **tous les steps suivants** en mode dégradé
|
||
(pas de recalcul OCR/UI, réutilisation du cache ou stub direct).
|
||
|
||
**Pourquoi le modifier** :
|
||
- Machines lentes (CPU, VM, Citrix) → augmenter à `15000` ou `20000`
|
||
- Serveurs dédiés GPU → réduire à `3000` pour détecter plus tôt
|
||
- Tests / profiling → utiliser `999999` pour désactiver le basculement
|
||
|
||
**Exemple** :
|
||
|
||
```python
|
||
loop = ExecutionLoop(
|
||
pipeline=pipeline,
|
||
analyze_timeout_ms=15000, # environnement lent (RDP/Citrix)
|
||
)
|
||
```
|
||
|
||
Le mode dégradé est porté par `ExecutionLoop._degraded_mode` et affiché dans
|
||
`StepResult.degraded`. Voir
|
||
[`_build_screen_state`](../core/execution/execution_loop.py) (~ligne 920).
|
||
|
||
### `window_info_provider: Optional[Callable[[], Optional[Dict]]] = None`
|
||
|
||
Callable renvoyant un `dict` décrivant la fenêtre active. Par défaut, la
|
||
boucle appelle `screen_capturer.get_active_window()`.
|
||
|
||
**Pourquoi fournir un provider custom** :
|
||
- **Citrix / RDP** : le client Windows local voit un seul process (le client
|
||
Citrix). L'info de fenêtre utile vient de l'agent distant, on doit donc la
|
||
passer explicitement.
|
||
- **Environnements headless** : pas de gestionnaire de fenêtres natif.
|
||
- **Tests** : injecter une fenêtre mockée sans toucher au capturer.
|
||
|
||
**Format attendu du dict** (au minimum) :
|
||
|
||
```python
|
||
{
|
||
"title": str, # Titre de la fenêtre
|
||
"app_name": str, # Nom de l'application
|
||
# champs optionnels utilisés par ScreenAnalyzer
|
||
"x": int, "y": int, "width": int, "height": int,
|
||
}
|
||
```
|
||
|
||
**Exemple Citrix** :
|
||
|
||
```python
|
||
def citrix_window_info():
|
||
# L'agent dans la session Citrix distante publie ces infos
|
||
# (par ex. via un fichier partagé ou une websocket)
|
||
return remote_agent.get_current_window_info()
|
||
|
||
loop = ExecutionLoop(
|
||
pipeline=pipeline,
|
||
window_info_provider=citrix_window_info,
|
||
)
|
||
```
|
||
|
||
## Combinaisons recommandées
|
||
|
||
| Cas d'usage | Flags |
|
||
|---|---|
|
||
| Production standard (GPU local) | `enable_ui_detection=True, enable_ocr=True, analyze_timeout_ms=8000` (défaut) |
|
||
| VLM down — mode fallback | `enable_ui_detection=False, enable_ocr=True` |
|
||
| Machine lente / VM | `analyze_timeout_ms=15000` |
|
||
| Citrix / RDP | `window_info_provider=<custom>` + valeurs par défaut |
|
||
| Benchmark CLIP-only | `enable_ui_detection=False, enable_ocr=False` |
|
||
|
||
## Remontée analytics
|
||
|
||
Les timings et flags dégradés persistent dans la table SQLite
|
||
`step_metrics` (colonnes `ocr_ms`, `ui_ms`, `analyze_ms`, `total_ms`,
|
||
`cache_hit`, `degraded`) via
|
||
[`AnalyticsExecutionIntegration.on_step_result`](../core/analytics/integration/execution_integration.py).
|
||
|
||
Exemple de requête d'analyse :
|
||
|
||
```sql
|
||
-- Steps avec OCR lent (>300 ms)
|
||
SELECT node_id, action_type, ocr_ms, analyze_ms
|
||
FROM step_metrics
|
||
WHERE ocr_ms > 300
|
||
ORDER BY ocr_ms DESC;
|
||
|
||
-- Taux de cache hit par workflow
|
||
SELECT workflow_id,
|
||
SUM(cache_hit) * 1.0 / COUNT(*) AS cache_hit_ratio
|
||
FROM step_metrics
|
||
GROUP BY workflow_id;
|
||
|
||
-- Steps ayant basculé en mode dégradé
|
||
SELECT execution_id, node_id, analyze_ms
|
||
FROM step_metrics
|
||
WHERE degraded = 1
|
||
ORDER BY started_at DESC;
|
||
```
|
||
|
||
## Voir aussi
|
||
|
||
- [`core/execution/execution_loop.py`](../core/execution/execution_loop.py) — implémentation
|
||
- [`core/pipeline/screen_analyzer.py`](../core/pipeline/screen_analyzer.py) — pipeline d'analyse
|
||
- [`core/pipeline/screen_state_cache.py`](../core/pipeline/screen_state_cache.py) — cache perceptuel
|
||
- [`tests/unit/test_execution_loop_vision_aware.py`](../tests/unit/test_execution_loop_vision_aware.py) — tests C1
|
||
- [`tests/unit/test_analytics_vision_metrics.py`](../tests/unit/test_analytics_vision_metrics.py) — tests analytics C1
|
||
- [docs/STATUS.md](STATUS.md) — état général du projet
|