page corrections ajout de boutons

This commit is contained in:
Tykayn 2025-08-30 23:10:43 +02:00 committed by tykayn
parent 7095f9633b
commit 1713aa30b5
7 changed files with 297 additions and 44 deletions

View file

@ -6,6 +6,12 @@ Ce script:
1. Fournit des endpoints pour appliquer des corrections au fichier livre.org
2. Permet d'ajouter des mots au dictionnaire personnalisé
3. Permet de marquer des erreurs comme "à ne pas traiter" dans le CSV
Modifications (2025-08-30):
- Amélioration de la recherche des chapitres dans le fichier livre.org
- Le motif de recherche est maintenant plus flexible pour gérer les chapitres avec des tags ou du texte supplémentaire
- Ajout de logs de débogage pour aider à diagnostiquer les problèmes de correspondance de chapitres
- Amélioration des fonctions load_spelling_errors et load_grammar_errors pour utiliser une correspondance flexible
"""
import os
@ -59,11 +65,28 @@ def apply_correction(data):
content = file.read()
# Trouver la section du chapitre
chapter_pattern = r'^\*\* ' + re.escape(chapter) + r'$(.*?)(?=^\*\* |\Z)'
# Motif plus flexible qui permet des textes supplémentaires après le nom du chapitre
chapter_pattern = r'^\*\* ' + re.escape(chapter) + r'(?:\s+.*?)?$(.*?)(?=^\*\* |\Z)'
chapter_match = re.search(chapter_pattern, content, re.MULTILINE | re.DOTALL)
# Si le motif flexible ne trouve pas de correspondance, essayer avec le motif original
if not chapter_match:
return jsonify({'success': False, 'message': f'Chapitre "{chapter}" non trouvé'}), 404
# Ajouter des logs pour le débogage
print(f"Recherche du chapitre: '{chapter}'")
print(f"Motif utilisé: {chapter_pattern}")
# Lister tous les titres de chapitres dans le fichier pour le débogage
all_chapters = re.findall(r'^\*\* (.*?)$', content, re.MULTILINE)
print(f"Chapitres trouvés dans le fichier: {all_chapters}")
return jsonify({
'success': False,
'message': f'Chapitre "{chapter}" non trouvé',
'debug_info': {
'pattern_used': chapter_pattern,
'chapters_in_file': all_chapters
}
}), 404
chapter_content = chapter_match.group(1)
chapter_start = chapter_match.start()
@ -96,17 +119,91 @@ def apply_correction(data):
context = error['context']
# Trouver le contexte dans le chapitre
context_pattern = re.escape(context.replace(error_text, error_text))
context_match = re.search(context_pattern, chapter_content)
# Créer un motif plus flexible pour la recherche de contexte
# 1. Échapper les caractères spéciaux dans le contexte
escaped_context = re.escape(context)
# 2. Remplacer les espaces échappées par un motif qui accepte plusieurs espaces
flexible_context = escaped_context.replace('\\ ', '\\s+')
# 3. Créer un motif qui permet des variations au début et à la fin du contexte
flexible_pattern = flexible_context
# Essayer d'abord avec le motif flexible
context_match = re.search(flexible_pattern, chapter_content)
# Si ça ne fonctionne pas, essayer avec une approche encore plus flexible
if not context_match:
# Extraire les mots significatifs du contexte (ignorer les mots très courts)
words = [word for word in re.findall(r'\b\w+\b', context) if len(word) > 3]
if words:
# Créer un motif qui recherche une phrase contenant ces mots dans l'ordre
words_pattern = r'.*'.join([re.escape(word) for word in words])
context_match = re.search(words_pattern, chapter_content)
# Si toujours pas de correspondance, essayer de trouver juste l'erreur et son contexte immédiat
if not context_match and error_text:
# Chercher l'erreur avec quelques mots avant et après
error_vicinity = r'[^\n]{0,30}' + re.escape(error_text) + r'[^\n]{0,30}'
context_match = re.search(error_vicinity, chapter_content)
if not context_match:
return jsonify({'success': False, 'message': 'Contexte non trouvé dans le chapitre'}), 404
# Ajouter des logs de débogage
print(f"Contexte non trouvé: '{context}'")
print(f"Motif flexible utilisé: {flexible_pattern}")
print(f"Erreur à corriger: '{error_text}'")
print(f"Correction à appliquer: '{correction}'")
print(f"Extrait du chapitre (100 premiers caractères): '{chapter_content[:100]}'")
return jsonify({
'success': False,
'message': 'Contexte non trouvé dans le chapitre',
'debug_info': {
'context': context,
'error_text': error_text,
'correction': correction,
'chapter_excerpt': chapter_content[:200] # Premiers 200 caractères du chapitre
}
}), 404
# Remplacer l'erreur dans le contexte
corrected_context = context.replace(error_text, correction)
# Remplacer l'erreur dans le contexte trouvé
matched_text = context_match.group(0)
# Remplacer le contexte dans le chapitre
modified_chapter = chapter_content.replace(context, corrected_context)
# Déterminer quelle stratégie de remplacement utiliser
if matched_text == context:
# Si le texte correspond exactement au contexte, utiliser la méthode simple
corrected_context = context.replace(error_text, correction)
modified_chapter = chapter_content.replace(matched_text, corrected_context)
else:
# Si nous avons utilisé une correspondance flexible, nous devons être plus précis
# Trouver la position de l'erreur dans le contexte original
error_pos = context.find(error_text)
if error_pos >= 0:
# Calculer les positions relatives dans le texte trouvé
error_length = len(error_text)
# Essayer de trouver l'erreur exacte dans le texte trouvé
error_in_match = re.search(re.escape(error_text), matched_text)
if error_in_match:
# Remplacer directement l'erreur dans le texte trouvé
start, end = error_in_match.span()
corrected_matched_text = matched_text[:start] + correction + matched_text[end:]
modified_chapter = chapter_content.replace(matched_text, corrected_matched_text)
else:
# Fallback: remplacer tout le texte trouvé
corrected_context = context.replace(error_text, correction)
modified_chapter = chapter_content.replace(matched_text, corrected_context)
else:
# Si nous ne pouvons pas localiser l'erreur, utiliser une approche plus simple
corrected_context = context.replace(error_text, correction)
modified_chapter = chapter_content.replace(matched_text, corrected_context)
# Ajouter des logs pour le débogage
print(f"Correction appliquée: '{error_text}' -> '{correction}'")
print(f"Contexte trouvé: '{matched_text}'")
print(f"Contexte après correction: '{corrected_context if 'corrected_context' in locals() else 'N/A'}'")
# Si le chapitre n'a pas été modifié, c'est qu'il y a un problème
if modified_chapter == chapter_content:
print("AVERTISSEMENT: Le chapitre n'a pas été modifié après la correction!")
# Mettre à jour le contenu complet
new_content = content[:chapter_start] + '** ' + chapter + modified_chapter + content[chapter_end:]
@ -214,9 +311,20 @@ def load_spelling_errors(chapter):
errors_by_chapter = parse_error_report('rapport_orthographe_grammaire.md')
# Recherche exacte d'abord
if chapter in errors_by_chapter:
return errors_by_chapter[chapter]['spelling']
# Si pas trouvé, essayer une recherche plus flexible
# Chercher un chapitre qui commence par le même nom (sans les tags ou autres textes)
for chap_name in errors_by_chapter.keys():
# Vérifier si le chapitre commence par le nom recherché
if chap_name.startswith(chapter) or chapter.startswith(chap_name):
print(f"Correspondance flexible trouvée: '{chapter}' -> '{chap_name}'")
return errors_by_chapter[chap_name]['spelling']
print(f"Aucune erreur d'orthographe trouvée pour le chapitre: '{chapter}'")
print(f"Chapitres disponibles: {list(errors_by_chapter.keys())}")
return []
def load_grammar_errors(chapter):
@ -230,9 +338,20 @@ def load_grammar_errors(chapter):
errors_by_chapter = parse_error_report('rapport_orthographe_grammaire.md')
# Recherche exacte d'abord
if chapter in errors_by_chapter:
return errors_by_chapter[chapter]['grammar']
# Si pas trouvé, essayer une recherche plus flexible
# Chercher un chapitre qui commence par le même nom (sans les tags ou autres textes)
for chap_name in errors_by_chapter.keys():
# Vérifier si le chapitre commence par le nom recherché
if chap_name.startswith(chapter) or chapter.startswith(chap_name):
print(f"Correspondance flexible trouvée: '{chapter}' -> '{chap_name}'")
return errors_by_chapter[chap_name]['grammar']
print(f"Aucune erreur grammaticale trouvée pour le chapitre: '{chapter}'")
print(f"Chapitres disponibles: {list(errors_by_chapter.keys())}")
return []
# Pour tester l'API indépendamment