llm_ticket3/.specstory/history/2025-04-08_09-12-comparaison-des-formats-ollama-et-mistral.md
2025-04-08 11:34:17 +02:00

26 KiB

Comparaison des formats Ollama et Mistral (2025-04-08 11:12:20)

User

j'ai une disparité lorsque j'utilise ollama ou mistral le tableau question/réponse ne se fait pas avec ollama je voudrai avoir des réglages équivalent que ce soit avec mistral ou ollama dans mon agent_report_generator.py il faudrait déterminer d'où vient cette différence de format des résultats


Assistant

Read file: agents/agent_report_generator.py


Read file: agents/agent_report_generator.py


          texte_rapport = texte_rapport.replace("CBAD", "CBAO")
          
-         # Rechercher un objet JSON dans le texte
-         json_match = re.search(r'```json\s*({.*?})\s*```', texte_rapport, re.DOTALL)
-         
-         if not json_match:
+         # Patterns de recherche plus variés pour s'adapter aux différents modèles
+         patterns = [
+             r'```json\s*({.*?})\s*```',  # Pattern standard avec backticks triples
+             r'```\s*({.*?"chronologie_echanges".*?})\s*```',  # Pattern sans spécifier json mais avec le contenu attendu
+             r'{[\s\n]*"chronologie_echanges"[\s\n]*:[\s\n]*\[.*?\][\s\n]*}',  # Pattern sans backticks
+             r'<json>(.*?)</json>'  # Pattern alternatif avec balises xml
+         ]
+         
+         # Essayer chaque pattern
+         json_text = None
+         for pattern in patterns:
+             json_match = re.search(pattern, texte_rapport, re.DOTALL)
+             if json_match:
+                 json_text = json_match.group(1).strip()
+                 logger.info(f"JSON trouvé avec le pattern: {pattern[:20]}...")
+                 break
+         
+         # Si aucun pattern n'a fonctionné, tenter une approche plus agressive pour extraire le JSON
+         if not json_text:
+             # Chercher des indices de début de JSON dans le texte
+             potential_starts = [
+                 texte_rapport.find('{"chronologie_echanges"'),
+                 texte_rapport.find('{\n  "chronologie_echanges"'),
+                 texte_rapport.find('{ "chronologie_echanges"')
+             ]
+             
+             # Filtrer les indices valides (non -1)
+             valid_starts = [idx for idx in potential_starts if idx != -1]
+             
+             if valid_starts:
+                 # Prendre l'indice le plus petit (premier dans le texte)
+                 start_idx = min(valid_starts)
+                 # Chercher la fin du JSON (accolade fermante suivie d'une nouvelle ligne ou de la fin du texte)
+                 json_extract = texte_rapport[start_idx:]
+                 # Compter les accolades pour trouver la fermeture du JSON
+                 open_braces = 0
+                 close_idx = -1
+                 
+                 for i, char in enumerate(json_extract):
+                     if char == '{':
+                         open_braces += 1
+                     elif char == '}':
+                         open_braces -= 1
+                         if open_braces == 0:
+                             close_idx = i
+                             break
+                 
+                 if close_idx != -1:
+                     json_text = json_extract[:close_idx + 1]
+                     logger.info(f"JSON extrait par analyse d'accolades: {len(json_text)} caractères")
+         
+         if not json_text:
              logger.warning("Aucun JSON trouvé dans le rapport")
              return texte_rapport, None, None
          
-         # Extraire le JSON et le parser
-         json_text = json_match.group(1)
-         try:
+         # Nettoyage supplémentaire du JSON
+         # Enlever caractères non imprimables ou indésirables qui pourraient être ajoutés par certains modèles
+         json_text = re.sub(r'[\x00-\x1F\x7F]', '', json_text)
+         
+         try:
+             # Vérifier que le texte commence par { et se termine par }
+             if not (json_text.startswith('{') and json_text.endswith('}')):
+                 logger.warning(f"Format JSON incorrect, tentative de correction. Texte: {json_text[:50]}...")
+                 # Chercher les délimiteurs du JSON
+                 start = json_text.find('{')
+                 end = json_text.rfind('}')
+                 if start != -1 and end != -1 and start < end:
+                     json_text = json_text[start:end+1]
+             
              echanges_json = json.loads(json_text)
              logger.info(f"JSON extrait avec succès: {len(json_text)} caractères")
              
