mirror of
https://github.com/Ladebeze66/llm_ticket3.git
synced 2025-12-15 20:06:51 +01:00
328 lines
13 KiB
Python
Executable File
328 lines
13 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
|
|
"""
|
|
Script de correction des rapports existants
|
|
Permet de:
|
|
1. Extraire correctement le JSON
|
|
2. Générer les fichiers CSV manquants
|
|
3. Analyser l'état des rapports générés
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
import json
|
|
import glob
|
|
import logging
|
|
import argparse
|
|
from datetime import datetime
|
|
import traceback
|
|
|
|
# Import des utilitaires
|
|
try:
|
|
from agents.utils.report_utils_bis import extraire_et_traiter_json
|
|
except ImportError:
|
|
print("ERREUR: Impossible d'importer les modules requis.")
|
|
print("Assurez-vous d'exécuter ce script depuis le répertoire racine du projet.")
|
|
sys.exit(1)
|
|
|
|
# Configuration du logging
|
|
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
|
logger = logging.getLogger("fix_reports")
|
|
|
|
def generate_csv_from_json(json_path, model_name=None):
|
|
"""
|
|
Génère un fichier CSV à partir du rapport JSON
|
|
|
|
Args:
|
|
json_path: Chemin vers le fichier JSON
|
|
model_name: Nom du modèle pour le nom du fichier CSV (facultatif)
|
|
"""
|
|
try:
|
|
# Charger le rapport JSON
|
|
with open(json_path, 'r', encoding='utf-8') as f:
|
|
rapport_data = json.load(f)
|
|
|
|
# Extraire l'ID du ticket
|
|
ticket_id = rapport_data.get("ticket_id", os.path.basename(json_path).split("_")[0])
|
|
|
|
# Extraire les échanges
|
|
chronologie_echanges = rapport_data.get("chronologie_echanges", [])
|
|
if not chronologie_echanges:
|
|
logger.error(f"Aucun échange trouvé dans le fichier JSON: {json_path}")
|
|
return False
|
|
|
|
# Déterminer le nom du modèle
|
|
if not model_name:
|
|
# Essayer de l'extraire des métadonnées
|
|
metadata = rapport_data.get("metadata", {})
|
|
model_name = metadata.get("model", "default").split(":")[0].lower()
|
|
|
|
# Créer le nom du fichier CSV
|
|
csv_path = os.path.join(os.path.dirname(json_path), f"{ticket_id}_{model_name}.csv")
|
|
|
|
# Générer le CSV complet avec toutes les colonnes
|
|
with open(csv_path, 'w', encoding='utf-8', newline='') as csvfile:
|
|
# Écrire l'en-tête
|
|
csvfile.write("Date,Émetteur,Type,Contenu\n")
|
|
|
|
# Écrire les échanges
|
|
for echange in chronologie_echanges:
|
|
date = echange.get('date', '').replace(',', ' ')
|
|
emetteur = echange.get('emetteur', '').replace(',', ' ')
|
|
type_msg = echange.get('type', '').replace(',', ' ')
|
|
contenu = echange.get('contenu', '').replace(',', ' ').replace('\n', ' ')
|
|
|
|
csvfile.write(f'"{date}","{emetteur}","{type_msg}","{contenu}"\n')
|
|
|
|
logger.info(f"Fichier CSV complet généré: {csv_path}")
|
|
|
|
# Générer également une version simplifiée Q&R pour la compatibilité
|
|
qr_csv_path = os.path.join(os.path.dirname(json_path), f"{ticket_id}_{model_name}_qr.csv")
|
|
|
|
with open(qr_csv_path, 'w', encoding='utf-8', newline='') as csvfile:
|
|
# Écrire l'en-tête
|
|
csvfile.write("Question,Réponse\n")
|
|
|
|
# Variables pour suivre les questions et réponses
|
|
current_question = None
|
|
|
|
# Parcourir les échanges et extraire les paires Q&R
|
|
for echange in chronologie_echanges:
|
|
emetteur = echange.get('emetteur', '').upper()
|
|
type_msg = echange.get('type', '').lower()
|
|
contenu = echange.get('contenu', '').replace(',', ' ').replace('\n', ' ')
|
|
|
|
# Si c'est une question du client
|
|
if emetteur == 'CLIENT' and (type_msg == 'question' or '?' in contenu):
|
|
# Si une question précédente existe sans réponse, l'écrire avec une réponse vide
|
|
if current_question:
|
|
csvfile.write(f'"{current_question}",""\n')
|
|
|
|
# Enregistrer la nouvelle question
|
|
current_question = contenu
|
|
|
|
# Si c'est une réponse ou un complément et qu'il y a une question en attente
|
|
elif emetteur == 'SUPPORT' and current_question:
|
|
# Préfixer la réponse pour la clarté
|
|
formatted_response = f"[{type_msg.upper()}] {contenu}"
|
|
|
|
# Écrire la paire question/réponse
|
|
csvfile.write(f'"{current_question}","{formatted_response}"\n')
|
|
current_question = None
|
|
|
|
# Si une question reste sans réponse à la fin
|
|
if current_question:
|
|
csvfile.write(f'"{current_question}",""\n')
|
|
|
|
logger.info(f"Fichier CSV Q&R simplifié généré: {qr_csv_path}")
|
|
|
|
return csv_path
|
|
|
|
except Exception as e:
|
|
logger.error(f"Erreur lors de la génération du CSV pour {json_path}: {e}")
|
|
traceback.print_exc()
|
|
return False
|
|
|
|
def fix_json_and_generate_csv(json_path):
|
|
"""
|
|
Corrige le JSON et génère le CSV manquant
|
|
|
|
Args:
|
|
json_path: Chemin vers le fichier JSON
|
|
"""
|
|
try:
|
|
# Charger le JSON
|
|
with open(json_path, 'r', encoding='utf-8') as f:
|
|
rapport_data = json.load(f)
|
|
|
|
# Extraire le rapport complet
|
|
rapport_complet = rapport_data.get("rapport_complet", "")
|
|
if not rapport_complet:
|
|
logger.error(f"Aucun rapport complet trouvé dans {json_path}")
|
|
return False
|
|
|
|
# Extraire et traiter le JSON
|
|
_, echanges_json, _ = extraire_et_traiter_json(rapport_complet)
|
|
|
|
# Vérifier si des échanges ont été extraits
|
|
if not echanges_json or "chronologie_echanges" not in echanges_json:
|
|
logger.error(f"Aucun échange extrait du rapport {json_path}")
|
|
return False
|
|
|
|
# Mettre à jour le JSON avec les échanges extraits
|
|
rapport_data["chronologie_echanges"] = echanges_json.get("chronologie_echanges", [])
|
|
|
|
# Sauvegarder le JSON corrigé
|
|
corrected_json_path = json_path.replace(".json", "_corrige.json")
|
|
with open(corrected_json_path, 'w', encoding='utf-8') as f:
|
|
json.dump(rapport_data, f, ensure_ascii=False, indent=2)
|
|
|
|
logger.info(f"Rapport JSON corrigé sauvegardé: {corrected_json_path}")
|
|
|
|
# Extraire le nom du modèle
|
|
metadata = rapport_data.get("metadata", {})
|
|
model_name = metadata.get("model", "unknown").split(":")[0].lower()
|
|
|
|
# Générer le CSV
|
|
csv_path = generate_csv_from_json(corrected_json_path, model_name)
|
|
|
|
if csv_path:
|
|
logger.info(f"CSV généré avec succès: {csv_path}")
|
|
return True
|
|
else:
|
|
logger.error("Échec de la génération du CSV")
|
|
return False
|
|
|
|
except Exception as e:
|
|
logger.error(f"Erreur lors de la correction du JSON {json_path}: {e}")
|
|
traceback.print_exc()
|
|
return False
|
|
|
|
def analyze_report(md_path):
|
|
"""
|
|
Analyse un rapport Markdown pour vérifier la présence des sections importantes
|
|
|
|
Args:
|
|
md_path: Chemin vers le fichier Markdown
|
|
"""
|
|
try:
|
|
# Lire le fichier
|
|
with open(md_path, 'r', encoding='utf-8') as f:
|
|
content = f.read()
|
|
|
|
# Vérifier les sections
|
|
has_table = "| Date | " in content or "| Question | Réponse |" in content
|
|
has_details = "## Détails des analyses" in content
|
|
|
|
# Vérifier la présence de la section synthèse globale (avec variations possibles)
|
|
has_synthese = any([
|
|
"## Synthèse globale des analyses d'images" in content,
|
|
"## 3.1 Synthèse globale des analyses d'images" in content,
|
|
"##3.1 Synthèse globale des analyses d'images" in content,
|
|
"## Synthèse globale" in content
|
|
])
|
|
|
|
# Vérifier si le fichier CSV existe
|
|
report_dir = os.path.dirname(md_path)
|
|
ticket_basename = os.path.basename(md_path).split('_')[0]
|
|
csv_files = [f for f in os.listdir(report_dir) if f.endswith('.csv') and ticket_basename in f]
|
|
has_csv = len(csv_files) > 0
|
|
|
|
# Afficher les résultats
|
|
print(f"\nAnalyse du rapport: {md_path}")
|
|
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 ❌'}")
|
|
print(f"- Synthèse globale: {'Présent ✅' if has_synthese else 'MANQUANT ❌'}")
|
|
|
|
if has_csv:
|
|
print(f"- Fichier CSV: Présent ✅ ({', '.join(csv_files)})")
|
|
else:
|
|
print(f"- Fichier CSV: MANQUANT ❌")
|
|
|
|
return {
|
|
"md_path": md_path,
|
|
"has_table": has_table,
|
|
"has_details": has_details,
|
|
"has_synthese": has_synthese,
|
|
"has_csv": has_csv,
|
|
"csv_files": csv_files
|
|
}
|
|
|
|
except Exception as e:
|
|
logger.error(f"Erreur lors de l'analyse du rapport {md_path}: {e}")
|
|
traceback.print_exc()
|
|
return None
|
|
|
|
def find_reports(base_dir=".", ticket_id=None):
|
|
"""
|
|
Recherche tous les rapports générés dans le répertoire de base
|
|
|
|
Args:
|
|
base_dir: Répertoire de base
|
|
ticket_id: Identifiant du ticket (optionnel)
|
|
|
|
Returns:
|
|
Liste de tuples (json_path, md_path)
|
|
"""
|
|
reports = []
|
|
|
|
# Motif de recherche des rapports
|
|
if ticket_id:
|
|
pattern = f"**/{ticket_id}/**/{ticket_id}_rapport_final.json"
|
|
else:
|
|
pattern = "**/T*/T*_rapport_final.json"
|
|
|
|
# Rechercher les fichiers JSON
|
|
json_files = glob.glob(os.path.join(base_dir, pattern), recursive=True)
|
|
|
|
for json_path in json_files:
|
|
# Trouver le fichier Markdown correspondant
|
|
md_path = json_path.replace(".json", ".md")
|
|
|
|
if os.path.exists(md_path):
|
|
reports.append((json_path, md_path))
|
|
|
|
return reports
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description="Outil de correction des rapports existants")
|
|
parser.add_argument("--dir", "-d", default=".", help="Répertoire de base contenant les rapports")
|
|
parser.add_argument("--ticket", "-t", help="ID du ticket à corriger (ex: T0101)")
|
|
parser.add_argument("--analyze", "-a", action="store_true", help="Analyser les rapports sans les corriger")
|
|
parser.add_argument("--fix", "-f", action="store_true", help="Corriger les rapports")
|
|
|
|
args = parser.parse_args()
|
|
|
|
# Rechercher les rapports
|
|
reports = find_reports(args.dir, args.ticket)
|
|
|
|
if not reports:
|
|
print(f"Aucun rapport trouvé dans {args.dir}" + (f" pour le ticket {args.ticket}" if args.ticket else ""))
|
|
return
|
|
|
|
print(f"Trouvé {len(reports)} rapport(s)")
|
|
|
|
# Analyser les rapports
|
|
if args.analyze or not args.fix:
|
|
analyze_results = []
|
|
for json_path, md_path in reports:
|
|
result = analyze_report(md_path)
|
|
if result:
|
|
analyze_results.append(result)
|
|
|
|
# Afficher un résumé
|
|
if analyze_results:
|
|
print("\nRésumé de l'analyse:")
|
|
print(f"- Total des rapports: {len(analyze_results)}")
|
|
print(f"- Rapports avec tableau: {sum(1 for r in analyze_results if r['has_table'])}")
|
|
print(f"- Rapports avec détails: {sum(1 for r in analyze_results if r['has_details'])}")
|
|
print(f"- Rapports avec synthèse: {sum(1 for r in analyze_results if r['has_synthese'])}")
|
|
print(f"- Rapports avec CSV: {sum(1 for r in analyze_results if r['has_csv'])}")
|
|
|
|
# Lister les rapports à corriger
|
|
reports_to_fix = [r["md_path"] for r in analyze_results if not (r["has_table"] and r["has_csv"])]
|
|
if reports_to_fix:
|
|
print("\nRapports à corriger (manque tableau ou CSV):")
|
|
for report in reports_to_fix:
|
|
print(f"- {report}")
|
|
|
|
# Corriger les rapports
|
|
if args.fix:
|
|
for json_path, md_path in reports:
|
|
# Analyser pour voir s'il a besoin d'être corrigé
|
|
result = analyze_report(md_path)
|
|
|
|
if result and not (result["has_table"] and result["has_csv"]):
|
|
print(f"\nCorrection du rapport {json_path}...")
|
|
success = fix_json_and_generate_csv(json_path)
|
|
|
|
if success:
|
|
print(f"✅ Rapport corrigé avec succès")
|
|
else:
|
|
print(f"❌ Échec de la correction du rapport")
|
|
else:
|
|
print(f"\nLe rapport {json_path} n'a pas besoin d'être corrigé")
|
|
|
|
if __name__ == "__main__":
|
|
main() |