Files
anonymisation/demo_evaluation.py
Domi31tls c78f9f415d demo: Ajout script de démonstration et correction tests
- Script demo_evaluation.py montrant tous les outils
- Correction test flottant dans test_quality_evaluator.py
- Installation pytest/pytest-cov
- Tous les tests passent (16/16)
2026-03-02 10:14:56 +01:00

315 lines
11 KiB
Python
Executable File

#!/usr/bin/env python3
"""
Démonstration du système d'évaluation de la qualité d'anonymisation.
Ce script montre comment utiliser les 3 composants principaux :
1. QualityEvaluator - Évaluation de la qualité
2. LeakScanner - Détection de fuites
3. Benchmark - Mesure de performance
"""
import json
from pathlib import Path
from evaluation import QualityEvaluator, LeakScanner, Benchmark
def demo_annotation_tool():
"""Démo de l'outil d'annotation."""
print("\n" + "="*80)
print("DÉMO 1 : OUTIL D'ANNOTATION")
print("="*80)
print("\nL'outil d'annotation permet d'annoter manuellement les documents PDF.")
print("\nCommandes disponibles:")
print(" python tools/annotation_tool.py --list")
print(" → Liste les 27 documents disponibles")
print("\n python tools/annotation_tool.py --resume")
print(" → Reprend l'annotation au prochain document non annoté")
print("\n python tools/annotation_tool.py tests/ground_truth/pdfs/001_simple_unknown_BACTERIO_23018396.pdf")
print(" → Annote un document spécifique")
# Afficher les documents disponibles
pdfs_dir = Path("tests/ground_truth/pdfs")
pdfs = sorted(pdfs_dir.glob("*.pdf"))
print(f"\n📁 {len(pdfs)} documents disponibles dans {pdfs_dir}")
print("\nExemples:")
for pdf in pdfs[:5]:
annotation_file = pdf.parent / f"{pdf.stem}.annotations.json"
status = "✓ Annoté" if annotation_file.exists() else "○ À annoter"
print(f" {status} {pdf.name}")
print(f" ... et {len(pdfs) - 5} autres")
def demo_quality_evaluator():
"""Démo de l'évaluateur de qualité."""
print("\n" + "="*80)
print("DÉMO 2 : ÉVALUATEUR DE QUALITÉ")
print("="*80)
print("\nL'évaluateur compare les annotations manuelles avec les détections automatiques.")
print("Il calcule : Précision, Rappel, F1-Score")
# Créer des données de test fictives
print("\n📝 Création d'annotations de test...")
test_pdf = Path("tests/ground_truth/pdfs/001_simple_unknown_BACTERIO_23018396.pdf")
test_annotation = test_pdf.parent / f"{test_pdf.stem}.annotations.json"
test_audit = test_pdf.parent / f"{test_pdf.stem}.audit.jsonl"
# Créer une annotation fictive
annotation_data = {
"pdf_path": str(test_pdf),
"metadata": {
"annotator": "demo",
"annotation_date": "2024-01-15T10:00:00",
"document_type": "bacterio",
"page_count": 1,
"difficulty": "simple"
},
"annotations": [
{
"id": "ann_001",
"page": 0,
"type": "NOM",
"text": "DUPONT",
"bbox": None,
"context": "Dr. DUPONT a examiné",
"mandatory": True,
"difficulty": "easy",
"detection_method_expected": ["regex", "ner"]
},
{
"id": "ann_002",
"page": 0,
"type": "TEL",
"text": "01 23 45 67 89",
"bbox": None,
"context": "Tel: 01 23 45 67 89",
"mandatory": True,
"difficulty": "easy",
"detection_method_expected": ["regex"]
},
{
"id": "ann_003",
"page": 0,
"type": "EMAIL",
"text": "jean.dupont@chu-bordeaux.fr",
"bbox": None,
"context": "Email: jean.dupont@chu-bordeaux.fr",
"mandatory": True,
"difficulty": "easy",
"detection_method_expected": ["regex"]
}
],
"medical_terms_to_preserve": ["Médecin DIM", "Service de bactériologie"],
"statistics": {
"total_pii": 3,
"by_type": {"NOM": 1, "TEL": 1, "EMAIL": 1}
}
}
with open(test_annotation, 'w', encoding='utf-8') as f:
json.dump(annotation_data, f, indent=2, ensure_ascii=False)
print(f"✓ Annotation créée: {test_annotation.name}")
print(f" - 3 PII annotés: 1 NOM, 1 TEL, 1 EMAIL")
# Créer un audit fictif (détections)
audit_data = [
{"page": 0, "kind": "NOM", "original": "DUPONT", "placeholder": "[NOM]"},
{"page": 0, "kind": "TEL", "original": "01 23 45 67 89", "placeholder": "[TEL]"},
{"page": 0, "kind": "EMAIL", "original": "jean.dupont@chu-bordeaux.fr", "placeholder": "[EMAIL]"},
{"page": 0, "kind": "NOM", "original": "MARTIN", "placeholder": "[NOM]"} # Faux positif
]
with open(test_audit, 'w', encoding='utf-8') as f:
for item in audit_data:
f.write(json.dumps(item) + '\n')
print(f"✓ Audit créé: {test_audit.name}")
print(f" - 4 PII détectés: 2 NOM, 1 TEL, 1 EMAIL")
# Évaluer
print("\n🔍 Évaluation en cours...")
evaluator = QualityEvaluator(Path("tests/ground_truth/pdfs"))
result = evaluator.evaluate(test_pdf, test_audit)
if result:
print("\n📊 RÉSULTATS:")
print(f" True Positives: {result.true_positives}")
print(f" False Positives: {result.false_positives}")
print(f" False Negatives: {result.false_negatives}")
print(f"\n Précision: {result.precision:.4f} ({result.precision*100:.2f}%)")
print(f" Rappel: {result.recall:.4f} ({result.recall*100:.2f}%)")
print(f" F1-Score: {result.f1_score:.4f}")
if result.false_positives > 0:
print(f"\n ⚠ Faux positifs détectés:")
for fp in result.false_detections:
print(f" - {fp['type']}: {fp['text']}")
# Générer un rapport
report = evaluator.generate_report([result])
print("\n" + ""*80)
print(report)
# Nettoyer
test_annotation.unlink()
test_audit.unlink()
print("\n✓ Fichiers de test nettoyés")
def demo_leak_scanner():
"""Démo du scanner de fuite."""
print("\n" + "="*80)
print("DÉMO 3 : SCANNER DE FUITE")
print("="*80)
print("\nLe scanner vérifie qu'aucun PII ne subsiste dans les documents anonymisés.")
print("Il détecte:")
print(" - PII originaux encore présents (CRITIQUE)")
print(" - Nouveaux PII non masqués (HAUTE)")
print(" - Métadonnées suspectes (MOYENNE)")
# Créer des données de test
print("\n📝 Création de données de test...")
test_pdf = Path("tests/ground_truth/pdfs/001_simple_unknown_BACTERIO_23018396.pdf")
test_audit = test_pdf.parent / f"{test_pdf.stem}.audit.jsonl"
# Créer un audit fictif
audit_data = [
{"page": 0, "kind": "NOM", "original": "DUPONT", "placeholder": "[NOM]"},
{"page": 0, "kind": "TEL", "original": "01 23 45 67 89", "placeholder": "[TEL]"}
]
with open(test_audit, 'w', encoding='utf-8') as f:
for item in audit_data:
f.write(json.dumps(item) + '\n')
print(f"✓ Audit créé: {test_audit.name}")
# Scanner (simulation - le PDF n'est pas vraiment anonymisé)
print("\n🔍 Scan en cours...")
scanner = LeakScanner()
# Simuler un scan avec du texte
print("\n📄 Simulation de scan de texte:")
# Cas 1 : Document sûr
safe_text = "Le patient [NOM] a été examiné le [DATE]. Contact: [TEL]"
original_pii = [
{"kind": "NOM", "original": "DUPONT"},
{"kind": "TEL", "original": "01 23 45 67 89"}
]
leaks = scanner.scan_text(safe_text, original_pii)
print(f"\n Texte: {safe_text}")
print(f" Résultat: {'✓ Aucune fuite' if len(leaks) == 0 else f'{len(leaks)} fuite(s)'}")
# Cas 2 : Document avec fuite
unsafe_text = "Le patient DUPONT a été examiné. Tel: 01 23 45 67 89"
leaks = scanner.scan_text(unsafe_text, original_pii)
print(f"\n Texte: {unsafe_text}")
print(f" Résultat: {'✓ Aucune fuite' if len(leaks) == 0 else f'{len(leaks)} fuite(s)'}")
if leaks:
for leak in leaks:
print(f" - {leak['severity']}: {leak['message']}")
# Cas 3 : Nouveau PII détecté
new_pii_text = "Contact: marie.martin@example.com"
leaks = scanner.scan_text(new_pii_text, original_pii)
print(f"\n Texte: {new_pii_text}")
print(f" Résultat: {'✓ Aucune fuite' if len(leaks) == 0 else f'{len(leaks)} fuite(s)'}")
if leaks:
for leak in leaks:
print(f" - {leak['severity']}: {leak['message']}")
# Nettoyer
test_audit.unlink()
print("\n✓ Fichiers de test nettoyés")
def demo_benchmark():
"""Démo du benchmark."""
print("\n" + "="*80)
print("DÉMO 4 : BENCHMARK DE PERFORMANCE")
print("="*80)
print("\nLe benchmark mesure les performances du système d'anonymisation:")
print(" - Temps de traitement (total, par page)")
print(" - Utilisation CPU (%)")
print(" - Utilisation RAM (MB)")
print(" - Nombre de PII détectés")
# Afficher les informations système
print("\n💻 Informations système:")
benchmark = Benchmark(Path("tests/ground_truth/pdfs"))
system_info = benchmark.get_system_info()
for key, value in system_info.items():
print(f" {key}: {value}")
print("\n📊 Exemple de résultats de benchmark:")
print("\n Document: 001_simple_unknown_BACTERIO_23018396.pdf")
print(" Temps: 3.45s")
print(" Temps/page: 3.45s")
print(" CPU: 45.2%")
print(" RAM: 512.3 MB")
print(" PII détectés: 12")
print("\n Document: 023_complexe_compte_rendu_CRH_23102610.pdf")
print(" Temps: 25.67s")
print(" Temps/page: 2.85s (9 pages)")
print(" CPU: 67.8%")
print(" RAM: 1024.5 MB")
print(" PII détectés: 45")
print("\n📈 Résumé (27 documents):")
print(" Temps moyen: 8.5s")
print(" Temps min/max: 2.1s / 25.7s")
print(" CPU moyen: 52.3%")
print(" RAM moyenne: 768.2 MB")
print(" PII détectés: 245 (moy: 9.1)")
def main():
"""Fonction principale."""
print("\n" + "="*80)
print("DÉMONSTRATION DU SYSTÈME D'ÉVALUATION DE LA QUALITÉ D'ANONYMISATION")
print("="*80)
print("\nCe système permet de:")
print(" 1. Annoter manuellement des documents PDF")
print(" 2. Évaluer la qualité des détections (Précision, Rappel, F1)")
print(" 3. Scanner les fuites de PII dans les documents anonymisés")
print(" 4. Benchmarker les performances du système")
# Lancer les démos
demo_annotation_tool()
demo_quality_evaluator()
demo_leak_scanner()
demo_benchmark()
print("\n" + "="*80)
print("FIN DE LA DÉMONSTRATION")
print("="*80)
print("\n📚 Pour en savoir plus:")
print(" - Guide d'annotation: docs/annotation_guide.md")
print(" - Documentation du module: evaluation/README.md")
print(" - Tests unitaires: tests/unit/")
print("\n🚀 Prochaines étapes:")
print(" 1. Annoter les 27 documents: python tools/annotation_tool.py --resume")
print(" 2. Anonymiser les documents avec le système actuel")
print(" 3. Évaluer la qualité: python -c 'from evaluation import QualityEvaluator; ...'")
print(" 4. Mesurer la baseline et identifier les améliorations")
print("\n✨ Bon travail !")
if __name__ == "__main__":
main()