+             # Vérifier si le JSON a la structure attendue
+             if not isinstance(echanges_json, dict) or "chronologie_echanges" not in echanges_json:
+                 # Tenter de corriger la structure si possible
+                 if len(echanges_json) > 0 and isinstance(list(echanges_json.values())[0], list):
+                     # Prendre la première liste comme chronologie
+                     key = list(echanges_json.keys())[0]
+                     echanges_json = {"chronologie_echanges": echanges_json[key]}
+                     logger.info(f"Structure JSON corrigée en utilisant la clé: {key}")
+                 else:
+                     logger.warning("Structure JSON incorrecte et non réparable")
+                     return texte_rapport, None, None
+             
              # Convertir en tableau Markdown
              echanges_markdown = "| Date | Émetteur | Type | Contenu | Statut |\n"
              
              # Remplacer le JSON dans le texte par le tableau Markdown
-             rapport_traite = texte_rapport.replace(json_match.group(0), echanges_markdown)
+             # Si le JSON était entouré de backticks, remplacer tout le bloc
+             if json_match:
+                 rapport_traite = texte_rapport.replace(json_match.group(0), echanges_markdown)
+             else:
+                 # Sinon, remplacer juste le texte JSON
+                 rapport_traite = texte_rapport.replace(json_text, echanges_markdown)
              
              return rapport_traite, echanges_json, echanges_markdown
              
          except json.JSONDecodeError as e:
              logger.error(f"Erreur lors du décodage JSON: {e}")
+             logger.debug(f"Contenu JSON problématique: {json_text[:100]}...")
              return texte_rapport, None, None
      

      ]
    }
+ - La structure doit être EXACTEMENT comme indiquée, avec le nom de clé "chronologie_echanges" obligatoirement
  - Chaque message du ticket doit apparaître comme un objet dans la liste
  - Indique clairement qui est CLIENT et qui est SUPPORT dans le champ "emetteur"
  - Si une question n'a pas de réponse, assure-toi de le noter clairement
  - Toute mention de "CBAD" doit être remplacée par "CBAO" qui est le nom correct de la société
  - Tu dois synthétiser au mieux les échanges (le plus court et clair possible)
+ 
+ IMPORTANT POUR LE FORMAT:
+ - Le JSON doit être valide et parsable
+ - Utilise ```json et ``` pour délimiter le bloc JSON
+ - Ne modifie pas la structure des clés ("chronologie_echanges", "date", "emetteur", "type", "contenu")
+ - Assure-toi que les accolades et crochets sont correctement équilibrés
  
  Structure ton rapport:
  1. Résumé exécutif: Synthèse du problème initial (nom de la demande + description)
- 2. Chronologie des échanges: Objet JSON avec la structure imposée ci-dessus
+ 2. Chronologie des échanges: Objet JSON avec la structure imposée ci-dessus (partie CRUCIALE)
  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 dans ton analyse.
  Les données d'échanges client/support sont l'élément le plus important du rapport.
- Tu DOIS inclure le JSON des échanges dans ta réponse au format:
+ Tu DOIS inclure le JSON des échanges dans ta réponse exactement au format:
  ```json
  {

                  params["temperature"] -= 0.05
              elif "ollama" in self.llm.__class__.__name__.lower():
-                 params["temperature"] += 0.1
+                 # Ajustements spécifiques pour Ollama pour forcer le respect du format
+                 params["temperature"] = 0.1  # Température plus basse pour plus de précision
                  params.update({
-                     "num_ctx": 2048,
-                     "repeat_penalty": 1.1,
-                 })
+                     "num_ctx": 4096,  # Contexte plus large
+                     "repeat_penalty": 1.3,  # Pénalité plus forte pour éviter la répétition
+                     "top_k": 30,  # Limiter les choix pour plus de cohérence
+                     "num_predict": 2048,  # Nombre de tokens à prédire
+                     "stop": ["```", "</json>"]  # Arrêter à ces marqueurs pour mieux délimiter le JSON
+                 })
+                 
+                 # Ajouter des exemples dans le système prompt pour Ollama si ce n'est pas déjà fait
+                 if not "EXEMPLES D'ÉCHANGES" in self.llm.prompt_system:
+                     exemple_json = """
+ EXEMPLES D'ÉCHANGES POUR RÉFÉRENCE:
+ 
+ Exemple 1:
+ ```json
+ {
+   "chronologie_echanges": [
+     {"date": "2023-01-15", "emetteur": "CLIENT", "type": "Question", "contenu": "Je n'arrive pas à me connecter à l'application"},
+     {"date": "2023-01-16", "emetteur": "SUPPORT", "type": "Réponse", "contenu": "Avez-vous essayé de réinitialiser votre mot de passe?"}
+   ]
+ }
+ ```
+ 
+ Exemple 2:
+ ```json
+ {
+   "chronologie_echanges": [
+     {"date": "2023-02-10", "emetteur": "CLIENT", "type": "Information technique", "contenu": "Version de l'application: 2.3.1"},
+     {"date": "2023-02-11", "emetteur": "SUPPORT", "type": "Réponse", "contenu": "Cette version contient un bug connu, veuillez mettre à jour"}
+   ]
+ }
+ ```
+ 
+ N'oublie pas que le format EXACT est important. Utilise TOUJOURS la clé "chronologie_echanges" comme clé principale.
+ """
+                     self.llm.prompt_system += exemple_json
+                     logger.info("Exemples JSON ajoutés au prompt système pour Ollama")
              
              self.llm.configurer(**params)
