#!/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_DeepSeek") class AgentTicketAnalyser(BaseAgent): """ Agent spécialisé pour analyser un ticket et en extraire les informations clés. Version optimisée pour DeepSeek. """ 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.1 # Température très basse pour une analyse factuelle self.top_p = 0.9 self.max_tokens = 4000 # System prompt spécifique pour l'analyse de tickets avec DeepSeek 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""" 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 += "Fournis une analyse structurée et complète qui servira de base à l'analyse des images." return prompt