llm_ticket3/test_multiple_analyses.py
2025-04-07 15:51:03 +02:00

294 lines
12 KiB
Python

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