feat: Phase 1 - Système d'évaluation de la qualité

- Sélection et copie de 27 documents représentatifs (10 simples, 12 moyens, 5 complexes)
- Outil d'annotation CLI complet (tools/annotation_tool.py)
- Guide d'annotation détaillé (docs/annotation_guide.md)
- Évaluateur de qualité (evaluation/quality_evaluator.py)
  * Calcul Précision, Rappel, F1-Score
  * Identification faux positifs/négatifs
  * Métriques par type de PII
  * Export JSON et rapports texte
- Scanner de fuite (evaluation/leak_scanner.py)
  * Détection PII résiduels (CRITIQUE)
  * Détection nouveaux PII (HAUTE)
  * Scan métadonnées PDF (MOYENNE)
- Benchmark de performance (evaluation/benchmark.py)
  * Mesure temps de traitement
  * Mesure CPU/RAM
  * Export JSON/CSV
- Tests unitaires complets pour tous les composants
- Documentation complète du module d'évaluation

Tâches complétées:
- 1.1.1 Sélection de 27 documents (au lieu de 30)
- 1.1.2 Outil d'annotation CLI
- 1.2.1 Évaluateur de qualité
- 1.2.2 Scanner de fuite
- 1.2.3 Benchmark de performance

Prochaines étapes:
- 1.1.3 Annotation des 27 documents (manuel)
- 1.1.4 Enrichissement stopwords médicaux
- 1.3 Mesure de la baseline
This commit is contained in:
2026-03-02 10:07:41 +01:00
parent 0067738df6
commit 340348b820
86 changed files with 35587 additions and 40 deletions

262
evaluation/README.md Normal file
View File

