This commit is contained in:
Ladebeze66 2025-04-07 16:35:33 +02:00
parent 6d5b487de8
commit 90448e8aa4
5 changed files with 1649 additions and 48 deletions

View File

@ -4,6 +4,7 @@ from .base_agent import BaseAgent
from datetime import datetime
from typing import Dict, Any, Tuple, Optional
import logging
import traceback
logger = logging.getLogger("AgentReportGenerator")
@ -21,20 +22,25 @@ class AgentReportGenerator(BaseAgent):
self.system_prompt = """Tu es un expert en génération de rapports techniques pour BRG-Lab.
Ta mission est de synthétiser les analyses (ticket et images) en un rapport structuré et exploitable.
IMPORTANCE DES ÉCHANGES CLIENT/SUPPORT:
- Tu dois impérativement présenter les échanges client/support sous forme d'un TABLEAU MARKDOWN clair
- Chaque ligne du tableau doit contenir: Date | Émetteur | Type (Question/Réponse) | Contenu
- Identifie clairement qui est l'émetteur (CLIENT ou SUPPORT)
- Mets en évidence les questions posées et les réponses fournies
EXIGENCE ABSOLUE - TABLEAU DES ÉCHANGES CLIENT/SUPPORT:
- Tu DOIS IMPÉRATIVEMENT créer un TABLEAU MARKDOWN des échanges client/support
- Le format du tableau DOIT être:
| Date | Émetteur (CLIENT/SUPPORT) | Type (Question/Réponse) | Contenu |
|------|---------------------------|-------------------------|---------|
| date1 | CLIENT | Question | contenu... |
| date2 | SUPPORT | Réponse | contenu... |
- Chaque message du ticket doit apparaître dans une ligne du tableau
- Indique clairement qui est CLIENT et qui est SUPPORT
- Le tableau DOIT être inclus dans la section "Chronologie des échanges"
Structure ton rapport:
1. Résumé exécutif: Synthèse du problème initial (nom de la demande + description)
2. Chronologie des échanges: TABLEAU des interactions client/support
2. Chronologie des échanges: TABLEAU des interactions client/support (format imposé ci-dessus)
3. Analyse des images: Ce que montrent les captures d'écran et leur pertinence
4. Diagnostic technique: Interprétation des informations techniques pertinentes
Reste factuel et précis. Ne fais pas d'analyses inutiles ou de recommandations non fondées.
Ton rapport doit mettre en avant la chronologie des échanges et les informations techniques clés."""
Reste factuel et précis dans ton analyse.
Le tableau des échanges client/support est l'élément le plus important du rapport."""
# Appliquer la configuration au LLM
self._appliquer_config_locale()
@ -97,15 +103,59 @@ Ton rapport doit mettre en avant la chronologie des échanges et les information
logger.info(f"Génération du rapport pour le ticket: {ticket_id}")
print(f"AgentReportGenerator: Génération du rapport pour {ticket_id}")
# Validation des données d'entrée
logger.info("Vérification de la complétude des données d'entrée:")
if "ticket_data" in rapport_data:
logger.info(f" - Données de ticket présentes: {len(str(rapport_data['ticket_data']))} caractères")
else:
logger.warning(" - Données de ticket manquantes")
# Vérification des analyses
ticket_analyse_exists = False
if "ticket_analyse" in rapport_data and rapport_data["ticket_analyse"]:
ticket_analyse_exists = True
logger.info(f" - Analyse du ticket présente: {len(rapport_data['ticket_analyse'])} caractères")
elif "analyse_json" in rapport_data and rapport_data["analyse_json"]:
ticket_analyse_exists = True
logger.info(f" - Analyse JSON présente: {len(rapport_data['analyse_json'])} caractères")
else:
logger.warning(" - Analyse du ticket manquante")
# Vérification des analyses d'images
if "analyse_images" in rapport_data and rapport_data["analyse_images"]:
n_images = len(rapport_data["analyse_images"])
n_relevant = sum(1 for _, data in rapport_data["analyse_images"].items()
if "sorting" in data and isinstance(data["sorting"], dict) and data["sorting"].get("is_relevant", False))
n_analyzed = sum(1 for _, data in rapport_data["analyse_images"].items()
if "analysis" in data and data["analysis"])
logger.info(f" - Analyses d'images présentes: {n_images} images, {n_relevant} pertinentes, {n_analyzed} analysées")
else:
logger.warning(" - Analyses d'images manquantes")
# S'assurer que le répertoire existe
if not os.path.exists(rapport_dir):
os.makedirs(rapport_dir)
logger.info(f"Répertoire de rapport créé: {rapport_dir}")
try:
# Préparer les données formatées pour l'analyse
ticket_analyse = rapport_data.get("ticket_analyse", "")
if not ticket_analyse and "analyse_json" in rapport_data:
ticket_analyse = rapport_data.get("analyse_json", "Aucune analyse de ticket disponible")
ticket_analyse = None
# Vérifier que l'analyse du ticket est disponible sous l'une des clés possibles
if "ticket_analyse" in rapport_data and rapport_data["ticket_analyse"]:
ticket_analyse = rapport_data["ticket_analyse"]
logger.info("Utilisation de ticket_analyse")
elif "analyse_json" in rapport_data and rapport_data["analyse_json"]:
ticket_analyse = rapport_data["analyse_json"]
logger.info("Utilisation de analyse_json en fallback")
else:
# Créer une analyse par défaut si aucune n'est disponible
logger.warning("Aucune analyse de ticket disponible, création d'un message par défaut")
ticket_data = rapport_data.get("ticket_data", {})
ticket_name = ticket_data.get("name", "Sans titre")
ticket_desc = ticket_data.get("description", "Pas de description disponible")
ticket_analyse = f"Analyse par défaut du ticket:\nNom: {ticket_name}\nDescription: {ticket_desc}\n(Aucune analyse détaillée n'a été fournie par l'agent d'analyse de ticket)"
# Préparer les données d'analyse d'images
images_analyses = []
@ -151,12 +201,41 @@ Ton rapport doit mettre en avant la chronologie des échanges et les information
num_images = len(images_analyses)
# Afficher un résumé des données collectées
logger.info(f"Résumé des données préparées pour le rapport:")
logger.info(f" - Ticket ID: {ticket_id}")
logger.info(f" - Analyse du ticket: {len(ticket_analyse) if ticket_analyse else 0} caractères")
logger.info(f" - Images analysées: {total_images}, Images pertinentes: {images_pertinentes}")
logger.info(f" - Images avec analyse détaillée: {num_images}")
# Mettre à jour les métadonnées avec les statistiques
rapport_data.setdefault("metadata", {}).update({
"images_analysees": total_images,
"images_pertinentes": images_pertinentes
"images_pertinentes": images_pertinentes,
"analyses_images_disponibles": num_images
})
# Extraire les messages pour aider à la création du tableau
messages_structure = []
try:
ticket_data = rapport_data.get("ticket_data", {})
if "messages" in ticket_data and isinstance(ticket_data["messages"], list):
for msg in ticket_data["messages"]:
if isinstance(msg, dict):
sender = msg.get("author_id", msg.get("from", "Inconnu"))
date = msg.get("date", "Date inconnue")
content = msg.get("content", "")
# Déterminer le type (client/support)
sender_type = "CLIENT" if "client" in sender.lower() else "SUPPORT" if "support" in sender.lower() else "AUTRE"
messages_structure.append({
"date": date,
"emetteur": sender_type,
"contenu": content[:100] + "..." if len(content) > 100 else content
})
logger.info(f" - {len(messages_structure)} messages extraits pour le tableau")
except Exception as e:
logger.warning(f"Erreur lors de l'extraction des messages: {e}")
# Créer un prompt détaillé en s'assurant que toutes les analyses sont incluses
prompt = f"""Génère un rapport technique complet pour le ticket #{ticket_id}, en te basant sur les analyses suivantes.
@ -171,27 +250,87 @@ Ton rapport doit mettre en avant la chronologie des échanges et les information
image_name = img_analyse.get("image_name", f"Image {i}")
analyse = img_analyse.get("analyse", "Analyse non disponible")
prompt += f"\n### IMAGE {i}: {image_name}\n{analyse}\n"
# Ajouter des informations sur les messages pour aider à la création du tableau
if messages_structure:
prompt += "\n## STRUCTURE DES MESSAGES POUR LE TABLEAU\n"
for i, msg in enumerate(messages_structure, 1):
prompt += f"{i}. Date: {msg['date']} | Émetteur: {msg['emetteur']} | Contenu: {msg['contenu']}\n"
prompt += f"""
Ton rapport doit être structuré avec les sections suivantes:
EXIGENCE ABSOLUE - TON RAPPORT DOIT IMPÉRATIVEMENT INCLURE:
- Un TABLEAU MARKDOWN structuré avec les échanges client/support au format:
| Date | Émetteur | Type | Contenu |
|------|----------|------|---------|
| date1 | CLIENT | Question | contenu... |
| date2 | SUPPORT | Réponse | contenu... |
Structure ton rapport:
1. Résumé exécutif: Synthèse concise du problème initial (reprend le nom de la demande + description)
2. Chronologie des échanges: PRÉSENTE IMPÉRATIVEMENT SOUS FORME DE TABLEAU MARKDOWN, avec colonnes: Date | Émetteur (CLIENT/SUPPORT) | Type (Question/Réponse) | Contenu
2. Chronologie des échanges: TABLEAU DES INTERACTIONS CLIENT/SUPPORT (format imposé ci-dessus)
3. Analyse des images pertinentes: Ce que montrent les captures d'écran
4. Diagnostic technique: Points clés et interprétation technique
IMPORTANT:
- Le tableau de chronologie doit être formaté correctement en Markdown (|---|---|---|---|)
- Tu dois clairement identifier qui est CLIENT et qui est SUPPORT
- Ne fais pas de recommandations génériques, reste factuel
- Utilise le format Markdown pour structurer ton rapport avec des titres clairs
Fournis un rapport concis, factuel et technique.
Ton rapport doit être factuel et précis. Le tableau des échanges client/support est OBLIGATOIRE.
"""
# Appeler le LLM pour générer le rapport
logger.info("Interrogation du LLM pour la génération du rapport")
rapport_contenu = self.llm.interroger(prompt)
# Vérifier que le rapport généré contient bien un tableau pour les échanges
contains_table = "|" in rapport_contenu and (
"| Date |" in rapport_contenu or
"| Émetteur |" in rapport_contenu or
"| Type |" in rapport_contenu or
"| CLIENT |" in rapport_contenu
)
if not contains_table:
logger.warning("ATTENTION: Le rapport généré ne semble pas contenir de tableau pour les échanges client/support")
print(" ATTENTION: Le rapport ne contient pas de tableau pour les échanges")
# Tenter une seconde génération avec un prompt plus direct
logger.info("Tentative de régénération du rapport avec focus sur le tableau")
# Prompt simplifié, focalisé sur le tableau
second_prompt = f"""Pour le ticket #{ticket_id}, crée un rapport incluant IMPÉRATIVEMENT:
UN TABLEAU MARKDOWN DES ÉCHANGES CLIENT/SUPPORT:
| Date | Émetteur | Type | Contenu |
|------|----------|------|---------|
| date1 | CLIENT | Question | contenu... |
Voici la structure des messages:
"""
# Ajouter les messages directement
for i, msg in enumerate(messages_structure, 1):
second_prompt += f"{i}. Date: {msg['date']} | Émetteur: {msg['emetteur']} | Contenu: {msg['contenu']}\n"
second_prompt += """
Structure obligatoire:
1. Résumé exécutif (très court)
2. Chronologie des échanges: TABLEAU MARKDOWN (comme ci-dessus)
3. Bref diagnostic
Le tableau est l'élément le plus important."""
# Tenter avec un autre prompt
second_rapport = self.llm.interroger(second_prompt)
# Vérifier à nouveau
if "|" in second_rapport and (
"| Date |" in second_rapport or
"| Émetteur |" in second_rapport or
"| Type |" in second_rapport or
"| CLIENT |" in second_rapport
):
rapport_contenu = second_rapport
logger.info("Succès: Le rapport régénéré contient un tableau")
print(" Tableau des échanges généré avec succès dans la seconde tentative")
else:
logger.warning("Le tableau est toujours absent dans la seconde tentative")
# Créer les noms de fichiers pour la sauvegarde
timestamp = self._get_timestamp()
base_filename = f"{ticket_id}_{timestamp}"
@ -209,7 +348,8 @@ Fournis un rapport concis, factuel et technique.
"system_prompt": self.system_prompt,
"agents_info": agents_info,
"images_analysees": total_images,
"images_pertinentes": images_pertinentes
"images_pertinentes": images_pertinentes,
"analyses_images_incluses": num_images
})
# Sauvegarder le rapport au format JSON (données brutes + rapport généré)
@ -217,6 +357,10 @@ Fournis un rapport concis, factuel et technique.
rapport_data_complet["rapport_genere"] = rapport_contenu
rapport_data_complet["metadata"] = metadata
# S'assurer que les clés nécessaires pour le markdown sont présentes
if "ticket_analyse" not in rapport_data_complet:
rapport_data_complet["ticket_analyse"] = ticket_analyse
with open(json_path, "w", encoding="utf-8") as f:
json.dump(rapport_data_complet, f, ensure_ascii=False, indent=2)
@ -227,6 +371,7 @@ Fournis un rapport concis, factuel et technique.
f.write(markdown_content)
logger.info(f"Rapport sauvegardé: {json_path} et {md_path}")
logger.info(f"Taille du rapport Markdown: {len(markdown_content)} caractères")
except Exception as e:
error_message = f"Erreur lors de la génération du rapport: {str(e)}"
@ -238,8 +383,9 @@ Fournis un rapport concis, factuel et technique.
self.ajouter_historique("generation_rapport",
{
"rapport_dir": rapport_dir,
"rapport_data": rapport_data,
"prompt": prompt,
"ticket_id": ticket_id,
"total_images": total_images,
"images_pertinentes": images_pertinentes,
"temperature": self.temperature,
"top_p": self.top_p,
"max_tokens": self.max_tokens
@ -247,11 +393,14 @@ Fournis un rapport concis, factuel et technique.
{
"json_path": json_path,
"md_path": md_path,
"taille_rapport": len(markdown_content) if 'markdown_content' in locals() else 0,
"rapport_contenu": rapport_contenu[:300] + ("..." if len(rapport_contenu) > 300 else "")
})
message = f"Rapports générés dans: {rapport_dir}"
print(f" {message}")
print(f" - JSON: {os.path.basename(json_path)}")
print(f" - Markdown: {os.path.basename(md_path)}")
return json_path, md_path
@ -330,14 +479,15 @@ Fournis un rapport concis, factuel et technique.
markdown = f"# Rapport d'analyse du ticket #{ticket_id}\n\n"
markdown += f"*Généré le: {timestamp}*\n\n"
# Ajouter le rapport principal
# Ajouter le rapport principal généré par le LLM
markdown += rapport_contenu + "\n\n"
# Ajouter les informations techniques (agents, LLM, paramètres)
markdown += "## Informations techniques\n\n"
# Section séparatrice pour les détails d'analyse
markdown += "---\n\n"
markdown += "# Détails des analyses effectuées\n\n"
# Ajouter un résumé du processus d'analyse complet
markdown += "### Processus d'analyse\n\n"
markdown += "## Processus d'analyse\n\n"
# 1. Analyse de ticket
ticket_analyse = rapport_data.get("ticket_analyse", "")
@ -345,13 +495,16 @@ Fournis un rapport concis, factuel et technique.
ticket_analyse = rapport_data.get("analyse_json", "")
if ticket_analyse:
markdown += "#### Analyse du ticket\n\n"
markdown += "### Étape 1: Analyse du ticket\n\n"
markdown += "L'agent d'analyse de ticket a extrait les informations suivantes du ticket d'origine:\n\n"
markdown += "<details>\n<summary>Cliquez pour voir l'analyse complète du ticket</summary>\n\n"
markdown += "```\n" + ticket_analyse + "\n```\n\n"
markdown += "</details>\n\n"
# 2. Tri des images
markdown += "#### Tri des images\n\n"
markdown += "### Étape 2: Tri des images\n\n"
markdown += "L'agent de tri d'images a évalué chaque image pour déterminer sa pertinence par rapport au problème client:\n\n"
analyse_images_data = rapport_data.get("analyse_images", {})
if analyse_images_data:
@ -375,9 +528,11 @@ Fournis un rapport concis, factuel et technique.
markdown += f"| {image_name} | {is_relevant} | {reason} |\n"
markdown += "\n"
else:
markdown += "*Aucune image n'a été trouvée ou analysée.*\n\n"
# 3. Analyse des images pertinentes
markdown += "#### Analyse des images pertinentes\n\n"
markdown += "### Étape 3: Analyse détaillée des images pertinentes\n\n"
images_pertinentes = 0
for image_path, analyse_data in analyse_images_data.items():
@ -398,13 +553,20 @@ Fournis un rapport concis, factuel et technique.
elif isinstance(analyse_data["analysis"], dict):
analyse_detail = str(analyse_data["analysis"])
markdown += f"##### Image: {image_name}\n\n"
markdown += f"#### Image pertinente {images_pertinentes}: {image_name}\n\n"
markdown += "<details>\n<summary>Cliquez pour voir l'analyse complète de l'image</summary>\n\n"
markdown += "```\n" + analyse_detail + "\n```\n\n"
markdown += "</details>\n\n"
if images_pertinentes == 0:
markdown += "Aucune image pertinente n'a été identifiée.\n\n"
markdown += "*Aucune image pertinente n'a été identifiée pour ce ticket.*\n\n"
# 4. Synthèse (rapport final)
markdown += "### Étape 4: Génération du rapport de synthèse\n\n"
markdown += "L'agent de génération de rapport a synthétisé toutes les analyses précédentes pour produire le rapport ci-dessus.\n\n"
# Informations techniques
markdown += "## Informations techniques\n\n"
# Ajouter les informations sur les agents utilisés
agents_info = rapport_data.get("metadata", {}).get("agents_info", {})
@ -455,13 +617,6 @@ Fournis un rapport concis, factuel et technique.
markdown += f"- **Images analysées**: {total_images}\n"
markdown += f"- **Images pertinentes**: {images_pertinentes}\n\n"
# Ajouter les métadonnées supplémentaires si présentes
if "metadata" in rapport_data:
metadata = rapport_data["metadata"]
for key, value in metadata.items():
if key not in ["agents_info", "timestamp"] and not isinstance(value, dict):
markdown += f"- **{key}**: {value}\n"
return markdown
def _get_timestamp(self) -> str:

View File

@ -0,0 +1,119 @@
{
"ticket_data": {
"id": "113",
"code": "T0101",
"name": "ACTIVATION LOGICIEL",
"description": "Problème de licence.",
"project_name": "Demandes",
"stage_name": "Clôturé",
"user_id": "",
"partner_id_email_from": "PROVENCALE S.A, Bruno Vernet <bruno.vernet@provencale.com>",
"create_date": "26/03/2020 14:46:36",
"write_date_last_modification": "03/10/2024 13:10:50",
"date_deadline": "25/05/2020 00:00:00",
"messages": [
{
"author_id": "PROVENCALE S.A",
"date": "26/03/2020 14:43:45",
"message_type": "E-mail",
"subject": "ACTIVATION LOGICIEL",
"id": "10758",
"content": "Bonjour,\n\nAu vu de la situation liée au Coronavirus, nous avons dû passer en télétravail.\n\nPour ce faire et avoir accès aux différents logiciels nécessaires, ESQ a été réinstallé sur un autre serveur afin de pouvoir travailler en bureau à distance.\n\nDu coup le logiciel nous demande une activation mais je ne sais pas si le N° de licence a été modifié suite à un achat version réseau faite par JB Lafitte en 2019 ou si le problème est autre.\n\nCi-dessous la fenêtre au lancement du logiciel.\n\nMerci davance pour votre aide.\n\nCordialement\n\n\n- image006.jpg (image/jpeg) [ID: 31760]\n- image005.jpg (image/jpeg) [ID: 31758]\n\n---\n"
}
],
"date_d'extraction": "04/04/2025 17:02:42",
"répertoire": "output/ticket_T0101/T0101_20250404_170239",
"metadata": {}
},
"ticket_id": "T0101",
"ticket_analyse": "1. Analyse du problème initial\n Le nom de la demande indique \"ACTIVATION LOGICIEL\", suggérant que le client est confronté à un problème d'activation d'un logiciel. La description du problème mentionne spécifiquement un \"Problème de licence\".\n\n2. Informations techniques essentielles\n - Logiciel : ESQ\n - Configuration : Le logiciel a été réinstallé sur un autre serveur pour permettre le travail à distance.\n - Licence : Il y a une incertitude quant à la modification du numéro de licence suite à un achat de version réseau en 2019 par JB Lafitte.\n\n3. Chronologie des échanges client/support\n - Message 1 - [AUTRE] De : Inconnu - Date : 26/03/2020 14:43:45\n - Question du client : Le client demande de l'aide pour l'activation du logiciel ESQ, car il n'est pas sûr si le numéro de licence a été modifié suite à un achat de version réseau en 2019 ou si le problème est autre.\n - Informations techniques fournies par le client : Le client a fourni des captures d'écran (image006.jpg et image005.jpg) montrant la fenêtre d'activation du logiciel au lancement.\n - Réponse du support : Aucune réponse n'est enregistrée dans les informations fournies.",
"analyse_images": {
"output/ticket_T0101/T0101_20250404_170239/attachments/image006.jpg": {
"sorting": {
"is_relevant": false,
"reason": "Non. Cette image montre le logo d'une entreprise nommée \"Provençale Carbone de Calcium\". Elle n'est pas pertinente pour le support technique de logiciels, car elle ne montre pas de captures d'écran de logiciels, de messages d'erreur, de configurations système, ou d'autres éléments techniques liés à l'informatique.",
"raw_response": "Non. Cette image montre le logo d'une entreprise nommée \"Provençale Carbone de Calcium\". Elle n'est pas pertinente pour le support technique de logiciels, car elle ne montre pas de captures d'écran de logiciels, de messages d'erreur, de configurations système, ou d'autres éléments techniques liés à l'informatique.",
"metadata": {
"image_path": "output/ticket_T0101/T0101_20250404_170239/attachments/image006.jpg",
"image_name": "image006.jpg",
"timestamp": "20250407_163210",
"model_info": {
"model": "pixtral-12b-latest",
"temperature": 0.2,
"top_p": 0.8,
"max_tokens": 300
}
}
},
"analysis": null
},
"output/ticket_T0101/T0101_20250404_170239/attachments/image005.jpg": {
"sorting": {
"is_relevant": true,
"reason": "oui. L'image montre une fenêtre d'activation de logiciel, ce qui est pertinent pour le support technique de logiciels.",
"raw_response": "oui. L'image montre une fenêtre d'activation de logiciel, ce qui est pertinent pour le support technique de logiciels.",
"metadata": {
"image_path": "output/ticket_T0101/T0101_20250404_170239/attachments/image005.jpg",
"image_name": "image005.jpg",
"timestamp": "20250407_163211",
"model_info": {
"model": "pixtral-12b-latest",
"temperature": 0.2,
"top_p": 0.8,
"max_tokens": 300
}
}
},
"analysis": {
"analyse": "### Analyse d'image\n\n#### 1. Description objective:\nL'image montre une fenêtre d'activation de logiciel intitulée \"Activation du logiciel\". La fenêtre contient un champ pour entrer l'ID du logiciel, un message d'instructions, et trois options pour l'activation du logiciel.\n\n#### 2. Éléments techniques clés:\n- **Titre de la fenêtre**: \"Activation du logiciel\"\n- **Champ d'ID du logiciel**: \"ID du logiciel\" avec un champ de texte vide\n- **Message d'instructions**:\n - \"Afin d'activer votre logiciel, veuillez saisir l'ID du logiciel fourni par CBAD.\"\n - \"Si vous ne disposez pas de votre ID de logiciel, veuillez contacter CBAD par mail à l'adresse suivante : support@cbad.fr ou par téléphone au 01 64 65 31 31 ou en cliquant sur le bouton téléphone situé en haut à droite de la fenêtre.\"\n- **Options d'activation**:\n - \"Activer le logiciel (par internet)\"\n - \"Activer plus tard (4 jours restants)\"\n - \"Activation par téléphone\"\n\n#### 3. Relation avec le problème:\nCette image se rapporte au problème décrit dans le ticket de support concernant l'activation du logiciel ESQ. Elle montre la fenêtre d'activation du logiciel où l'utilisateur doit entrer l'ID du logiciel pour procéder à l'activation. Le message d'instructions indique que si l'utilisateur ne dispose pas de l'ID, il doit contacter CBAD pour obtenir de l'aide. Cela correspond à la description du problème initial où le client demande de l'aide pour l'activation du logiciel et mentionne une incertitude quant à la modification du numéro de licence.",
"metadata": {
"image_path": "output/ticket_T0101/T0101_20250404_170239/attachments/image005.jpg",
"image_name": "image005.jpg",
"timestamp": "20250407_163218",
"model_info": {
"model": "pixtral-12b-latest",
"temperature": 0.3,
"top_p": 0.9,
"max_tokens": 1200
}
}
}
}
},
"metadata": {
"timestamp_debut": "20250407_163218",
"ticket_id": "T0101",
"images_analysees": 2,
"images_pertinentes": 1,
"analyses_images_disponibles": 1,
"timestamp": "20250407_163232",
"model": "mistral-medium",
"temperature": 0.4,
"top_p": 0.9,
"max_tokens": 2500,
"system_prompt": "Tu es un expert en génération de rapports techniques pour BRG-Lab.\nTa mission est de synthétiser les analyses (ticket et images) en un rapport structuré et exploitable.\n\nIMPORTANCE DES ÉCHANGES CLIENT/SUPPORT:\n- Tu dois IMPÉRATIVEMENT présenter les échanges client/support sous forme d'un TABLEAU MARKDOWN clair\n- Chaque ligne du tableau doit contenir: Date | Émetteur | Type (Question/Réponse) | Contenu\n- Identifie clairement qui est l'émetteur (CLIENT ou SUPPORT)\n- Mets en évidence les questions posées et les réponses fournies\n\nStructure ton rapport:\n1. Résumé exécutif: Synthèse du problème initial (nom de la demande + description)\n2. Chronologie des échanges: TABLEAU des interactions client/support\n3. Analyse des images: Ce que montrent les captures d'écran et leur pertinence\n4. Diagnostic technique: Interprétation des informations techniques pertinentes\n\nReste factuel et précis. Ne fais pas d'analyses inutiles ou de recommandations non fondées.\nTon rapport doit mettre en avant la chronologie des échanges et les informations techniques clés.",
"agents_info": {
"image_sorter": {
"model": "pixtral-12b-latest",
"temperature": 0.2,
"top_p": 0.8,
"max_tokens": 300
},
"image_analyser": {
"model": "pixtral-12b-latest",
"temperature": 0.3,
"top_p": 0.9,
"max_tokens": 1200
},
"report_generator": {
"model": "mistral-medium",
"temperature": 0.4,
"top_p": 0.9,
"max_tokens": 2500
}
},
"analyses_images_incluses": 1
},
"analyse_json": "1. Analyse du problème initial\n Le nom de la demande indique \"ACTIVATION LOGICIEL\", suggérant que le client est confronté à un problème d'activation d'un logiciel. La description du problème mentionne spécifiquement un \"Problème de licence\".\n\n2. Informations techniques essentielles\n - Logiciel : ESQ\n - Configuration : Le logiciel a été réinstallé sur un autre serveur pour permettre le travail à distance.\n - Licence : Il y a une incertitude quant à la modification du numéro de licence suite à un achat de version réseau en 2019 par JB Lafitte.\n\n3. Chronologie des échanges client/support\n - Message 1 - [AUTRE] De : Inconnu - Date : 26/03/2020 14:43:45\n - Question du client : Le client demande de l'aide pour l'activation du logiciel ESQ, car il n'est pas sûr si le numéro de licence a été modifié suite à un achat de version réseau en 2019 ou si le problème est autre.\n - Informations techniques fournies par le client : Le client a fourni des captures d'écran (image006.jpg et image005.jpg) montrant la fenêtre d'activation du logiciel au lancement.\n - Réponse du support : Aucune réponse n'est enregistrée dans les informations fournies.",
"rapport_genere": "**Rapport technique pour le ticket #T0101**\n\n**1. Résumé exécutif**\n\nProblème initial : ACTIVATION LOGICIEL\nDescription : Le client rencontre un problème d'activation du logiciel ESQ suite à sa réinstallation sur un autre serveur pour permettre le travail à distance. Il y a une incertitude quant à la modification du numéro de licence suite à un achat de version réseau en 2019.\n\n**2. Chronologie des échanges**\n\n| Date | Émetteur | Type | Contenu |\n| --- | --- | --- | --- |\n| 26/03/2020 14:43:45 | CLIENT | Question | Bonjour,<br>Au vu de la situation liée au Coronavirus, nous avons dû passer en télétravail.<br>Pour ce faire, nous avons réinstallé le logiciel ESQ sur un autre serveur. Cependant, nous rencontrons un problème d'activation lié à la licence. Nous ne sommes pas sûrs si le numéro de licence a été modifié suite à un achat de version réseau en 2019 ou si le problème est autre. Pourriez-vous nous aider à résoudre ce problème ?<br>Cordialement, [Nom du client] |\n| - | SUPPORT | Réponse | (Aucune réponse enregistrée) |\n\n**3. Analyse des images pertinentes**\n\n*Image 1 : image005.jpg*\n\nCette image montre une fenêtre d'activation de logiciel intitulée \"Activation du logiciel\". La fenêtre contient un champ pour entrer l'ID du logiciel, un message d'instructions, et trois options pour l'activation du logiciel. Cette image est pertinente car elle montre le problème d'activation du logiciel ESQ rencontré par le client.\n\n**4. Diagnostic technique**\n\n- Logiciel : ESQ\n- Configuration : Le logiciel a été réinstallé sur un autre serveur pour permettre le travail à distance.\n- Licence : Il y a une incertitude quant à la modification du numéro de licence suite à un achat de version réseau en 2019 par JB Lafitte.\n\nLe client doit vérifier s'il dispose du bon numéro de licence pour activer le logiciel ESQ. S'il ne dispose pas de l'ID de logiciel, il doit contacter CBAD par mail à l'adresse support@cbad.fr ou par téléphone au 01 64 65 31 31 pour obtenir de l'aide."
}

View File

@ -0,0 +1,133 @@
# Rapport d'analyse du ticket #T0101
*Généré le: 20250407_163232*
**Rapport technique pour le ticket #T0101**
**1. Résumé exécutif**
Problème initial : ACTIVATION LOGICIEL
Description : Le client rencontre un problème d'activation du logiciel ESQ suite à sa réinstallation sur un autre serveur pour permettre le travail à distance. Il y a une incertitude quant à la modification du numéro de licence suite à un achat de version réseau en 2019.
**2. Chronologie des échanges**
| Date | Émetteur | Type | Contenu |
| --- | --- | --- | --- |
| 26/03/2020 14:43:45 | CLIENT | Question | Bonjour,<br>Au vu de la situation liée au Coronavirus, nous avons dû passer en télétravail.<br>Pour ce faire, nous avons réinstallé le logiciel ESQ sur un autre serveur. Cependant, nous rencontrons un problème d'activation lié à la licence. Nous ne sommes pas sûrs si le numéro de licence a été modifié suite à un achat de version réseau en 2019 ou si le problème est autre. Pourriez-vous nous aider à résoudre ce problème ?<br>Cordialement, [Nom du client] |
| - | SUPPORT | Réponse | (Aucune réponse enregistrée) |
**3. Analyse des images pertinentes**
*Image 1 : image005.jpg*
Cette image montre une fenêtre d'activation de logiciel intitulée "Activation du logiciel". La fenêtre contient un champ pour entrer l'ID du logiciel, un message d'instructions, et trois options pour l'activation du logiciel. Cette image est pertinente car elle montre le problème d'activation du logiciel ESQ rencontré par le client.
**4. Diagnostic technique**
- Logiciel : ESQ
- Configuration : Le logiciel a été réinstallé sur un autre serveur pour permettre le travail à distance.
- Licence : Il y a une incertitude quant à la modification du numéro de licence suite à un achat de version réseau en 2019 par JB Lafitte.
Le client doit vérifier s'il dispose du bon numéro de licence pour activer le logiciel ESQ. S'il ne dispose pas de l'ID de logiciel, il doit contacter CBAD par mail à l'adresse support@cbad.fr ou par téléphone au 01 64 65 31 31 pour obtenir de l'aide.
---
# Détails des analyses effectuées
## Processus d'analyse
### Étape 1: Analyse du ticket
L'agent d'analyse de ticket a extrait les informations suivantes du ticket d'origine:
<details>
<summary>Cliquez pour voir l'analyse complète du ticket</summary>
```
1. Analyse du problème initial
Le nom de la demande indique "ACTIVATION LOGICIEL", suggérant que le client est confronté à un problème d'activation d'un logiciel. La description du problème mentionne spécifiquement un "Problème de licence".
2. Informations techniques essentielles
- Logiciel : ESQ
- Configuration : Le logiciel a été réinstallé sur un autre serveur pour permettre le travail à distance.
- Licence : Il y a une incertitude quant à la modification du numéro de licence suite à un achat de version réseau en 2019 par JB Lafitte.
3. Chronologie des échanges client/support
- Message 1 - [AUTRE] De : Inconnu - Date : 26/03/2020 14:43:45
- Question du client : Le client demande de l'aide pour l'activation du logiciel ESQ, car il n'est pas sûr si le numéro de licence a été modifié suite à un achat de version réseau en 2019 ou si le problème est autre.
- Informations techniques fournies par le client : Le client a fourni des captures d'écran (image006.jpg et image005.jpg) montrant la fenêtre d'activation du logiciel au lancement.
- Réponse du support : Aucune réponse n'est enregistrée dans les informations fournies.
```
</details>
### Étape 2: Tri des images
L'agent de tri d'images a évalué chaque image pour déterminer sa pertinence par rapport au problème client:
| Image | Pertinence | Raison |
|-------|------------|--------|
| image006.jpg | Non | Non. Cette image montre le logo d'une entreprise nommée "Provençale Carbone de Calcium". Elle n'est pas pertinente pour le support technique de logiciels, car elle ne montre pas de captures d'écran de logiciels, de messages d'erreur, de configurations système, ou d'autres éléments techniques liés à l'informatique. |
| image005.jpg | Oui | oui. L'image montre une fenêtre d'activation de logiciel, ce qui est pertinent pour le support technique de logiciels. |
### Étape 3: Analyse détaillée des images pertinentes
#### Image pertinente 1: image005.jpg
<details>
<summary>Cliquez pour voir l'analyse complète de l'image</summary>
```
### Analyse d'image
#### 1. Description objective:
L'image montre une fenêtre d'activation de logiciel intitulée "Activation du logiciel". La fenêtre contient un champ pour entrer l'ID du logiciel, un message d'instructions, et trois options pour l'activation du logiciel.
#### 2. Éléments techniques clés:
- **Titre de la fenêtre**: "Activation du logiciel"
- **Champ d'ID du logiciel**: "ID du logiciel" avec un champ de texte vide
- **Message d'instructions**:
- "Afin d'activer votre logiciel, veuillez saisir l'ID du logiciel fourni par CBAD."
- "Si vous ne disposez pas de votre ID de logiciel, veuillez contacter CBAD par mail à l'adresse suivante : support@cbad.fr ou par téléphone au 01 64 65 31 31 ou en cliquant sur le bouton téléphone situé en haut à droite de la fenêtre."
- **Options d'activation**:
- "Activer le logiciel (par internet)"
- "Activer plus tard (4 jours restants)"
- "Activation par téléphone"
#### 3. Relation avec le problème:
Cette image se rapporte au problème décrit dans le ticket de support concernant l'activation du logiciel ESQ. Elle montre la fenêtre d'activation du logiciel où l'utilisateur doit entrer l'ID du logiciel pour procéder à l'activation. Le message d'instructions indique que si l'utilisateur ne dispose pas de l'ID, il doit contacter CBAD pour obtenir de l'aide. Cela correspond à la description du problème initial où le client demande de l'aide pour l'activation du logiciel et mentionne une incertitude quant à la modification du numéro de licence.
```
</details>
### Étape 4: Génération du rapport de synthèse
L'agent de génération de rapport a synthétisé toutes les analyses précédentes pour produire le rapport ci-dessus.
## Informations techniques
### Agents et modèles utilisés
#### Agent de tri d'images
- **Modèle**: pixtral-12b-latest
- **Température**: 0.2
- **Top-p**: 0.8
- **Max tokens**: 300
#### Agent d'analyse d'images
- **Modèle**: pixtral-12b-latest
- **Température**: 0.3
- **Top-p**: 0.9
- **Max tokens**: 1200
#### Agent de génération de rapport
- **Modèle**: mistral-medium
- **Température**: 0.4
- **Top-p**: 0.9
- **Max tokens**: 2500
### Statistiques
- **Images analysées**: 2
- **Images pertinentes**: 1

View File

@ -1,17 +1,31 @@
from orchestrator import Orchestrator
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Script de test pour exécuter l'orchestrateur sur un ticket spécifique.
Utilisation: python test_orchestrator.py [code_ticket]
Exemple: python test_orchestrator.py T0101
"""
import os
import sys
import time
import logging
import traceback
from datetime import datetime
# Import des agents
from agents.agent_ticket_analyser import AgentTicketAnalyser
from agents.agent_image_sorter import AgentImageSorter
from agents.agent_image_analyser import AgentImageAnalyser
from agents.agent_report_generator import AgentReportGenerator
# Utilisation des modèles Medium pour les tests
# Import des modèles LLM
from llm_classes.mistral_medium import MistralMedium
from llm_classes.pixtral_12b import Pixtral12b
import os
import logging
import sys
import time
# Import de l'orchestrateur
from orchestrator import Orchestrator
# Configuration du logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s',
@ -70,6 +84,25 @@ def test_orchestrator(ticket_id=None):
image_analyser = AgentImageAnalyser(image_analyser_llm)
report_generator = AgentReportGenerator(report_generator_llm)
# Renforcer le system prompt du générateur de rapport pour s'assurer que le tableau est généré
report_generator.system_prompt = """Tu es un expert en génération de rapports techniques pour BRG-Lab.
Ta mission est de synthétiser les analyses (ticket et images) en un rapport structuré et exploitable.
IMPORTANCE DES ÉCHANGES CLIENT/SUPPORT:
- Tu dois IMPÉRATIVEMENT présenter les échanges client/support sous forme d'un TABLEAU MARKDOWN clair
- Chaque ligne du tableau doit contenir: Date | Émetteur | Type (Question/Réponse) | Contenu
- Identifie clairement qui est l'émetteur (CLIENT ou SUPPORT)
- Mets en évidence les questions posées et les réponses fournies
Structure ton rapport:
1. Résumé exécutif: Synthèse du problème initial (nom de la demande + description)
2. Chronologie des échanges: TABLEAU des interactions client/support
3. Analyse des images: Ce que montrent les captures d'écran et leur pertinence
4. Diagnostic technique: Interprétation des informations techniques pertinentes
Reste factuel et précis. Ne fais pas d'analyses inutiles ou de recommandations non fondées.
Ton rapport doit mettre en avant la chronologie des échanges et les informations techniques clés."""
print("Tous les agents ont été créés")
# Initialisation de l'orchestrateur avec les agents
@ -103,12 +136,56 @@ def test_orchestrator(ticket_id=None):
logger.info("Début de l'exécution de l'orchestrateur")
print("Début de l'exécution de l'orchestrateur")
orchestrator.executer(specific_ticket_path)
try:
orchestrator.executer(ticket_id)
# Vérifier le rapport généré et afficher un résumé
if ticket_id:
# Chercher le rapport Markdown le plus récent
ticket_dir = os.path.join("output", f"ticket_{ticket_id}")
latest_md = None
for extraction in os.listdir(ticket_dir):
extraction_path = os.path.join(ticket_dir, extraction)
if os.path.isdir(extraction_path):
rapports_dir = os.path.join(extraction_path, f"{ticket_id}_rapports", f"{ticket_id}")
if os.path.exists(rapports_dir):
md_files = [f for f in os.listdir(rapports_dir) if f.endswith('.md')]
if md_files:
md_files.sort(reverse=True) # Le plus récent en premier
latest_md = os.path.join(rapports_dir, md_files[0])
break
if latest_md:
print(f"\nVérification du rapport: {latest_md}")
try:
with open(latest_md, 'r', encoding='utf-8') as f:
content = f.read()
# Vérifier si le tableau des échanges est présent
has_table = "| Date | " in content
has_details = "Détails des analyses effectuées" in content
print(f"- Tableau des échanges: {'Présent' if has_table else 'MANQUANT'}")
print(f"- Détails des analyses: {'Présent' if has_details else 'MANQUANT'}")
if not has_table:
print("\nATTENTION: Le tableau des échanges client/support est manquant!")
print("Vérifiez le system prompt de l'agent de rapport et la transmission des données.")
except Exception as e:
print(f"Erreur lors de la vérification du rapport: {e}")
except Exception as e:
logger.error(f"Erreur lors de l'exécution de l'orchestrateur: {str(e)}")
print(f"ERREUR: {str(e)}")
traceback.print_exc()
total_time = time.time() - total_start_time
logger.info(f"Fin de l'exécution de l'orchestrateur (durée: {total_time:.2f} secondes)")
print(f"Fin de l'exécution de l'orchestrateur (durée: {total_time:.2f} secondes)")
if __name__ == "__main__":
print("Démarrage du test de l'orchestrateur")