+             logger.info(f"Configuration appliquée au modèle: {str(params)}")
+         else:
+             logger.warning("Le modèle LLM ne supporte pas la méthode configurer()")
      
      def executer(self, rapport_data: Dict, rapport_dir: str) -> Tuple[Optional[str], Optional[str]]:

              logger.info(f"Ajout de l'analyse de l'image {image_name} au prompt ({len(str(analyse))} caractères)")
          
-         # Ne pas répéter les instructions déjà présentes dans le system_prompt
+         # Instructions claires pour Ollama et autres modèles
          prompt += f"""
- N'oublie pas d'inclure un objet JSON structuré des échanges client/support selon le format demandé.
- Assure-toi que le JSON est valide et clairement balisé avec ```json et ``` dans ta réponse.
+ ## INSTRUCTIONS POUR LA GÉNÉRATION DU RAPPORT
+ 
+ 1. Résume d'abord le problème principal du ticket en quelques phrases.
+ 
+ 2. GÉNÉRER OBLIGATOIREMENT LE JSON DES ÉCHANGES CLIENT/SUPPORT:
+    - Les données d'échanges sont l'élément le plus important du rapport
+    - Utilise EXACTEMENT la structure suivante, sans la modifier:
+    ```json
+    {{
+      "chronologie_echanges": [
+        {{"date": "date1", "emetteur": "CLIENT", "type": "Question", "contenu": "contenu de la question"}},
+        {{"date": "date2", "emetteur": "SUPPORT", "type": "Réponse", "contenu": "contenu de la réponse"}}
+      ]
+    }}
+    ```
+    - La clé principale DOIT être "chronologie_echanges"
+    - N'ajoute pas de commentaires ou de texte dans le JSON
+    - Assure-toi que le JSON est valide et correspond EXACTEMENT au format demandé
+    - Entoure le JSON avec ```json et ``` pour faciliter l'extraction
+ 
+ 3. Après le JSON, analyse les images pertinentes et leur contribution à la compréhension du problème.
+ 
+ 4. Termine par une analyse technique des causes probables du problème.
+ 
+ IMPORTANT: Le JSON des échanges client/support est OBLIGATOIRE et doit être parfaitement formaté.
+ """
+         
+         # Vérifier si nous utilisons Ollama et ajouter un exemple supplémentaire si nécessaire
+         if hasattr(self.llm, "__class__") and "ollama" in self.llm.__class__.__name__.lower():
+             prompt += """
+ EXEMPLE EXACT DU FORMAT JSON ATTENDU:
+ ```json
+ {
+   "chronologie_echanges": [
+     {"date": "2023-05-10", "emetteur": "CLIENT", "type": "Question", "contenu": "L'application affiche une erreur lors de la connexion"},
+     {"date": "2023-05-11", "emetteur": "SUPPORT", "type": "Réponse", "contenu": "Pouvez-vous préciser le message d'erreur?"},
+     {"date": "2023-05-12", "emetteur": "CLIENT", "type": "Information technique", "contenu": "Message: Erreur de connexion au serveur"}
+   ]
+ }
+ ```
  """
          

