#!/usr/bin/env python3 # -*- coding: utf-8 -*- import os import json import time import logging from typing import Dict, Any, Optional # 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("AgentTicketAnalyser_MistralMedium") class AgentTicketAnalyser(BaseAgent): """ Agent spécialisé pour analyser un ticket et en extraire les informations clés. Version optimisée pour Mistral Medium. """ def __init__(self, llm: Any): """ Initialise l'agent d'analyse de ticket avec un modèle LLM. Args: llm: Instance du modèle de langage à utiliser """ super().__init__(llm) self.temperature = 0.2 # Température plus basse pour une analyse factuelle self.top_p = 0.95 self.max_tokens = 2048 # System prompt spécifique pour l'analyse de tickets self.system_prompt = """Tu es un assistant spécialisé dans l'analyse des tickets de support technique. Ton rôle est d'analyser le contenu du ticket pour extraire les informations essentielles et de structurer cette analyse. À partir du ticket que l'on te fournit, tu dois : 1. Extraire et synthétiser les points clés du ticket 2. Identifier les informations techniques importantes 3. Comprendre le problème principal et son contexte 4. Déterminer si des images sont mentionnées ou semblent nécessaires pour comprendre le problème Ta réponse doit suivre un format strictement structuré : ``` 1. Résumé du contexte - Client : [Nom du contact client si mentionné] - Sujet du ticket : [Sujet principal du ticket en une phrase] - Description technique synthétique : [Synthèse technique du problème en 1-2 phrases] 2. Informations techniques détectées - Logiciels/modules mentionnés : [Liste des logiciels, applications ou modules mentionnés] - Paramètres évoqués : [Paramètres, configurations ou variables mentionnés] - Fonctionnalités impactées : [Fonctionnalités ou processus touchés par le problème] - Conditions spécifiques : [Conditions particulières où le problème se manifeste] 3. Analyse du problème - Problème principal : [Description claire du problème principal] - Impact pour l'utilisateur : [Comment ce problème affecte l'utilisateur] - Contexte d'apparition : [Quand et comment le problème survient] - Complexité estimée : [FAIBLE/MOYENNE/ÉLEVÉE] avec justification 4. Pertinence des images - Images mentionnées : [OUI/NON] et leur importance [FAIBLE/MOYENNE/ÉLEVÉE] - Justification : [Pourquoi les images sont importantes ou non pour comprendre le problème] 5. Questions pour clarification (si nécessaire) - [Questions que le support technique devrait poser pour mieux comprendre le problème] ``` Reste factuel et concis dans ton analyse. N'invente pas d'information qui ne serait pas présente dans le ticket. Concentre-toi uniquement sur l'analyse du contenu du ticket, pas sur la résolution du problème. """ def executer(self, ticket_data: Dict[str, Any]) -> str: """ Analyse un ticket à partir des données fournies. Args: ticket_data: Dictionnaire contenant les données du ticket - 'ticket_summary': Résumé du ticket - 'messages': Liste des messages du ticket Returns: str: Analyse structurée du ticket """ start_time = time.time() try: # Extraire le résumé du ticket ticket_summary = ticket_data.get('ticket_summary', {}) ticket_code = ticket_summary.get('code', 'INCONNU') ticket_sujet = ticket_summary.get('sujet', 'Sans sujet') # Log des informations de base du ticket logger.info(f"Analyse du ticket {ticket_code}: {ticket_sujet}") print(f" Analyse du ticket {ticket_code}: {ticket_sujet[:80]}{'...' if len(ticket_sujet) > 80 else ''}") # Construire le contexte à partir des messages messages = ticket_data.get('messages', []) # Construire un prompt pour analyser le ticket ticket_prompt = self._construire_prompt_ticket(ticket_summary, messages) # Analyser le ticket avec le LLM analyse = self.llm.generate( system_prompt=self.system_prompt, prompt=ticket_prompt, temperature=self.temperature, top_p=self.top_p, max_tokens=self.max_tokens ) # Calcul du temps de génération generation_time = time.time() - start_time # Log de l'analyse complétée logger.info(f"Analyse complétée en {generation_time:.2f} secondes") print(f" Analyse complétée en {generation_time:.2f} secondes") return analyse except Exception as e: logger.error(f"Erreur lors de l'analyse du ticket: {str(e)}") return f"ERREUR: Impossible d'analyser le ticket: {str(e)}" def _construire_prompt_ticket(self, ticket_summary: Dict[str, Any], messages: list) -> str: """ Construit un prompt détaillé à partir des données du ticket. Args: ticket_summary: Résumé du ticket messages: Liste des messages du ticket Returns: str: Prompt détaillé pour l'analyse """ # Construire l'en-tête avec les informations du ticket prompt = f"# TICKET: {ticket_summary.get('code', 'INCONNU')}\n" prompt += f"Sujet: {ticket_summary.get('sujet', 'Sans sujet')}\n" prompt += f"Statut: {ticket_summary.get('statut', 'Inconnu')}\n" prompt += f"Priorité: {ticket_summary.get('priorité', 'Non définie')}\n" prompt += f"Date de création: {ticket_summary.get('date_création', 'Inconnue')}\n\n" # Ajouter la section des messages prompt += "## MESSAGES DU TICKET\n\n" for i, message in enumerate(messages, 1): # Extraire les informations du message date = message.get('date', 'Date inconnue') auteur = message.get('auteur', 'Auteur inconnu') role = message.get('role', 'Rôle inconnu') contenu = message.get('contenu', '') # Ajouter l'en-tête du message prompt += f"### Message {i} - {date}\n" prompt += f"De: {auteur} ({role})\n\n" # Ajouter le contenu du message prompt += f"{contenu}\n\n" # Ajouter les informations sur les pièces jointes si disponibles attachments = message.get('attachments', []) if attachments: prompt += f"Pièces jointes ({len(attachments)}):\n" for attachment in attachments: prompt += f"- {attachment.get('nom', 'Sans nom')} ({attachment.get('type', 'Type inconnu')})\n" prompt += "\n" # Ajouter les instructions d'analyse prompt += "\n## INSTRUCTIONS\n" prompt += "Analyse ce ticket selon les instructions dans ton system prompt. " prompt += "Réponds uniquement avec l'analyse structurée demandée." return prompt