# 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=` + 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