J'ai apporté plusieurs modifications importantes pour résoudre le problème de disparité entre Mistral et Ollama concernant la génération du tableau question/réponse:

  1. Extraction JSON améliorée:

    • Ajout de multiples patterns de recherche pour s'adapter aux différentes façons dont les modèles formatent le JSON
    • Méthode alternative d'extraction basée sur l'analyse des accolades quand les expressions régulières échouent
    • Nettoyage et correction du JSON extrait pour augmenter les chances de réussite du parsing
  2. Prompt système renforcé:

    • Instructions plus précises sur la structure JSON attendue
    • Mise en évidence de l'importance de la clé "chronologie_echanges"
    • Ajout d'une section dédiée au format pour renforcer les contraintes
  3. Configuration spécifique pour Ollama:

    • Température réduite à 0.1 pour favoriser une génération plus déterministe
    • Paramètres spécifiques ajustés: repeat_penalty, top_k, num_ctx, num_predict
    • Ajout de tokens d'arrêt pour mieux délimiter le JSON
    • Exemples concrets intégrés au prompt système
  4. Instructions dans le prompt de génération:

    • Format JSON explicitement montré avec la structure attendue
    • Instructions étape par étape plus claires
    • Exemple supplémentaire pour Ollama

Ces changements devraient harmoniser le comportement entre Mistral et Ollama en:

  • Renforçant les contraintes de format pour Ollama
  • Améliorant la robustesse de l'extraction JSON quand le format n'est pas parfaitement respecté
  • Fournissant plus d'exemples concrets pour guider Ollama

Les modifications permettront d'obtenir des tableaux de questions/réponses cohérents, quel que soit le modèle utilisé.


User

pourquoi j'ai cette partie de code a quoi sert elle?


Assistant

Searched codebase "pourquoi j'ai cette partie de code a quoi sert elle?" • **25** results
File Lines
.specstory/history/2025-04-01_13-55-amélioration-de-l'extraction-des-pièces-jointes.md L13646-13684
.specstory/history/2025-04-01_13-55-problème-d'exécution-du-programme.md L1957-1991
.specstory/history/2025-04-01_13-55-problème-d'exécution-du-programme.md L11216-11254
llm_classes/base_llm.py L60-93
.specstory/history/2025-04-01_13-55-problème-d'exécution-du-programme.md L5124-5204
.specstory/history/2025-04-01_13-55-amélioration-de-l'extraction-des-pièces-jointes.md L14674-14707
.specstory/history/2025-04-01_13-55-amélioration-de-l'extraction-des-pièces-jointes.md L11758-11799
.specstory/history/2025-04-01_13-55-amélioration-de-l'extraction-des-pièces-jointes.md L3244-3296
.specstory/history/2025-04-01_13-55-amélioration-de-l'extraction-des-pièces-jointes.md L6527-6630
.specstory/history/2025-04-01_13-55-amélioration-de-l'extraction-des-pièces-jointes.md L14403-14468
.specstory/history/2025-04-07_07-17-analyse-de-code-et-ajout-de-logs.md L4351-4407
.specstory/history/2025-04-01_13-55-amélioration-de-l'extraction-des-pièces-jointes.md L11799-11843
.specstory/history/2025-04-07_07-12-analyse-de-code-et-ajout-de-logs.md L205-239
orchestrator.py L145-162
.specstory/history/2025-04-01_13-55-problème-d'exécution-du-programme.md L11295-11491
.specstory/history/2025-04-01_13-55-amélioration-de-l'extraction-des-pièces-jointes.md L14468-14508
.specstory/history/2025-04-01_13-55-amélioration-de-l'extraction-des-pièces-jointes.md L11364-11399
.specstory/history/2025-04-07_07-17-analyse-de-code-et-ajout-de-logs.md L2536-2724
.specstory/history/2025-04-01_13-55-amélioration-de-l'extraction-des-pièces-jointes.md L3014-3052
.specstory/history/2025-04-07_07-17-analyse-de-code-et-ajout-de-logs.md L4312-4351
.specstory/history/2025-04-07_07-17-analyse-de-code-et-ajout-de-logs.md L859-886
.specstory/history/2025-04-07_07-17-analyse-de-code-et-ajout-de-logs.md L1210-1239
.specstory/history/2025-04-01_13-55-amélioration-de-l'extraction-des-pièces-jointes.md L11320-11364
.specstory/history/2025-04-01_13-55-problème-d'exécution-du-programme.md L11019-11061
.specstory/history/2025-04-07_07-17-analyse-de-code-et-ajout-de-logs.md L248-276

Read file: agents/agent_report_generator.py


