mirror of
https://github.com/Ladebeze66/llm_ticket3.git
synced 2025-12-16 21:37:49 +01:00
189 lines
7.6 KiB
Python
189 lines
7.6 KiB
Python
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
|
|
import os
|
|
import json
|
|
import logging
|
|
from typing import Dict, Any, Optional
|
|
from datetime import datetime
|
|
|
|
# Importer BaseAgent depuis le répertoire utils
|
|
from agents.utils.base_agent import BaseAgent
|
|
|
|
logger = logging.getLogger("AgentImageAnalyser_Pixtral12b")
|
|
|
|
class AgentImageAnalyser(BaseAgent):
|
|
"""
|
|
Agent pour analyser en détail les images des tickets.
|
|
Utilise un LLM avec capacités de vision pour décrire et analyser le contenu des images.
|
|
"""
|
|
def __init__(self, llm):
|
|
super().__init__(llm)
|
|
|
|
# Configuration locale de l'agent
|
|
self.system_prompt = """Tu es un expert en analyse d'images techniques.
|
|
Ta mission est d'analyser en détail des captures d'écran et images techniques pour le support informatique.
|
|
|
|
Tu dois:
|
|
1. Décrire précisément le contenu visible de l'image
|
|
2. Identifier tout texte, message d'erreur ou information technique visible
|
|
3. Repérer les problèmes potentiels ou anomalies visibles
|
|
4. Fournir un contexte sur ce que l'image montre dans le cadre d'un problème informatique
|
|
|
|
Sois factuel, précis et exhaustif dans ton analyse. Concentre-toi sur les aspects techniques.
|
|
Format ta réponse de manière structurée pour faciliter la compréhension.
|
|
"""
|
|
|
|
def executer(self, image_path: str, contexte: Optional[str] = None) -> Dict[str, Any]:
|
|
"""
|
|
Analyse une image en détail pour en extraire les informations pertinentes.
|
|
|
|
Args:
|
|
image_path: Chemin vers l'image à analyser
|
|
contexte: Contexte optionnel sur le ticket pour aider à l'analyse
|
|
|
|
Returns:
|
|
Dictionnaire contenant l'analyse détaillée de l'image
|
|
"""
|
|
image_name = os.path.basename(image_path)
|
|
logger.info(f"Analyse détaillée de l'image: {image_name}")
|
|
|
|
# Vérifier que l'image existe
|
|
if not os.path.exists(image_path):
|
|
logger.error(f"L'image n'existe pas: {image_path}")
|
|
return {
|
|
"error": True,
|
|
"message": f"L'image n'existe pas: {image_name}",
|
|
"image_path": image_path
|
|
}
|
|
|
|
# Préparer le prompt avec le contexte si disponible
|
|
prompt_base = "Analyse cette image en détail et réponds au format JSON."
|
|
if contexte:
|
|
prompt_base = f"Analyse cette image en détail dans le contexte suivant:\n{contexte}\n\nRéponds au format JSON."
|
|
|
|
prompt = f"""{prompt_base}
|
|
Analyse chaque élément important visible et fournit une description détaillée.
|
|
|
|
Format JSON attendu:
|
|
{{
|
|
"description_generale": "Description générale de ce que montre l'image",
|
|
"elements_techniques": ["Liste des éléments techniques visibles"],
|
|
"texte_visible": "Tout texte important visible dans l'image",
|
|
"messages_erreur": ["Liste des messages d'erreur si présents"],
|
|
"problemes_identifies": ["Liste des problèmes potentiels identifiés"],
|
|
"contexte_technique": "Explication du contexte technique de cette image",
|
|
"recommandations": ["Suggestions basées sur ce qui est visible"]
|
|
}}"""
|
|
|
|
# Effectuer l'analyse via le LLM
|
|
try:
|
|
# Utiliser la méthode d'interrogation avec image
|
|
resultat_brut = self.llm.interroger_avec_image(image_path, prompt)
|
|
|
|
# Tenter d'extraire le JSON de la réponse
|
|
json_str = self._extraire_json(resultat_brut)
|
|
if json_str:
|
|
try:
|
|
# Charger le JSON
|
|
analyse = json.loads(json_str)
|
|
|
|
# Ajouter des métadonnées
|
|
analyse["image_path"] = image_path
|
|
analyse["image_name"] = image_name
|
|
analyse["timestamp"] = self._get_timestamp()
|
|
analyse["source"] = "agent_image_analyser"
|
|
|
|
# Ajouter la réponse brute pour référence
|
|
analyse["raw_response"] = resultat_brut
|
|
|
|
logger.info(f"Analyse complétée avec succès pour {image_name}")
|
|
return analyse
|
|
except json.JSONDecodeError as e:
|
|
logger.error(f"Erreur de décodage JSON pour {image_name}: {e}")
|
|
# Fournir une analyse de secours plus simple
|
|
return self._analyse_fallback(resultat_brut, image_path)
|
|
else:
|
|
logger.warning(f"Format de réponse non-JSON pour {image_name}")
|
|
# Fournir une analyse de secours plus simple
|
|
return self._analyse_fallback(resultat_brut, image_path)
|
|
except Exception as e:
|
|
logger.error(f"Erreur lors de l'analyse de l'image {image_name}: {str(e)}")
|
|
return {
|
|
"error": True,
|
|
"message": f"Erreur d'analyse: {str(e)}",
|
|
"image_path": image_path,
|
|
"image_name": image_name,
|
|
"timestamp": self._get_timestamp()
|
|
}
|
|
|
|
def _extraire_json(self, texte: str) -> Optional[str]:
|
|
"""
|
|
Extrait le contenu JSON d'une chaîne de texte.
|
|
|
|
Args:
|
|
texte: Texte contenant potentiellement du JSON
|
|
|
|
Returns:
|
|
Chaîne JSON extraite ou None si aucun JSON n'est trouvé
|
|
"""
|
|
# Chercher des accolades ouvrantes et fermantes
|
|
debut = texte.find('{')
|
|
fin = texte.rfind('}')
|
|
|
|
if debut != -1 and fin != -1 and fin > debut:
|
|
return texte[debut:fin+1]
|
|
|
|
return None
|
|
|
|
def _analyse_fallback(self, texte: str, image_path: str) -> Dict[str, Any]:
|
|
"""
|
|
Crée une analyse de secours quand le format JSON n'est pas utilisable.
|
|
|
|
Args:
|
|
texte: Texte de l'analyse brute
|
|
image_path: Chemin de l'image
|
|
|
|
Returns:
|
|
Dictionnaire avec l'analyse simplifiée
|
|
"""
|
|
image_name = os.path.basename(image_path)
|
|
|
|
# Diviser le texte en paragraphes
|
|
paragraphes = [p.strip() for p in texte.split('\n\n') if p.strip()]
|
|
|
|
# Extraire ce qui pourrait être une description générale (premier paragraphe)
|
|
description = paragraphes[0] if paragraphes else "Analyse non disponible au format JSON"
|
|
|
|
# Chercher des éléments techniques ou messages d'erreur
|
|
elements_techniques = []
|
|
messages_erreur = []
|
|
|
|
for p in paragraphes[1:]:
|
|
if "erreur" in p.lower() or "error" in p.lower() or "exception" in p.lower():
|
|
messages_erreur.append(p)
|
|
elif any(terme in p.lower() for terme in ["technique", "système", "logiciel", "interface", "configuration"]):
|
|
elements_techniques.append(p)
|
|
|
|
# Construire un dictionnaire simplifié
|
|
analyse = {
|
|
"description_generale": description,
|
|
"elements_techniques": elements_techniques,
|
|
"messages_erreur": messages_erreur,
|
|
"texte_visible": "Extraction de texte non disponible",
|
|
"problemes_identifies": [],
|
|
"contexte_technique": "Contexte non disponible au format JSON",
|
|
"recommandations": [],
|
|
"image_path": image_path,
|
|
"image_name": image_name,
|
|
"timestamp": self._get_timestamp(),
|
|
"source": "agent_image_analyser",
|
|
"format_fallback": True,
|
|
"raw_response": texte
|
|
}
|
|
|
|
return analyse
|
|
|
|
def _get_timestamp(self) -> str:
|
|
"""Retourne un timestamp au format YYYYMMDD_HHMMSS"""
|
|
return datetime.now().strftime("%Y%m%d_%H%M%S") |