@@ -0,0 +1,262 @@
# Module d'Évaluation de la Qualité d'Anonymisation
Ce module fournit des outils pour évaluer et valider la qualité de l'anonymisation des documents PDF médicaux.
## Composants
### 1. QualityEvaluator
Évalue la qualité d'anonymisation en comparant les annotations manuelles (ground truth) avec les détections automatiques.
**Métriques calculées** :
- Précision (Precision) : TP / (TP + FP)
- Rappel (Recall) : TP / (TP + FN)
- F1-Score : 2 × (Precision × Recall) / (Precision + Recall)
**Usage** :
```python
from evaluation import QualityEvaluator
from pathlib import Path
evaluator = QualityEvaluator(Path("tests/ground_truth/pdfs"))
# Évaluer un document
result = evaluator.evaluate(
pdf_path=Path("tests/ground_truth/pdfs/001_simple_unknown_BACTERIO_23018396.pdf"),
audit_path=Path("tests/ground_truth/pdfs/001_simple_unknown_BACTERIO_23018396.audit.jsonl")
)
print(f"Précision: {result.precision:.4f}")
print(f"Rappel: {result.recall:.4f}")
print(f"F1-Score: {result.f1_score:.4f}")
# Générer un rapport
report = evaluator.generate_report([result])
print(report)
# Exporter en JSON
evaluator.export_json([result], Path("evaluation_results.json"))
```
### 2. LeakScanner
Scanne les documents anonymisés pour détecter les fuites de PII (données personnelles résiduelles).
**Vérifications** :
- PII originaux encore présents (CRITIQUE)
- Nouveaux PII détectés (HAUTE)
- Métadonnées PDF suspectes (MOYENNE)
**Usage** :
```python
from evaluation import LeakScanner
from pathlib import Path
scanner = LeakScanner()
# Scanner un document anonymisé
report = scanner.scan(
anonymized_pdf=Path("output/document.redacted.pdf"),
original_audit=Path("output/document.audit.jsonl")
)
if report.is_safe:
print("✓ Document sûr - Aucune fuite détectée")
else:
print(f"{report.leak_count} fuite(s) détectée(s)")
for leak in report.leaks:
print(f" - {leak['severity']}: {leak['message']}")
# Générer un rapport
report_text = scanner.generate_report(report, Path("document.pdf"))
print(report_text)
# Exporter en JSON
scanner.export_json(report, Path("leak_report.json"))
```
### 3. Benchmark
Mesure les performances du système d'anonymisation (temps, CPU, RAM).
**Métriques collectées** :
- Temps de traitement (total, par page)
- Utilisation CPU (%)
- Utilisation RAM (MB)
- Nombre de PII détectés
**Usage** :
```python
from evaluation import Benchmark
from pathlib import Path
benchmark = Benchmark(Path("tests/ground_truth/pdfs"))
# Définir la fonction d'anonymisation à benchmarker
def anonymize_func(pdf_path):
# Votre code d'anonymisation ici
# Retourner le chemin vers le fichier .audit.jsonl
return pdf_path.parent / f"{pdf_path.stem}.audit.jsonl"
# Benchmarker des documents
pdf_list = list(Path("tests/ground_truth/pdfs").glob("*.pdf"))
results = benchmark.run(pdf_list, anonymize_func)
# Générer un rapport
report = benchmark.generate_report(results)
print(report)
# Exporter en JSON
benchmark.export_json(results, Path("benchmark_results.json"))
# Exporter en CSV
benchmark.export_csv(results, Path("benchmark_results.csv"))
```
## Installation
Dépendances requises :
```bash
pip install pymupdf psutil
```
## Tests
Exécuter les tests unitaires :
```bash
pytest tests/unit/test_quality_evaluator.py -v
pytest tests/unit/test_leak_scanner.py -v
pytest tests/unit/test_benchmark.py -v
```
## Format des Données
### Annotations (ground truth)
Format JSON :
```json
{
"pdf_path": "document.pdf",
"metadata": {
"annotator": "annotator_1",
"annotation_date": "2024-01-15T10:30:00",
"document_type": "compte_rendu",
"page_count": 3,
"difficulty": "medium"
},
"annotations": [
{
"id": "ann_001",
"page": 0,
"type": "NOM",
"text": "DUPONT",
"bbox": null,
"context": "Dr. DUPONT a examiné le patient",
"mandatory": true,
"difficulty": "easy",
"detection_method_expected": ["regex", "ner", "contextual"]
}
],
"medical_terms_to_preserve": [
"Médecin DIM",
"Service de cardiologie"
],
"statistics": {
"total_pii": 1,
"by_type": {
"NOM": 1
}
}
}
```
### Audit (détections)
Format JSONL (une ligne par PII détecté) :
```json
{"page": 0, "kind": "NOM", "original": "DUPONT", "placeholder": "[NOM]"}
{"page": 0, "kind": "TEL", "original": "01 23 45 67 89", "placeholder": "[TEL]"}
```
## Métriques Cibles
Pour garantir la conformité RGPD et la qualité d'anonymisation :
- **Rappel (Recall)** : ≥ 99.5% (maximum 0.5% de PII manqués)
- **Précision (Precision)** : ≥ 97% (maximum 3% de faux positifs)
- **F1-Score** : ≥ 0.98
- **Taux de documents sûrs** : ≥ 98% (documents avec 0 faux négatif)
## Workflow Complet
1. **Annoter les documents** : Utiliser `tools/annotation_tool.py`
2. **Anonymiser les documents** : Utiliser le système d'anonymisation
3. **Évaluer la qualité** : Utiliser `QualityEvaluator`
4. **Scanner les fuites** : Utiliser `LeakScanner`
5. **Benchmarker les performances** : Utiliser `Benchmark`
6. **Analyser les résultats** : Identifier les améliorations nécessaires
## Exemples de Rapports
### Rapport d'Évaluation
```
================================================================================
RAPPORT D'ÉVALUATION DE LA QUALITÉ D'ANONYMISATION
================================================================================
Documents évalués: 27
MÉTRIQUES GLOBALES:
True Positives: 245
False Positives: 8
False Negatives: 2
Précision moyenne: 0.9684 (96.84%)
Rappel moyen: 0.9919 (99.19%)
F1-Score moyen: 0.9800
RÉSULTATS PAR DOCUMENT:
001_simple_unknown_BACTERIO_23018396.pdf
Précision: 1.0000 Rappel: 1.0000 F1: 1.0000
TP: 10 FP: 0 FN: 0
```
### Rapport de Fuite
```
================================================================================
RAPPORT DE FUITE - document.redacted.pdf
================================================================================
✓ DOCUMENT SÛR - Aucune fuite détectée
================================================================================
```
### Rapport de Benchmark
```
================================================================================
RAPPORT DE BENCHMARK - PERFORMANCE D'ANONYMISATION
================================================================================
SYSTÈME:
OS: Linux 6.8.0
CPU: AMD Ryzen 9 9950X
Cœurs: 16 physiques / 32 logiques
RAM: 128.0 GB
Python: 3.12.0
RÉSUMÉ:
Documents: 27
Temps moyen: 8.5s
Temps min/max: 2.1s / 25.3s
CPU moyen: 45.2%
RAM moyenne: 1024.5 MB
PII détectés: 245 (moy: 9.1)
```
## Licence
Ce module fait partie du système d'anonymisation de documents PDF médicaux.