Les modifications que vous avez récemment acceptées concernent trois aspects principaux pour résoudre les problèmes de compatibilité entre Mistral et Ollama lors de la génération du tableau question/réponse dans le rapport :

  1. L'extraction robuste du JSON (méthode _extraire_et_traiter_json)

    • Cette partie de code a été modifiée pour rechercher le JSON dans différents formats possibles
    • Elle utilise plusieurs expressions régulières et une méthode basée sur le comptage des accolades
    • Elle nettoie et corrige automatiquement le JSON mal formaté
    • Elle transforme ensuite ce JSON en tableau Markdown structuré
  2. Le prompt spécifique pour Ollama (méthode _formater_prompt_pour_rapport)

    • Des instructions plus précises ont été ajoutées pour guider spécifiquement Ollama
    • Un exemple concret du format JSON attendu a été ajouté pour Ollama
    • Le code vérifie si on utilise Ollama et adapte le prompt en conséquence
  3. La configuration spécifique pour Ollama (méthode _appliquer_config_locale)

    • Paramètres ajustés pour Ollama (température, repeat_penalty, etc.)
    • Ajout d'exemples dans le prompt système quand Ollama est détecté
    • Configuration de tokens d'arrêt spécifiques pour Ollama

Ces modifications étaient nécessaires car Ollama (en tant que modèle open-source local) a tendance à être moins strict dans le respect des formats spécifiés comparé à Mistral (modèle API). Les changements garantissent que les deux modèles produisent des résultats compatibles pour le tableau question/réponse, soit en guidant Ollama pour produire un format JSON correct, soit en améliorant la robustesse de l'extraction JSON quand le format n'est pas parfait.


User

je veux parler de la partie ajustements selon le type de modèle qu'elle impact a t elle quels sont les paramètres pris en compte ceux du début du fichier ou ceux-ci car si c'est le cas mon protocole de test est alors erroné


Assistant

Read file: agents/agent_report_generator.py


Read file: agents/agent_report_generator.py


La partie "Ajustements selon le type de modèle" dans la méthode _appliquer_config_locale() a un impact crucial sur votre protocole de test, car elle modifie significativement les paramètres initiaux définis au début de la classe.

Voici ce qui se passe exactement:

  1. Définition initiale des paramètres - Au début de la classe, vous définissez:

    self.temperature = 0.4
    self.top_p = 0.9
    self.max_tokens = 2500
    
  2. Ajustements spécifiques par modèle - Dans la méthode _appliquer_config_locale(), ces valeurs sont modifiées:

    • Pour Mistral Medium:
      • temperature = 0.45 (0.4 + 0.05)
      • max_tokens = 1000 (remplacé complètement)
    • Pour Pixtral:
      • temperature = 0.35 (0.4 - 0.05)
    • Pour Ollama:
      • temperature = 0.1 (remplacé complètement)
      • Paramètres supplémentaires: num_ctx, repeat_penalty, top_k, num_predict, stop
  3. Application effective des paramètres - Ces paramètres modifiés sont ceux qui sont réellement appliqués au modèle via self.llm.configurer(**params), et non les valeurs initiales.

Impact sur votre protocole de test:

Si votre protocole de test considère que les paramètres utilisés sont ceux définis au début de la classe (0.4, 0.9, 2500), alors vos résultats seront trompeurs car ce ne sont pas les valeurs effectivement utilisées. Pour Ollama en particulier, la différence est importante:

  • Température 0.4 → 0.1 (beaucoup plus déterministe)
  • Ajout de paramètres spécifiques à Ollama qui changent complètement son comportement

Pour corriger votre protocole de test:

  1. Vous devez considérer les paramètres effectifs après les ajustements spécifiques par modèle
  2. Si vous souhaitez tester avec des paramètres identiques, vous devriez désactiver ces ajustements spécifiques
  3. Les logs contiennent les paramètres appliqués grâce à la ligne: logger.info(f"Configuration appliquée au modèle: {str(params)}")

Cette différence de paramétrage explique potentiellement pourquoi vous obteniez des résultats différents entre Mistral et Ollama dans votre situation initiale - ils n'utilisaient pas du tout les mêmes configurations.


User

peux tu supprimer ce paramètrage spécifique de mon agent pour avoir les meme paramètres tout le temps


Assistant

              self.llm.prompt_system = self.system_prompt
          
-         # Appliquer les paramètres
+         # Appliquer les paramètres - mêmes paramètres pour tous les modèles
          if hasattr(self.llm, "configurer"):
              params = {
              }
              
