From 5ceee9c39369125e48a5e56da58ebece0a21844c Mon Sep 17 00:00:00 2001 From: Dom Date: Tue, 31 Mar 2026 14:08:21 +0200 Subject: [PATCH] =?UTF-8?q?fix:=20cascade=20serveur-first=20=E2=80=94=20So?= =?UTF-8?q?mEngine=20avant=20template=20matching?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Le template matching compare des pixels et donne des faux positifs quand l'écran n'est pas dans le même état que l'enregistrement. SomEngine + VLM comprend sémantiquement ce qu'on cherche. Nouvelle cascade : 1. Serveur SomEngine + VLM (compréhension sémantique) 2. Template matching local (fallback si serveur down) 3. VLM local (fallback dev/test) Co-Authored-By: Claude Opus 4.6 (1M context) --- agent_v0/agent_v1/core/executor.py | 36 ++++++++++++++++-------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/agent_v0/agent_v1/core/executor.py b/agent_v0/agent_v1/core/executor.py index 8c16c4cb5..6fc3f8931 100644 --- a/agent_v0/agent_v1/core/executor.py +++ b/agent_v0/agent_v1/core/executor.py @@ -395,10 +395,15 @@ class ActionExecutorV1: ) -> dict: """Résoudre la position d'un clic visuellement. - Stratégie hybride en cascade : - 1. Template matching avec le crop anchor (rapide, fiable si l'UI n'a pas changé) - 2. Serveur resolve_target (SomEngine + VLM, si serveur accessible) - 3. VLM local (fallback pour dev/test Linux) + Stratégie en cascade — compréhension sémantique d'abord : + 1. Serveur resolve_target (SomEngine + VLM) — comprend CE QU'ON CHERCHE + 2. Template matching local (fallback rapide si serveur indisponible) + 3. VLM local (fallback dev/test Linux) + + Le template matching compare des pixels et donne des faux positifs quand + l'écran n'est pas dans le même état que l'enregistrement. Le SomEngine + comprend sémantiquement les éléments UI (bouton, menu, texte) et trouve + le bon élément peu importe l'état de l'écran. """ import time as _time t_start = _time.time() @@ -418,14 +423,8 @@ class ActionExecutorV1: result["resolution_elapsed_ms"] = round(elapsed_ms, 1) return result - # ---- ÉTAPE 1 : Template matching avec le crop anchor ---- - anchor_b64 = target_spec.get("anchor_image_base64", "") - if anchor_b64: - tm_result = self._template_match_anchor(screenshot_b64, anchor_b64, screen_width, screen_height) - if tm_result and tm_result.get("resolved"): - return _with_metrics(tm_result) - - # ---- ÉTAPE 2 : Résolution serveur (SomEngine + VLM) ---- + # ---- ÉTAPE 1 : Résolution serveur (SomEngine + VLM) ---- + # Le serveur comprend sémantiquement ce qu'on cherche. Pas de faux positifs. if server_url: server_result = self._server_resolve_target( server_url, screenshot_b64, target_spec, @@ -434,7 +433,14 @@ class ActionExecutorV1: if server_result and server_result.get("resolved"): return _with_metrics(server_result) - # ---- ÉTAPE 3 : VLM local (fallback dev/test, si Ollama accessible) ---- + # ---- ÉTAPE 2 : Template matching local (fallback si serveur down) ---- + anchor_b64 = target_spec.get("anchor_image_base64", "") + if anchor_b64: + tm_result = self._template_match_anchor(screenshot_b64, anchor_b64, screen_width, screen_height) + if tm_result and tm_result.get("resolved"): + return _with_metrics(tm_result) + + # ---- ÉTAPE 3 : VLM local (fallback dev/test Linux) ---- by_text = target_spec.get("by_text", "") vlm_description = target_spec.get("vlm_description", "") if vlm_description or by_text: @@ -444,10 +450,6 @@ class ActionExecutorV1: if hybrid_result and hybrid_result.get("resolved"): return _with_metrics(hybrid_result) - vlm_result = self._vlm_direct_resolve(screenshot_b64, target_spec) - if vlm_result and vlm_result.get("resolved"): - return _with_metrics(vlm_result) - print(" [VISUAL] Toutes les méthodes ont échoué") return None