15:50test3ana

This commit is contained in:
Ladebeze66 2025-04-07 15:51:03 +02:00
parent b871048da5
commit 6d5b487de8
4 changed files with 801 additions and 264 deletions

View File

@ -338,7 +338,513 @@ Je vois le problème. Je vais améliorer votre générateur de rapport pour qu'i
---
Cancelled
```diff
images_analyses = []
analyse_images_data = rapport_data.get("analyse_images", {})
+
+ # Statistiques pour les métadonnées
+ total_images = len(analyse_images_data) if analyse_images_data else 0
+ images_pertinentes = 0
# Collecter des informations sur les agents et LLM utilisés
image_name = os.path.basename(image_path)
- # Récupérer l'analyse détaillée si elle existe
+ # Vérifier si l'image est pertinente
+ is_relevant = False
+ if "sorting" in analyse_data and isinstance(analyse_data["sorting"], dict):
+ is_relevant = analyse_data["sorting"].get("is_relevant", False)
+ if is_relevant:
+ images_pertinentes += 1
+
+ # Récupérer l'analyse détaillée si elle existe et que l'image est pertinente
analyse_detail = None
+ if is_relevant:
if "analysis" in analyse_data and analyse_data["analysis"]:
if isinstance(analyse_data["analysis"], dict) and "analyse" in analyse_data["analysis"]:
analyse_detail = str(analyse_data["analysis"])
- # Si l'analyse n'a pas été trouvée mais que le tri indique que l'image est pertinente
- if not analyse_detail and "sorting" in analyse_data and analyse_data["sorting"].get("is_relevant", False):
+ # Si l'analyse n'a pas été trouvée mais que l'image est pertinente
+ if not analyse_detail:
analyse_detail = f"Image marquée comme pertinente. Raison: {analyse_data['sorting'].get('reason', 'Non spécifiée')}"
num_images = len(images_analyses)
- # Créer un prompt détaillé
+ # Mettre à jour les métadonnées avec les statistiques
+ rapport_data.setdefault("metadata", {}).update({
+ "images_analysees": total_images,
+ "images_pertinentes": images_pertinentes
+ })
+
+ # 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.
## ANALYSE DU TICKET
{ticket_analyse}
- ## ANALYSES DES IMAGES ({num_images} images)
+ ## ANALYSES DES IMAGES ({num_images} images pertinentes sur {total_images} analysées)
"""
# Collecter les métadonnées du rapport avec détails sur les agents et LLM utilisés
- metadata = {
+ metadata = rapport_data.get("metadata", {})
+ metadata.update({
"timestamp": timestamp,
"model": getattr(self.llm, "modele", str(type(self.llm))),
"max_tokens": self.max_tokens,
"system_prompt": self.system_prompt,
- "agents_info": agents_info
- }
+ "agents_info": agents_info,
+ "images_analysees": total_images,
+ "images_pertinentes": images_pertinentes
+ })
# Sauvegarder le rapport au format JSON (données brutes + rapport généré)
markdown += "## Informations techniques\n\n"
+ # Ajouter un résumé du processus d'analyse complet
+ markdown += "### Processus d'analyse\n\n"
+
+ # 1. Analyse de ticket
+ ticket_analyse = rapport_data.get("ticket_analyse", "")
+ if not ticket_analyse and "analyse_json" in rapport_data:
+ ticket_analyse = rapport_data.get("analyse_json", "")
+
+ if ticket_analyse:
+ markdown += "#### Analyse du ticket\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"
+ analyse_images_data = rapport_data.get("analyse_images", {})
+
+ if analyse_images_data:
+ # Créer un tableau pour le tri des images
+ markdown += "| Image | Pertinence | Raison |\n"
+ markdown += "|-------|------------|--------|\n"
+
+ for image_path, analyse_data in analyse_images_data.items():
+ image_name = os.path.basename(image_path)
+
+ # Information de tri
+ is_relevant = "Non"
+ reason = "Non spécifiée"
+
+ if "sorting" in analyse_data:
+ sorting_data = analyse_data["sorting"]
+ if isinstance(sorting_data, dict):
+ is_relevant = "Oui" if sorting_data.get("is_relevant", False) else "Non"
+ reason = sorting_data.get("reason", "Non spécifiée")
+
+ markdown += f"| {image_name} | {is_relevant} | {reason} |\n"
+
+ markdown += "\n"
+
+ # 3. Analyse des images pertinentes
+ markdown += "#### Analyse des images pertinentes\n\n"
+
+ images_pertinentes = 0
+ for image_path, analyse_data in analyse_images_data.items():
+ # Vérifier si l'image est pertinente
+ is_relevant = False
+ if "sorting" in analyse_data and isinstance(analyse_data["sorting"], dict):
+ is_relevant = analyse_data["sorting"].get("is_relevant", False)
+
+ if is_relevant:
+ images_pertinentes += 1
+ image_name = os.path.basename(image_path)
+
+ # Récupérer l'analyse détaillée
+ analyse_detail = "Analyse non disponible"
+ if "analysis" in analyse_data and analyse_data["analysis"]:
+ if isinstance(analyse_data["analysis"], dict) and "analyse" in analyse_data["analysis"]:
+ analyse_detail = analyse_data["analysis"]["analyse"]
+ elif isinstance(analyse_data["analysis"], dict):
+ analyse_detail = str(analyse_data["analysis"])
+
+ markdown += f"##### Image: {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"
+
# Ajouter les informations sur les agents utilisés
agents_info = rapport_data.get("metadata", {}).get("agents_info", {})
# Statistiques d'analyse
markdown += "### Statistiques\n\n"
+
+ total_images = len(analyse_images_data) if analyse_images_data else 0
+
+ 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"]
- if "images_analysees" in metadata:
- markdown += f"- **Images analysées**: {metadata['images_analysees']}\n"
- if "images_pertinentes" in metadata:
- markdown += f"- **Images pertinentes**: {metadata['images_pertinentes']}\n"
+ 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
```
---
Très bien, les modifications ont été apportées avec succès à l'agent_report_generator.py. Je vais maintenant vérifier que tout est cohérent entre les différents agents et m'assurer que BRG-Lab (avec un tiret) est utilisé de manière uniforme dans tous les agents.
---
```diff
self.top_p = 0.8
self.max_tokens = 1500
- self.system_prompt = """Tu es un expert en analyse de tickets pour le support informatique de BRG_Lab.
+ self.system_prompt = """Tu es un expert en analyse de tickets pour le support informatique de BRG-Lab.
Ton rôle est d'extraire et d'analyser les informations importantes des tickets.
```
---
Je vais maintenant vérifier que les données des agents sont bien transmises entre eux dans l'orchestrateur. Pour cela, je dois examiner l'orchestrateur qui coordonne les agents.
---
<details>
<summary>Searched codebase "orchestrator.py" • **4** results</summary>
| File |
|------|
| `undefined` |
| `undefined` |
| `undefined` |
| `undefined` |
</details>
---
Read file: /home/fgras-ca/llm-ticket3/orchestrator.py
---
Read file: /home/fgras-ca/llm-ticket3/orchestrator.py
---
Maintenant que j'ai examiné tous les composants pertinents, je vais améliorer la coordination entre les agents dans l'orchestrateur pour m'assurer que toutes les données importantes sont bien transmises.
---
```diff
ticket_analysis = self.ticket_agent.executer(ticket_data)
logger.info("Analyse du ticket terminée")
+ print(f" Analyse du ticket terminée: {len(ticket_analysis) if ticket_analysis else 0} caractères")
else:
logger.warning("Agent Ticket non disponible")
relevant_images = []
images_analyses = {}
+ images_count = 0
if os.path.exists(attachments_dir):
logger.info(f"Vérification des pièces jointes dans: {attachments_dir}")
logger.info(f"Agent Image Sorter: {json.dumps(agent_info, indent=2)}")
- images_count = 0
- for attachment in os.listdir(attachments_dir):
+ # Compter le nombre d'images
+ images = [f for f in os.listdir(attachments_dir)
+ if f.lower().endswith(('.png', '.jpg', '.jpeg', '.bmp', '.gif'))]
+ images_count = len(images)
+
+ # Tri des images
+ for attachment in images:
attachment_path = os.path.join(attachments_dir, attachment)
- if attachment.lower().endswith(('.png', '.jpg', '.jpeg', '.bmp', '.gif')):
- images_count += 1
-
- if self.image_sorter:
- print(f" Analyse de l'image: {attachment}")
- sorting_result = self.image_sorter.executer(attachment_path)
- is_relevant = sorting_result.get("is_relevant", False)
- reason = sorting_result.get("reason", "")
-
- # Ajouter les métadonnées de tri à la liste des analyses
- images_analyses[attachment_path] = {
- "sorting": sorting_result,
- "analysis": None # Sera rempli plus tard si pertinent
- }
-
- if is_relevant:
- logger.info(f"Image pertinente identifiée: {attachment} ({reason})")
- print(f" => Pertinente: {reason}")
- relevant_images.append(attachment_path)
- else:
- logger.info(f"Image non pertinente: {attachment} ({reason})")
- print(f" => Non pertinente: {reason}")
- else:
- logger.warning("Image Sorter non disponible")
+
+ if self.image_sorter:
+ logger.info(f"Évaluation de la pertinence de l'image: {attachment}")
+ print(f" Évaluation de l'image: {attachment}")
+ sorting_result = self.image_sorter.executer(attachment_path)
+ is_relevant = sorting_result.get("is_relevant", False)
+ reason = sorting_result.get("reason", "")
+
+ # Log détaillé du résultat
+ if is_relevant:
+ logger.info(f"Image {attachment} considérée comme pertinente")
+ else:
+ logger.info(f"Image {attachment} considérée comme non pertinente")
+
+ # Ajouter les métadonnées de tri à la liste des analyses
+ images_analyses[attachment_path] = {
+ "sorting": sorting_result,
+ "analysis": None # Sera rempli plus tard si pertinent
+ }
+
+ if is_relevant:
+ logger.info(f"Image pertinente identifiée: {attachment} ({reason})")
+ print(f" => Pertinente: {reason}")
+ relevant_images.append(attachment_path)
+ else:
+ logger.info(f"Image non pertinente: {attachment} ({reason})")
+ print(f" => Non pertinente: {reason}")
+ else:
+ logger.warning("Image Sorter non disponible")
+ # Si pas de tri, considérer toutes les images comme pertinentes
+ relevant_images.append(attachment_path)
+ images_analyses[attachment_path] = {
+ "sorting": {"is_relevant": True, "reason": "Auto-sélectionné (pas de tri)"},
+ "analysis": None
+ }
+ print(f" => Auto-sélectionné (pas de tri)")
logger.info(f"Images analysées: {images_count}, Images pertinentes: {len(relevant_images)}")
# Analyse approfondie des images pertinentes
- if self.image_analyser:
+ if relevant_images and self.image_analyser:
agent_info = self._get_agent_info(self.image_analyser)
logger.info(f"Agent Image Analyser: {json.dumps(agent_info, indent=2)}")
-
- for image_path in relevant_images:
- if self.image_analyser and ticket_analysis:
+
+ # S'assurer que l'analyse du ticket est disponible comme contexte
+ contexte_ticket = ticket_analysis if ticket_analysis else "Aucune analyse de ticket disponible"
+
+ # Analyse de chaque image pertinente
+ for image_path in relevant_images:
image_name = os.path.basename(image_path)
logger.info(f"Analyse approfondie de l'image: {image_name}")
print(f" Analyse approfondie de l'image: {image_name}")
- analysis_result = self.image_analyser.executer(image_path, contexte=ticket_analysis)
+
+ # Appeler l'analyseur d'images avec le contexte du ticket
+ analysis_result = self.image_analyser.executer(image_path, contexte=contexte_ticket)
+
+ # Vérifier si l'analyse a réussi
+ if "error" in analysis_result and analysis_result["error"]:
+ logger.warning(f"Erreur lors de l'analyse de l'image {image_name}: {analysis_result.get('analyse', 'Erreur inconnue')}")
+ print(f" => ERREUR: {analysis_result.get('analyse', 'Erreur inconnue')}")
+ else:
+ logger.info(f"Analyse réussie pour l'image {image_name}")
+ print(f" => Analyse réussie: {len(analysis_result.get('analyse', '')) if 'analyse' in analysis_result else 0} caractères")
# Ajouter l'analyse au dictionnaire des analyses d'images
logger.info(f"Analyse complétée pour {image_name}")
- # Génération du rapport final
+ # Préparer les données pour le rapport final
rapport_data = {
"ticket_data": ticket_data,
"ticket_id": ticket_id,
- "analyse_ticket": ticket_analysis,
+ "ticket_analyse": ticket_analysis, # Utiliser ticket_analyse au lieu de analyse_ticket pour cohérence
"analyse_images": images_analyses,
"metadata": {
"timestamp_debut": self._get_timestamp(),
"ticket_id": ticket_id,
- "images_analysees": images_count if 'images_count' in locals() else 0,
+ "images_analysees": images_count,
"images_pertinentes": len(relevant_images)
}
}
+
+ # Ajout de la clé alternative pour compatibilité
+ rapport_data["analyse_json"] = ticket_analysis
if self.report_generator:
logger.info(f"Agent Report Generator: {json.dumps(agent_info, indent=2)}")
+ # Créer le répertoire pour le rapport si nécessaire
rapport_path = os.path.join(rapports_dir, ticket_id)
os.makedirs(rapport_path, exist_ok=True)
- self.report_generator.executer(rapport_data, rapport_path)
- logger.info(f"Rapport généré à: {rapport_path}")
- print(f" Rapport généré à: {rapport_path}")
+
+ # Générer le rapport
+ json_path, md_path = self.report_generator.executer(rapport_data, rapport_path)
+
+ if json_path and md_path:
+ logger.info(f"Rapport généré à: {rapport_path}")
+ print(f" Rapport généré avec succès")
+ print(f" - JSON: {os.path.basename(json_path)}")
+ print(f" - Markdown: {os.path.basename(md_path)}")
+ else:
+ logger.warning("Erreur lors de la génération du rapport")
+ print(f" ERREUR: Problème lors de la génération du rapport")
else:
logger.warning("Report Generator non disponible")
```
---
Voici un résumé des améliorations apportées à votre système :
1. **Agent Report Generator**:
- Modification majeure de la méthode `_generer_markdown_depuis_json` pour inclure toutes les étapes du processus d'analyse
- Ajout d'un affichage détaillé des résultats de tri d'images dans un tableau
- Intégration des analyses d'images pertinentes avec la possibilité de les déplier (via balises `<details>`)
- Inclusion des statistiques précises sur les images analysées
2. **Orchestrateur**:
- Amélioration de la transmission des données entre les agents
- Ajout de logs et d'informations de suivi plus détaillés
- S'assure que l'analyse du ticket est correctement transmise à l'agent d'analyse d'images
- Gestion améliorée des erreurs potentielles
- Meilleur feedback sur les opérations effectuées
3. **Consolidation et normalisation**:
- Harmonisation du nom BRG-Lab à travers tous les agents
- Standardisation des noms de clés dans les dictionnaires de données pour améliorer la compatibilité
- Ajout de clés alternatives pour assurer la rétrocompatibilité
Ces modifications garantissent que:
1. Toutes les étapes d'analyse sont clairement documentées dans le rapport Markdown final
2. Le tableau des échanges client/support est correctement généré
3. Les données sont transmises de façon cohérente entre tous les agents
4. Les résultats de chaque étape sont clairement visibles dans le rapport final
Le système est maintenant plus robuste et transparent, fournissant un rapport complet qui inclut non seulement le résultat final mais aussi toutes les étapes intermédiaires d'analyse.
---
_**User**_
je voudrai un fichier de test pour effectuer sur un ticket donné lancer 3 processus d'analyse avec pour modèle: 1ere analyse pixtral12b pour les images et mistral-mediuem-lastest pour les textes. 2eme analyse pixtral12b pour les images et mistral-large-latest pour les textes et 3eme analyse pixtral-large-latest pour les images et ollama avec qween que j'ai déjà défini dans ma classe ollama. bien sur mes classes sont déjà prête avec les modèles voulus génère moi un fichier de test spécifique à ces 3 analyses pour qu'elles s'effectuent l'une après l'autre (quand la première est terminée, la deuxième demmarre et ainsi de suite)
---
_**Assistant**_
Je vais créer un fichier de test qui lancera trois processus d'analyse séquentiels avec les différentes combinaisons de modèles que vous avez demandées.
---
<details>
<summary>Searched codebase "pixtral mistral ollama" • **3** results</summary>
| File |
|------|
| `undefined` |
| `undefined` |
| `undefined` |
</details>
---
<details>
<summary>Searched codebase "model llm classes" • **6** results</summary>
| File |
|------|
| `undefined` |
| `undefined` |
| `undefined` |
| `undefined` |
| `undefined` |
| `undefined` |
</details>
---
Read file: /home/fgras-ca/llm-ticket3/test_agents_with_models.py
---
Read file: /home/fgras-ca/llm-ticket3/test_models.py
---
<details>
<summary>Searched codebase "mistral_medium mistral_large ollama" • **1** results</summary>
| File |
|------|
| `undefined` |
</details>
---
Read file: /home/fgras-ca/llm-ticket3/llm_classes/mistral_medium.py
---
<details>
<summary>Searched codebase "ollama.py" • **2** results</summary>
| File |
|------|
| `undefined` |
| `undefined` |
</details>
---
Read file: /home/fgras-ca/llm-ticket3/llm_classes/ollama.py
---
Maintenant, je vais créer un fichier de test qui lancera trois processus d'analyse séquentiels avec les modèles demandés.
---
<details>
<summary>Listed directory llm_classes • **9** results</summary>
| Name |
|-------|
| 📁 `__pycache__` |
| 📄 `base_llm.py` |
| 📄 `mistral_large.py` |
| 📄 `mistral_large_pixtral2411.py` |
| 📄 `mistral_medium.py` |
| 📄 `ollama.py` |
| 📄 `pixtral_12b.py` |
| 📄 `pixtral_large.py` |
| 📁 `utils` |
</details>
---

