feat(vwb): Ajouter SeeClick, Self-Healing interactif et Dashboard confiance
## Nouvelles fonctionnalités ### 1. SeeClick Adapter (visual grounding fallback) - Nouvel adapter pour le modèle SeeClick (HuggingFace) - Intégré dans la chaîne de fallback: CLIP → Template → SeeClick → Static - Localise les éléments GUI à partir de descriptions textuelles ### 2. Self-Healing Interactif - Dialogue qui propose des alternatives quand l'ancre n'est pas trouvée - L'utilisateur peut choisir: candidat alternatif, coords statiques, ou sauter - Nouveaux endpoints: /healing/status, /healing/choose, /healing/candidates - État "waiting_for_choice" pour mettre l'exécution en pause ### 3. Dashboard Confiance (temps réel) - Affiche les scores de confiance pendant l'exécution - Montre: méthode utilisée, distance, taux de succès - Interface pliable en bas à droite - Visible uniquement en mode intelligent/debug ## Fichiers ajoutés - core/detection/seeclick_adapter.py - frontend_v4/src/components/SelfHealingDialog.tsx - frontend_v4/src/components/ConfidenceDashboard.tsx ## Fichiers modifiés - core/detection/__init__.py - backend/services/intelligent_executor.py - backend/api_v3/execute.py - frontend_v4/src/App.tsx - frontend_v4/src/services/api.ts - docs/VISION_RPA_INTELLIGENT.md Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -6,11 +6,18 @@ Utilise UI-DETR-1 pour la détection et le matching d'ancres visuelles
|
||||
import time
|
||||
import base64
|
||||
import io
|
||||
import sys
|
||||
import os
|
||||
from typing import Dict, Any, Optional, List, Tuple
|
||||
from dataclasses import dataclass
|
||||
from PIL import Image
|
||||
import numpy as np
|
||||
|
||||
# Ajouter le chemin racine pour les imports de core
|
||||
RPA_ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
||||
if RPA_ROOT not in sys.path:
|
||||
sys.path.insert(0, RPA_ROOT)
|
||||
|
||||
# Import du service de détection UI
|
||||
from .ui_detection_service import detect_ui_elements, DetectionResult, UIElement
|
||||
|
||||
@@ -764,7 +771,53 @@ def find_and_click(
|
||||
global_result['search_time_ms'] = (_time.time() - start_time) * 1000
|
||||
return global_result
|
||||
|
||||
# === STRATÉGIE 4: Coordonnées statiques (dernier recours) ===
|
||||
# === STRATÉGIE 4: SeeClick (visual grounding) ===
|
||||
# Essayer SeeClick si les autres méthodes ont échoué
|
||||
try:
|
||||
print("🎯 [Vision] Essai SeeClick (visual grounding)...")
|
||||
from core.detection.seeclick_adapter import get_seeclick
|
||||
|
||||
seeclick = get_seeclick()
|
||||
if seeclick.available:
|
||||
# Utiliser une description générique basée sur l'ancre
|
||||
# TODO: Améliorer avec une description plus précise
|
||||
description = "the clickable element or button"
|
||||
|
||||
grounding_result = seeclick.ground(screen_image, description, return_pixels=True)
|
||||
|
||||
if grounding_result.found:
|
||||
found_x = grounding_result.x_pixel
|
||||
found_y = grounding_result.y_pixel
|
||||
|
||||
# Vérifier la distance à la position originale si anchor_bbox existe
|
||||
accept_seeclick = True
|
||||
if anchor_bbox:
|
||||
orig_x = anchor_bbox.get('x', 0) + anchor_bbox.get('width', 0) // 2
|
||||
orig_y = anchor_bbox.get('y', 0) + anchor_bbox.get('height', 0) // 2
|
||||
distance = np.sqrt((found_x - orig_x)**2 + (found_y - orig_y)**2)
|
||||
|
||||
MAX_SEECLICK_DISTANCE = 200 # Plus permissif car c'est un fallback
|
||||
if distance > MAX_SEECLICK_DISTANCE:
|
||||
print(f"⛔ [Vision] SeeClick rejeté: distance {distance:.0f}px > {MAX_SEECLICK_DISTANCE}px max")
|
||||
accept_seeclick = False
|
||||
|
||||
if accept_seeclick:
|
||||
print(f"✅ [Vision] SeeClick réussi! Coordonnées: ({found_x}, {found_y})")
|
||||
return {
|
||||
'found': True,
|
||||
'confidence': grounding_result.confidence,
|
||||
'coordinates': {'x': found_x, 'y': found_y},
|
||||
'bbox': anchor_bbox,
|
||||
'method': 'seeclick_grounding',
|
||||
'search_time_ms': (_time.time() - start_time) * 1000,
|
||||
'raw_output': grounding_result.raw_output
|
||||
}
|
||||
except ImportError:
|
||||
print("ℹ️ [Vision] SeeClick non disponible (module non trouvé)")
|
||||
except Exception as seeclick_err:
|
||||
print(f"⚠️ [Vision] Erreur SeeClick: {seeclick_err}")
|
||||
|
||||
# === STRATÉGIE 5: Coordonnées statiques (dernier recours) ===
|
||||
if anchor_bbox:
|
||||
best_conf = max(global_result.get('confidence', 0), 0)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user