# Utilisation de Qwen3-VL dans le Système ## Vue d'ensemble **Qwen3-VL:8b** est un modèle vision-langage utilisé via **Ollama** pour le raisonnement visuel et la prise de décision intelligente. ## Architecture ``` ┌─────────────────┐ │ Screenshots │ │ + Détections │ └────────┬────────┘ │ ▼ ┌─────────────────┐ │ LLM Manager │ ← Interface Python └────────┬────────┘ │ ▼ ┌─────────────────┐ │ Ollama │ ← Serveur local (localhost:11434) └────────┬────────┘ │ ▼ ┌─────────────────┐ │ Qwen3-VL:8b │ ← Modèle vision-langage └─────────────────┘ ``` ## Configuration Dans `config.py` : ```python "llm": "qwen3-vl:8b", "ollama": { "host": "localhost:11434", "timeout": 30 } ``` ## Trois Usages Principaux ### 1. Raisonnement sur les Détections **Quand ?** Après que OWL-v2/DINO/YOLO ont détecté plusieurs éléments UI **Pourquoi ?** Pour choisir intelligemment le bon élément parmi plusieurs candidats **Comment ?** ```python # Dans orchestrator.py, ligne 525 llm_result = self.llm.reason_about_detections( detections_data, # Liste des éléments détectés context, # Fenêtre active, historique intent # Intention de l'utilisateur ) ``` **Exemple concret :** ``` Situation : 3 boutons détectés sur l'écran - Bouton "Annuler" (confiance: 0.92) - Bouton "Enregistrer" (confiance: 0.88) - Bouton "Fermer" (confiance: 0.85) Intention utilisateur : "Sauvegarder le document" Qwen3-VL analyse les screenshots + le contexte et répond : { "element_index": 1, "confidence": 0.95, "reasoning": "Le bouton 'Enregistrer' correspond à l'intention de sauvegarder" } ``` **Entrées envoyées à Qwen3-VL :** - **Images** : Screenshots des ROI (régions d'intérêt) de chaque élément détecté, encodés en base64 - **Prompt** : Description textuelle avec l'intention et le contexte - **Format** : Demande une réponse JSON structurée **Sortie attendue :** ```json { "element_index": 1, "confidence": 0.95, "reasoning": "Explication du choix" } ``` ### 2. Génération avec Vision **Quand ?** Pour analyser des screenshots et générer des descriptions **Pourquoi ?** Pour comprendre ce qui se passe dans l'interface **Comment ?** ```python response = llm_manager.generate_with_vision( prompt="Décris cette interface utilisateur", images=[screenshot] ) ``` **Exemple :** ``` Input : Screenshot d'une fenêtre + prompt "Que vois-tu ?" Qwen3-VL répond : "Je vois une fenêtre de traitement de texte avec une barre d'outils en haut contenant des boutons pour enregistrer, imprimer et formater le texte. Le document actuel semble être vide." ``` ### 3. Score de Pertinence d'Action **Quand ?** Pour évaluer si une action proposée est pertinente **Pourquoi ?** Pour éviter d'exécuter des actions incorrectes **Comment ?** ```python score = llm_manager.score_action_relevance( action={"action_type": "click", "target_element": "button"}, intent="Fermer la fenêtre" ) # Retourne : 0.85 (très pertinent) ``` ## Flux de Données Complet ### Exemple : Détection d'un pattern de 3 clics ``` 1. Utilisateur clique 3 fois sur un bouton ↓ 2. EventCapture détecte le pattern répétitif ↓ 3. Orchestrator récupère les 3 screenshots ↓ 4. VisionAnalysis crée les signatures visuelles ↓ 5. OWL-v2/DINO/YOLO détectent les éléments UI ↓ 6. LLMManager envoie à Qwen3-VL : - Screenshots des éléments (base64) - Contexte : "Fenêtre Firefox, 3 clics répétés" - Intention : "Rafraîchir la page" ↓ 7. Qwen3-VL analyse et répond : { "element_index": 0, "confidence": 0.92, "reasoning": "C'est le bouton de rafraîchissement" } ↓ 8. Orchestrator crée une tâche apprise ↓ 9. Prochaine fois, le système peut rejouer automatiquement ``` ## Format des Images Envoyées Les images sont converties en base64 PNG : ```python def _image_to_base64(self, image: np.ndarray) -> str: # 1. Convertir numpy array en PIL Image pil_image = Image.fromarray(image.astype(np.uint8)) # 2. Encoder en PNG buffered = BytesIO() pil_image.save(buffered, format="PNG") # 3. Convertir en base64 img_str = base64.b64encode(buffered.getvalue()).decode() return img_str ``` ## Fallback Automatique Si Qwen3-VL n'est pas disponible (Ollama arrêté, modèle non téléchargé), le système utilise un **fallback** : ```python def _fallback_to_vision_only(self, detections): # Sélectionne simplement l'élément avec la confiance la plus élevée best_detection = max(detections, key=lambda d: d['confidence']) return { "selected_element": best_detection, "confidence": best_detection['confidence'], "reasoning": "Sélection basée sur la confiance vision (fallback)" } ``` ## Vérifier que Qwen3-VL fonctionne ```bash # 1. Vérifier qu'Ollama est lancé curl http://localhost:11434/api/tags # 2. Lister les modèles disponibles ollama list # 3. Si qwen3-vl:8b n'est pas là, le télécharger ollama pull qwen3-vl:8b # 4. Tester le modèle ollama run qwen3-vl:8b "Bonjour" ``` ## Logs et Debugging Le LLMManager log toutes ses actions : ```python self.logger.log_action({ "action": "llm_reasoning", "intent": intent, "num_detections": len(detections), "selected_index": result.get("element_index"), "confidence": result.get("confidence") }) ``` Cherche dans `data/logs/` pour voir l'historique des décisions de Qwen3-VL. ## Performance - **Latence** : ~1-2 secondes par requête (dépend du GPU) - **Mémoire** : ~8 GB VRAM pour le modèle 8b - **Précision** : Excellente pour le raisonnement visuel UI ## Différence avec les Modèles de Détection | Modèle | Rôle | Sortie | |--------|------|--------| | **OWL-v2/DINO/YOLO** | Détection d'objets | Bounding boxes + labels | | **Qwen3-VL** | Raisonnement | Décision intelligente + explication | **Exemple :** - OWL-v2 dit : "J'ai trouvé 3 boutons" - Qwen3-VL dit : "Le bouton du milieu est le bon car il correspond à l'intention de sauvegarder" ## Résumé Qwen3-VL est le **cerveau** du système qui : 1. ✅ Comprend le contexte visuel 2. ✅ Raisonne sur les intentions 3. ✅ Prend des décisions intelligentes 4. ✅ Explique ses choix Les modèles de détection (OWL-v2, DINO, YOLO) sont les **yeux** qui trouvent les éléments, mais Qwen3-VL est le **cerveau** qui décide quoi faire avec.