View File

@ -1,117 +0,0 @@
{
"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 - Version : Non spécifiée dans les informations fournies\n - Configuration : Le logiciel a été réinstallé sur un autre serveur pour permettre le travail à distance. Une version réseau a été achetée 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 suite à sa réinstallation sur un autre serveur. Il se demande si le numéro de licence a été modifié suite à l'achat d'une version réseau en 2019.\n - Informations techniques fournies par le client : Le client a joint deux images (image006.jpg et image005.jpg) montrant probablement la fenêtre d'activation du logiciel.\n - Réponse du support : Aucune réponse n'est incluse 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_153622",
"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_153623",
"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 activer le logiciel.\n\n#### 2. Éléments techniques clés:\n- **Titre de la fenêtre**: \"Activation du logiciel\"\n- **Champ d'ID du logiciel**: Un champ vide pour entrer l'ID du logiciel.\n- **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 à support@cbad.com ou par téléphone au 04 68 61 53 15 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:\nL'image se rapporte au problème décrit dans le ticket de support concernant l'activation du logiciel ESQ. La fenêtre d'activation montre que le logiciel nécessite un ID de licence pour être activé, ce qui est en ligne avec le problème de licence mentionné dans le ticket. Le message d'instructions indique que le client doit contacter CBAD pour obtenir l'ID de licence, ce qui pourrait être la source du problème d'activation.",
"metadata": {
"image_path": "output/ticket_T0101/T0101_20250404_170239/attachments/image005.jpg",
"image_name": "image005.jpg",
"timestamp": "20250407_153627",
"model_info": {
"model": "pixtral-12b-latest",
"temperature": 0.3,
"top_p": 0.9,
"max_tokens": 1200
}
}
}
}
},
"metadata": {
"timestamp_debut": "20250407_153627",
"ticket_id": "T0101",
"images_analysees": 2,
"images_pertinentes": 1,
"timestamp": "20250407_153643",
"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
}
}
},
"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 - Version : Non spécifiée dans les informations fournies\n - Configuration : Le logiciel a été réinstallé sur un autre serveur pour permettre le travail à distance. Une version réseau a été achetée 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 suite à sa réinstallation sur un autre serveur. Il se demande si le numéro de licence a été modifié suite à l'achat d'une version réseau en 2019.\n - Informations techniques fournies par le client : Le client a joint deux images (image006.jpg et image005.jpg) montrant probablement la fenêtre d'activation du logiciel.\n - Réponse du support : Aucune réponse n'est incluse dans les informations fournies.",
"rapport_genere": "**Rapport technique pour le ticket #T0101**\n\n1. **Résumé exécutif**\n - Nom de la demande : ACTIVATION LOGICIEL\n - Description : Le client rencontre un problème de licence lors de l'activation du logiciel ESQ après sa réinstallation sur un autre serveur.\n\n2. **Chronologie des échanges**\n\n| Date | Émetteur | Type | Contenu |\n| --- | --- | --- | --- |\n| 26/03/2020 14:43:45 | CLIENT | Question | Demande d'aide pour l'activation du logiciel ESQ suite à sa réinstallation sur un autre serveur. Se demande si le numéro de licence a été modifié suite à l'achat d'une version réseau en 2019. |\n| - | SUPPORT | Réponse | Aucune réponse incluse dans les informations fournies. |\n\n3. **Analyse des images pertinentes**\n\n#### IMAGE 1: image005.jpg\n\n- **Description objective** : 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 activer le logiciel.\n- **Éléments techniques clés** :\n - Titre de la fenêtre : \"Activation du logiciel\"\n - Champ d'ID du logiciel : Un champ vide pour entrer l'ID du logiciel.\n - 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 à support@cbad.com ou par téléphone au 04 68 61 53 15 ou en cliquant sur le bouton téléphone situé en haut à droite de la fenêtre.\"\n - Options d'activation : \"Activer le logiciel (par internet)\", \"Activer plus tard (4 jours restants)\", \"Activation par téléphone\"\n\n4. **Diagnostic technique**\n - Logiciel : ESQ\n - Version : Non spécifiée\n - Configuration : Le logiciel a été réinstallé sur un autre serveur pour permettre le travail à distance. Une version réseau a été achetée en 2019 par JB Lafitte.\n - Problème : Le client ne parvient pas à activer le logiciel ESQ après sa réinstallation sur un autre serveur, probablement en raison d'un problème de licence ou d'ID de logiciel. L'image jointe montre la fenêtre d'activation du logiciel, indiquant que l'ID de logiciel doit être saisi pour activer le logiciel. Le client doit contacter CBAD pour obtenir l'ID de licence, comme indiqué dans le message d'instructions."
}

