mirror of
https://github.com/Ladebeze66/llm_ticket3.git
synced 2025-12-17 15:07:47 +01:00
195 lines
7.4 KiB
Python
195 lines
7.4 KiB
Python
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
|
|
import os
|
|
import json
|
|
import time
|
|
import logging
|
|
import base64
|
|
from typing import Dict, Any, List, Optional, Tuple
|
|
|
|
# Importer BaseAgent depuis le répertoire utils
|
|
from agents.utils.base_agent import BaseAgent
|
|
|
|
# Configuration du logging
|
|
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
|
logger = logging.getLogger("AgentImageAnalyser_Pixtral12b")
|
|
|
|
class AgentImageAnalyser(BaseAgent):
|
|
"""
|
|
Agent spécialisé pour analyser des images et en extraire les informations pertinentes.
|
|
Version optimisée pour Pixtral 12B.
|
|
"""
|
|
|
|
def __init__(self, llm: Any):
|
|
"""
|
|
Initialise l'agent d'analyse d'images avec un modèle LLM.
|
|
|
|
Args:
|
|
llm: Instance du modèle de langage à utiliser
|
|
"""
|
|
super().__init__(llm)
|
|
self.temperature = 0.1 # Température basse pour des analyses factuelles
|
|
self.top_p = 0.9
|
|
self.max_tokens = 3000
|
|
|
|
# System prompt spécifique pour l'analyse d'images
|
|
self.system_prompt = """Tu es un expert en analyse d'images de captures d'écran d'applications métier.
|
|
Tu vas analyser des images techniques pour en extraire des informations pertinentes.
|
|
|
|
Pour chaque image, tu dois :
|
|
1. Identifier le type d'interface visible (formulaire, tableau, menu, etc.)
|
|
2. Extraire tous les éléments visuels importants (champs, boutons, menus, messages)
|
|
3. Repérer les anomalies ou problèmes visibles (erreurs, incohérences, éléments manquants)
|
|
4. Identifier le contexte fonctionnel de l'image (à quelle fonctionnalité elle correspond)
|
|
|
|
Ta réponse suivra ce format structuré :
|
|
|
|
```
|
|
## Analyse de l'image: [Titre basé sur le contenu]
|
|
|
|
### Description générale
|
|
- Type d'interface: [type d'interface identifié]
|
|
- Éléments principaux: [liste des éléments UI dominants]
|
|
- Contexte fonctionnel: [fonctionnalité ou module apparent]
|
|
|
|
### Éléments détaillés
|
|
- [Liste détaillée des éléments visibles importants]
|
|
- [Valeurs de champs, options sélectionnées, etc.]
|
|
- [Messages système ou d'erreur si présents]
|
|
|
|
### Anomalies détectées
|
|
- [Description précise des problèmes visibles]
|
|
- [Éléments manquants ou incohérents]
|
|
- [Messages d'erreur et leur contexte]
|
|
|
|
### Interprétation technique
|
|
- [Explication technique de ce qui est affiché]
|
|
- [Relation avec le problème décrit dans le ticket]
|
|
- [Indications sur la source probable du problème]
|
|
```
|
|
|
|
Reste factuel et précis. Ne spécule pas au-delà de ce qui est clairement visible.
|
|
Concentre-toi sur les détails techniques plutôt que sur l'esthétique de l'interface."""
|
|
|
|
def executer(self, images: List[Dict[str, Any]], ticket_analyse: Optional[str] = None) -> List[Dict[str, Any]]:
|
|
"""
|
|
Analyse une liste d'images pour en extraire les informations pertinentes.
|
|
|
|
Args:
|
|
images: Liste de dictionnaires contenant les informations sur les images
|
|
- 'path': Chemin de l'image
|
|
- 'type': Type de l'image
|
|
- 'nom': Nom de l'image
|
|
ticket_analyse: Analyse du ticket (contexte pour l'analyse des images)
|
|
|
|
Returns:
|
|
Liste de dictionnaires contenant les analyses d'images
|
|
"""
|
|
results = []
|
|
|
|
if not images:
|
|
logger.warning("Aucune image à analyser")
|
|
return results
|
|
|
|
logger.info(f"Analyse de {len(images)} images")
|
|
print(f" Analyse de {len(images)} images")
|
|
|
|
# Analyser chaque image
|
|
for i, image_info in enumerate(images, 1):
|
|
image_path = image_info.get('path', '')
|
|
image_name = image_info.get('nom', os.path.basename(image_path))
|
|
|
|
if not os.path.exists(image_path):
|
|
logger.warning(f"Image non trouvée: {image_path}")
|
|
results.append({
|
|
"image": image_info,
|
|
"analyse": f"ERREUR: Image non trouvée: {image_path}",
|
|
"pertinent": False
|
|
})
|
|
continue
|
|
|
|
logger.info(f"Analyse de l'image {i}/{len(images)}: {image_name}")
|
|
print(f" Analyse de l'image {i}/{len(images)}: {image_name}")
|
|
|
|
start_time = time.time()
|
|
|
|
try:
|
|
# Encoder l'image en base64
|
|
image_base64 = self._encoder_image_base64(image_path)
|
|
|
|
# Construire le prompt pour l'analyse
|
|
prompt = self._construire_prompt_image(image_name, ticket_analyse)
|
|
|
|
# Analyser l'image avec le LLM
|
|
analyse = self.llm.generate_vision(
|
|
system_prompt=self.system_prompt,
|
|
prompt=prompt,
|
|
image_base64=image_base64,
|
|
temperature=self.temperature,
|
|
top_p=self.top_p,
|
|
max_tokens=self.max_tokens
|
|
)
|
|
|
|
# Calculer le temps d'analyse
|
|
analysis_time = time.time() - start_time
|
|
|
|
# Log de l'analyse complétée
|
|
logger.info(f"Analyse de l'image {image_name} complétée en {analysis_time:.2f} secondes")
|
|
print(f" Analyse complétée en {analysis_time:.2f} secondes")
|
|
|
|
# Ajouter le résultat à la liste
|
|
results.append({
|
|
"image": image_info,
|
|
"analyse": analyse,
|
|
"pertinent": True,
|
|
"analysis_time": analysis_time
|
|
})
|
|
|
|
except Exception as e:
|
|
error_message = f"Erreur lors de l'analyse de l'image {image_name}: {str(e)}"
|
|
logger.error(error_message)
|
|
print(f" ERREUR: {error_message}")
|
|
|
|
results.append({
|
|
"image": image_info,
|
|
"analyse": f"ERREUR: {error_message}",
|
|
"pertinent": False
|
|
})
|
|
|
|
return results
|
|
|
|
def _encoder_image_base64(self, image_path: str) -> str:
|
|
"""
|
|
Encode une image en base64.
|
|
|
|
Args:
|
|
image_path: Chemin de l'image à encoder
|
|
|
|
Returns:
|
|
Chaîne encodée en base64
|
|
"""
|
|
with open(image_path, "rb") as image_file:
|
|
return base64.b64encode(image_file.read()).decode('utf-8')
|
|
|
|
def _construire_prompt_image(self, image_name: str, ticket_analyse: Optional[str] = None) -> str:
|
|
"""
|
|
Construit un prompt pour l'analyse d'une image.
|
|
|
|
Args:
|
|
image_name: Nom de l'image à analyser
|
|
ticket_analyse: Analyse du ticket (contexte pour l'analyse de l'image)
|
|
|
|
Returns:
|
|
Prompt pour l'analyse de l'image
|
|
"""
|
|
prompt = f"Analyse cette capture d'écran: {image_name}\n\n"
|
|
|
|
if ticket_analyse:
|
|
prompt += "### Contexte du ticket\n"
|
|
prompt += f"{ticket_analyse[:1000]}...\n\n" if len(ticket_analyse) > 1000 else f"{ticket_analyse}\n\n"
|
|
|
|
prompt += "Examine attentivement tous les éléments visuels, repère les anomalies, et identifie les informations techniques pertinentes. "
|
|
prompt += "Fournis une analyse complète et structurée de cette image selon le format demandé."
|
|
|
|
return prompt |