-             # Ajustements selon le type de modèle
-             if "mistral_medium" in self.llm.__class__.__name__.lower():
-                 params["temperature"] += 0.05
-                 params["max_tokens"] = 1000
-             elif "pixtral" in self.llm.__class__.__name__.lower():
-                 params["temperature"] -= 0.05
-             elif "ollama" in self.llm.__class__.__name__.lower():
-                 # Ajustements spécifiques pour Ollama pour forcer le respect du format
-                 params["temperature"] = 0.1  # Température plus basse pour plus de précision
-                 params.update({
-                     "num_ctx": 4096,  # Contexte plus large
-                     "repeat_penalty": 1.3,  # Pénalité plus forte pour éviter la répétition
-                     "top_k": 30,  # Limiter les choix pour plus de cohérence
-                     "num_predict": 2048,  # Nombre de tokens à prédire
-                     "stop": ["```", "</json>"]  # Arrêter à ces marqueurs pour mieux délimiter le JSON
-                 })
-                 
-                 # Ajouter des exemples dans le système prompt pour Ollama si ce n'est pas déjà fait
+             # Ajout des exemples dans le prompt système pour tous les modèles
              if not "EXEMPLES D'ÉCHANGES" in self.llm.prompt_system:
                  exemple_json = """
  """
                  self.llm.prompt_system += exemple_json
-                     logger.info("Exemples JSON ajoutés au prompt système pour Ollama")
+                 logger.info("Exemples JSON ajoutés au prompt système")
              
              self.llm.configurer(**params)

              logger.info(f"Ajout de l'analyse de l'image {image_name} au prompt ({len(str(analyse))} caractères)")
          
-         # Instructions claires pour Ollama et autres modèles
+         # Instructions claires pour tous les modèles
          prompt += f"""
  ## INSTRUCTIONS POUR LA GÉNÉRATION DU RAPPORT
  
  IMPORTANT: Le JSON des échanges client/support est OBLIGATOIRE et doit être parfaitement formaté.
- """
  
-         # Vérifier si nous utilisons Ollama et ajouter un exemple supplémentaire si nécessaire
-         if hasattr(self.llm, "__class__") and "ollama" in self.llm.__class__.__name__.lower():
-             prompt += """
  EXEMPLE EXACT DU FORMAT JSON ATTENDU:
  ```json

J'ai modifié le code pour uniformiser les paramètres utilisés par tous les modèles LLM :

  1. Dans la méthode _appliquer_config_locale() :

    • Suppression des ajustements spécifiques pour Mistral, Pixtral et Ollama
    • Conservation des paramètres initiaux (temperature=0.4, top_p=0.9, max_tokens=2500) pour tous les modèles
    • Ajout des exemples JSON au prompt système pour tous les modèles, pas seulement pour Ollama
  2. Dans la méthode _formater_prompt_pour_rapport() :

    • Suppression de la condition spécifique à Ollama
    • Ajout de l'exemple JSON pour tous les modèles

Avec ces modifications, vos tests seront plus cohérents car tous les modèles utiliseront exactement les mêmes paramètres et recevront les mêmes instructions, ce qui devrait faciliter la comparaison des résultats.

Ces changements vous permettront d'avoir un protocole de test plus rigoureux en éliminant les variables qui pourraient influencer les résultats différemment selon le modèle utilisé.


User

roblème de génération de rapport


Assistant

Read file: agents/agent_report_generator.py


  
  IMPORTANT: Le JSON des échanges client/support est OBLIGATOIRE et doit être parfaitement formaté.
+ """
  
+         # Ajouter l'exemple non formaté (sans f-string) pour éviter les erreurs de formatage
+         prompt += """
  EXEMPLE EXACT DU FORMAT JSON ATTENDU:
  ```json

cd ~/llm-ticket3 && cat agents/agent_report_generator.py | grep -A 3 -B 3 "Invalid format"
< cat agents/agent_report_generator.py | grep -A 3 -B 3 "Invalid format"
fgras-ca@PC-DEV:~/llm-ticket3$

cd ~/llm-ticket3 && python traitement.py T0101
fgras-ca@PC-DEV:~/llm-ticket3$ cd ~/llm-ticket3 && python traitement.py T0101
python: can't open file '/home/fgras-ca/llm-ticket3/traitement.py': [Errno 2] No such file or directory
fgras-ca@PC-DEV:~/llm-ticket3$