llm_ticket3/agents/mistral_large/agent_ticket_analyser.py
2025-04-17 17:32:02 +02:00

198 lines
7.7 KiB
Python

from ..base_agent import BaseAgent
from typing import Dict, Any
import logging
import json
import os
from datetime import datetime
from loaders.ticket_data_loader import TicketDataLoader
from ..utils.pipeline_logger import sauvegarder_donnees
logger = logging.getLogger("AgentTicketAnalyser")
class AgentTicketAnalyser(BaseAgent):
def __init__(self, llm):
super().__init__("AgentTicketAnalyser", llm)
self.temperature = 0.1
self.top_p = 0.2
self.max_tokens = 7000
self.system_prompt = """Tu es un expert en analyse de tickets pour le support informatique de BRG-Lab pour la société CBAO.
Tu interviens avant l'analyse des captures d'écran pour contextualiser le ticket, identifier les questions posées, et structurer les échanges de manière claire.
Ta mission principale :
1. Identifier le client et le contexte du ticket (demande "name" et "description")
- Récupère le nom de l'auteur si présent
- Indique si un `user_id` est disponible
- Conserve uniquement les informations d'identification utiles (pas d'adresse ou signature de mail inutile)
2. Mettre en perspective le `name` du ticket
- Il peut contenir une ou plusieurs questions implicites
- Reformule ces questions de façon explicite
3. Analyser la `description`
- Elle fournit souvent le vrai point d'entrée technique
- Repère les formulations interrogatives ou les demandes spécifiques
- Identifie si cette partie complète ou précise les questions du nom
4. Structurer le fil de discussion
- Conserve uniquement les échanges pertinents
-Conserve les questions soulevés par "name" ou "description"
- CONSERVE ABSOLUMENT les références documentation, FAQ, liens utiles et manuels
- Identifie clairement chaque intervenant (client / support)
- Classe les informations par ordre chronologique avec date et rôle
5. Préparer la transmission à l'agent suivant
- Préserve tous les éléments utiles à l'analyse d'image : modules cités, options évoquées, comportements décrits
- Mentionne si des images sont attachées au ticket
Structure ta réponse :
1. Résumé du contexte
- Client (nom, email si disponible)
- Sujet du ticket reformulé en une ou plusieurs questions
- Description technique synthétique
2. Informations techniques détectées
- Logiciels/modules mentionnés
- Paramètres évoqués
- Fonctionnalités impactées
- Conditions spécifiques (multi-laboratoire, utilisateur non valide, etc.)
3. Fil de discussion (filtrée, nettoyée, classée)
- Intervenant (Client/Support)
- Date et contenu de chaque échange
- Résumés techniques
- INCLURE TOUS les liens documentaires (manuel, FAQ, documentation technique)
4. Éléments liés à l'analyse visuelle
- Nombre d'images attachées
- Références aux interfaces ou options à visualiser
- Points à vérifier dans les captures (listes incomplètes, cases à cocher, utilisateurs grisés, etc.)
IMPORTANT :
- Ne propose aucune solution ni interprétation
- Ne génère pas de tableau
- Reste strictement factuel en te basant uniquement sur les informations fournies
- Ne reformule pas les messages, conserve les formulations exactes sauf nettoyage de forme"""
self.ticket_loader = TicketDataLoader()
self._appliquer_config_locale()
logger.info("AgentTicketAnalyser initialisé")
def _appliquer_config_locale(self) -> None:
if hasattr(self.llm, "prompt_system"):
self.llm.prompt_system = self.system_prompt
if hasattr(self.llm, "configurer"):
self.llm.configurer(
temperature=self.temperature,
top_p=self.top_p,
max_tokens=self.max_tokens
)
def executer(self, ticket_data: Dict[str, Any]) -> str:
if isinstance(ticket_data, str) and os.path.exists(ticket_data):
ticket_data = self.ticket_loader.charger(ticket_data)
if not isinstance(ticket_data, dict):
logger.error("Les données du ticket ne sont pas valides")
return "ERREUR: Format de ticket invalide"
ticket_code = ticket_data.get("code", "Inconnu")
logger.info(f"Analyse du ticket {ticket_code}")
print(f"AgentTicketAnalyser: analyse du ticket {ticket_code}")
prompt = self._generer_prompt(ticket_data)
try:
response = self.llm.interroger(prompt)
logger.info("Analyse du ticket terminée avec succès")
print(f" Analyse terminée: {len(response)} caractères")
result = {
"prompt": prompt,
"response": response,
"metadata": {
"timestamp": self._get_timestamp(),
"source_agent": self.nom,
"ticket_id": ticket_code,
"model_info": {
"model": getattr(self.llm, "modele", str(type(self.llm))),
**getattr(self.llm, "params", {})
}
}
}
sauvegarder_donnees(ticket_code, "analyse_ticket", result, base_dir="reports", is_resultat=True)
except Exception as e:
logger.error(f"Erreur d'analyse: {str(e)}")
return f"ERREUR: {str(e)}"
self.ajouter_historique("analyse_ticket", {
"ticket_id": ticket_code,
"prompt": prompt,
"timestamp": self._get_timestamp()
}, response)
return response
def _generer_prompt(self, ticket_data: Dict[str, Any]) -> str:
ticket_code = ticket_data.get("code", "Inconnu")
name = ticket_data.get("name", "").strip()
description = ticket_data.get("description", "").strip()
create_date = ticket_data.get("create_date", "")
auteur_initial = ticket_data.get("partner_id_email_from", "Client")
texte = f"### TICKET {ticket_code}\n\n"
if name:
texte += f"--- MESSAGE INITIAL DU CLIENT ---\n"
texte += f"Auteur : {auteur_initial}\n"
texte += f"Date : {self._formater_date(create_date)}\n"
texte += f"Contenu :\n{name}\n"
if description and description != "<p><br></p>":
texte += f"{description}\n\n"
messages = ticket_data.get("messages", [])
for i, msg in enumerate(messages):
if not isinstance(msg, dict):
continue
auteur = msg.get("author_id", "inconnu")
date = self._formater_date(msg.get("date", "inconnue"))
sujet = msg.get("subject", "").strip()
message_type = msg.get("message_type", "").strip()
contenu = msg.get("content", "").strip()
texte += f"--- MESSAGE {i+1} ---\n"
texte += f"Auteur : {auteur}\n"
texte += f"Date : {date}\n"
texte += f"Type : {message_type}\n"
if sujet:
texte += f"Sujet : {sujet}\n"
texte += f"Contenu :\n{contenu}\n\n"
return texte
def _formater_date(self, date_str: str) -> str:
if not date_str:
return "date inconnue"
try:
formats = [
"%Y-%m-%dT%H:%M:%S.%fZ", "%Y-%m-%dT%H:%M:%SZ",
"%Y-%m-%dT%H:%M:%S", "%Y-%m-%d %H:%M:%S",
"%d/%m/%Y %H:%M:%S", "%d/%m/%Y"
]
for fmt in formats:
try:
dt = datetime.strptime(date_str, fmt)
return dt.strftime("%d/%m/%Y %H:%M")
except ValueError:
continue
return date_str
except Exception:
return date_str
def _get_timestamp(self) -> str:
return datetime.now().strftime("%Y%m%d_%H%M%S")