mirror of
https://github.com/Ladebeze66/llm_ticket3.git
synced 2025-12-13 15:46:52 +01:00
1604-09:20
This commit is contained in:
parent
215e7d95ed
commit
19d133e7da
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@ -1,20 +0,0 @@
|
||||
<!-- Generated by SpecStory -->
|
||||
|
||||
# Correction d'anomalie dans le rapport T0282 (2025-04-04 15:44:07)
|
||||
|
||||
_**User**_
|
||||
|
||||
comme tu peux le constater il y a une anomalie ligne 102-103 du rapport T0282_rapport.md qu'il faudrai éliminer dans clean_html.py quand le même problème se représentera dans d'autre traitement de ticket
|
||||
|
||||
---
|
||||
|
||||
_**Assistant**_
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,52 +0,0 @@
|
||||
<!-- Generated by SpecStory -->
|
||||
|
||||
# Analyse de code et ajout de logs (2025-04-07 09:17:46)
|
||||
|
||||
_**User**_
|
||||
|
||||
il faudrait que tu analyses mon code et que tu m'aides avec précision pour ajouter des logs ainsi que des print statement dans les endroits indispensables dans mon code car le fichier de test s'execute sans problème mais je ne retrouve aucun résultat il doit y avoir un soucis quelque part. Allons-y méthodiquement pour vérifier l'execution du programme
|
||||
|
||||
---
|
||||
|
||||
_**Assistant**_
|
||||
|
||||
Je vais analyser votre code et ajouter des logs stratégiques pour identifier le problème. Commençons par explorer la structure du projet.
|
||||
|
||||
---
|
||||
|
||||
<details>
|
||||
<summary>Listed current directory • **22** results</summary>
|
||||
|
||||
| Name |
|
||||
|-------|
|
||||
| 📄 `orchestrator.py` |
|
||||
| 📁 `__pycache__` |
|
||||
| 📄 `test_orchestrator.py` |
|
||||
| 📁 `.git` |
|
||||
| 📁 `agents` |
|
||||
| 📁 `llm_classes` |
|
||||
| 📄 `.gitignore` |
|
||||
| 📁 `.specstory` |
|
||||
| 📄 `orchestrator.py.backup` |
|
||||
| 📄 `orchestrator.py.new` |
|
||||
| 📄 `test_agents_with_models.py` |
|
||||
| 📁 `utils` |
|
||||
| 📁 `output` |
|
||||
| 📁 `prompt` |
|
||||
| 📄 `retrieve_ticket.log` |
|
||||
| 📄 `retrieve_ticket.py` |
|
||||
| 📄 `config.json` |
|
||||
| 📄 `README.md` |
|
||||
| 📄 `config.template.json` |
|
||||
| 📄 `requirements.txt` |
|
||||
| 📁 `venv` |
|
||||
| 📁 `data` |
|
||||
|
||||
</details>
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,230 +0,0 @@
|
||||
<!-- Generated by SpecStory -->
|
||||
|
||||
# Reprise du projet de rapport (2025-04-09 10:31:45)
|
||||
|
||||
_**User**_
|
||||
|
||||
tu peux reprendre où tu en étais
|
||||
|
||||
---
|
||||
|
||||
_**Assistant**_
|
||||
|
||||
Je vais reprendre notre travail sur les fichiers de génération de rapport. Laissez-moi examiner où nous en sommes avec le projet.
|
||||
|
||||
---
|
||||
|
||||
Read file: agents/agent_report_generator.py
|
||||
|
||||
---
|
||||
|
||||
Maintenant, examinons le fichier report_formatter.py pour comprendre l'interaction entre ces fichiers.
|
||||
|
||||
---
|
||||
|
||||
<details>
|
||||
<summary>Searched codebase "report_formatter.py markdown generation" • **25** results</summary>
|
||||
|
||||
| File | Lines |
|
||||
|------|-------|
|
||||
| `formatters/report_formatter.py` | L51-76 |
|
||||
| `formatters/__init__.py` | L1-8 |
|
||||
| `utils/report_formatter.py` | L51-76 |
|
||||
| `formatters/report_formatter.py` | L1-51 |
|
||||
| `formatters/report_formatter.py` | L376-416 |
|
||||
| `utils/report_formatter.py` | L1-51 |
|
||||
| `formatters/report_formatter.py` | L296-335 |
|
||||
| `utils/report_formatter.py` | L296-335 |
|
||||
| `utils/report_formatter.py` | L376-416 |
|
||||
| `formatters/report_formatter.py` | L416-431 |
|
||||
| `utils/report_formatter.py` | L416-431 |
|
||||
| `formatters/report_formatter.py` | L198-238 |
|
||||
| `utils/report_formatter.py` | L431-447 |
|
||||
| `utils/report_formatter.py` | L198-238 |
|
||||
| `formatters/report_formatter.py` | L431-447 |
|
||||
| `agents/agent_report_generator.py` | L598-629 |
|
||||
| `formatters/report_formatter.py` | L160-198 |
|
||||
| `formatters/report_formatter.py` | L114-160 |
|
||||
| `utils/report_formatter.py` | L160-198 |
|
||||
| `formatters/report_formatter.py` | L238-265 |
|
||||
| `utils/report_formatter.py` | L114-160 |
|
||||
| `utils/report_formatter.py` | L238-265 |
|
||||
| `formatters/json_to_markdown.py` | L58-100 |
|
||||
| `formatters/json_to_markdown.py` | L350-391 |
|
||||
| `.specstory/history/2025-04-08_09-12-comparaison-des-formats-ollama-et-mistral.md` | L1558-1596 |
|
||||
|
||||
</details>
|
||||
|
||||
---
|
||||
|
||||
Je vais maintenant examiner plus précisément comment les prompts sont gérés dans le code, puisque cela semble être un point clé de la conversation précédente.
|
||||
|
||||
---
|
||||
|
||||
<details>
|
||||
<summary>Grep search for "prompts" • **5** files</summary>
|
||||
|
||||
| File | Line | Match |
|
||||
|------|------|-------|
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/formatters/report_formatter.py` | L280 | `# Ajouter une section pour les prompts s'ils sont présents` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/formatters/report_formatter.py` | L281 | `if "prompts_utilisés" in rapport_data and rapport_data["prompts_utilisés"]:` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/formatters/report_formatter.py` | L282 | `markdown += "\n## Prompts utilisés\n\n"` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/formatters/report_formatter.py` | L283 | `prompts = rapport_data["prompts_utilisés"]` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/formatters/report_formatter.py` | L285 | `for agent, prompt in prompts.items():` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-07_07-17-analyse-de-code-et-ajout-de-logs.md` | L628 | `# Détails des prompts système` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-07_07-17-analyse-de-code-et-ajout-de-logs.md` | L629 | `f_md.write("### Prompts Système\n\n")` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-07_07-17-analyse-de-code-et-ajout-de-logs.md` | L1399 | `- # Détails des prompts système` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-07_07-17-analyse-de-code-et-ajout-de-logs.md` | L1400 | `- f_md.write("### Prompts Système\n\n")` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-07_07-17-analyse-de-code-et-ajout-de-logs.md` | L2379 | `1. **Amélioration des prompts système pour tous les agents**` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-07_07-17-analyse-de-code-et-ajout-de-logs.md` | L2390 | `- Enregistrement des prompts utilisés dans l'historique` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-07_07-17-analyse-de-code-et-ajout-de-logs.md` | L4703 | `- Ajout d'instructions explicites dans les prompts pour éviter les réponses "Je ne peux pas visualiser l'image"` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-07_07-17-analyse-de-code-et-ajout-de-logs.md` | L4739 | `plusieurs problèmes la gestion des prompts de mes agents n'est pas claire j'ai un fichier config @agent_config.py mais également les rôles d'agents@agent_image_sorter.py où les prompts sont redondant je voudrai simplifier la situation pour une meilleur gestion. Je voudrai égalemnt comprendre pourquoi mon LLM ne peut pas accéder aux images alors qu'elles sont bien présente` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-07_07-17-analyse-de-code-et-ajout-de-logs.md` | L7941 | `⟪ 392 characters skipped ⟫ivre les agents, les llm utilisées, les prompts et les paramètres utilisés à chaque étapes` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-07_07-17-analyse-de-code-et-ajout-de-logs.md` | L8041 | `⟪ 134 characters skipped ⟫e les informations sur les agents, LLM, prompts et paramètres utilisés :` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-07_07-17-analyse-de-code-et-ajout-de-logs.md` | L8230 | `Ajoutons maintenant des traces de log plus détaillées pour suivre les paramètres des agents et les prompts dans l'orchestrateur :` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-07_07-17-analyse-de-code-et-ajout-de-logs.md` | L8678 | `- Des logs plus détaillés concernant les paramètres des agents et les prompts utilisés` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-07_07-17-analyse-de-code-et-ajout-de-logs.md` | L8775 | `1. **Qualité des prompts** :` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L512 | `avant de continuer je voudrai savoir s'il était possible de créer un fichier avec les rapports finaux affichant les prompts des différents agents utilisés pour tracer les modifications de prompt future` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L518 | `Oui, il est tout à fait possible de créer un fichier de traçabilité pour les prompts des différents agents. Cette approche est excellente pour le suivi des modifications et l'amélioration continue des prompts.` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L520 | `Je propose la création d'un système de journalisation des prompts avec la structure suivante:` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L591 | `Voici ma proposition pour implémenter un système de traçabilité des prompts:` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L593 | `1. **Créer un nouveau dossier `prompt_history`** pour stocker l'historique des prompts` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L603 | `3. **Implémenter une fonction de journalisation** des prompts dans le système` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L617 | `Système de journalisation des prompts pour les agents LLM.` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L618 | `Permet de tracer l'évolution des prompts et leurs modifications.` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L622 | `Initialiser le logger de prompts.` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L625 | `base_dir: Répertoire de base pour stocker l'historique des prompts` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L652 | `"""Sauvegarde l'index des prompts."""` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L730 | `Récupère l'historique des prompts pour un agent donné.` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L736 | `Liste des entrées de prompts pour cet agent` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L777 | `Génère un rapport sur l'évolution des prompts.` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L785 | `report = "# Évolution des prompts LLM\n\n"` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L849 | `# Génère un rapport de l'évolution des prompts` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L856 | `2. Modifier les classes d'agents pour utiliser ce logger lors du chargement/modification des prompts` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L857 | `3. Ajouter une tâche dans l'orchestrateur pour générer périodiquement un rapport d'évolution des prompts` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L859 | `Cette solution permet de garder une trace complète des modifications de prompts, leurs justifications et leurs impacts, ce qui est très utile pour l'amélioration continue de votre système.` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L871 | `Compris, allons au plus simple. Vous souhaitez simplement ajouter les prompts utilisés à chaque rapport généré, afin de garder une trace de quels prompts ont été utilisés spécifiquement pour chaque analyse de ticket.` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L875 | `1. Créer une fonction qui ajoute les prompts au rapport final (JSON et MD)` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L881 | `def ajouter_prompts_au_rapport(ticket_code, rapport_dir):` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L883 | `Ajoute les prompts utilisés aux rapports finaux (JSON et MD)` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L893 | `# Récupérer les prompts utilisés pour cette analyse` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L894 | `prompts = {` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L901 | `# Filtrer les prompts None` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L902 | `prompts = {k: v for k, v in prompts.items() if v is not None}` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L909 | `# Ajouter la section des prompts` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L910 | `rapport_json["prompts_utilisés"] = prompts` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L921 | `# Ajouter la section des prompts à la fin` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L922 | `prompt_section = "\n\n## Prompts utilisés\n\n"` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L923 | `for agent, prompt in prompts.items():` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L943 | `# Chemin vers les prompts des agents` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L984 | `# Une fois les rapports JSON et MD générés, ajouter les prompts` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L985 | `ajouter_prompts_au_rapport(ticket_code, self.output_dir)` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L991 | `1. Récupère les prompts actuels des agents` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L993 | `3. Permet de voir facilement quels prompts ont été utilisés pour chaque analyse` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L996 | `Vous aurez ainsi une section "Prompts utilisés" à la fin de chaque rapport, ce qui vous permettra de les copier facilement pour une utilisation ailleurs.` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L1020 | `Maintenant, je vais créer le code pour ajouter les prompts aux rapports. Je vais chercher d'abord où se trouvent les prompts actuels.` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L1039 | `Maintenant que j'ai analysé le code, je vais créer la fonction pour ajouter les prompts aux rapports et l'intégrer dans le code existant. Voici l'implémentation complète:` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L1078 | `Basé sur l'analyse du code, je vais maintenant ajouter les modifications pour inclure les prompts dans les rapports:` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L1088 | `1. Je vais ajouter une nouvelle fonction pour collecter les prompts des agents` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L1089 | `2. Je vais modifier la méthode `executer` pour ajouter ces prompts au rapport final MD` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L1099 | `Maintenant je vais créer les modifications nécessaires au fichier `agent_report_generator.py` pour ajouter les prompts aux rapports finaux:` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L1103 | `def _collecter_prompts_agents(self) -> Dict[str, str]:` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L1105 | `Collecte les prompts système de tous les agents impliqués dans l'analyse.` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L1108 | `Dictionnaire contenant les prompts des agents` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L1110 | `prompts = {` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L1114 | `# Essayer de charger les prompts depuis les fichiers` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L1117 | `# Si le répertoire des prompts existe` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L1119 | `# Essayer de charger les prompts des autres agents` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L1130 | `prompts[agent_name] = f.read()` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L1135 | `return prompts` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L1137 | `# Nouvelle fonction pour ajouter les prompts au rapport Markdown` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L1138 | `def _ajouter_prompts_au_rapport_md(self, md_path: str, prompts: Dict[str, str]) -> None:` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L1140 | `Ajoute les prompts utilisés au rapport Markdown.` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L1144 | `prompts: Dictionnaire des prompts par agent` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L1147 | `logger.warning(f"Impossible d'ajouter les prompts au rapport: {md_path} n'existe pas")` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L1155 | `# Ajouter une section pour les prompts` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L1156 | `nouvelle_section = "\n\n## Prompts utilisés\n\n"` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L1157 | `for agent, prompt in prompts.items():` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L1172 | `logger.info(f"Prompts ajoutés au rapport Markdown: {md_path}")` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L1174 | `logger.error(f"Erreur lors de l'ajout des prompts au rapport: {str(e)}")` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L1232 | `# NOUVELLE PARTIE: Ajouter les prompts au rapport Markdown` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L1233 | `prompts = self._collecter_prompts_agents()` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L1234 | `self._ajouter_prompts_au_rapport_md(markdown_path, prompts)` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L1236 | `# NOUVELLE PARTIE: Ajouter les prompts au rapport JSON` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L1237 | `rapport_data_complet["prompts_utilisés"] = prompts` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/.specstory/history/2025-04-08_12-54-disparition-de-phrase-dans-les-fichiers.md` | L1238 | `# Mettre à jour le fichier JSON avec les prompts` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/agents/agent_report_generator.py` | L506 | `# Collecter les prompts et les ajouter au rapport` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/agents/agent_report_generator.py` | L507 | `prompts = self._collecter_prompts_agents()` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/agents/agent_report_generator.py` | L508 | `rapport_data_complet["prompts_utilisés"] = prompts` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/agents/agent_report_generator.py` | L603 | `def _collecter_prompts_agents(self) -> Dict[str, str]:` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/agents/agent_report_generator.py` | L605 | `Collecte les prompts système de tous les agents impliqués dans l'analyse.` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/agents/agent_report_generator.py` | L608 | `Dictionnaire contenant les prompts des agents` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/agents/agent_report_generator.py` | L610 | `prompts = {` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/agents/agent_report_generator.py` | L614 | `# Importer les classes d'agents pour accéder à leurs prompts` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/agents/agent_report_generator.py` | L621 | `# Créer des instances temporaires pour récupérer les prompts` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/agents/agent_report_generator.py` | L625 | `prompts["ticket_analyser"] = ticket_analyser.system_prompt` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/agents/agent_report_generator.py` | L632 | `prompts["image_analyser"] = image_analyser.system_prompt` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/agents/agent_report_generator.py` | L639 | `prompts["image_sorter"] = image_sorter.system_prompt` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/agents/agent_report_generator.py` | L647 | `return prompts` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/formatters/report_formatter.py` | L280 | `# Ajouter une section pour les prompts s'ils sont présents` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/formatters/report_formatter.py` | L281 | `if "prompts_utilisés" in rapport_data and rapport_data["prompts_utilisés"]:` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/formatters/report_formatter.py` | L282 | `markdown += "\n## Prompts utilisés\n\n"` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/formatters/report_formatter.py` | L283 | `prompts = rapport_data["prompts_utilisés"]` |
|
||||
| `vscode-remote://wsl%2Bubuntu-24.04/home/fgras-ca/llm-ticket3/formatters/report_formatter.py` | L285 | `for agent, prompt in prompts.items():` |
|
||||
|
||||
</details>
|
||||
|
||||
---
|
||||
|
||||
Maintenant, examinons le fichier report_formatter.py pour voir comment il gère les prompts.
|
||||
|
||||
---
|
||||
|
||||
Read file: formatters/report_formatter.py
|
||||
|
||||
---
|
||||
|
||||
D'après l'analyse des fichiers, je comprends que nous avions précédemment travaillé sur l'intégration des prompts des agents dans les rapports générés. Voici un résumé de ce que nous avons fait et de la situation actuelle :
|
||||
|
||||
1. Nous avons ajouté une fonction `_collecter_prompts_agents()` dans la classe `AgentReportGenerator` qui récupère les prompts système de tous les agents impliqués dans l'analyse du ticket.
|
||||
|
||||
2. Ces prompts sont ensuite inclus dans le rapport JSON final via la clé `"prompts_utilisés"`.
|
||||
|
||||
3. Le formateur de rapport (`report_formatter.py`) est configuré pour afficher ces prompts dans le rapport Markdown généré, avec un tronquage pour les prompts très longs.
|
||||
|
||||
Examinons maintenant l'interaction entre les deux fichiers, en particulier la manière dont le fichier JSON est généré par `agent_report_generator.py` puis traité par `report_formatter.py` pour créer le rapport Markdown.
|
||||
|
||||
---
|
||||
|
||||
Read file: agents/agent_report_generator.py
|
||||
|
||||
---
|
||||
|
||||
D'après l'analyse du code, je vois que tout est prêt pour inclure les prompts des agents dans les rapports générés. Le flux de travail est le suivant :
|
||||
|
||||
1. Dans `agent_report_generator.py` :
|
||||
- La méthode `_collecter_prompts_agents()` récupère les prompts système de tous les agents impliqués
|
||||
- Les prompts sont ajoutés au dictionnaire `rapport_data_complet` avec la clé `"prompts_utilisés"`
|
||||
- Le rapport JSON est sauvegardé avec ces informations
|
||||
|
||||
2. Dans `report_formatter.py` :
|
||||
- La fonction `_generate_markdown_content()` vérifie la présence de `"prompts_utilisés"` dans les données
|
||||
- Si présent, une section "## Prompts utilisés" est ajoutée au rapport Markdown
|
||||
- Les prompts longs sont tronqués pour éviter des rapports trop volumineux
|
||||
|
||||
Le système est fonctionnel et permet d'inclure les prompts des agents dans les rapports générés, ce qui était l'objectif souhaité.
|
||||
|
||||
Pour résumer la situation actuelle :
|
||||
|
||||
1. Nous avons mis en place un système qui collecte les prompts système de tous les agents impliqués dans l'analyse du ticket
|
||||
2. Ces prompts sont inclus dans le rapport JSON et Markdown final
|
||||
3. Le code est bien structuré et modulaire, avec une bonne séparation des responsabilités
|
||||
|
||||
Tout est fonctionnel et prêt à être utilisé. Voulez-vous apporter des améliorations spécifiques à ce système ou avez-vous d'autres questions sur son fonctionnement?
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,183 +0,0 @@
|
||||
<!-- Generated by SpecStory -->
|
||||
|
||||
# Éléments manquants avec DeepSeek (2025-04-10 17:33:14)
|
||||
|
||||
_**User**_
|
||||
|
||||
j'ai maintenant des éléments manquants avec deepseek notamment tableau échanges et csv@T9656_rapport_final.json @T9656_rapport_final.md
|
||||
|
||||
---
|
||||
|
||||
_**Assistant**_
|
||||
|
||||
Je vais analyser les éléments manquants dans les rapports générés avec DeepSeek.
|
||||
|
||||
---
|
||||
|
||||
Could not find file 'output_deepseek_20250410_172418/ticket_T9656/T9656_20250410_171035/T9656_rapports/T9656_rapport_final.json'. Did you mean one of:
|
||||
- output_deepseek_20250410_172418/ticket_T9656/T9656_20250410_171035/T9656_rapports/T9656/T9656_rapport_final.json
|
||||
|
||||
---
|
||||
|
||||
Read file: output_deepseek_20250410_172418/ticket_T9656/T9656_20250410_171035/T9656_rapports/T9656/T9656_rapport_final.json
|
||||
|
||||
---
|
||||
|
||||
<details>
|
||||
<summary>Searched codebase "issue with csv and chronologie_echanges in report generator" • **25** results</summary>
|
||||
|
||||
| File | Lines |
|
||||
|------|-------|
|
||||
| `fix_reports.py` | L31-76 |
|
||||
| `fix_reports.py` | L125-175 |
|
||||
| `generate_csv.py` | L51-74 |
|
||||
| `generate_csv.py` | L1-51 |
|
||||
| `.specstory/history/2025-04-10_08-33-analyse-et-simplification-de-agent-report-generator-py.md` | L581-636 |
|
||||
| `agents/utils/report_formatter.py` | L344-395 |
|
||||
| `fix_reports.py` | L76-116 |
|
||||
| `utils_old/report_formatter.py` | L76-114 |
|
||||
| `test_extraction_json.py` | L52-73 |
|
||||
| `formatters/report_formatter.py` | L82-120 |
|
||||
| `agents/utils/csv_exporter.py` | L1-46 |
|
||||
| `.specstory/history/2025-04-10_11-45-affinement-de-l'analyse-d'image.md` | L1540-1585 |
|
||||
| `.specstory/history/2025-04-10_14-24-problèmes-d'api-et-génération-de-rapports.md` | L2386-2421 |
|
||||
| `agents/utils/report_utils.py` | L204-236 |
|
||||
| `agents/utils/report_utils_bis.py` | L329-351 |
|
||||
| `agents/utils/report_utils_bis.py` | L351-383 |
|
||||
| `utils_old/report_formatter.py` | L51-76 |
|
||||
| `generate_csv.py` | L74-114 |
|
||||
| `reports/T0129_08_04/mistral-medium/T0129_rapport_final.json` | L7-35 |
|
||||
| `reports/T0124_08_04/mistral-large/T0124_rapport_final.json` | L7-23 |
|
||||
| `.specstory/history/2025-04-10_08-33-analyse-et-simplification-de-agent-report-generator-py.md` | L686-737 |
|
||||
| `.specstory/history/2025-04-10_08-33-analyse-et-simplification-de-agent-report-generator-py.md` | L2685-2737 |
|
||||
| `.specstory/history/2025-04-08_09-12-comparaison-des-formats-ollama-et-mistral.md` | L885-931 |
|
||||
| `.specstory/history/2025-04-09_12-06-correction-et-documentation-du-programme-odoo.md` | L4780-4836 |
|
||||
| `.specstory/history/2025-04-09_09-04-problème-d'extraction-de-ticket-odoo.md` | L1105-1245 |
|
||||
|
||||
</details>
|
||||
|
||||
---
|
||||
|
||||
<details>
|
||||
<summary>Searched codebase "agent_report_generator chronologie_echanges deepseek" • **24** results</summary>
|
||||
|
||||
| File | Lines |
|
||||
|------|-------|
|
||||
| `.specstory/history/2025-04-10_11-45-affinement-de-l'analyse-d'image.md` | L3642-3683 |
|
||||
| `.specstory/history/2025-04-10_14-24-problèmes-d'api-et-génération-de-rapports.md` | L3034-3059 |
|
||||
| `agents/utils/report_formatter.py` | L344-395 |
|
||||
| `.specstory/history/2025-04-10_08-33-analyse-et-simplification-de-agent-report-generator-py.md` | L581-636 |
|
||||
| `agents/agent_report_generator_bis.py` | L259-286 |
|
||||
| `agents/utils/report_utils.py` | L204-236 |
|
||||
| `agents/utils/report_utils_bis.py` | L329-351 |
|
||||
| `output_deepseek_20250410_172418/ticket_T9656/T9656_20250410_171035/T9656_rapports/T9656/T9656_rapport_final.md` | L1-53 |
|
||||
| `agents/utils/report_utils_bis.py` | L351-383 |
|
||||
| `.specstory/history/2025-04-10_08-33-analyse-et-simplification-de-agent-report-generator-py.md` | L2685-2737 |
|
||||
| `fix_reports.py` | L31-76 |
|
||||
| `agents/agent_report_generator.py` | L297-339 |
|
||||
| `output_deepseek_20250410_172418/ticket_T9656/T9656_20250410_171035/T9656_rapports/T9656/T9656_rapport_final.md` | L254-307 |
|
||||
| `.specstory/history/2025-04-10_08-33-analyse-et-simplification-de-agent-report-generator-py.md` | L3017-3061 |
|
||||
| `.specstory/history/2025-04-09_09-04-problème-d'extraction-de-ticket-odoo.md` | L1105-1245 |
|
||||
| `agents/utils/report_formatter.py` | L661-683 |
|
||||
| `.specstory/history/2025-04-10_11-45-affinement-de-l'analyse-d'image.md` | L3565-3606 |
|
||||
| `agents/utils/report_utils_bis.py` | L167-194 |
|
||||
| `.specstory/history/2025-04-10_08-33-analyse-et-simplification-de-agent-report-generator-py.md` | L2439-2482 |
|
||||
| `agents/utils/report_utils_bis.py` | L383-410 |
|
||||
| `agents/utils/report_formatter.py` | L614-661 |
|
||||
| `test_orchestrator_deepseek.py` | L159-191 |
|
||||
| `agents/utils/report_utils_bis.py` | L250-271 |
|
||||
| `test_orchestrator_deepseek_bis.py` | L159-191 |
|
||||
|
||||
</details>
|
||||
|
||||
---
|
||||
|
||||
Read file: output_deepseek_20250410_172418/ticket_T9656/T9656_20250410_171035/T9656_rapports/T9656_rapport.md
|
||||
|
||||
---
|
||||
|
||||
<details>
|
||||
<summary>Searched codebase "fix deepseek error "Invalid max_tokens value, the valid range of max_tokens is [1, 8192]" jsonschema agent_report_generator" • **24** results</summary>
|
||||
|
||||
| File | Lines |
|
||||
|------|-------|
|
||||
| `output_deepseek_20250410_172418/ticket_T9656/T9656_20250410_171035/T9656_rapports/T9656/T9656_rapport_final.json` | L113-153 |
|
||||
| `reports/T0101_09_04/T0101/large/T0101_rapport_final.json` | L17-44 |
|
||||
| `reports/T0101_09_04/T0101/qwen/T0101_rapport_final.json` | L17-44 |
|
||||
| `output_qwen_bis_20250410_171846/ticket_T9656/T9656_20250410_171035/T9656_rapports/T9656/T9656_rapport_final.json` | L144-185 |
|
||||
| `agents/agent_report_generator_bis.py` | L101-127 |
|
||||
| `output_deepseek_20250410_172418/ticket_T9656/T9656_20250410_171035/T9656_rapports/T9656/T9656_rapport_final.json` | L1-6 |
|
||||
| `agents/agent_report_generator.py` | L26-116 |
|
||||
| `reports/T0101_09_04/T0101/mistral_medium/T0101_rapport_final.json` | L55-86 |
|
||||
| `agents/agent_report_generator_bis.py` | L1-27 |
|
||||
| `llm_classes/deepseek.py` | L45-93 |
|
||||
| `.specstory/history/2025-04-10_14-24-problèmes-d'api-et-génération-de-rapports.md` | L3034-3059 |
|
||||
| `agents/agent_report_generator_bis.py` | L27-101 |
|
||||
| `test_orchestrator_deepseek_bis.py` | L34-83 |
|
||||
| `output_deepseek_20250410_172418/ticket_T9656/T9656_20250410_171035/T9656_rapports/T9656/T9656_rapport_final.md` | L429-484 |
|
||||
| `.specstory/history/2025-04-10_08-33-analyse-et-simplification-de-agent-report-generator-py.md` | L257-307 |
|
||||
| `.specstory/history/2025-04-07_07-17-analyse-de-code-et-ajout-de-logs.md` | L5425-5483 |
|
||||
| `agents/agent_report_generator.py` | L297-339 |
|
||||
| `reports/T0182_08_04/mistral_medium/T0182_rapport_final.json` | L55-87 |
|
||||
| `reports/T0182_08_04/mistral_large/T0182_rapport_final.json` | L55-87 |
|
||||
| `agents/agent_report_generator_bis.py` | L259-286 |
|
||||
| `test_orchestrator_deepseek.py` | L34-84 |
|
||||
| `agents/agent_report_generator_bis.py` | L216-259 |
|
||||
| `agents/agent_report_generator.py` | L525-550 |
|
||||
| `agents/utils/report_utils_bis.py` | L1-21 |
|
||||
|
||||
</details>
|
||||
|
||||
---
|
||||
|
||||
```bash
|
||||
python -c "import os; print(os.path.isfile('agents/agent_report_generator_bis.py'))"
|
||||
```
|
||||
|
||||
```
|
||||
<port os; print(os.path.isfile('agents/agent_report_generator_bis.py'))"
|
||||
True
|
||||
fgras-ca@PC-DEV:~/llm-ticket3$
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
<details>
|
||||
<summary>Searched codebase "test_orchestrator_deepseek.py" • **25** results</summary>
|
||||
|
||||
| File | Lines |
|
||||
|------|-------|
|
||||
| `test_orchestrator_deepseek.py` | L191-201 |
|
||||
| `test_orchestrator_deepseek.py` | L124-159 |
|
||||
| `test_orchestrator_deepseek_bis.py` | L191-201 |
|
||||
| `test_orchestrator_deepseek.py` | L1-34 |
|
||||
| `test_orchestrator_deepseek.py` | L34-84 |
|
||||
| `test_orchestrator_deepseek.py` | L201-214 |
|
||||
| `test_orchestrator_deepseek_bis.py` | L105-138 |
|
||||
| `test_orchestrator_deepseek_bis.py` | L34-83 |
|
||||
| `test_orchestrator_deepseek.py` | L84-124 |
|
||||
| `test_orchestrator_deepseek_bis.py` | L1-34 |
|
||||
| `test_orchestrator_deepseek_bis.py` | L201-214 |
|
||||
| `.specstory/history/2025-04-10_11-45-affinement-de-l'analyse-d'image.md` | L3511-3565 |
|
||||
| `test_orchestrator_deepseek_bis.py` | L83-105 |
|
||||
| `test_orchestrator_deepseek_bis.py` | L138-159 |
|
||||
| `test_orchestrator_deepseek.py` | L159-191 |
|
||||
| `test_orchestrator_deepseek_bis.py` | L159-191 |
|
||||
| `.specstory/history/2025-04-10_11-45-affinement-de-l'analyse-d'image.md` | L3606-3642 |
|
||||
| `test_orchestrator.py` | L83-118 |
|
||||
| `test_orchestrator_qwen.py` | L83-118 |
|
||||
| `.specstory/history/2025-04-10_11-45-affinement-de-l'analyse-d'image.md` | L3683-3724 |
|
||||
| `test_orchestrator_qwen_bis.py` | L123-158 |
|
||||
| `test_orchestrator_large.py` | L83-118 |
|
||||
| `test_orchestrator.py` | L33-83 |
|
||||
| `.specstory/history/2025-04-10_11-45-affinement-de-l'analyse-d'image.md` | L2423-2662 |
|
||||
| `.specstory/history/2025-04-10_11-45-affinement-de-l'analyse-d'image.md` | L3565-3606 |
|
||||
|
||||
</details>
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
503
formatters/clean_html.bak
Normal file
503
formatters/clean_html.bak
Normal file
@ -0,0 +1,503 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Fonctions utilitaires pour nettoyer le HTML et formater les dates.
|
||||
Version simplifiée et robuste: ignore les lignes problématiques.
|
||||
"""
|
||||
|
||||
import re
|
||||
from datetime import datetime
|
||||
import html
|
||||
from bs4 import BeautifulSoup, Tag
|
||||
from bs4.element import NavigableString, PageElement
|
||||
from typing import Union, List, Tuple, Optional, Any, Dict, cast
|
||||
import logging
|
||||
import html2text
|
||||
|
||||
def clean_html(html_content: Union[str, None], is_forwarded: bool = False, is_description: bool = False, strategy: str = "standard", preserve_links: bool = False, preserve_images: bool = False):
|
||||
"""
|
||||
Nettoie le contenu HTML pour le Markdown en identifiant et ignorant les parties problématiques.
|
||||
|
||||
Args:
|
||||
html_content (Union[str, None]): Contenu HTML à nettoyer
|
||||
is_forwarded (bool): Indique si le message est transféré
|
||||
is_description (bool): Paramètre de compatibilité (ignoré)
|
||||
strategy (str): Paramètre de compatibilité (ignoré)
|
||||
preserve_links (bool): Paramètre de compatibilité (ignoré)
|
||||
preserve_images (bool): Paramètre de compatibilité (ignoré)
|
||||
|
||||
Returns:
|
||||
str: Texte nettoyé
|
||||
"""
|
||||
if html_content is None or not isinstance(html_content, str) or html_content.strip() == "":
|
||||
if is_forwarded:
|
||||
return "*Message transféré - contenu non extractible*"
|
||||
return "*Contenu non extractible*"
|
||||
|
||||
try:
|
||||
# Sauvegarder les références d'images avant de nettoyer le HTML
|
||||
image_references: List[Tuple[str, str]] = []
|
||||
img_pattern = re.compile(r'<img[^>]+src=["\']([^"\']+)["\'][^>]*>')
|
||||
for match in img_pattern.finditer(html_content):
|
||||
full_tag = match.group(0)
|
||||
img_url = match.group(1)
|
||||
|
||||
# Vérifier si c'est une image Odoo
|
||||
if "/web/image/" in img_url:
|
||||
image_references.append((full_tag, img_url))
|
||||
|
||||
# Nettoyer le HTML
|
||||
soup = BeautifulSoup(html_content, 'html.parser')
|
||||
|
||||
# Supprimer les éléments script, style et head
|
||||
for elem in soup.find_all(['script', 'style', 'head']):
|
||||
elem.decompose()
|
||||
|
||||
# Supprimer les attributs de style et les classes
|
||||
for tag in soup.recursiveChildGenerator():
|
||||
if isinstance(tag, Tag):
|
||||
if tag.attrs and 'style' in tag.attrs:
|
||||
del tag.attrs['style']
|
||||
if tag.attrs and 'class' in tag.attrs:
|
||||
del tag.attrs['class']
|
||||
|
||||
# Conserver uniquement les balises HTML essentielles
|
||||
allowed_tags = ['p', 'br', 'b', 'i', 'u', 'strong', 'em', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',
|
||||
'ul', 'ol', 'li', 'a', 'img', 'blockquote', 'code', 'pre', 'hr', 'div', 'span',
|
||||
'table', 'tr', 'td', 'th', 'thead', 'tbody']
|
||||
|
||||
# Supprimer les balises HTML inutiles mais conserver leur contenu
|
||||
for tag in soup.find_all():
|
||||
if isinstance(tag, Tag) and tag.name.lower() not in allowed_tags:
|
||||
tag.unwrap()
|
||||
|
||||
# Amélioration: vérifier si nous avons du contenu significatif
|
||||
text_content = soup.get_text().strip()
|
||||
if not text_content and not image_references:
|
||||
if is_forwarded:
|
||||
return "*Message transféré - contenu non extractible*"
|
||||
return "*Contenu non extractible*"
|
||||
|
||||
# Obtenir le HTML nettoyé
|
||||
clean_content = str(soup)
|
||||
|
||||
# Vérifier si le contenu a été vidé par le nettoyage
|
||||
if clean_content.strip() == "" or clean_content.strip() == "<html><body></body></html>":
|
||||
# Si nous avons des références d'images mais pas de texte
|
||||
if image_references:
|
||||
image_descriptions = []
|
||||
for _, img_url in image_references:
|
||||
img_id = None
|
||||
id_match = re.search(r"/web/image/(\d+)", img_url)
|
||||
if id_match:
|
||||
img_id = id_match.group(1)
|
||||
image_descriptions.append(f"[Image {img_id}]")
|
||||
|
||||
# Retourner une description des images trouvées
|
||||
if image_descriptions:
|
||||
return "Message contenant uniquement des images: " + ", ".join(image_descriptions)
|
||||
|
||||
if is_forwarded:
|
||||
return "*Message transféré - contenu non extractible*"
|
||||
return "*Contenu non extractible*"
|
||||
|
||||
return clean_content
|
||||
except Exception as e:
|
||||
logging.error(f"Erreur lors du nettoyage HTML: {str(e)}")
|
||||
if is_forwarded:
|
||||
return "*Message transféré - contenu non extractible*"
|
||||
return "*Contenu non extractible*"
|
||||
|
||||
def extract_from_complex_html(html_content, preserve_images=False):
|
||||
"""
|
||||
Extrait le contenu d'un HTML complexe en utilisant BeautifulSoup.
|
||||
Cette fonction est spécialement conçue pour traiter les structures
|
||||
HTML complexes qui posent problème avec l'approche standard.
|
||||
|
||||
Args:
|
||||
html_content (str): Contenu HTML à traiter
|
||||
preserve_images (bool): Conserver les images
|
||||
|
||||
Returns:
|
||||
str: Contenu extrait et nettoyé
|
||||
"""
|
||||
try:
|
||||
soup = BeautifulSoup(html_content, 'html.parser')
|
||||
|
||||
# Extraction d'images - Étape 1: Rechercher toutes les images avant toute modification
|
||||
image_markdowns = []
|
||||
if preserve_images or True: # Toujours préserver les images
|
||||
# Chercher directement les balises img dans le HTML brut
|
||||
img_matches = re.finditer(r'<img[^>]+src=["\']([^"\']+)["\'][^>]*>', html_content)
|
||||
for match in img_matches:
|
||||
src = match.group(1)
|
||||
if '/web/image/' in src or 'access_token' in src or src.startswith('http'):
|
||||
image_markdowns.append(f"")
|
||||
|
||||
# Méthode alternative avec BeautifulSoup
|
||||
images = soup.find_all('img')
|
||||
for img in images:
|
||||
try:
|
||||
if isinstance(img, Tag) and img.has_attr('src'):
|
||||
src = img['src']
|
||||
if src and ('/web/image/' in src or 'access_token' in src or str(src).startswith('http')):
|
||||
alt = img['alt'] if img.has_attr('alt') else 'Image'
|
||||
image_markdowns.append(f"")
|
||||
except Exception:
|
||||
continue
|
||||
|
||||
# 1. Rechercher d'abord le contenu du message principal
|
||||
# Essayer différents sélecteurs en ordre de priorité
|
||||
content_selectors = [
|
||||
'.o_thread_message_content', # Contenu principal
|
||||
'.o_mail_body', # Corps du message
|
||||
'.o_mail_note_content', # Contenu d'une note
|
||||
'.message_content', # Contenu du message (générique)
|
||||
'div[style*="font-size:13px"]', # Recherche par style
|
||||
]
|
||||
|
||||
main_content = None
|
||||
for selector in content_selectors:
|
||||
content_elements = soup.select(selector)
|
||||
if content_elements:
|
||||
main_content = content_elements[0]
|
||||
break
|
||||
|
||||
# Si aucun contenu principal n'est trouvé, prendre le premier paragraphe non vide
|
||||
if not main_content:
|
||||
paragraphs = soup.find_all('p')
|
||||
for p in paragraphs:
|
||||
try:
|
||||
if isinstance(p, Tag) and p.text.strip():
|
||||
classes = p['class'] if p.has_attr('class') else []
|
||||
if not any(cls in str(classes) for cls in ['o_mail_info', 'recipient_link']):
|
||||
main_content = p
|
||||
break
|
||||
except Exception:
|
||||
continue
|
||||
|
||||
# Si toujours rien, prendre la première div non vide
|
||||
if not main_content:
|
||||
divs = soup.find_all('div')
|
||||
for div in divs:
|
||||
try:
|
||||
if isinstance(div, Tag) and div.text.strip():
|
||||
classes = div['class'] if div.has_attr('class') else []
|
||||
if not any(cls in str(classes) for cls in ['o_mail_info', 'o_thread']):
|
||||
main_content = div
|
||||
break
|
||||
except Exception:
|
||||
continue
|
||||
|
||||
# 2. Si on a trouvé du contenu, l'extraire
|
||||
if main_content:
|
||||
# Extraire toutes les images si demandé
|
||||
if preserve_images or True: # Toujours préserver les images
|
||||
try:
|
||||
if isinstance(main_content, Tag):
|
||||
content_images = main_content.find_all('img')
|
||||
for img in content_images:
|
||||
try:
|
||||
if isinstance(img, Tag) and img.has_attr('src'):
|
||||
src = img['src']
|
||||
if src and ('/web/image/' in src or 'access_token' in src or str(src).startswith('http')):
|
||||
alt = img['alt'] if img.has_attr('alt') else 'Image'
|
||||
image_markdowns.append(f"")
|
||||
|
||||
# Supprimer l'image pour éviter qu'elle apparaisse dans le texte
|
||||
img.decompose()
|
||||
except Exception:
|
||||
continue
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Extraire le texte
|
||||
try:
|
||||
if isinstance(main_content, Tag):
|
||||
text_content = main_content.get_text(separator='\n', strip=True)
|
||||
|
||||
# Nettoyer le texte
|
||||
text_content = re.sub(r'\n{3,}', '\n\n', text_content)
|
||||
text_content = text_content.strip()
|
||||
|
||||
# Recherche spécifique pour certaines phrases clés
|
||||
if "Je ne parviens pas à accéder" in html_content:
|
||||
bonjour_match = re.search(r'<p[^>]*>.*?Bonjour.*?</p>', html_content, re.DOTALL)
|
||||
acces_match = re.search(r'<p[^>]*>.*?Je ne parviens pas à accéder[^<]*</p>', html_content, re.DOTALL)
|
||||
|
||||
specific_content = []
|
||||
if bonjour_match:
|
||||
specific_content.append(pre_clean_html(bonjour_match.group(0)))
|
||||
if acces_match:
|
||||
specific_content.append(pre_clean_html(acces_match.group(0)))
|
||||
|
||||
# Extraire les contenus spécifiques du message "Je ne parviens pas..."
|
||||
merci_match = re.search(r'<p[^>]*>.*?Merci par avance.*?</p>', html_content, re.DOTALL)
|
||||
if merci_match:
|
||||
specific_content.append(pre_clean_html(merci_match.group(0)))
|
||||
|
||||
cordial_match = re.search(r'<p[^>]*>.*?Cordialement.*?</p>', html_content, re.DOTALL)
|
||||
if cordial_match:
|
||||
specific_content.append(pre_clean_html(cordial_match.group(0)))
|
||||
|
||||
if specific_content:
|
||||
text_content = '\n'.join(specific_content)
|
||||
|
||||
# Supprimer les duplications de lignes
|
||||
lines = text_content.split('\n')
|
||||
unique_lines = []
|
||||
for line in lines:
|
||||
if line not in unique_lines:
|
||||
unique_lines.append(line)
|
||||
text_content = '\n'.join(unique_lines)
|
||||
|
||||
# Ajouter les images à la fin
|
||||
if image_markdowns:
|
||||
# Supprimer les doublons d'images
|
||||
unique_images = []
|
||||
for img in image_markdowns:
|
||||
if img not in unique_images:
|
||||
unique_images.append(img)
|
||||
|
||||
text_content += "\n\n" + "\n".join(unique_images)
|
||||
|
||||
return text_content if text_content else "*Contenu non extractible*"
|
||||
except Exception as e:
|
||||
print(f"Erreur lors de l'extraction du texte: {e}")
|
||||
|
||||
# 3. Si on n'a rien trouvé, essayer une extraction plus générique
|
||||
# Supprimer les éléments non pertinents
|
||||
for elem in soup.select('.o_mail_info, .o_mail_tracking, .o_thread_tooltip, .o_thread_icons, .recipients_info'):
|
||||
try:
|
||||
elem.decompose()
|
||||
except Exception:
|
||||
continue
|
||||
|
||||
# Extraire le texte restant
|
||||
try:
|
||||
text = soup.get_text(separator='\n', strip=True)
|
||||
text = re.sub(r'\n{3,}', '\n\n', text)
|
||||
|
||||
# Préserver les images si demandé
|
||||
if preserve_images or True: # Toujours préserver les images
|
||||
# Les images ont déjà été extraites au début de la fonction
|
||||
|
||||
if image_markdowns:
|
||||
# Supprimer les doublons d'images
|
||||
unique_images = []
|
||||
for img in image_markdowns:
|
||||
if img not in unique_images:
|
||||
unique_images.append(img)
|
||||
|
||||
text += "\n\n" + "\n".join(unique_images)
|
||||
|
||||
# Si on a du contenu, le retourner
|
||||
if text and len(text.strip()) > 5:
|
||||
return text
|
||||
except Exception as e:
|
||||
print(f"Erreur lors de l'extraction générique: {e}")
|
||||
|
||||
# Si rien n'a fonctionné mais qu'on a des images, au moins les retourner
|
||||
if image_markdowns:
|
||||
unique_images = []
|
||||
for img in image_markdowns:
|
||||
if img not in unique_images:
|
||||
unique_images.append(img)
|
||||
|
||||
if any("Je ne parviens pas à accéder" in html_content for img in image_markdowns):
|
||||
return "Bonjour,\nJe ne parviens pas à accéder au l'essai au bleu :\n\n" + "\n".join(unique_images) + "\n\nMerci par avance pour votre.\nCordialement"
|
||||
else:
|
||||
return "Images extraites :\n\n" + "\n".join(unique_images)
|
||||
|
||||
return "*Contenu non extractible*"
|
||||
|
||||
except Exception as e:
|
||||
print(f"Erreur lors de l'extraction complexe: {e}")
|
||||
|
||||
# Dernière tentative : extraction directe avec regex
|
||||
try:
|
||||
# Extraire des images
|
||||
image_markdowns = []
|
||||
img_matches = re.finditer(r'<img[^>]+src=["\']([^"\']+)["\'][^>]*>', html_content)
|
||||
for match in img_matches:
|
||||
src = match.group(1)
|
||||
if '/web/image/' in src or 'access_token' in src or src.startswith('http'):
|
||||
image_markdowns.append(f"")
|
||||
|
||||
# Extraire du texte significatif
|
||||
text_parts = []
|
||||
|
||||
bonjour_match = re.search(r'<p[^>]*>.*?Bonjour.*?</p>', html_content, re.DOTALL)
|
||||
if bonjour_match:
|
||||
text_parts.append(pre_clean_html(bonjour_match.group(0)))
|
||||
|
||||
content_match = re.search(r'<p[^>]*>.*?Je ne parviens pas à accéder.*?</p>', html_content, re.DOTALL)
|
||||
if content_match:
|
||||
text_parts.append(pre_clean_html(content_match.group(0)))
|
||||
|
||||
# Combiner texte et images
|
||||
if text_parts or image_markdowns:
|
||||
result = ""
|
||||
if text_parts:
|
||||
result += "\n".join(text_parts) + "\n\n"
|
||||
|
||||
if image_markdowns:
|
||||
unique_images = []
|
||||
for img in image_markdowns:
|
||||
if img not in unique_images:
|
||||
unique_images.append(img)
|
||||
result += "\n".join(unique_images)
|
||||
|
||||
return result
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
return "*Contenu non extractible*"
|
||||
|
||||
def pre_clean_html(html_content):
|
||||
"""
|
||||
Fonction interne pour nettoyer le HTML basique avant traitement avancé.
|
||||
|
||||
Args:
|
||||
html_content: Contenu HTML à pré-nettoyer
|
||||
|
||||
Returns:
|
||||
Texte avec les balises HTML basiques retirées
|
||||
"""
|
||||
if not html_content:
|
||||
return ""
|
||||
|
||||
# Remplacer les balises <br>, <p>, <div> par des sauts de ligne
|
||||
content = html_content.replace('<br>', '\n').replace('<br/>', '\n').replace('<br />', '\n')
|
||||
content = content.replace('</p>', '\n').replace('</div>', '\n')
|
||||
|
||||
# Préserver les URLs des images
|
||||
image_urls = []
|
||||
img_matches = re.finditer(r'<img[^>]+src=["\']([^"\']+)["\'][^>]*>', content)
|
||||
for match in img_matches:
|
||||
if '/web/image/' in match.group(1) or match.group(1).startswith('http'):
|
||||
image_urls.append(match.group(1))
|
||||
|
||||
# Supprimer les balises HTML
|
||||
content = re.sub(r'<[^>]*>', '', content)
|
||||
|
||||
# Supprimer les espaces multiples
|
||||
content = re.sub(r' {2,}', ' ', content)
|
||||
|
||||
# Supprimer les sauts de ligne multiples
|
||||
content = re.sub(r'\n{3,}', '\n\n', content)
|
||||
|
||||
# Décoder les entités HTML courantes
|
||||
content = content.replace(' ', ' ')
|
||||
content = content.replace('<', '<')
|
||||
content = content.replace('>', '>')
|
||||
content = content.replace('&', '&')
|
||||
content = content.replace('"', '"')
|
||||
|
||||
# Supprimer les tabulations
|
||||
content = content.replace('\t', ' ')
|
||||
|
||||
# Ajouter les images préservées à la fin
|
||||
if image_urls:
|
||||
content += "\n\n"
|
||||
for url in image_urls:
|
||||
content += f"\n"
|
||||
|
||||
return content.strip()
|
||||
|
||||
def format_date(date_str):
|
||||
"""
|
||||
Formate une date ISO en format lisible.
|
||||
"""
|
||||
if not date_str:
|
||||
return ""
|
||||
|
||||
try:
|
||||
dt = datetime.fromisoformat(date_str.replace('Z', '+00:00'))
|
||||
return dt.strftime("%d/%m/%Y %H:%M:%S")
|
||||
except (ValueError, TypeError):
|
||||
return date_str
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Tests
|
||||
html = """<p>Bonjour,</p>
|
||||
<p>Voici un message avec <b>du HTML</b> et une signature.</p>
|
||||
<p>Cordialement,</p>
|
||||
<p>John Doe</p>
|
||||
<p>Support technique</p>
|
||||
<p>Afin d'assurer une meilleure traçabilité et vous garantir une prise en charge optimale,
|
||||
nous vous invitons à envoyer vos demandes d'assistance technique à support@exemple.fr</p>
|
||||
<p></p>
|
||||
"""
|
||||
|
||||
cleaned = clean_html(html)
|
||||
print("HTML nettoyé :\n", cleaned)
|
||||
|
||||
# Test avec un message transféré
|
||||
forwarded = """\\-------- Message transféré -------- Sujet : | Test message
|
||||
---|---
|
||||
Date : | Mon, 30 Mar 2020 11:18:20 +0200
|
||||
De : | [test@example.com](mailto:test@example.com)
|
||||
Pour : | John Doe [](mailto:john@example.com)
|
||||
Copie à : | [other@example.com](mailto:other@example.com)
|
||||
|
||||
Bonjour John,
|
||||
|
||||
Voici un message de test.
|
||||
|
||||
Cordialement,
|
||||
Test User
|
||||
|
||||
__________________________________________________________________ Ce message et toutes les pièces jointes sont confidentiels et établis à l'intention exclusive de ses destinataires. __________________________________________________________________"""
|
||||
|
||||
cleaned_forwarded = clean_html(forwarded)
|
||||
print("\nMessage transféré nettoyé :\n", cleaned_forwarded)
|
||||
|
||||
# Test avec le cas problématique du ticket T0282
|
||||
test_t0282 = """Bonjour,
|
||||
|
||||
Je reviens vers vous pour savoir si vous souhaitez toujours renommer le numéro d'identification de certaines formules dans BCN ou si vous avez trouvé une solution alternative ?
|
||||
|
||||
En vous remerciant par avance, je reste à votre disposition pour tout complément d'information.
|
||||
|
||||
Cordialement.
|
||||
|
||||
**Youness BENDEQ**
|
||||
|
||||
[
|
||||
|
||||
Affin d'assurer une meilleure traçabilité et vous garantir une prise en charge optimale, nous vous invitons à envoyer vos demandes d'assistance technique à support@cbao.fr Notre service est ouvert du lundi au vendredi de 9h à 12h et de 14h à 18h. Dès réception, un technicien prendra en charge votre demande et au besoin vous rappellera."""
|
||||
|
||||
cleaned_t0282 = clean_html(test_t0282)
|
||||
print("\nTest ticket T0282 nettoyé :\n", cleaned_t0282)
|
||||
|
||||
# Test avec le cas problématique de bas de page avec formatage markdown
|
||||
test_cbao_markdown = """Bonjour,
|
||||
|
||||
Voici un message de test pour vérifier la suppression des bas de page CBAO.
|
||||
|
||||
Cordialement,
|
||||
Jean Dupont
|
||||
|
||||
[ CBAO S.A.R.L. ](https://example.com/link) .
|
||||
|
||||
 """
|
||||
|
||||
cleaned_markdown = clean_html(test_cbao_markdown)
|
||||
print("\nTest avec formatage Markdown CBAO nettoyé :\n", cleaned_markdown)
|
||||
|
||||
# Test avec le cas exact du rapport
|
||||
test_rapport = """Bonjour,
|
||||
|
||||
Voici un message de test.
|
||||
|
||||
Cordialement,
|
||||
Pierre Martin
|
||||
|
||||
Envoyé par [ CBAO S.A.R.L. ](https://ciibcee.r.af.d.sendibt2.com/tr/cl/h2uBsi9hBosNYeSHMsPH47KAmufMTuNZjreF6M_tfRE63xzft8fwSbEQNb0aYIor74WQB5L6TF4kR9szVpQnalHFa3PUn_0jeLw42JNzIwsESwVlYad_3xCC1xi7qt3-dQ7i_Rt62MG217XgidnJxyNVcXWaWG5B75sB0GoqJq13IZc-hQ) .
|
||||
|
||||
 """
|
||||
|
||||
cleaned_rapport = clean_html(test_rapport)
|
||||
print("\nTest avec cas exact du rapport nettoyé :\n", cleaned_rapport)
|
||||
@ -15,7 +15,21 @@ from typing import Union, List, Tuple, Optional, Any, Dict, cast
|
||||
import logging
|
||||
import html2text
|
||||
|
||||
def clean_html(html_content: Union[str, None], is_forwarded: bool = False):
|
||||
def clean_html(html_content: Union[str, None], is_forwarded: bool = False, is_description: bool = False, strategy: str = "standard", preserve_links: bool = False, preserve_images: bool = False):
|
||||
"""
|
||||
Nettoie le contenu HTML pour le Markdown en identifiant et ignorant les parties problématiques.
|
||||
|
||||
Args:
|
||||
html_content (Union[str, None]): Contenu HTML à nettoyer
|
||||
is_forwarded (bool): Indique si le message est transféré
|
||||
is_description (bool): Paramètre de compatibilité (ignoré)
|
||||
strategy (str): Paramètre de compatibilité (ignoré)
|
||||
preserve_links (bool): Paramètre de compatibilité (ignoré)
|
||||
preserve_images (bool): Paramètre de compatibilité (ignoré)
|
||||
|
||||
Returns:
|
||||
str: Texte nettoyé
|
||||
"""
|
||||
if html_content is None or not isinstance(html_content, str) or html_content.strip() == "":
|
||||
if is_forwarded:
|
||||
return "*Message transféré - contenu non extractible*"
|
||||
@ -118,7 +132,7 @@ def extract_from_complex_html(html_content, preserve_images=False):
|
||||
img_matches = re.finditer(r'<img[^>]+src=["\']([^"\']+)["\'][^>]*>', html_content)
|
||||
for match in img_matches:
|
||||
src = match.group(1)
|
||||
if '/web/image/' in src or 'access_token' in src or src.startswith('http'):
|
||||
if '/web/image/' in src or 'access_token' in src or (isinstance(src, str) and src.startswith('http')):
|
||||
image_markdowns.append(f"")
|
||||
|
||||
# Méthode alternative avec BeautifulSoup
|
||||
@ -127,7 +141,7 @@ def extract_from_complex_html(html_content, preserve_images=False):
|
||||
try:
|
||||
if isinstance(img, Tag) and img.has_attr('src'):
|
||||
src = img['src']
|
||||
if src and ('/web/image/' in src or 'access_token' in src or str(src).startswith('http')):
|
||||
if src and ('/web/image/' in src or 'access_token' in src or (isinstance(src, str) and str(src).startswith('http'))):
|
||||
alt = img['alt'] if img.has_attr('alt') else 'Image'
|
||||
image_markdowns.append(f"")
|
||||
except Exception:
|
||||
@ -187,7 +201,7 @@ def extract_from_complex_html(html_content, preserve_images=False):
|
||||
try:
|
||||
if isinstance(img, Tag) and img.has_attr('src'):
|
||||
src = img['src']
|
||||
if src and ('/web/image/' in src or 'access_token' in src or str(src).startswith('http')):
|
||||
if src and ('/web/image/' in src or 'access_token' in src or (isinstance(src, str) and str(src).startswith('http'))):
|
||||
alt = img['alt'] if img.has_attr('alt') else 'Image'
|
||||
image_markdowns.append(f"")
|
||||
|
||||
@ -308,7 +322,7 @@ def extract_from_complex_html(html_content, preserve_images=False):
|
||||
img_matches = re.finditer(r'<img[^>]+src=["\']([^"\']+)["\'][^>]*>', html_content)
|
||||
for match in img_matches:
|
||||
src = match.group(1)
|
||||
if '/web/image/' in src or 'access_token' in src or src.startswith('http'):
|
||||
if '/web/image/' in src or 'access_token' in src or (isinstance(src, str) and src.startswith('http')):
|
||||
image_markdowns.append(f"")
|
||||
|
||||
# Extraire du texte significatif
|
||||
@ -362,7 +376,7 @@ def pre_clean_html(html_content):
|
||||
image_urls = []
|
||||
img_matches = re.finditer(r'<img[^>]+src=["\']([^"\']+)["\'][^>]*>', content)
|
||||
for match in img_matches:
|
||||
if '/web/image/' in match.group(1) or match.group(1).startswith('http'):
|
||||
if '/web/image/' in match.group(1) or (isinstance(match.group(1), str) and match.group(1).startswith('http')):
|
||||
image_urls.append(match.group(1))
|
||||
|
||||
# Supprimer les balises HTML
|
||||
|
||||
181
odoo/attachment_manager.bak
Normal file
181
odoo/attachment_manager.bak
Normal file
@ -0,0 +1,181 @@
|
||||
import os
|
||||
import base64
|
||||
import logging
|
||||
from typing import List, Dict, Any, Optional
|
||||
from .auth_manager import AuthManager
|
||||
from core.utils import save_json, normalize_filename
|
||||
|
||||
class AttachmentManager:
|
||||
"""
|
||||
Gestionnaire de pièces jointes pour extraire et sauvegarder les fichiers attachés aux tickets.
|
||||
"""
|
||||
|
||||
def __init__(self, auth: AuthManager):
|
||||
"""
|
||||
Initialise le gestionnaire de pièces jointes.
|
||||
|
||||
Args:
|
||||
auth: Gestionnaire d'authentification
|
||||
"""
|
||||
self.auth = auth
|
||||
self.model_name = "project.task"
|
||||
self.excluded_mime_types = [] # Types MIME à exclure si nécessaire
|
||||
|
||||
def get_ticket_attachments(self, ticket_id: int) -> List[Dict[str, Any]]:
|
||||
"""
|
||||
Récupère les pièces jointes associées à un ticket.
|
||||
|
||||
Args:
|
||||
ticket_id: ID du ticket
|
||||
|
||||
Returns:
|
||||
Liste des pièces jointes avec leurs métadonnées
|
||||
"""
|
||||
params = {
|
||||
"model": "ir.attachment",
|
||||
"method": "search_read",
|
||||
"args": [[["res_id", "=", ticket_id], ["res_model", "=", self.model_name]]],
|
||||
"kwargs": {
|
||||
"fields": ["id", "name", "mimetype", "file_size", "create_date",
|
||||
"create_uid", "datas", "description", "res_name"]
|
||||
}
|
||||
}
|
||||
|
||||
attachments = self.auth._rpc_call("/web/dataset/call_kw", params)
|
||||
|
||||
# Résoudre les informations sur le créateur
|
||||
for attachment in attachments:
|
||||
if "create_uid" in attachment and isinstance(attachment["create_uid"], list) and len(attachment["create_uid"]) >= 2:
|
||||
attachment["creator_name"] = attachment["create_uid"][1]
|
||||
attachment["creator_id"] = attachment["create_uid"][0]
|
||||
elif "create_uid" in attachment and isinstance(attachment["create_uid"], int):
|
||||
# Récupérer le nom du créateur
|
||||
params = {
|
||||
"model": "res.users",
|
||||
"method": "name_get",
|
||||
"args": [[attachment["create_uid"]]],
|
||||
"kwargs": {}
|
||||
}
|
||||
result = self.auth._rpc_call("/web/dataset/call_kw", params)
|
||||
if result and isinstance(result, list) and result[0] and len(result[0]) >= 2:
|
||||
attachment["creator_name"] = result[0][1]
|
||||
attachment["creator_id"] = result[0][0]
|
||||
|
||||
return attachments if isinstance(attachments, list) else []
|
||||
|
||||
def download_attachment(self, attachment: Dict[str, Any], output_dir: str) -> Dict[str, Any]:
|
||||
"""
|
||||
Télécharge et sauvegarde une pièce jointe dans le répertoire spécifié.
|
||||
|
||||
Args:
|
||||
attachment: Dictionnaire contenant les métadonnées de la pièce jointe
|
||||
output_dir: Répertoire où sauvegarder la pièce jointe
|
||||
|
||||
Returns:
|
||||
Dictionnaire avec les informations sur le fichier sauvegardé
|
||||
"""
|
||||
result = {
|
||||
"id": attachment.get("id"),
|
||||
"name": attachment.get("name", "Sans nom"),
|
||||
"mimetype": attachment.get("mimetype", "application/octet-stream"),
|
||||
"file_size": attachment.get("file_size", 0),
|
||||
"create_date": attachment.get("create_date"),
|
||||
"creator": attachment.get("creator_name", "Inconnu"),
|
||||
"status": "error",
|
||||
"file_path": "",
|
||||
"error": ""
|
||||
}
|
||||
|
||||
if not attachment.get("datas"):
|
||||
result["error"] = "Données de pièce jointe manquantes"
|
||||
return result
|
||||
|
||||
try:
|
||||
# Créer le dossier attachments s'il n'existe pas
|
||||
attachments_dir = os.path.join(output_dir, "attachments")
|
||||
os.makedirs(attachments_dir, exist_ok=True)
|
||||
|
||||
# Construire un nom de fichier sécurisé
|
||||
safe_filename = normalize_filename(attachment.get("name", f"attachment_{attachment.get('id')}.bin"))
|
||||
file_path = os.path.join(attachments_dir, safe_filename)
|
||||
|
||||
# Vérifier si un fichier avec le même nom existe déjà
|
||||
if os.path.exists(file_path):
|
||||
base, ext = os.path.splitext(safe_filename)
|
||||
counter = 1
|
||||
while os.path.exists(file_path):
|
||||
new_filename = f"{base}_{counter}{ext}"
|
||||
file_path = os.path.join(attachments_dir, new_filename)
|
||||
counter += 1
|
||||
|
||||
# Décoder et sauvegarder le contenu
|
||||
file_content = base64.b64decode(attachment["datas"])
|
||||
with open(file_path, "wb") as f:
|
||||
f.write(file_content)
|
||||
|
||||
result["status"] = "success"
|
||||
result["file_path"] = file_path
|
||||
return result
|
||||
|
||||
except Exception as e:
|
||||
logging.error(f"Erreur lors du téléchargement de la pièce jointe {attachment.get('name', '')}: {e}")
|
||||
result["error"] = str(e)
|
||||
return result
|
||||
|
||||
def save_attachments(self, ticket_id: int, output_dir: str, download: bool = True) -> List[Dict[str, Any]]:
|
||||
"""
|
||||
Récupère et sauvegarde toutes les pièces jointes d'un ticket.
|
||||
|
||||
Args:
|
||||
ticket_id: ID du ticket
|
||||
output_dir: Répertoire de sortie
|
||||
download: Si True, télécharge les pièces jointes, sinon récupère seulement les métadonnées
|
||||
|
||||
Returns:
|
||||
Liste des informations sur les pièces jointes
|
||||
"""
|
||||
# Récupérer les pièces jointes
|
||||
attachments = self.get_ticket_attachments(ticket_id)
|
||||
|
||||
if not attachments:
|
||||
logging.info(f"Aucune pièce jointe trouvée pour le ticket {ticket_id}")
|
||||
return []
|
||||
|
||||
logging.info(f"Traitement de {len(attachments)} pièces jointes pour le ticket {ticket_id}")
|
||||
|
||||
# Préparer les résultats
|
||||
attachments_info = []
|
||||
|
||||
# Télécharger chaque pièce jointe
|
||||
for i, attachment in enumerate(attachments):
|
||||
# Ne pas inclure le contenu binaire dans les métadonnées
|
||||
attachment_meta = {key: value for key, value in attachment.items() if key != "datas"}
|
||||
|
||||
if download:
|
||||
# Télécharger et sauvegarder la pièce jointe
|
||||
download_result = self.download_attachment(attachment, output_dir)
|
||||
attachment_meta.update({
|
||||
"download_status": download_result.get("status"),
|
||||
"local_path": download_result.get("file_path", ""),
|
||||
"error": download_result.get("error", "")
|
||||
})
|
||||
|
||||
if download_result.get("status") == "success":
|
||||
logging.info(f"Pièce jointe téléchargée: {attachment_meta.get('name')} ({i+1}/{len(attachments)})")
|
||||
else:
|
||||
logging.warning(f"Échec du téléchargement de la pièce jointe: {attachment_meta.get('name')} - {download_result.get('error')}")
|
||||
else:
|
||||
# Seulement récupérer les métadonnées
|
||||
attachment_meta.update({
|
||||
"download_status": "not_attempted",
|
||||
"local_path": "",
|
||||
"error": ""
|
||||
})
|
||||
|
||||
attachments_info.append(attachment_meta)
|
||||
|
||||
# Sauvegarder les informations sur les pièces jointes
|
||||
attachments_info_path = os.path.join(output_dir, "attachments_info.json")
|
||||
save_json(attachments_info, attachments_info_path)
|
||||
|
||||
return attachments_info
|
||||
@ -1,9 +1,12 @@
|
||||
import os
|
||||
import base64
|
||||
import logging
|
||||
from typing import List, Dict, Any, Optional
|
||||
import requests
|
||||
import re
|
||||
from typing import List, Dict, Any, Optional, Set
|
||||
from .auth_manager import AuthManager
|
||||
from core.utils import save_json, normalize_filename
|
||||
from utils.image_extractor.html_image_extractor import extract_images_from_ticket
|
||||
|
||||
class AttachmentManager:
|
||||
"""
|
||||
@ -122,7 +125,168 @@ class AttachmentManager:
|
||||
result["error"] = str(e)
|
||||
return result
|
||||
|
||||
def save_attachments(self, ticket_id: int, output_dir: str, download: bool = True) -> List[Dict[str, Any]]:
|
||||
def download_image_from_url(self, url: str, output_dir: str, filename: str = None) -> Dict[str, Any]:
|
||||
"""
|
||||
Télécharge une image à partir d'une URL et la sauvegarde dans le répertoire des pièces jointes.
|
||||
|
||||
Args:
|
||||
url: URL de l'image à télécharger
|
||||
output_dir: Répertoire de sortie
|
||||
filename: Nom de fichier à utiliser (facultatif)
|
||||
|
||||
Returns:
|
||||
Dictionnaire avec les informations sur le fichier téléchargé
|
||||
"""
|
||||
result = {
|
||||
"url": url,
|
||||
"status": "error",
|
||||
"file_path": "",
|
||||
"error": ""
|
||||
}
|
||||
|
||||
try:
|
||||
# Extraire le nom de fichier de l'URL si non fourni
|
||||
if not filename:
|
||||
# Extraire le nom de fichier de l'URL
|
||||
url_path = url.split('?')[0] # Supprimer les paramètres de requête
|
||||
path_parts = url_path.split('/')
|
||||
filename = path_parts[-1] if path_parts else f"image_{hash(url)}.jpg"
|
||||
|
||||
# Créer le dossier attachments s'il n'existe pas
|
||||
attachments_dir = os.path.join(output_dir, "attachments")
|
||||
os.makedirs(attachments_dir, exist_ok=True)
|
||||
|
||||
# Construire un nom de fichier sécurisé
|
||||
safe_filename = normalize_filename(filename)
|
||||
file_path = os.path.join(attachments_dir, safe_filename)
|
||||
|
||||
# Vérifier si un fichier avec le même nom existe déjà
|
||||
if os.path.exists(file_path):
|
||||
base, ext = os.path.splitext(safe_filename)
|
||||
counter = 1
|
||||
while os.path.exists(file_path):
|
||||
new_filename = f"{base}_{counter}{ext}"
|
||||
file_path = os.path.join(attachments_dir, new_filename)
|
||||
counter += 1
|
||||
|
||||
# Télécharger l'image en utilisant la session authentifiée
|
||||
response = requests.get(url, cookies=self.auth.cookies, headers=self.auth.headers, verify=self.auth.verify_ssl)
|
||||
response.raise_for_status()
|
||||
|
||||
# Sauvegarder l'image
|
||||
with open(file_path, 'wb') as f:
|
||||
f.write(response.content)
|
||||
|
||||
# Déterminer le type MIME basé sur l'extension
|
||||
_, ext = os.path.splitext(file_path)
|
||||
mimetype = {
|
||||
'.jpg': 'image/jpeg',
|
||||
'.jpeg': 'image/jpeg',
|
||||
'.png': 'image/png',
|
||||
'.gif': 'image/gif',
|
||||
'.svg': 'image/svg+xml'
|
||||
}.get(ext.lower(), 'application/octet-stream')
|
||||
|
||||
result.update({
|
||||
"status": "success",
|
||||
"file_path": file_path,
|
||||
"mimetype": mimetype,
|
||||
"file_size": len(response.content),
|
||||
"name": os.path.basename(file_path)
|
||||
})
|
||||
|
||||
return result
|
||||
|
||||
except Exception as e:
|
||||
logging.error(f"Erreur lors du téléchargement de l'image depuis {url}: {e}")
|
||||
result["error"] = str(e)
|
||||
return result
|
||||
|
||||
def extract_missing_images(self, messages_data: Dict[str, Any], output_dir: str) -> List[Dict[str, Any]]:
|
||||
"""
|
||||
Extrait les images manquantes qui sont intégrées dans les messages HTML mais non attachées au ticket.
|
||||
|
||||
Args:
|
||||
messages_data: Données des messages du ticket
|
||||
output_dir: Répertoire de sortie
|
||||
|
||||
Returns:
|
||||
Liste des informations sur les images extraites
|
||||
"""
|
||||
extracted_images = []
|
||||
|
||||
# Utiliser l'extracteur d'images HTML pour trouver les images intégrées
|
||||
try:
|
||||
# Vérifier si l'extracteur d'images est disponible
|
||||
image_paths = extract_images_from_ticket(output_dir)
|
||||
logging.info(f"Images trouvées par l'extracteur HTML: {len(image_paths)}")
|
||||
|
||||
# Chercher aussi les URL d'images dans les messages
|
||||
image_urls = self._extract_image_urls_from_messages(messages_data)
|
||||
logging.info(f"URLs d'images trouvées dans les messages: {len(image_urls)}")
|
||||
|
||||
# Télécharger les images depuis les URLs
|
||||
for url in image_urls:
|
||||
result = self.download_image_from_url(url, output_dir)
|
||||
if result["status"] == "success":
|
||||
extracted_images.append(result)
|
||||
logging.info(f"Image téléchargée depuis l'URL: {url}")
|
||||
|
||||
except Exception as e:
|
||||
logging.error(f"Erreur lors de l'extraction des images manquantes: {e}")
|
||||
|
||||
return extracted_images
|
||||
|
||||
def _extract_image_urls_from_messages(self, messages_data: Dict[str, Any]) -> Set[str]:
|
||||
"""
|
||||
Extrait les URLs d'images des messages.
|
||||
|
||||
Args:
|
||||
messages_data: Données des messages du ticket
|
||||
|
||||
Returns:
|
||||
Ensemble des URLs d'images trouvées
|
||||
"""
|
||||
image_urls = set()
|
||||
|
||||
# Récupérer la liste des messages
|
||||
messages = messages_data.get("messages", [])
|
||||
if not messages:
|
||||
return image_urls
|
||||
|
||||
# Parcourir chaque message
|
||||
for message in messages:
|
||||
# Chercher dans body_original s'il existe, sinon dans body
|
||||
body = message.get("body_original", message.get("body", ""))
|
||||
if not body or not isinstance(body, str):
|
||||
continue
|
||||
|
||||
# Recherche des URLs d'images dans le HTML
|
||||
# 1. Images Odoo internes avec /web/image/ ou /web/content/
|
||||
odoo_image_urls = re.findall(r'src=["\']((https?://[^"\']+)?/web/(image|content)/[^"\']+)["\']', body)
|
||||
for match in odoo_image_urls:
|
||||
url = match[0]
|
||||
# Ajouter le domaine Odoo si l'URL est relative
|
||||
if not url.startswith(('http://', 'https://')):
|
||||
# Utiliser le domaine de base de l'API Odoo
|
||||
if self.auth.url:
|
||||
base_url = self.auth.url.split('/xmlrpc')[0] # Extraire le domaine de base
|
||||
url = f"{base_url}{url if url.startswith('/') else '/' + url}"
|
||||
|
||||
# Ne pas inclure les URLs avec data:
|
||||
if url and not url.startswith('data:'):
|
||||
image_urls.add(url)
|
||||
|
||||
# 2. Images externes
|
||||
external_image_urls = re.findall(r'src=["\']((https?://[^"\']+)\.(jpe?g|png|gif|svg)([^"\']*)?)["\']', body)
|
||||
for match in external_image_urls:
|
||||
url = match[0]
|
||||
if url and not url.startswith('data:'):
|
||||
image_urls.add(url)
|
||||
|
||||
return image_urls
|
||||
|
||||
def save_attachments(self, ticket_id: int, output_dir: str, download: bool = True, messages_data: Dict[str, Any] = None) -> List[Dict[str, Any]]:
|
||||
"""
|
||||
Récupère et sauvegarde toutes les pièces jointes d'un ticket.
|
||||
|
||||
@ -130,6 +294,7 @@ class AttachmentManager:
|
||||
ticket_id: ID du ticket
|
||||
output_dir: Répertoire de sortie
|
||||
download: Si True, télécharge les pièces jointes, sinon récupère seulement les métadonnées
|
||||
messages_data: Données des messages pour extraire les images intégrées (optionnel)
|
||||
|
||||
Returns:
|
||||
Liste des informations sur les pièces jointes
|
||||
@ -139,41 +304,71 @@ class AttachmentManager:
|
||||
|
||||
if not attachments:
|
||||
logging.info(f"Aucune pièce jointe trouvée pour le ticket {ticket_id}")
|
||||
return []
|
||||
# Si aucune pièce jointe trouvée mais que nous avons les messages,
|
||||
# on peut quand même chercher des images intégrées
|
||||
attachments_info = []
|
||||
else:
|
||||
logging.info(f"Traitement de {len(attachments)} pièces jointes pour le ticket {ticket_id}")
|
||||
|
||||
logging.info(f"Traitement de {len(attachments)} pièces jointes pour le ticket {ticket_id}")
|
||||
|
||||
# Préparer les résultats
|
||||
attachments_info = []
|
||||
|
||||
# Télécharger chaque pièce jointe
|
||||
for i, attachment in enumerate(attachments):
|
||||
# Ne pas inclure le contenu binaire dans les métadonnées
|
||||
attachment_meta = {key: value for key, value in attachment.items() if key != "datas"}
|
||||
# Préparer les résultats
|
||||
attachments_info = []
|
||||
|
||||
if download:
|
||||
# Télécharger et sauvegarder la pièce jointe
|
||||
download_result = self.download_attachment(attachment, output_dir)
|
||||
attachment_meta.update({
|
||||
"download_status": download_result.get("status"),
|
||||
"local_path": download_result.get("file_path", ""),
|
||||
"error": download_result.get("error", "")
|
||||
})
|
||||
# Télécharger chaque pièce jointe
|
||||
for i, attachment in enumerate(attachments):
|
||||
# Ne pas inclure le contenu binaire dans les métadonnées
|
||||
attachment_meta = {key: value for key, value in attachment.items() if key != "datas"}
|
||||
|
||||
if download_result.get("status") == "success":
|
||||
logging.info(f"Pièce jointe téléchargée: {attachment_meta.get('name')} ({i+1}/{len(attachments)})")
|
||||
if download:
|
||||
# Télécharger et sauvegarder la pièce jointe
|
||||
download_result = self.download_attachment(attachment, output_dir)
|
||||
attachment_meta.update({
|
||||
"download_status": download_result.get("status"),
|
||||
"local_path": download_result.get("file_path", ""),
|
||||
"error": download_result.get("error", "")
|
||||
})
|
||||
|
||||
if download_result.get("status") == "success":
|
||||
logging.info(f"Pièce jointe téléchargée: {attachment_meta.get('name')} ({i+1}/{len(attachments)})")
|
||||
else:
|
||||
logging.warning(f"Échec du téléchargement de la pièce jointe: {attachment_meta.get('name')} - {download_result.get('error')}")
|
||||
else:
|
||||
logging.warning(f"Échec du téléchargement de la pièce jointe: {attachment_meta.get('name')} - {download_result.get('error')}")
|
||||
else:
|
||||
# Seulement récupérer les métadonnées
|
||||
attachment_meta.update({
|
||||
"download_status": "not_attempted",
|
||||
"local_path": "",
|
||||
"error": ""
|
||||
})
|
||||
# Seulement récupérer les métadonnées
|
||||
attachment_meta.update({
|
||||
"download_status": "not_attempted",
|
||||
"local_path": "",
|
||||
"error": ""
|
||||
})
|
||||
|
||||
attachments_info.append(attachment_meta)
|
||||
|
||||
# Extraction des images intégrées si les données des messages sont fournies
|
||||
if messages_data:
|
||||
try:
|
||||
logging.info("Extraction des images intégrées aux messages...")
|
||||
missing_images = self.extract_missing_images(messages_data, output_dir)
|
||||
|
||||
attachments_info.append(attachment_meta)
|
||||
|
||||
# Ajouter les images extraites à la liste des pièces jointes
|
||||
for image in missing_images:
|
||||
image_info = {
|
||||
"id": f"embedded_{len(attachments_info) + 1}", # Identifiant unique pour l'image intégrée
|
||||
"name": image.get("name", "Sans nom"),
|
||||
"mimetype": image.get("mimetype", "image/jpeg"),
|
||||
"file_size": image.get("file_size", 0),
|
||||
"create_date": None,
|
||||
"creator_name": "Extraction automatique",
|
||||
"download_status": image.get("status"),
|
||||
"local_path": image.get("file_path", ""),
|
||||
"error": image.get("error", ""),
|
||||
"is_embedded_image": True,
|
||||
"source_url": image.get("url", "")
|
||||
}
|
||||
attachments_info.append(image_info)
|
||||
|
||||
logging.info(f"{len(missing_images)} images intégrées extraites et ajoutées aux pièces jointes")
|
||||
|
||||
except Exception as e:
|
||||
logging.error(f"Erreur lors de l'extraction des images intégrées: {e}")
|
||||
|
||||
# Sauvegarder les informations sur les pièces jointes
|
||||
attachments_info_path = os.path.join(output_dir, "attachments_info.json")
|
||||
save_json(attachments_info, attachments_info_path)
|
||||
|
||||
181
odoo/attachment_manager.py.bak
Normal file
181
odoo/attachment_manager.py.bak
Normal file
@ -0,0 +1,181 @@
|
||||
import os
|
||||
import base64
|
||||
import logging
|
||||
from typing import List, Dict, Any, Optional
|
||||
from .auth_manager import AuthManager
|
||||
from core.utils import save_json, normalize_filename
|
||||
|
||||
class AttachmentManager:
|
||||
"""
|
||||
Gestionnaire de pièces jointes pour extraire et sauvegarder les fichiers attachés aux tickets.
|
||||
"""
|
||||
|
||||
def __init__(self, auth: AuthManager):
|
||||
"""
|
||||
Initialise le gestionnaire de pièces jointes.
|
||||
|
||||
Args:
|
||||
auth: Gestionnaire d'authentification
|
||||
"""
|
||||
self.auth = auth
|
||||
self.model_name = "project.task"
|
||||
self.excluded_mime_types = [] # Types MIME à exclure si nécessaire
|
||||
|
||||
def get_ticket_attachments(self, ticket_id: int) -> List[Dict[str, Any]]:
|
||||
"""
|
||||
Récupère les pièces jointes associées à un ticket.
|
||||
|
||||
Args:
|
||||
ticket_id: ID du ticket
|
||||
|
||||
Returns:
|
||||
Liste des pièces jointes avec leurs métadonnées
|
||||
"""
|
||||
params = {
|
||||
"model": "ir.attachment",
|
||||
"method": "search_read",
|
||||
"args": [[["res_id", "=", ticket_id], ["res_model", "=", self.model_name]]],
|
||||
"kwargs": {
|
||||
"fields": ["id", "name", "mimetype", "file_size", "create_date",
|
||||
"create_uid", "datas", "description", "res_name"]
|
||||
}
|
||||
}
|
||||
|
||||
attachments = self.auth._rpc_call("/web/dataset/call_kw", params)
|
||||
|
||||
# Résoudre les informations sur le créateur
|
||||
for attachment in attachments:
|
||||
if "create_uid" in attachment and isinstance(attachment["create_uid"], list) and len(attachment["create_uid"]) >= 2:
|
||||
attachment["creator_name"] = attachment["create_uid"][1]
|
||||
attachment["creator_id"] = attachment["create_uid"][0]
|
||||
elif "create_uid" in attachment and isinstance(attachment["create_uid"], int):
|
||||
# Récupérer le nom du créateur
|
||||
params = {
|
||||
"model": "res.users",
|
||||
"method": "name_get",
|
||||
"args": [[attachment["create_uid"]]],
|
||||
"kwargs": {}
|
||||
}
|
||||
result = self.auth._rpc_call("/web/dataset/call_kw", params)
|
||||
if result and isinstance(result, list) and result[0] and len(result[0]) >= 2:
|
||||
attachment["creator_name"] = result[0][1]
|
||||
attachment["creator_id"] = result[0][0]
|
||||
|
||||
return attachments if isinstance(attachments, list) else []
|
||||
|
||||
def download_attachment(self, attachment: Dict[str, Any], output_dir: str) -> Dict[str, Any]:
|
||||
"""
|
||||
Télécharge et sauvegarde une pièce jointe dans le répertoire spécifié.
|
||||
|
||||
Args:
|
||||
attachment: Dictionnaire contenant les métadonnées de la pièce jointe
|
||||
output_dir: Répertoire où sauvegarder la pièce jointe
|
||||
|
||||
Returns:
|
||||
Dictionnaire avec les informations sur le fichier sauvegardé
|
||||
"""
|
||||
result = {
|
||||
"id": attachment.get("id"),
|
||||
"name": attachment.get("name", "Sans nom"),
|
||||
"mimetype": attachment.get("mimetype", "application/octet-stream"),
|
||||
"file_size": attachment.get("file_size", 0),
|
||||
"create_date": attachment.get("create_date"),
|
||||
"creator": attachment.get("creator_name", "Inconnu"),
|
||||
"status": "error",
|
||||
"file_path": "",
|
||||
"error": ""
|
||||
}
|
||||
|
||||
if not attachment.get("datas"):
|
||||
result["error"] = "Données de pièce jointe manquantes"
|
||||
return result
|
||||
|
||||
try:
|
||||
# Créer le dossier attachments s'il n'existe pas
|
||||
attachments_dir = os.path.join(output_dir, "attachments")
|
||||
os.makedirs(attachments_dir, exist_ok=True)
|
||||
|
||||
# Construire un nom de fichier sécurisé
|
||||
safe_filename = normalize_filename(attachment.get("name", f"attachment_{attachment.get('id')}.bin"))
|
||||
file_path = os.path.join(attachments_dir, safe_filename)
|
||||
|
||||
# Vérifier si un fichier avec le même nom existe déjà
|
||||
if os.path.exists(file_path):
|
||||
base, ext = os.path.splitext(safe_filename)
|
||||
counter = 1
|
||||
while os.path.exists(file_path):
|
||||
new_filename = f"{base}_{counter}{ext}"
|
||||
file_path = os.path.join(attachments_dir, new_filename)
|
||||
counter += 1
|
||||
|
||||
# Décoder et sauvegarder le contenu
|
||||
file_content = base64.b64decode(attachment["datas"])
|
||||
with open(file_path, "wb") as f:
|
||||
f.write(file_content)
|
||||
|
||||
result["status"] = "success"
|
||||
result["file_path"] = file_path
|
||||
return result
|
||||
|
||||
except Exception as e:
|
||||
logging.error(f"Erreur lors du téléchargement de la pièce jointe {attachment.get('name', '')}: {e}")
|
||||
result["error"] = str(e)
|
||||
return result
|
||||
|
||||
def save_attachments(self, ticket_id: int, output_dir: str, download: bool = True) -> List[Dict[str, Any]]:
|
||||
"""
|
||||
Récupère et sauvegarde toutes les pièces jointes d'un ticket.
|
||||
|
||||
Args:
|
||||
ticket_id: ID du ticket
|
||||
output_dir: Répertoire de sortie
|
||||
download: Si True, télécharge les pièces jointes, sinon récupère seulement les métadonnées
|
||||
|
||||
Returns:
|
||||
Liste des informations sur les pièces jointes
|
||||
"""
|
||||
# Récupérer les pièces jointes
|
||||
attachments = self.get_ticket_attachments(ticket_id)
|
||||
|
||||
if not attachments:
|
||||
logging.info(f"Aucune pièce jointe trouvée pour le ticket {ticket_id}")
|
||||
return []
|
||||
|
||||
logging.info(f"Traitement de {len(attachments)} pièces jointes pour le ticket {ticket_id}")
|
||||
|
||||
# Préparer les résultats
|
||||
attachments_info = []
|
||||
|
||||
# Télécharger chaque pièce jointe
|
||||
for i, attachment in enumerate(attachments):
|
||||
# Ne pas inclure le contenu binaire dans les métadonnées
|
||||
attachment_meta = {key: value for key, value in attachment.items() if key != "datas"}
|
||||
|
||||
if download:
|
||||
# Télécharger et sauvegarder la pièce jointe
|
||||
download_result = self.download_attachment(attachment, output_dir)
|
||||
attachment_meta.update({
|
||||
"download_status": download_result.get("status"),
|
||||
"local_path": download_result.get("file_path", ""),
|
||||
"error": download_result.get("error", "")
|
||||
})
|
||||
|
||||
if download_result.get("status") == "success":
|
||||
logging.info(f"Pièce jointe téléchargée: {attachment_meta.get('name')} ({i+1}/{len(attachments)})")
|
||||
else:
|
||||
logging.warning(f"Échec du téléchargement de la pièce jointe: {attachment_meta.get('name')} - {download_result.get('error')}")
|
||||
else:
|
||||
# Seulement récupérer les métadonnées
|
||||
attachment_meta.update({
|
||||
"download_status": "not_attempted",
|
||||
"local_path": "",
|
||||
"error": ""
|
||||
})
|
||||
|
||||
attachments_info.append(attachment_meta)
|
||||
|
||||
# Sauvegarder les informations sur les pièces jointes
|
||||
attachments_info_path = os.path.join(output_dir, "attachments_info.json")
|
||||
save_json(attachments_info, attachments_info_path)
|
||||
|
||||
return attachments_info
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 25 KiB |
@ -1,34 +0,0 @@
|
||||
[
|
||||
{
|
||||
"id": 145453,
|
||||
"name": "image.png",
|
||||
"mimetype": "image/png",
|
||||
"file_size": 76543,
|
||||
"create_date": "2025-04-03 12:17:41",
|
||||
"create_uid": [
|
||||
22,
|
||||
"Fabien LAFAY"
|
||||
],
|
||||
"description": false,
|
||||
"res_name": "[T11143] BRGLAB - Essai inaccessible",
|
||||
"creator_name": "Fabien LAFAY",
|
||||
"creator_id": 22,
|
||||
"download_status": "success",
|
||||
"local_path": "output/ticket_T11143/T11143_20250415_171834/attachments/image.png",
|
||||
"error": ""
|
||||
},
|
||||
{
|
||||
"id": 145435,
|
||||
"name": "image_145435.png",
|
||||
"mimetype": "image/png",
|
||||
"file_size": 25267,
|
||||
"create_date": "2025-04-15 17:37:30",
|
||||
"creator_name": "Fabien LAFAY",
|
||||
"download_status": "success",
|
||||
"local_path": "output/ticket_T11143/T11143_20250415_171834/attachments/image_145435.png",
|
||||
"error": "",
|
||||
"was_missing": true,
|
||||
"message_id": 228942,
|
||||
"access_token": "608ac9e7-3627-4a13-a8ec-06ff5046ebf3"
|
||||
}
|
||||
]
|
||||
File diff suppressed because one or more lines are too long
@ -212,5 +212,5 @@ avec la communication du contenu des informations est strictement interdit.</spa
|
||||
|
||||
## Informations sur l'extraction
|
||||
|
||||
- **Date d'extraction**: 15/04/2025 17:38:28
|
||||
- **Répertoire**: output/ticket_T11143/T11143_20250415_171834
|
||||
- **Date d'extraction**: 16/04/2025 09:18:58
|
||||
- **Répertoire**: output/ticket_T11143/T11143_20250416_091857
|
||||
@ -7,7 +7,7 @@
|
||||
"project_name": "Demandes",
|
||||
"stage_id": 8,
|
||||
"stage_name": "Clôturé",
|
||||
"date_extraction": "2025-04-15T17:18:34.812109"
|
||||
"date_extraction": "2025-04-16T09:18:58.395055"
|
||||
},
|
||||
"metadata": {
|
||||
"message_count": {
|
||||
@ -66,7 +66,7 @@
|
||||
},
|
||||
{
|
||||
"id": 228942,
|
||||
"body": "*Contenu non extractible*",
|
||||
"body": "\n\n GIRAUD TP (JCG), Victor BOLLÉE\n \n\n - il y a 9 minutes\n\n\n\n\n\n\n\n\n\n\n \n À: \n \n \n \nCBAO S.A.R.L., Quentin FAIVRE\n ; \n \n\nFabien LAFAY\n ; \n \n\nRomuald GRUSON\n ; \n \n\nsupport\n ; \n \n\n\n\nÀ:\n\n support\n \n\n\n\n\n\n \n \n -\n \n \n \n Quentin FAIVRE\n \n\n\n\n\n\n \n \n -\n \n \n \n Fabien LAFAY\n \n\n\n\n\n\n \n \n -\n \n \n \n Romuald GRUSON\n \n\n\n\n\n\n\n\n\n\n\nBonjour,\n \nJe ne parviens pas à accéder au l’essai au bleu :\n\n \nMerci par avance pour votre.\n \nCordialement",
|
||||
"date": "2025-04-03 08:35:20",
|
||||
"author_id": [
|
||||
28961,
|
||||
@ -145,7 +145,7 @@
|
||||
},
|
||||
{
|
||||
"id": 228968,
|
||||
"body": "Bonjour,\nPouvez-vous vérifier si vous avez bien accès à la page suivante en l'ouvrant dans votre navigateur :\nhttps://zk1.brg-lab.com/\nVoici ce que vous devriez voir affiché : \n\nSi ce n'est pas le cas, pouvez-vous me faire une capture d'écran de ce qui est affiché?\nJe reste à votre entière disposition pour toute information complémentaire.\nCordialement,\n---\nSupport technique\n \n\n \n\nL'objectif du Support Technique est de vous aider : si vous rencontrez une difficulté, ou pour nous soumettre une ou des suggestions d'amélioration de nos logiciels ou de nos méthodes. Notre service est ouvert du lundi au vendredi de 9h à 12h et de 14h à 18h. Dès réception, un technicien prendra en charge votre demande et au besoin vous rappellera.\nConfidentialité : Ce courriel contient des informations confidentielles exclusivement réservées au destinataire mentionné. Si vous deviez recevoir cet e-mail par erreur, merci d’en avertir immédiatement l’expéditeur et de le supprimer de votre système informatique. Au cas où vous ne seriez pas destinataire de ce message, veuillez noter que sa divulgation, sa copie ou tout acte en rapport avec la communication du contenu des informations est strictement interdit.",
|
||||
"body": "Bonjour,Pouvez-vous vérifier si vous avez bien accès à la page suivante en l'ouvrant dans votre navigateur :https://zk1.brg-lab.com/Voici ce que vous devriez voir affiché : Si ce n'est pas le cas, pouvez-vous me faire une capture d'écran de ce qui est affiché?Je reste à votre entière disposition pour toute information complémentaire.Cordialement,---Support technique \n\nAfin d'assurer une meilleure traçabilité et vous garantir une prise en charge optimale, nous vous invitons à envoyer vos demandes d'assistance technique à support@cbao.frL'objectif du Support Technique est de vous aider : si vous rencontrez une difficulté, ou pour nous soumettre une ou des suggestions d'amélioration de nos logiciels ou de nos méthodes. Notre service est ouvert du lundi au vendredi de 9h à 12h et de 14h à 18h. Dès réception, un technicien prendra en charge votre demande et au besoin vous rappellera.Confidentialité : Ce courriel contient des informations confidentielles exclusivement réservées au destinataire mentionné. Si vous deviez recevoir cet e-mail par erreur, merci d’en avertir immédiatement l’expéditeur et de le supprimer de votre système informatique. Au cas où vous ne seriez pas destinataire de ce message, veuillez noter que sa divulgation, sa copie ou tout acte en rapport avec la communication du contenu des informations est strictement interdit.",
|
||||
"date": "2025-04-03 12:17:41",
|
||||
"author_id": [
|
||||
28961,
|
||||
@ -227,7 +227,7 @@
|
||||
},
|
||||
{
|
||||
"id": 228971,
|
||||
"body": "Bonjour,\n\n\r\n \n\n\r\nLe problème s’est résolu seul par la suite.\n\n\r\n \n\n\r\nJe vous remercie pour votre retour.\n\n\r\n \n\n\r\nBonne journée\n\n\r\n \n\n\r\nPS : l’adresse fonctionne\n\n\r\n \n\n\r\n\r\nDe :\r\nsupport@cbao.fr \r\n\n\r\nEnvoyé : jeudi 3 avril 2025 14:18\n\r\nÀ : victor Bollée \n\r\nObjet : Re: [T11143] - BRGLAB - Essai inaccessible\n\n\r\n\n\r\n\n \n\r\n\n\r\n\r\n\r\n\r\n\r\n\r\n\r\nVoir\r\n Tâche \n\n\r\n\r\n\r\n\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\n\r\n\n\r\n\r\n\r\n\r\n\r\n\n\r\n\r\nBonjour,\n\n\r\nPouvez-vous vérifier si vous avez bien accès à la page suivante en l'ouvrant dans votre navigateur :\n\n\r\nhttps://zk1.brg-lab.com/\n\n\r\nVoici ce que vous devriez voir affiché : \n\n\r\n\n\r\nSi ce n'est pas le cas, pouvez-vous me faire une capture d'écran de ce qui est affiché?\n\n\r\nJe reste à votre entière disposition pour toute information complémentaire.\n\n\r\nCordialement,\n\n\r\n---\n\n\r\nSupport technique\n\r\n \n\n\r\n\n\r\n technique à support@cbao.fr\n\r\nL'objectif du Support Technique est de vous aider : si vous rencontrez une difficulté, ou pour nous soumettre une ou des suggestions d'amélioration de nos logiciels ou de\r\n nos méthodes. Notre service est ouvert du lundi au vendredi de 9h à 12h et de 14h à 18h. Dès réception, un technicien prendra en charge votre demande et au besoin vous rappellera.\n\n\r\nConfidentialité : Ce courriel contient des informations confidentielles exclusivement réservées au destinataire mentionné. Si vous\r\n deviez recevoir cet e-mail par erreur, merci d’en avertir immédiatement l’expéditeur et de le supprimer de votre système informatique. Au cas où vous ne seriez pas destinataire de ce message, veuillez noter que sa divulgation, sa copie ou tout acte en rapport\r\n avec la communication du contenu des informations est strictement interdit.\n\n\r\n\n\r\nEnvoyé par \r\nCBAO S.A.R.L. .",
|
||||
"body": "\n\nBonjour,\n \nLe problème s’est résolu seul par la suite.\n \nJe vous remercie pour votre retour.\n \nBonne journée\n \nPS : l’adresse fonctionne\n \n\nDe :\nsupport@cbao.fr <support@cbao.fr>\r\n\nEnvoyé : jeudi 3 avril 2025 14:18\nÀ : victor Bollée <v.bollee@labojcg.fr>\nObjet : Re: [T11143] - BRGLAB - Essai inaccessible\n\n \n\n\n\n\n\n\n\nVoir\r\n Tâche \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nBonjour,\nPouvez-vous vérifier si vous avez bien accès à la page suivante en l'ouvrant dans votre navigateur :\nhttps://zk1.brg-lab.com/\nVoici ce que vous devriez voir affiché : \n\nSi ce n'est pas le cas, pouvez-vous me faire une capture d'écran de ce qui est affiché?\nJe reste à votre entière disposition pour toute information complémentaire.\nCordialement,\n---\nSupport technique\r\n \n\nAfin d'assurer une meilleure traçabilité et vous garantir une prise en charge optimale, nous vous invitons à envoyer vos demandes d'assistance\r\n technique à support@cbao.fr\nL'objectif du Support Technique est de vous aider : si vous rencontrez une difficulté, ou pour nous soumettre une ou des suggestions d'amélioration de nos logiciels ou de\r\n nos méthodes. Notre service est ouvert du lundi au vendredi de 9h à 12h et de 14h à 18h. Dès réception, un technicien prendra en charge votre demande et au besoin vous rappellera.\nConfidentialité : Ce courriel contient des informations confidentielles exclusivement réservées au destinataire mentionné. Si vous\r\n deviez recevoir cet e-mail par erreur, merci d’en avertir immédiatement l’expéditeur et de le supprimer de votre système informatique. Au cas où vous ne seriez pas destinataire de ce message, veuillez noter que sa divulgation, sa copie ou tout acte en rapport\r\n avec la communication du contenu des informations est strictement interdit.\n\nEnvoyé par \nCBAO S.A.R.L. . \n\n\n\n\n",
|
||||
"date": "2025-04-03 12:21:13",
|
||||
"author_id": [
|
||||
28897,
|
||||
@ -1,5 +1,5 @@
|
||||
TICKET: T11143 - BRGLAB - Essai inaccessible
|
||||
Date d'extraction: 2025-04-15 17:18:34
|
||||
Date d'extraction: 2025-04-16 09:18:58
|
||||
Nombre de messages: 7
|
||||
|
||||
================================================================================
|
||||
@ -23,7 +23,106 @@ DATE: 2025-04-03 08:35:20
|
||||
DE: Fabien LAFAY
|
||||
OBJET: Re: [T11143] BRGLAB - Essai inaccessible
|
||||
|
||||
*Contenu non extractible*
|
||||
|
||||
|
||||
GIRAUD TP (JCG), Victor BOLLÉE
|
||||
|
||||
|
||||
- il y a 9 minutes
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
À:
|
||||
|
||||
|
||||
|
||||
CBAO S.A.R.L., Quentin FAIVRE
|
||||
;
|
||||
|
||||
|
||||
Fabien LAFAY
|
||||
;
|
||||
|
||||
|
||||
Romuald GRUSON
|
||||
;
|
||||
|
||||
|
||||
support
|
||||
;
|
||||
|
||||
|
||||
|
||||
|
||||
À:
|
||||
|
||||
support
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
-
|
||||
|
||||
|
||||
|
||||
Quentin FAIVRE
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
-
|
||||
|
||||
|
||||
|
||||
Fabien LAFAY
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
-
|
||||
|
||||
|
||||
|
||||
Romuald GRUSON
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Bonjour,
|
||||
|
||||
Je ne parviens pas à accéder au l’essai au bleu :
|
||||
|
||||
|
||||
Merci par avance pour votre.
|
||||
|
||||
Cordialement
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
@ -46,22 +145,9 @@ DATE: 2025-04-03 12:17:41
|
||||
DE: Fabien LAFAY
|
||||
OBJET: Re: [T11143] - BRGLAB - Essai inaccessible
|
||||
|
||||
Bonjour,
|
||||
Pouvez-vous vérifier si vous avez bien accès à la page suivante en l'ouvrant dans votre navigateur :
|
||||
https://zk1.brg-lab.com/
|
||||
Voici ce que vous devriez voir affiché :
|
||||
Bonjour,Pouvez-vous vérifier si vous avez bien accès à la page suivante en l'ouvrant dans votre navigateur :https://zk1.brg-lab.com/Voici ce que vous devriez voir affiché : Si ce n'est pas le cas, pouvez-vous me faire une capture d'écran de ce qui est affiché?Je reste à votre entière disposition pour toute information complémentaire.Cordialement,---Support technique
|
||||
|
||||
Si ce n'est pas le cas, pouvez-vous me faire une capture d'écran de ce qui est affiché?
|
||||
Je reste à votre entière disposition pour toute information complémentaire.
|
||||
Cordialement,
|
||||
---
|
||||
Support technique
|
||||
|
||||
|
||||
|
||||
|
||||
L'objectif du Support Technique est de vous aider : si vous rencontrez une difficulté, ou pour nous soumettre une ou des suggestions d'amélioration de nos logiciels ou de nos méthodes. Notre service est ouvert du lundi au vendredi de 9h à 12h et de 14h à 18h. Dès réception, un technicien prendra en charge votre demande et au besoin vous rappellera.
|
||||
Confidentialité : Ce courriel contient des informations confidentielles exclusivement réservées au destinataire mentionné. Si vous deviez recevoir cet e-mail par erreur, merci d’en avertir immédiatement l’expéditeur et de le supprimer de votre système informatique. Au cas où vous ne seriez pas destinataire de ce message, veuillez noter que sa divulgation, sa copie ou tout acte en rapport avec la communication du contenu des informations est strictement interdit.
|
||||
Afin d'assurer une meilleure traçabilité et vous garantir une prise en charge optimale, nous vous invitons à envoyer vos demandes d'assistance technique à support@cbao.frL'objectif du Support Technique est de vous aider : si vous rencontrez une difficulté, ou pour nous soumettre une ou des suggestions d'amélioration de nos logiciels ou de nos méthodes. Notre service est ouvert du lundi au vendredi de 9h à 12h et de 14h à 18h. Dès réception, un technicien prendra en charge votre demande et au besoin vous rappellera.Confidentialité : Ce courriel contient des informations confidentielles exclusivement réservées au destinataire mentionné. Si vous deviez recevoir cet e-mail par erreur, merci d’en avertir immédiatement l’expéditeur et de le supprimer de votre système informatique. Au cas où vous ne seriez pas destinataire de ce message, veuillez noter que sa divulgation, sa copie ou tout acte en rapport avec la communication du contenu des informations est strictement interdit.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
@ -84,135 +170,81 @@ DATE: 2025-04-03 12:21:13
|
||||
DE: Victor BOLLÉE
|
||||
OBJET: TR: [T11143] - BRGLAB - Essai inaccessible
|
||||
|
||||
|
||||
|
||||
Bonjour,
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Le problème s’est résolu seul par la suite.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Je vous remercie pour votre retour.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Bonne journée
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
PS : l’adresse fonctionne
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
De :
|
||||
support@cbao.fr
|
||||
De :
|
||||
support@cbao.fr <support@cbao.fr>
|
||||
|
||||
|
||||
Envoyé : jeudi 3 avril 2025 14:18
|
||||
|
||||
À : victor Bollée
|
||||
|
||||
À : victor Bollée <v.bollee@labojcg.fr>
|
||||
Objet : Re: [T11143] - BRGLAB - Essai inaccessible
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Voir
|
||||
Tâche
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Bonjour,
|
||||
|
||||
|
||||
Pouvez-vous vérifier si vous avez bien accès à la page suivante en l'ouvrant dans votre navigateur :
|
||||
|
||||
|
||||
https://zk1.brg-lab.com/
|
||||
|
||||
|
||||
Voici ce que vous devriez voir affiché :
|
||||
|
||||
|
||||
|
||||
|
||||
Si ce n'est pas le cas, pouvez-vous me faire une capture d'écran de ce qui est affiché?
|
||||
|
||||
|
||||
Je reste à votre entière disposition pour toute information complémentaire.
|
||||
|
||||
|
||||
Cordialement,
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||
Support technique
|
||||
|
||||
Support technique
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Afin d'assurer une meilleure traçabilité et vous garantir une prise en charge optimale, nous vous invitons à envoyer vos demandes d'assistance
|
||||
technique à support@cbao.fr
|
||||
|
||||
L'objectif du Support Technique est de vous aider : si vous rencontrez une difficulté, ou pour nous soumettre une ou des suggestions d'amélioration de nos logiciels ou de
|
||||
nos méthodes. Notre service est ouvert du lundi au vendredi de 9h à 12h et de 14h à 18h. Dès réception, un technicien prendra en charge votre demande et au besoin vous rappellera.
|
||||
|
||||
|
||||
Confidentialité : Ce courriel contient des informations confidentielles exclusivement réservées au destinataire mentionné. Si vous
|
||||
deviez recevoir cet e-mail par erreur, merci d’en avertir immédiatement l’expéditeur et de le supprimer de votre système informatique. Au cas où vous ne seriez pas destinataire de ce message, veuillez noter que sa divulgation, sa copie ou tout acte en rapport
|
||||
avec la communication du contenu des informations est strictement interdit.
|
||||
|
||||
|
||||
Envoyé par
|
||||
CBAO S.A.R.L. .
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Envoyé par
|
||||
CBAO S.A.R.L. .
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
|
Before Width: | Height: | Size: 75 KiB After Width: | Height: | Size: 75 KiB |
@ -0,0 +1,20 @@
|
||||
[
|
||||
{
|
||||
"id": 145453,
|
||||
"name": "image.png",
|
||||
"mimetype": "image/png",
|
||||
"file_size": 76543,
|
||||
"create_date": "2025-04-03 12:17:41",
|
||||
"create_uid": [
|
||||
22,
|
||||
"Fabien LAFAY"
|
||||
],
|
||||
"description": false,
|
||||
"res_name": "[T11143] BRGLAB - Essai inaccessible",
|
||||
"creator_name": "Fabien LAFAY",
|
||||
"creator_id": 22,
|
||||
"download_status": "success",
|
||||
"local_path": "output/ticket_T11143/T11143_20250416_091857/attachments/image.png",
|
||||
"error": ""
|
||||
}
|
||||
]
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"timestamp": "20250415_171834",
|
||||
"timestamp": "20250416_091857",
|
||||
"ticket_code": "T11143",
|
||||
"output_directory": "output/ticket_T11143/T11143_20250415_171834",
|
||||
"output_directory": "output/ticket_T11143/T11143_20250416_091857",
|
||||
"message_count": 7,
|
||||
"attachment_count": 1,
|
||||
"files_created": [
|
||||
@ -1,9 +1,9 @@
|
||||
{
|
||||
"date_extraction": "2025-04-15T17:18:34.902937",
|
||||
"date_extraction": "2025-04-16T09:18:58.496625",
|
||||
"ticket_id": 11122,
|
||||
"ticket_code": "T11143",
|
||||
"ticket_name": "BRGLAB - Essai inaccessible",
|
||||
"output_dir": "output/ticket_T11143/T11143_20250415_171834",
|
||||
"output_dir": "output/ticket_T11143/T11143_20250416_091857",
|
||||
"files": {
|
||||
"ticket_info": "ticket_info.json",
|
||||
"ticket_summary": "ticket_summary.json",
|
||||
@ -167,3 +167,42 @@
|
||||
2025-04-15 17:18:34 - root - INFO - Messages traités: 7
|
||||
2025-04-15 17:18:34 - root - INFO - Pièces jointes: 1
|
||||
2025-04-15 17:18:34 - root - INFO - ------------------------------------------------------------
|
||||
2025-04-16 08:45:46 - root - INFO - Extraction du ticket T11143
|
||||
2025-04-16 08:45:46 - root - INFO - ------------------------------------------------------------
|
||||
2025-04-16 08:45:46 - root - ERROR - Échec de l'extraction du ticket T11143
|
||||
2025-04-16 08:46:18 - root - INFO - Extraction du ticket T11143
|
||||
2025-04-16 08:46:18 - root - INFO - ------------------------------------------------------------
|
||||
2025-04-16 08:46:18 - root - ERROR - Échec de l'extraction du ticket T11143
|
||||
2025-04-16 08:48:59 - root - INFO - Extraction du ticket T11143
|
||||
2025-04-16 08:48:59 - root - INFO - ------------------------------------------------------------
|
||||
2025-04-16 08:49:00 - root - INFO - Traitement de 1 pièces jointes pour le ticket 11122
|
||||
2025-04-16 08:49:00 - root - INFO - Pièce jointe téléchargée: image.png (1/1)
|
||||
2025-04-16 08:49:00 - root - INFO - ------------------------------------------------------------
|
||||
2025-04-16 08:49:00 - root - INFO - Extraction terminée avec succès
|
||||
2025-04-16 08:49:00 - root - INFO - Ticket: T11143
|
||||
2025-04-16 08:49:00 - root - INFO - Répertoire: output/ticket_T11143/T11143_20250416_084859
|
||||
2025-04-16 08:49:00 - root - INFO - Messages traités: 7
|
||||
2025-04-16 08:49:00 - root - INFO - Pièces jointes: 1
|
||||
2025-04-16 08:49:00 - root - INFO - ------------------------------------------------------------
|
||||
2025-04-16 08:49:38 - root - INFO - Extraction du ticket T11143
|
||||
2025-04-16 08:49:38 - root - INFO - ------------------------------------------------------------
|
||||
2025-04-16 08:49:39 - root - INFO - Traitement de 1 pièces jointes pour le ticket 11122
|
||||
2025-04-16 08:49:39 - root - INFO - Pièce jointe téléchargée: image.png (1/1)
|
||||
2025-04-16 08:49:39 - root - INFO - ------------------------------------------------------------
|
||||
2025-04-16 08:49:39 - root - INFO - Extraction terminée avec succès
|
||||
2025-04-16 08:49:39 - root - INFO - Ticket: T11143
|
||||
2025-04-16 08:49:39 - root - INFO - Répertoire: output/ticket_T11143/T11143_20250416_084938
|
||||
2025-04-16 08:49:39 - root - INFO - Messages traités: 7
|
||||
2025-04-16 08:49:39 - root - INFO - Pièces jointes: 1
|
||||
2025-04-16 08:49:39 - root - INFO - ------------------------------------------------------------
|
||||
2025-04-16 09:18:57 - root - INFO - Extraction du ticket T11143
|
||||
2025-04-16 09:18:57 - root - INFO - ------------------------------------------------------------
|
||||
2025-04-16 09:18:58 - root - INFO - Traitement de 1 pièces jointes pour le ticket 11122
|
||||
2025-04-16 09:18:58 - root - INFO - Pièce jointe téléchargée: image.png (1/1)
|
||||
2025-04-16 09:18:58 - root - INFO - ------------------------------------------------------------
|
||||
2025-04-16 09:18:58 - root - INFO - Extraction terminée avec succès
|
||||
2025-04-16 09:18:58 - root - INFO - Ticket: T11143
|
||||
2025-04-16 09:18:58 - root - INFO - Répertoire: output/ticket_T11143/T11143_20250416_091857
|
||||
2025-04-16 09:18:58 - root - INFO - Messages traités: 7
|
||||
2025-04-16 09:18:58 - root - INFO - Pièces jointes: 1
|
||||
2025-04-16 09:18:58 - root - INFO - ------------------------------------------------------------
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user