fix: cascade serveur-first — SomEngine avant template matching

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) <noreply@anthropic.com>
This commit is contained in:
Dom
2026-03-31 14:08:21 +02:00
parent 5e0b53cfd1
commit 5ceee9c393

View File

@@ -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