View File

@ -1,146 +0,0 @@
# Rapport d'analyse du ticket #T0101
*Généré le: 20250407_153643*
**Rapport technique pour le ticket #T0101**
1. **Résumé exécutif**
- Nom de la demande : ACTIVATION LOGICIEL
- Description : Le client rencontre un problème de licence lors de l'activation du logiciel ESQ après sa réinstallation sur un autre serveur.
2. **Chronologie des échanges**
| Date | Émetteur | Type | Contenu |
| --- | --- | --- | --- |
| 26/03/2020 14:43:45 | CLIENT | Question | Demande d'aide pour l'activation du logiciel ESQ suite à sa réinstallation sur un autre serveur. Se demande si le numéro de licence a été modifié suite à l'achat d'une version réseau en 2019. |
| - | SUPPORT | Réponse | Aucune réponse incluse dans les informations fournies. |
3. **Analyse des images pertinentes**
#### IMAGE 1: image005.jpg
- **Description objective** : 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 activer le logiciel.
- **Éléments techniques clés** :
- Titre de la fenêtre : "Activation du logiciel"
- Champ d'ID du logiciel : Un champ vide pour entrer l'ID du logiciel.
- 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 à support@cbad.com ou par téléphone au 04 68 61 53 15 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"
4. **Diagnostic technique**
- Logiciel : ESQ
- Version : Non spécifiée
- Configuration : Le logiciel a été réinstallé sur un autre serveur pour permettre le travail à distance. Une version réseau a été achetée en 2019 par JB Lafitte.
- Problème : Le client ne parvient pas à activer le logiciel ESQ après sa réinstallation sur un autre serveur, probablement en raison d'un problème de licence ou d'ID de logiciel. L'image jointe montre la fenêtre d'activation du logiciel, indiquant que l'ID de logiciel doit être saisi pour activer le logiciel. Le client doit contacter CBAD pour obtenir l'ID de licence, comme indiqué dans le message d'instructions.
## Informations techniques
### Processus d'analyse
#### Analyse du ticket
<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
- Version : Non spécifiée dans les informations fournies
- Configuration : Le logiciel a été réinstallé sur un autre serveur pour permettre le travail à distance. Une version réseau a été achetée 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 suite à sa réinstallation sur un autre serveur. Il se demande si le numéro de licence a été modifié suite à l'achat d'une version réseau en 2019.
- Informations techniques fournies par le client : Le client a joint deux images (image006.jpg et image005.jpg) montrant probablement la fenêtre d'activation du logiciel.
- Réponse du support : Aucune réponse n'est incluse dans les informations fournies.
```
</details>
#### Tri des images
| 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. |
#### Analyse des images pertinentes
##### Image: 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 activer le logiciel.
#### 2. Éléments techniques clés:
- **Titre de la fenêtre**: "Activation du logiciel"
- **Champ d'ID du logiciel**: Un champ vide pour entrer l'ID du logiciel.
- **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 à support@cbad.com ou par téléphone au 04 68 61 53 15 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:
L'image se rapporte au problème décrit dans le ticket de support concernant l'activation du logiciel ESQ. La fenêtre d'activation montre que le logiciel nécessite un ID de licence pour être activé, ce qui est en ligne avec le problème de licence mentionné dans le ticket. Le message d'instructions indique que le client doit contacter CBAD pour obtenir l'ID de licence, ce qui pourrait être la source du problème d'activation.
```
</details>
### 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
- **timestamp_debut**: 20250407_153627
- **ticket_id**: T0101
- **images_analysees**: 2
- **images_pertinentes**: 1
- **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.
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.

