diff --git a/CSV/T11143/T11143_llama3-2-vision-90b-instruct-q8-0_exchanges.csv b/CSV/T11143/T11143_llama3-2-vision-90b-instruct-q8-0_exchanges.csv new file mode 100644 index 0000000..a99a6b1 --- /dev/null +++ b/CSV/T11143/T11143_llama3-2-vision-90b-instruct-q8-0_exchanges.csv @@ -0,0 +1,3 @@ +Émetteur,Type,Date,Contenu,Éléments visuels +Client (Victor Bollée),Question,2025-04-24,"Problème signalé avec l'accès à l'URL ""https://zk1.brg-lab.com/""",Capture d'écran de la page d'erreur (ID: 145435) +Support (Fabien Lay),Réponse,2025-04-24,"Les étapes de dépannage fournies, notamment la vérification de la connectivité réseau et du cache du navigateur","Image des paramètres réseau (image.png, id: 145453)" diff --git a/CSV/T11143/T11143_llama3.2-vision_90b-instruct-q8_0_exchanges.csv b/CSV/T11143/T11143_llama3.2-vision_90b-instruct-q8_0_exchanges.csv deleted file mode 100644 index f5dd607..0000000 --- a/CSV/T11143/T11143_llama3.2-vision_90b-instruct-q8_0_exchanges.csv +++ /dev/null @@ -1,5 +0,0 @@ -Émetteur,Type,Date,Contenu,Éléments visuels -Victor Bollée,Question,2025-04-24 13:50:51,"Le test ""bleu"" ne fonctionne pas comme prévu. J'ai joint une capture d'écran (image_145435.png).",Image_145435.png (capture d'écran du problème) -Support,Réponse,2025-04-24 14:00:00,Pouvez-vous fournir plus d'informations sur le message d'erreur que vous recevez? Pouvez-vous également joindre une autre capture d'écran avec les détails d'erreur?,- -Victor Bollée,Réponse,2025-04-24 14:10:00,"J'ai joint une autre capture d'écran (image.png) avec les détails d'erreur. Le message d'erreur est ""Erreur lors de l'analyse:"" Llamavision ""L'objet n'a pas d'attribut 'can_analyse_images'"".",image.png (capture d'écran des détails d'erreur) -Support,Réponse,2025-04-24 14:20:00,Merci d'avoir fourni les informations nécessaires. Nous avons identifié le problème et fourni une solution. Le problème était dû à un attribut manquant dans l'objet Llamavision. Nous avons mis à jour le code et le problème devrait être résolu maintenant.,- diff --git a/agents/llama_vision/agent_image_analyser.py b/agents/llama_vision/agent_image_analyser.py index 3197a5c..cc52fc2 100644 --- a/agents/llama_vision/agent_image_analyser.py +++ b/agents/llama_vision/agent_image_analyser.py @@ -5,6 +5,8 @@ from typing import Dict, Any, List, Optional from PIL import Image from ..utils.pipeline_logger import sauvegarder_donnees from utils.translate_utils import fr_to_en, en_to_fr +from datetime import datetime +import re logger = logging.getLogger("AgentImageAnalyser") @@ -154,7 +156,6 @@ class AgentImageAnalyser(BaseAgent): Returns: List of extracted URLs """ - import re # Pattern to detect URLs (more complete than a simple http:// search) url_pattern = r'https?://(?:[-\w.]|(?:%[\da-fA-F]{2}))+' @@ -238,80 +239,72 @@ Structure your analysis clearly with headers and bullet points. return prompt - def executer(self, image_path: str, contexte: Optional[Dict[str, Any]] = None) -> Dict[str, Any]: + def _extraire_ticket_id_depuis_path(self, path: str) -> str: + """Extrait l'ID du ticket depuis le chemin de l'image. + + Args: + path (str): Chemin de l'image + + Returns: + str: ID du ticket ou 'unknown' si non trouvé """ - Exécute l'analyse d'une image en utilisant les capacités du LLM. + try: + # Recherche un pattern comme T12345 dans le chemin + match = re.search(r'T\d+', path) + if match: + return match.group(0) + except Exception as e: + logger.error(f"Erreur lors de l'extraction de l'ID du ticket: {e}") + return "unknown" + + def executer(self, image_path: str, contexte: Optional[dict] = None) -> dict: + """Exécute l'analyse d'une image. + + Args: + image_path (str): Chemin vers l'image à analyser + contexte (Optional[dict], optional): Contexte supplémentaire. Defaults to None. + + Returns: + dict: Résultat de l'analyse """ - if contexte is None: - contexte = {} + if not self._verifier_image(image_path): + return self._erreur(message="Image invalide ou inaccessible", path=image_path) + + if not self.llm.peut_analyser_images(): + return self._erreur(message="Le modèle ne supporte pas l'analyse d'images", path=image_path) nom_image = os.path.basename(image_path) - logger.info(f"Début de l'analyse de l'image {nom_image}") + ticket_id = self._extraire_ticket_id_depuis_path(image_path) try: - if not self._verifier_image(image_path): - return self._erreur(f"Image invalide ou inaccessible: {image_path}", path=image_path) + reponse = self.llm.analyser_image(image_path) + if not reponse: + return self._erreur(message="Pas de réponse du modèle", path=image_path) - ticket_id = self._extraire_ticket_id(image_path, contexte) - prompt = self._construire_prompt(image_path, contexte) - - if not self.llm.peut_analyser_images(): - return self._erreur("Le modèle ne supporte pas l'analyse d'images", path=image_path) - - reponse = self.llm.interroger_avec_image(image_path, prompt) - if self._verifier_reponse_invalide(reponse): - return self._erreur(f"Réponse invalide du modèle pour {image_path}", path=image_path) - - # Vérifier si une traduction est nécessaire - if not self.llm.mode_anglais_uniquement: - reponse_en = reponse - reponse_fr = self.llm.traduire(reponse) - else: - reponse_en = reponse - reponse_fr = None - - # Obtenir le nom du modèle de manière plus robuste - model_name = None - if hasattr(self.llm, "pipeline_normalized_name") and self.llm.pipeline_normalized_name: - model_name = self.llm.pipeline_normalized_name - elif hasattr(self.llm, "modele") and self.llm.modele: - model_name = self.llm.modele - else: - model_name = "llama3-vision-90b-instruct" - - # Obtenir les paramètres du modèle de manière sécurisée - model_params = {} - if hasattr(self.llm, "params"): - model_params = self.llm.params - elif hasattr(self, "params"): - model_params = self.params + model_name = getattr(self.llm, "pipeline_normalized_name", "llama3-vision-90b-instruct") resultat = { - "timestamp": self._get_timestamp(), + "timestamp": datetime.now().isoformat(), "image": nom_image, "ticket_id": ticket_id, "analyse": { - "en": reponse_en, - "fr": reponse_fr if reponse_fr else reponse_en + "en": reponse, + "fr": self.llm.traduire(reponse) }, - "metadata": { - "model_info": { - "name": model_name, - "type": "vision", - "parameters": model_params - }, - "image_path": image_path, - "success": True, - "source_agent": self.nom + "model_info": { + "name": model_name, + "params": { + "temperature": 0.2, + "max_tokens": 1000 + } } } - logger.info(f"Analyse de {nom_image} terminée avec succès") return resultat except Exception as e: - logger.error(f"Erreur lors de l'analyse de {image_path}: {str(e)}") - return self._erreur(f"Erreur lors de l'analyse: {str(e)}", path=image_path) + logger.error(f"Erreur lors de l'analyse de l'image {nom_image}: {str(e)}") + return self._erreur(message=f"Erreur lors de l'analyse: {str(e)}", path=image_path) def _corriger_termes_courants(self, texte: str) -> str: """ @@ -331,26 +324,33 @@ Structure your analysis clearly with headers and bullet points. return texte - def _erreur(self, message: str, path: str, raw: str = "") -> Dict[str, Any]: + def _erreur(self, message: str, path: str, details: Any = None) -> Dict[str, Any]: """ - Creates an error response dictionary + Crée un dictionnaire d'erreur standardisé. + + Args: + message: Message d'erreur + path: Chemin du fichier concerné + details: Détails supplémentaires de l'erreur (optionnel) + + Returns: + Dictionnaire contenant les informations d'erreur """ - return { - "analyse": f"ERROR: {message}", - "raw_response": raw, - "error": True, + error_dict = { + "timestamp": self._get_timestamp(), + "success": False, + "error": message, + "image": os.path.basename(path), "metadata": { - "image_path": path, - "image_name": os.path.basename(path), - "timestamp": self._get_timestamp(), - "error": True, + "error_details": details if details else {}, "source_agent": self.nom } } + logger.error(f"Erreur: {message} pour {path}") + return error_dict def _get_timestamp(self) -> str: """Returns a timestamp in YYYYMMDD_HHMMSS format""" - from datetime import datetime return datetime.now().strftime("%Y%m%d_%H%M%S") def _extraire_ticket_id(self, image_path: str, contexte: Dict[str, Any]) -> str: diff --git a/agents/llama_vision/agent_report_generator.py b/agents/llama_vision/agent_report_generator.py index 9d3bad6..803c11c 100644 --- a/agents/llama_vision/agent_report_generator.py +++ b/agents/llama_vision/agent_report_generator.py @@ -208,72 +208,35 @@ Stay strictly factual. Make no assumptions. Do not suggest steps or interpretati } # Utiliser sauvegarder_donnees pour centraliser la logique de sauvegarde - # et éviter les doublons tout en respectant la structure de répertoires try: - # Normaliser le nom du modèle pour le log - model_name = getattr(self.llm, "modele", "unknown") - if ":" in model_name: - model_name = model_name.replace(":", "-") - if "." in model_name: - model_name = model_name.replace(".", "-") + # Récupérer le nom normalisé du modèle + model_name = getattr(self.llm, "pipeline_normalized_name", getattr(self.llm, "modele", "unknown")) - # Sauvegarder le rapport via la fonction centralisée - sauvegarder_donnees(ticket_id, "rapport_final", result, base_dir=None, is_resultat=True) + # Mettre à jour les métadonnées avec le nom du modèle + result["metadata"]["model_info"]["model"] = model_name + + # Sauvegarder le rapport via la fonction centralisée uniquement + sauvegarder_donnees( + ticket_id=ticket_id, + step_name="rapport_final", + data=result, + base_dir=None, + is_resultat=True + ) print(f"Rapport final généré et sauvegardé pour le ticket {ticket_id}") - - # Le code suivant pour les versions texte directes est conservé uniquement pour compatibilité - # mais je m'assure qu'il utilise le nom de modèle normalisé - extraction_dir = self._trouver_repertoire_extraction(ticket_id) - if extraction_dir: - rapports_dir = os.path.join(extraction_dir, f"{ticket_id}_rapports") - pipeline_dir = os.path.join(rapports_dir, "pipeline") - - # Vérifier si le fichier txt a déjà été créé via pipeline_logger pour éviter les doublons - if os.path.exists(pipeline_dir): - # Récupérer ou normaliser le nom du modèle - def normaliser_nom_modele(nom): - if not nom: - return "unknown-model" - # Convertir points et underscores en tirets - normalized = nom.lower().replace(".", "-").replace("_", "-").replace(":", "-") - # Supprimer les caractères non-alphanumériques (sauf tirets) - result = "" - for c in normalized: - if c.isalnum() or c == '-': - result += c - return result - - # Normaliser le nom du modèle pour éviter les problèmes de fichiers - safe_model_name = normaliser_nom_modele(model_name) - - # Sauvegarder uniquement la version TXT (la JSON est déjà gérée par pipeline_logger) - txt_path = os.path.join(pipeline_dir, f"rapport_final_{safe_model_name}.txt") - with open(txt_path, "w", encoding="utf-8") as f: - f.write(f"RAPPORT D'ANALYSE DU TICKET {ticket_id}\n") - f.write("="*50 + "\n\n") - f.write(response_fr) # Version française - print(f"Version texte formatée sauvegardée dans: {txt_path}") - - # Créer également un chemin standard pour le report directory - reports_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), "../..", "reports")) - ticket_reports_dir = os.path.join(reports_dir, ticket_id) - os.makedirs(ticket_reports_dir, exist_ok=True) - txt_report_path = os.path.join(ticket_reports_dir, f"rapport_final_{ticket_id}.txt") - with open(txt_report_path, "w", encoding="utf-8") as f: - f.write(response_fr) - print(f"Rapport également sauvegardé en texte dans {reports_dir}/{ticket_id}") + + # Créer un chemin standard pour le report directory (pour compatibilité) + reports_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), "../..", "reports")) + ticket_reports_dir = os.path.join(reports_dir, ticket_id) + os.makedirs(ticket_reports_dir, exist_ok=True) + txt_report_path = os.path.join(ticket_reports_dir, f"rapport_final_{ticket_id}.txt") + with open(txt_report_path, "w", encoding="utf-8") as f: + f.write(response_fr) + print(f"Rapport également sauvegardé en texte dans {reports_dir}/{ticket_id}") + except Exception as e: logger.error(f"Erreur lors de la sauvegarde des résultats: {str(e)}") - # Fallback: créer un fichier de debug - try: - debug_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), "../../debug")) - os.makedirs(debug_dir, exist_ok=True) - debug_path = os.path.join(debug_dir, f"rapport_debug_{ticket_id}.json") - with open(debug_path, "w", encoding="utf-8") as f: - json.dump(result, f, ensure_ascii=False, indent=2) - print(f"Fichier de débogage créé: {debug_path}") - except Exception as debug_err: - print(f"Même la sauvegarde de débogage a échoué: {str(debug_err)}") + logger.debug(traceback.format_exc()) # Add to history self.ajouter_historique("rapport_final", { diff --git a/main_llama.py b/main_llama.py index b593757..79ad914 100644 --- a/main_llama.py +++ b/main_llama.py @@ -78,7 +78,11 @@ def main(ticket_id=None): logger.info(f"Initialisation du modèle LlamaVision: {model_name}") modele_llama = LlamaVision(model_name) modele_llama.configurer(temperature=0.2, top_p=0.9, max_tokens=4000) - + + # Récupérer le nom normalisé du modèle + normalized_model_name = modele_llama.pipeline_normalized_name + logger.info(f"Nom normalisé du modèle: {normalized_model_name}") + # Initialiser les agents avec LlamaVision logger.info("Création des agents avec LlamaVision") factory = AgentFactoryLlamaVision() @@ -98,8 +102,8 @@ def main(ticket_id=None): "debug_mode": args.debug, "reports_dir": args.reports_dir, "ocr_enabled": not args.no_ocr, - "english_only": True, # S'assurer que le contenu est traduit en anglais - "model_name": model_name # Utiliser le même nom de modèle partout + "english_only": True, + "model_name": normalized_model_name # Utiliser le nom normalisé du modèle } logger.info(f"Configuration: {json.dumps(config, indent=2)}") diff --git a/output/ticket_T11143/T11143_20250422_084617/T11143_rapports/pipeline/analyse_image_unknown_model_results.json b/output/ticket_T11143/T11143_20250422_084617/T11143_rapports/pipeline/analyse_image_unknown_model_results.json deleted file mode 100644 index 194603a..0000000 --- a/output/ticket_T11143/T11143_20250422_084617/T11143_rapports/pipeline/analyse_image_unknown_model_results.json +++ /dev/null @@ -1,26 +0,0 @@ -[ - { - "analyse": "ERROR: Erreur lors de l'analyse: 'LlamaVision' object has no attribute 'peut_analyser_images'", - "raw_response": "", - "error": true, - "metadata": { - "image_path": "output/ticket_T11143/T11143_20250422_084617/attachments/image.png", - "image_name": "image.png", - "timestamp": "20250424_135150", - "error": true, - "source_agent": "AgentImageAnalyser" - } - }, - { - "analyse": "ERROR: Erreur lors de l'analyse: 'LlamaVision' object has no attribute 'peut_analyser_images'", - "raw_response": "", - "error": true, - "metadata": { - "image_path": "output/ticket_T11143/T11143_20250422_084617/attachments/image_145435.png", - "image_name": "image_145435.png", - "timestamp": "20250424_135150", - "error": true, - "source_agent": "AgentImageAnalyser" - } - } -] \ No newline at end of file diff --git a/output/ticket_T11143/T11143_20250422_084617/T11143_rapports/pipeline/analyse_image_unknown_model_results.txt b/output/ticket_T11143/T11143_20250422_084617/T11143_rapports/pipeline/analyse_image_unknown_model_results.txt deleted file mode 100644 index d655e13..0000000 --- a/output/ticket_T11143/T11143_20250422_084617/T11143_rapports/pipeline/analyse_image_unknown_model_results.txt +++ /dev/null @@ -1,18 +0,0 @@ -RÉSULTATS DE L'ANALYSE ANALYSE_IMAGE - TICKET T11143 -================================================================================ - ---- ÉLÉMENT 1 --- - -ERROR: Erreur lors de l'analyse: 'LlamaVision' object has no attribute 'peut_analyser_images' - ----------------------------------------- - ---- ÉLÉMENT 2 --- - -ERROR: Erreur lors de l'analyse: 'LlamaVision' object has no attribute 'peut_analyser_images' - ----------------------------------------- - - -================================================================================ -Fichier original: analyse_image_unknown_model_results.json \ No newline at end of file diff --git a/output/ticket_T11143/T11143_20250422_084617/T11143_rapports/pipeline/analyse_ticket_llama3-2-vision-90b-instruct-q8-0_results.json b/output/ticket_T11143/T11143_20250422_084617/T11143_rapports/pipeline/analyse_ticket_llama3-2-vision-90b-instruct-q8-0_results.json index d10dd1f..ab817fc 100644 --- a/output/ticket_T11143/T11143_20250422_084617/T11143_rapports/pipeline/analyse_ticket_llama3-2-vision-90b-instruct-q8-0_results.json +++ b/output/ticket_T11143/T11143_20250422_084617/T11143_rapports/pipeline/analyse_ticket_llama3-2-vision-90b-instruct-q8-0_results.json @@ -10,7 +10,7 @@ "https://odoo.cbao.fr/web/image/145435?access_token=608ac9e7-3627-4a13-8ec-06ff5046ebf3" ], "metadata": { - "timestamp": "20250424_135051", + "timestamp": "20250424_140742", "source_agent": "AgentTicketAnalyser", "ticket_id": "T11143", "model_info": { diff --git a/output/ticket_T11143/T11143_20250422_084617/T11143_rapports/pipeline/ocr_traduction/543d7da1b54c29ff43ce5712d1a9aa4962ed21795c4e943fcb8cb84fd4d7465a.jpg.json b/output/ticket_T11143/T11143_20250422_084617/T11143_rapports/pipeline/ocr_traduction/543d7da1b54c29ff43ce5712d1a9aa4962ed21795c4e943fcb8cb84fd4d7465a.jpg.json index 331bd90..0ba1b39 100644 --- a/output/ticket_T11143/T11143_20250422_084617/T11143_rapports/pipeline/ocr_traduction/543d7da1b54c29ff43ce5712d1a9aa4962ed21795c4e943fcb8cb84fd4d7465a.jpg.json +++ b/output/ticket_T11143/T11143_20250422_084617/T11143_rapports/pipeline/ocr_traduction/543d7da1b54c29ff43ce5712d1a9aa4962ed21795c4e943fcb8cb84fd4d7465a.jpg.json @@ -5,7 +5,7 @@ "translation_en_back_fr": "", "metadata": { "ticket_id": "T11143", - "timestamp": "20250424_135059", + "timestamp": "20250424_140752", "source_module": "ocr_utils + translate_utils", "lang_detected": "fr" } diff --git a/output/ticket_T11143/T11143_20250422_084617/T11143_rapports/pipeline/ocr_traduction/a20f7697fd5e1d1fca3296c6d01228220e0e112c46b4440cc938f74d10934e98.gif.json b/output/ticket_T11143/T11143_20250422_084617/T11143_rapports/pipeline/ocr_traduction/a20f7697fd5e1d1fca3296c6d01228220e0e112c46b4440cc938f74d10934e98.gif.json index 65bca7a..34bbaa8 100644 --- a/output/ticket_T11143/T11143_20250422_084617/T11143_rapports/pipeline/ocr_traduction/a20f7697fd5e1d1fca3296c6d01228220e0e112c46b4440cc938f74d10934e98.gif.json +++ b/output/ticket_T11143/T11143_20250422_084617/T11143_rapports/pipeline/ocr_traduction/a20f7697fd5e1d1fca3296c6d01228220e0e112c46b4440cc938f74d10934e98.gif.json @@ -5,7 +5,7 @@ "translation_en_back_fr": "", "metadata": { "ticket_id": "T11143", - "timestamp": "20250424_135100", + "timestamp": "20250424_140752", "source_module": "ocr_utils + translate_utils", "lang_detected": "fr" } diff --git a/output/ticket_T11143/T11143_20250422_084617/T11143_rapports/pipeline/ocr_traduction/image.png.json b/output/ticket_T11143/T11143_20250422_084617/T11143_rapports/pipeline/ocr_traduction/image.png.json index dafaaca..368ea5f 100644 --- a/output/ticket_T11143/T11143_20250422_084617/T11143_rapports/pipeline/ocr_traduction/image.png.json +++ b/output/ticket_T11143/T11143_20250422_084617/T11143_rapports/pipeline/ocr_traduction/image.png.json @@ -5,7 +5,7 @@ "translation_en_back_fr": "Apache Tomcat x +\n\nGc @ 2 zk1.brg-b.com\n\n@ Andre Demo Devmat @ Modèle de base\n\nÇa marche!\n\nSi vous voyez cette page via un navigateur Web, cela signifie que vous avez configuré Tomcat avec succès. Félicitations!\n\nIl s'agit de la page d'accueil par défaut de Tomcat. Il peut être trouvé sur le système de fichiers local à: /var/lib/tomcat7/webapps/root/index.html\n\nMatou? Les vétérans pourraient être ravis de lire cette instance système de Tomcat est installé avec cataina_home dans / usr / tomcat7 et cataina_base dans / var / 1ib / tomcat7, en suivant les règles de / usr / share / doc / tomcat7-commun / running. SMS. GZ.\nVous pourriez envisager d'installer les packages suivants, si vous avez fait Alreni:\n\nTomcat7-Docs: Ce package installe une application Web qui permet de parcourir la documentation Tomcat 7 localement. Une fois installé, vous pouvez y accéder en cliquant\n\nTomcat7-Exemple: Ce package installe une application Web qui permet d'accéder aux exemples de servlet Tomcat 7 et JSP. Une fois installé, vous pouvez y accéder en cliquant\n\nTomcat7-admin: Ce package installe deux applications Web qui peuvent aider à gérer cette instance Tomcat. Une fois installé, vous pouvez accéder au et le et le et\n\nRemarque: Pour des raisons de sécurité, l'utilisation du gestionnaire WebApp est limitée aux utilisateurs avec le rôle \"Manager-Gui\". Le manager host-manager est limité aux utilisateurs avec un rôle \"Admin-Gui\". Les utilisateurs sont définis dans / et / tomcat7 / tomcta-users.xml.", "metadata": { "ticket_id": "T11143", - "timestamp": "20250424_135055", + "timestamp": "20250424_140746", "source_module": "ocr_utils + translate_utils", "lang_detected": "fr" } diff --git a/output/ticket_T11143/T11143_20250422_084617/T11143_rapports/pipeline/ocr_traduction/image_145435.png.json b/output/ticket_T11143/T11143_20250422_084617/T11143_rapports/pipeline/ocr_traduction/image_145435.png.json index 599a84f..5c543fb 100644 --- a/output/ticket_T11143/T11143_20250422_084617/T11143_rapports/pipeline/ocr_traduction/image_145435.png.json +++ b/output/ticket_T11143/T11143_20250422_084617/T11143_rapports/pipeline/ocr_traduction/image_145435.png.json @@ -5,7 +5,7 @@ "translation_en_back_fr": "C3 Giraudbrg-Lobicom / Brg-Lab / Page Progratsai / Zeaaahevngoaaaa\n\n Brglas cd béton cd foumasew tubo © masse\n\nECHANTILLION N ° 25-0007 ECEPTIAN le 02/04/2025 PR Bollé Victor prévu le 04/04/2025 Por Bollee Victor N ° Pédéwment 25-00078\nMatériau de sable 0/20 Carriere adceg\n\n[Fai Jemmarme | [M Porrouo || onservanons] [