#!/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()