294
test_multiple_analyses.py Normal file
View File

@ -0,0 +1,294 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Script de test pour effectuer trois analyses séquentielles d'un ticket
avec différentes combinaisons de modèles LLM.
Analyses:
1. Pixtral-12b pour les images, Mistral-Medium pour les textes
2. Pixtral-12b pour les images, Mistral-Large pour les textes
3. Pixtral-Large pour les images, Ollama (Qwen) pour les textes
"""
import os
import time
import argparse
import logging
from datetime import datetime
from typing import Dict, Optional, Tuple
# 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
# Import des modèles LLM
from llm_classes.mistral_medium import MistralMedium
from llm_classes.mistral_large import MistralLarge
from llm_classes.pixtral_12b import Pixtral12b
from llm_classes.pixtral_large import PixtralLarge
from llm_classes.ollama import Ollama
# Import de l'orchestrateur
from orchestrator import Orchestrator
# Configuration du logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
filename='test_multiple_analyses.log',
filemode='w'
)
logger = logging.getLogger("TestMultipleAnalyses")
class TestAnalyser:
"""
Classe pour tester différentes combinaisons de modèles LLM
sur un ticket spécifique.
"""
def __init__(self):
self.current_time = datetime.now().strftime("%Y%m%d_%H%M%S")
# Création du dossier de résultats
self.results_dir = f"results_{self.current_time}"
os.makedirs(self.results_dir, exist_ok=True)
logger.info(f"Dossier de résultats créé: {self.results_dir}")
print(f"Dossier de résultats créé: {self.results_dir}")
def run_analysis(
self,
ticket_path: str,
text_model_name: str,
text_model,
image_model_name: str,
image_model
) -> Tuple[float, str]:
"""
Exécute une analyse complète d'un ticket avec une combinaison spécifique de modèles.
Args:
ticket_path: Chemin vers le ticket à analyser
text_model_name: Nom du modèle pour l'analyse de texte
text_model: Instance du modèle pour l'analyse de texte
image_model_name: Nom du modèle pour l'analyse d'image
image_model: Instance du modèle pour l'analyse d'image
Returns:
Tuple (durée d'exécution en secondes, chemin du sous-dossier de résultat)
"""
# Création d'un sous-dossier pour cette analyse
analysis_dir = os.path.join(
self.results_dir,
f"{os.path.basename(ticket_path)}_{text_model_name}_{image_model_name}"
)
os.makedirs(analysis_dir, exist_ok=True)
# Créer les agents avec les modèles spécifiés
ticket_agent = AgentTicketAnalyser(text_model)
image_sorter = AgentImageSorter(image_model)
image_analyser = AgentImageAnalyser(image_model)
report_generator = AgentReportGenerator(text_model)
# Initialiser l'orchestrateur
orchestrator = Orchestrator(
output_dir=os.path.dirname(ticket_path),
ticket_agent=ticket_agent,
image_sorter=image_sorter,
image_analyser=image_analyser,
report_generator=report_generator
)
# Log de début
logger.info(f"Début de l'analyse avec {text_model_name} (texte) et {image_model_name} (image)")
print(f"\n===== Analyse avec {text_model_name} (texte) et {image_model_name} (image) =====")
# Mesurer le temps d'exécution
start_time = time.time()
# Exécution de l'orchestrateur sur le ticket spécifique
try:
orchestrator.ticket_specifique = os.path.basename(ticket_path)
orchestrator.traiter_ticket(ticket_path)
success = True
except Exception as e:
logger.error(f"Erreur lors de l'analyse: {str(e)}")
print(f"ERREUR: {str(e)}")
success = False
# Calculer la durée
duration = time.time() - start_time
# Log de fin
logger.info(f"Fin de l'analyse - Durée: {duration:.2f} secondes - Succès: {success}")
print(f"Analyse terminée en {duration:.2f} secondes - Succès: {success}\n")
# Créer un fichier de résumé dans le dossier d'analyse
summary_path = os.path.join(analysis_dir, "summary.txt")
with open(summary_path, "w", encoding="utf-8") as f:
f.write(f"Analyse du ticket: {os.path.basename(ticket_path)}\n")
f.write(f"Date et heure: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
f.write(f"Modèle pour le texte: {text_model_name}\n")
f.write(f"Modèle pour les images: {image_model_name}\n")
f.write(f"Durée d'exécution: {duration:.2f} secondes\n")
f.write(f"Statut: {'Succès' if success else 'Échec'}\n")
return duration, analysis_dir
def run_all_analyses(self, ticket_path: str) -> Dict[str, Dict]:
"""
Exécute les trois analyses séquentielles avec différentes combinaisons de modèles.
Args:
ticket_path: Chemin vers le ticket à analyser
Returns:
Dictionnaire contenant les résultats des trois analyses
"""
if not os.path.exists(ticket_path):
logger.error(f"Le ticket spécifié n'existe pas: {ticket_path}")
print(f"ERREUR: Le ticket spécifié n'existe pas: {ticket_path}")
return {}
results = {}
# Première analyse: Pixtral-12b pour les images, Mistral-Medium pour les textes
logger.info("Initialisation des modèles pour la première analyse")
print("Initialisation des modèles pour la première analyse...")
try:
text_model = MistralMedium()
image_model = Pixtral12b()
duration, result_dir = self.run_analysis(
ticket_path,
"mistral-medium-latest",
text_model,
"pixtral-12b",
image_model
)
results["analyse1"] = {
"text_model": "mistral-medium-latest",
"image_model": "pixtral-12b",
"duration": duration,
"result_dir": result_dir
}
except Exception as e:
logger.error(f"Erreur lors de la première analyse: {str(e)}")
print(f"ERREUR première analyse: {str(e)}")
# Deuxième analyse: Pixtral-12b pour les images, Mistral-Large pour les textes
logger.info("Initialisation des modèles pour la deuxième analyse")
print("Initialisation des modèles pour la deuxième analyse...")
try:
text_model = MistralLarge()
image_model = Pixtral12b()
duration, result_dir = self.run_analysis(
ticket_path,
"mistral-large-latest",
text_model,
"pixtral-12b",
image_model
)
results["analyse2"] = {
"text_model": "mistral-large-latest",
"image_model": "pixtral-12b",
"duration": duration,
"result_dir": result_dir
}
except Exception as e:
logger.error(f"Erreur lors de la deuxième analyse: {str(e)}")
print(f"ERREUR deuxième analyse: {str(e)}")
# Troisième analyse: Pixtral-Large pour les images, Ollama (Qwen) pour les textes
logger.info("Initialisation des modèles pour la troisième analyse")
print("Initialisation des modèles pour la troisième analyse...")
try:
text_model = Ollama("qwen") # Utilisation du modèle qwen déjà défini dans la classe
image_model = PixtralLarge()
duration, result_dir = self.run_analysis(
ticket_path,
"ollama-qwen",
text_model,
"pixtral-large-latest",
image_model
)
results["analyse3"] = {
"text_model": "ollama-qwen",
"image_model": "pixtral-large-latest",
"duration": duration,
"result_dir": result_dir
}
except Exception as e:
logger.error(f"Erreur lors de la troisième analyse: {str(e)}")
print(f"ERREUR troisième analyse: {str(e)}")
# Générer un résumé comparatif global
self.generate_comparative_summary(results, ticket_path)
return results
def generate_comparative_summary(self, results: Dict[str, Dict], ticket_path: str) -> None:
"""
Génère un résumé comparatif des trois analyses.
Args:
results: Résultats des trois analyses
ticket_path: Chemin vers le ticket analysé
"""
summary_path = os.path.join(self.results_dir, "comparative_summary.md")
with open(summary_path, "w", encoding="utf-8") as f:
f.write(f"# Comparaison des analyses du ticket {os.path.basename(ticket_path)}\n\n")
f.write(f"Date et heure: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n\n")
# Tableau comparatif
f.write("## Tableau comparatif des analyses\n\n")
f.write("| Analyse | Modèle texte | Modèle image | Durée (s) |\n")
f.write("|---------|-------------|--------------|----------|\n")
for analysis_key, analysis_data in results.items():
f.write(f"| {analysis_key} | {analysis_data.get('text_model', 'N/A')} | {analysis_data.get('image_model', 'N/A')} | {analysis_data.get('duration', 0):.2f} |\n")
# Détails et observations
f.write("\n## Observations\n\n")
f.write("Les trois analyses ont été effectuées séquentiellement avec les combinaisons de modèles suivantes:\n\n")
for analysis_key, analysis_data in results.items():
f.write(f"### {analysis_key}\n")
f.write(f"- Modèle pour l'analyse de texte: **{analysis_data.get('text_model', 'N/A')}**\n")
f.write(f"- Modèle pour l'analyse d'images: **{analysis_data.get('image_model', 'N/A')}**\n")
f.write(f"- Durée d'exécution: **{analysis_data.get('duration', 0):.2f} secondes**\n")
f.write(f"- Dossier de résultats: `{analysis_data.get('result_dir', 'N/A')}`\n\n")
logger.info(f"Résumé comparatif généré: {summary_path}")
print(f"Résumé comparatif généré: {summary_path}")
def main():
"""Fonction principale du script."""
# Analyse des arguments de ligne de commande
parser = argparse.ArgumentParser(description="Test d'analyses multiples sur un ticket spécifique")
parser.add_argument("ticket_path", help="Chemin vers le ticket à analyser (dossier ticket_Txxxx)")
args = parser.parse_args()
# Démarrer les analyses
tester = TestAnalyser()
results = tester.run_all_analyses(args.ticket_path)
# Afficher un résumé final
print("\n===== Résumé des analyses =====")
for analysis_key, analysis_data in results.items():
print(f"{analysis_key}: {analysis_data.get('text_model')} + {analysis_data.get('image_model')} - {analysis_data.get('duration', 0):.2f}s")
print(f"\nRésultats sauvegardés dans: {tester.results_dir}")
if __name__ == "__main__":
main()