mirror of
https://github.com/Ladebeze66/llm_ticket3.git
synced 2025-12-15 21:56:49 +01:00
212 lines
8.6 KiB
Python
212 lines
8.6 KiB
Python
from ..base_agent import BaseAgent
|
|
import logging
|
|
import os
|
|
from typing import Dict, Any
|
|
from PIL import Image
|
|
from ..utils.pipeline_logger import sauvegarder_donnees
|
|
|
|
logger = logging.getLogger("AgentImageAnalyser")
|
|
|
|
class AgentImageAnalyser(BaseAgent):
|
|
"""
|
|
Agent pour analyser les images et extraire les informations pertinentes.
|
|
"""
|
|
def __init__(self, llm):
|
|
super().__init__("AgentImageAnalyser", llm)
|
|
|
|
# Configuration personnalisable
|
|
self.params = {
|
|
"temperature": 0.2,
|
|
"top_p": 0.9,
|
|
"max_tokens": 3000
|
|
}
|
|
|
|
self.instructions_analyse = (
|
|
"""
|
|
1. Description objective
|
|
Décris précisément ce que montre l'image :
|
|
- Interface logicielle, menus, fenêtres, onglets
|
|
- Messages d'erreur, messages système, code ou script
|
|
- Nom ou titre du logiciel ou du module si visible
|
|
|
|
2. Éléments techniques clés
|
|
Identifie :
|
|
- Versions logicielles ou modules affichés
|
|
- Codes d'erreur visibles
|
|
- Paramètres configurables (champs de texte, sliders, dropdowns, cases à cocher)
|
|
- Valeurs affichées ou préremplies dans les champs
|
|
- Éléments désactivés, grisés ou masqués (souvent non modifiables)
|
|
- Boutons actifs/inactifs
|
|
|
|
3. Éléments mis en évidence
|
|
- Recherche les zones entourées, encadrées, surlignées ou fléchées
|
|
- Ces éléments sont souvent importants pour le client ou le support
|
|
- Mentionne explicitement leur contenu et leur style de mise en valeur
|
|
|
|
4. Relation avec le problème
|
|
- Établis le lien entre les éléments visibles et le problème décrit dans le ticket
|
|
- Indique si des composants semblent liés à une mauvaise configuration ou une erreur
|
|
|
|
5. Réponses potentielles
|
|
- Détermine si l'image apporte des éléments de réponse à une question posée dans :
|
|
- Le titre du ticket
|
|
- La description du problème
|
|
|
|
6. Lien avec la discussion
|
|
- Vérifie si l'image fait écho à une étape décrite dans le fil de discussion
|
|
- Note les correspondances (ex: même module, même message d'erreur que précédemment mentionné)
|
|
|
|
Règles importantes :
|
|
- Ne fais AUCUNE interprétation ni diagnostic
|
|
- Ne propose PAS de solution ou recommandation
|
|
- Reste strictement factuel et objectif
|
|
- Concentre-toi uniquement sur ce qui est visible dans l'image
|
|
- Reproduis les textes exacts(ex : messages d'erreur, libellés de paramètres)
|
|
- Prête une attention particulière aux éléments modifiables (interactifs) et non modifiables (grisés)
|
|
"""
|
|
)
|
|
|
|
self.system_prompt = (
|
|
"""
|
|
Tu es un expert en analyse d'images pour le support technique de BRG-Lab pour la société CBAO.
|
|
Ta mission est d'analyser des captures d'écran en lien avec le contexte du ticket de support.
|
|
|
|
Structure ton analyse d'image de façon factuelle:
|
|
{instructions}
|
|
|
|
Ton analyse sera utilisée comme élément factuel pour un rapport technique plus complet.
|
|
"""
|
|
).format(
|
|
instructions=self.instructions_analyse
|
|
)
|
|
|
|
self._appliquer_config_locale()
|
|
logger.info("AgentImageAnalyser initialisé")
|
|
|
|
def _appliquer_config_locale(self) -> None:
|
|
"""
|
|
Applique la configuration locale au modèle LLM.
|
|
"""
|
|
if hasattr(self.llm, "prompt_system"):
|
|
self.llm.prompt_system = self.system_prompt
|
|
|
|
if hasattr(self.llm, "configurer"):
|
|
self.llm.configurer(**self.params)
|
|
|
|
def _verifier_image(self, image_path: str) -> bool:
|
|
"""
|
|
Vérifie si l'image existe et est accessible
|
|
"""
|
|
try:
|
|
if not os.path.exists(image_path) or not os.access(image_path, os.R_OK):
|
|
return False
|
|
|
|
with Image.open(image_path) as img:
|
|
width, height = img.size
|
|
return width > 0 and height > 0
|
|
except Exception as e:
|
|
logger.error(f"Vérification impossible pour {image_path}: {e}")
|
|
return False
|
|
|
|
def _generer_prompt_analyse(self, contexte: str, prefix: str = "") -> str:
|
|
"""
|
|
Génère le prompt d'analyse d'image
|
|
"""
|
|
return f"""{prefix}
|
|
|
|
CONTEXTE DU TICKET:
|
|
{contexte}
|
|
|
|
Fournis une analyse STRICTEMENT FACTUELLE de l'image avec les sections suivantes:
|
|
{self.instructions_analyse}"""
|
|
|
|
def executer(self, image_path: str, contexte: str = "") -> Dict[str, Any]:
|
|
"""
|
|
Analyse une image en tenant compte du contexte du ticket
|
|
"""
|
|
image_name = os.path.basename(image_path)
|
|
print(f" AgentImageAnalyser: Analyse de {image_name}")
|
|
|
|
if not self._verifier_image(image_path):
|
|
return self._erreur("Erreur d'accès ou image invalide", image_path)
|
|
|
|
try:
|
|
prompt = self._generer_prompt_analyse(contexte, "Analyse cette image en tenant compte du contexte suivant:")
|
|
|
|
if hasattr(self.llm, "interroger_avec_image"):
|
|
response = self.llm.interroger_avec_image(image_path, prompt)
|
|
elif hasattr(self.llm, "_encoder_image_base64"):
|
|
img_base64 = self.llm._encoder_image_base64(image_path)
|
|
if img_base64:
|
|
prompt_base64 = self._generer_prompt_analyse(contexte, f"Analyse cette image:\n{img_base64}")
|
|
response = self.llm.interroger(prompt_base64)
|
|
else:
|
|
return self._erreur("Impossible d'encoder l'image en base64", image_path)
|
|
else:
|
|
return self._erreur("Le modèle ne supporte pas l'analyse d'images", image_path)
|
|
|
|
# Vérifier si la réponse contient des indications que le modèle ne peut pas analyser l'image
|
|
error_phrases = [
|
|
"je ne peux pas directement visualiser",
|
|
"je n'ai pas accès à l'image",
|
|
"je ne peux pas voir l'image",
|
|
"sans accès direct à l'image",
|
|
"je n'ai pas la possibilité de voir",
|
|
"je ne peux pas accéder directement",
|
|
"erreur: impossible d'analyser l'image"
|
|
]
|
|
|
|
if any(phrase in response.lower() for phrase in error_phrases):
|
|
return self._erreur("Le modèle n'a pas pu analyser l'image correctement", image_path, raw=response)
|
|
|
|
result = {
|
|
"analyse": response,
|
|
"raw_response": response,
|
|
"metadata": {
|
|
"image_path": image_path,
|
|
"image_name": image_name,
|
|
"timestamp": self._get_timestamp(),
|
|
"model_info": {
|
|
"model": getattr(self.llm, "modele", str(type(self.llm))),
|
|
**getattr(self.llm, "params", {})
|
|
},
|
|
"source_agent": self.nom
|
|
}
|
|
}
|
|
|
|
# Sauvegarder les données dans le fichier
|
|
sauvegarder_donnees(None, "analyse_image", result, base_dir="reports", is_resultat=True)
|
|
|
|
# Enregistrer l'analyse dans l'historique
|
|
self.ajouter_historique(
|
|
"analyse_image",
|
|
{"image_path": image_path, "contexte": contexte, "prompt": prompt},
|
|
result
|
|
)
|
|
|
|
return result
|
|
|
|
except Exception as e:
|
|
return self._erreur(str(e), image_path)
|
|
|
|
def _erreur(self, message: str, path: str, raw: str = "") -> Dict[str, Any]:
|
|
"""
|
|
Crée un dictionnaire de réponse en cas d'erreur
|
|
"""
|
|
return {
|
|
"analyse": f"ERREUR: {message}",
|
|
"raw_response": raw,
|
|
"error": True,
|
|
"metadata": {
|
|
"image_path": path,
|
|
"image_name": os.path.basename(path),
|
|
"timestamp": self._get_timestamp(),
|
|
"error": True,
|
|
"source_agent": self.nom
|
|
}
|
|
}
|
|
|
|
def _get_timestamp(self) -> str:
|
|
"""Retourne un timestamp au format YYYYMMDD_HHMMSS"""
|
|
from datetime import datetime
|
|
return datetime.now().strftime("%Y%m%d_%H%M%S") |