spec: Architecture complète avec VLM (5 couches détection)

- Ajout documentation VLM (Ollama qwen2.5vl:7b)
- Pipeline complet: Regex → VLM → EDS-Pseudo → CamemBERT → Contextuel
- Nouvelles exigences REQ-013/REQ-014 pour optimisation VLM
- Tâches Phase 2.5: amélioration prompt, validation croisée, perf
- Document ARCHITECTURE_REELLE.md avec détails complets
- Matériel: AMD Ryzen 9 9950X, 128GB RAM, RTX 5070 12GB
- Objectifs: Rappel ≥99.5%, Précision ≥97%, F1 ≥0.98
This commit is contained in:
2026-03-02 09:52:49 +01:00
parent cb84698c2d
commit 0067738df6
8 changed files with 3251 additions and 0 deletions

View File

@@ -0,0 +1,7 @@
{
"specType": "feature",
"workflowType": "requirements-first",
"featureName": "anonymization-quality-optimization",
"createdAt": "2024-01-15T10:00:00Z",
"version": "1.0.0"
}

View File

@@ -0,0 +1,473 @@
# Architecture Réelle du Système d'Anonymisation
## Vue d'Ensemble
Le système d'anonymisation combine **5 couches de détection** pour garantir une couverture maximale des PII dans les documents médicaux PDF.
## 1. Extraction de Texte (5 passes)
### Méthodes d'extraction (ordre de priorité)
1. **pdfplumber** : Extraction textuelle native (PDF textuels)
2. **pdfminer** : Extraction alternative avec LAParams
3. **PyMuPDF** : Fallback si artefacts `(cid:xx)` détectés
4. **docTR OCR** : OCR deep learning pour PDF scannés (parallèle avec tesseract)
5. **tesseract OCR** : OCR complémentaire
### OCR Word Map
Pour les PDF scannés, génération d'une carte de mots avec coordonnées normalisées (0→1) :
```python
OcrWordMap = Dict[int, List[Tuple[str, float, float, float, float]]]
# {page_idx: [(word_text, x0_norm, y0_norm, x1_norm, y1_norm), ...]}
```
Utilisée pour :
- Matching flou des identifiants numériques manuscrits (VLM)
- Redaction raster précise
---
## 2. Détection PII (5 couches)
### 2.1 Regex (Couche 1)
**Fichier** : `anonymizer_core_refactored_onnx.py`
**PII détectés** :
- EMAIL, TEL (formats fragmentés), IBAN, NIR (avec validation clé modulo 97)
- IPP, FINESS, RPPS, OGC
- Dates (multiples formats), dates de naissance
- Adresses postales, codes postaux, BP
- Âges, numéros de dossier, épisodes
- Établissements de santé, services hospitaliers
**Patterns contextuels** :
- `Dr. NOM`, `Patient: NOM`, `Rédigé par NOM`
- Listes virgulées : `Dr. X, Y, DUPONT`
- Champs structurés Trackare
**Configuration** : `config/dictionnaires.yml`
- Listes blanches (sections_titres, noms_maj_excepts)
- Force-mask (termes/regex à masquer systématiquement)
- Regex overrides personnalisées
### 2.2 VLM - Vision Language Model (Couche 2)
**Fichier** : `vlm_manager.py`
**Modèle** : Ollama avec qwen2.5vl:7b (ou qwen3-vl:8b)
**Fonctionnement** :
1. Conversion de chaque page PDF en image (150 DPI)
2. Redimensionnement si > 2048px (côté le plus long)
3. Envoi à Ollama avec prompt structuré
4. Parsing de la réponse JSON (avec réparation si tronquée)
**20+ catégories détectées** :
- Identité : NOM, PRENOM, DATE_NAISSANCE, NIR, AGE
- Contact : ADRESSE, TELEPHONE, EMAIL, CODE_POSTAL, VILLE
- Identifiants médicaux : IPP, NDA, RPPS, NUMERO_PATIENT, NUMERO_LOT, NUMERO_ORDONNANCE, NUMERO_SEJOUR
- Contexte : ETABLISSEMENT, SERVICE, DATE
**Gestion des pages manuscrites** :
- Si < 100 mots OCR détectés → masquage total de la page
- Évite les hallucinations du VLM sur pages complexes
**Matching flou** :
- Pour identifiants numériques manuscrits
- Compare séquences de chiffres (ratio ≥ 0.7)
- Utilise l'OCR word map pour localisation
**Configuration** :
```python
@dataclass
class VlmConfig:
base_url: str = "http://localhost:11434"
model: str = "qwen2.5vl:7b"
timeout: int = 180
max_image_size: int = 2048
temperature: float = 0.1
num_predict: int = 8192
min_confidence: float = 0.5
```
**Prompt système** :
```
Tu identifies les données personnelles et identifiants traçables dans les documents
médicaux français. Réponds uniquement en JSON.
```
**Dégradation gracieuse** : Si Ollama indisponible, le pipeline continue sans VLM.
### 2.3 NER - Named Entity Recognition (Couche 3)
#### Option A : EDS-Pseudo (recommandé)
**Fichier** : `eds_pseudo_manager.py`
**Modèle** : AP-HP/eds-pseudo-public via edsnlp
**Performance** : F1=0.97 sur données cliniques AP-HP (11M documents)
**13 labels détectés** :
- NOM, PRENOM, MAIL, TEL, SECU (NIR)
- ADRESSE, ZIP, VILLE, HOPITAL
- DATE, DATE_NAISSANCE, IPP, NDA
**Mapping vers PLACEHOLDERS** :
```python
EDS_LABEL_MAP = {
"NOM": "NOM",
"PRENOM": "NOM",
"MAIL": "EMAIL",
"TEL": "TEL",
"SECU": "NIR",
# ...
}
```
#### Option B : CamemBERT-NER (fallback)
**Fichier** : `ner_manager_onnx.py`
**Modèles** :
- `cmarkea/distilcamembert-base-ner` (rapide, quantifié)
- `Jean-Baptiste/camembert-ner` (robuste)
**Runtime** : ONNX avec optimum.onnxruntime
**Tags supportés** : PER, LOC, ORG, DATE
**Seuils de confiance** :
```python
@dataclass
class NerThresholds:
per: float = 0.90
org: float = 0.90
loc: float = 0.90
date: float = 0.85
```
### 2.4 Extraction Trackare (Couche 4)
**Fonction** : `_extract_trackare_identity()`
**Champs structurés extraits** :
- Nom de naissance, Nom et Prénom
- Lieu de naissance, Ville de résidence
- Contacts (Conjoint, Parent, Époux, etc.)
- Personnel médical (Rédigé par, Aide:, IDE:, etc.)
- Pattern multi-lignes : `Prenom\nNOM`
**Regex spécialisées** :
- `RE_EXTRACT_PATIENT`, `RE_EXTRACT_NOM_NAISSANCE`
- `RE_EXTRACT_CONTACT`, `RE_EXTRACT_STAFF_ROLE`
- `RE_EXTRACT_DR_DEST`, `RE_EXTRACT_PR`
### 2.5 Détection Contextuelle (Couche 5)
**Patterns** :
- Noms après titres : `Dr. DUPONT`, `Pr. MARTIN`
- Noms en MAJUSCULES (hors stopwords médicaux)
- Listes virgulées : `le Dr X, Y, LAZARO`
**Stopwords médicaux** : ~4000 termes
- Médicaments (edsnlp drugs.json)
- Termes médicaux, anatomie, pathologies
- Abréviations, services hospitaliers
- Mots courants français
---
## 3. Consolidation Globale
**Fonction** : `_apply_global_pii_tokens()`
### Propagation des PII
Chaque PII détecté est propagé sur toutes les pages du document :
**Types propagés globalement** :
- `NOM_GLOBAL` : tous les tokens de noms
- `TEL_GLOBAL`, `EMAIL_GLOBAL`, `ADRESSE_GLOBAL`
- `CODE_POSTAL_GLOBAL`, `VILLE_GLOBAL`, `ETAB_GLOBAL`
- `VLM_SERVICE`, `VLM_ETAB`, `DATE_NAISSANCE`
### Noms compagnons
Détection de mots en MAJUSCULES adjacents à un nom connu :
```python
# Si "DUPONT" est détecté, et "JEAN-PIERRE DUPONT" apparaît
# → "JEAN-PIERRE" est ajouté comme nom compagnon
```
### Noms composés
Traitement en bloc : `JEAN-PIERRE`, `CAZELLES-BOUDIER`
### Rescan sélectif
Rescan des PII critiques ayant pu échapper au premier passage :
- EMAIL, TEL, IBAN, NIR
- Téléphones fragmentés sur plusieurs lignes
- Codes postaux orphelins
---
## 4. Redaction PDF
### 4.1 Vector Redaction (PDF textuels)
**Méthode** : `page.search_for()` (PyMuPDF)
1. Pour chaque PII dans l'audit
2. Recherche du texte exact dans la page
3. Si non trouvé et PII avec espaces → recherche mot par mot
4. Génération de rectangles de redaction
5. Application des rectangles (texte remplacé par noir)
### 4.2 Raster Redaction (PDF scannés)
**Méthode** : Conversion en image + redaction pixel
1. Conversion de chaque page en pixmap (DPI configurable)
2. Matching des PII via OCR word map
3. **Matching flou pour VLM** : identifiants numériques manuscrits
4. Dessin de rectangles noirs sur les zones PII
5. Reconstruction du PDF depuis les images
**Matching flou VLM** :
```python
def _search_ocr_words_fuzzy_digits(ocr_words, token, page_rect, min_ratio=0.7):
"""Compare les séquences de chiffres entre le token VLM et les mots OCR.
Accepte une correspondance si ≥ min_ratio des chiffres matchent."""
```
Appliqué aux catégories :
- `VLM_NUM_PATIENT`, `VLM_NUM_LOT`, `VLM_NUM_ORD`
- `VLM_NDA`, `VLM_NIR`, `VLM_IPP`, `VLM_RPPS`
---
## 5. Audit Trail
**Format** : `.audit.jsonl` (JSON Lines)
**Structure** :
```python
@dataclass
class PiiHit:
page: int
kind: str # Type de PII (EMAIL, NOM, VLM_TEL, etc.)
original: str # Texte original détecté
placeholder: str # Placeholder de remplacement
bbox_hint: Optional[Tuple[float, float, float, float]] # Coordonnées (optionnel)
```
**Traçabilité** :
- Chaque PII détecté est enregistré avec sa méthode de détection
- Permet l'analyse post-traitement
- Utilisé pour la validation post-anonymisation
---
## 6. Matériel et Performance
### Configuration actuelle
- **CPU** : AMD Ryzen 9 9950X (16 cœurs / 32 threads)
- **RAM** : 128 GB
- **GPU** : NVIDIA RTX 5070 (12 GB VRAM)
- **CUDA** : PyTorch 2.10.0 avec support CUDA
### Temps de traitement
**PDF textuels** :
- Extraction : < 1s
- Détection (Regex + NER GPU) : 2-5s
- Redaction : 1-2s
- **Total** : < 10s par PDF
**PDF scannés** :
- Extraction + OCR : 5-15s
- VLM (Ollama) : 10-30s par page (dépend du modèle)
- Détection (Regex + NER GPU) : 2-5s
- Redaction raster : 3-10s
- **Total** : 20-60s par PDF (selon nombre de pages)
### Optimisations possibles
1. **VLM** : Vérifier support GPU Ollama (CUDA)
2. **NER** : Batch processing optimisé (12 GB VRAM)
3. **Parallélisation** : 8-12 workers sur 16 cœurs
4. **Cache** : Résultats VLM par hash d'image
---
## 7. Points d'Attention
### Hallucinations VLM
Le VLM peut détecter des PII inexistants, surtout sur :
- Pages manuscrites complexes
- Documents mal orientés
- Tableaux denses
**Mitigation actuelle** :
- Masquage total si < 100 mots OCR
- Seuil de confiance (0.5)
**Amélioration proposée** :
- Validation croisée VLM ↔ NER
- Prompt amélioré avec exemples négatifs
- Rejet des détections non confirmées
### Faux Positifs NER
EDS-Pseudo peut détecter comme NOM :
- Médicaments (ex: "Eliquis", "Trulicity")
- Termes médicaux (ex: "Diabétique", "Cutanée")
- Mots courants (ex: "Toilette", "Repas")
**Mitigation** : Stopwords médicaux (~4000 termes)
### Performance VLM
Ollama en local peut être lent (10-30s par page).
**Solutions** :
- Vérifier support GPU
- Réduire `max_image_size` (trade-off qualité/vitesse)
- Cache des résultats
- Traitement parallèle (attention : charge GPU)
---
## 8. Dépendances Complètes
```
# Core
python>=3.12
pyyaml
# PDF
pymupdf
pdfplumber
pdfminer.six
pillow
# OCR
doctr[torch]
pytesseract
# NER
edsnlp[ml]>=0.12.0 # EDS-Pseudo
transformers
optimum
onnxruntime # ou onnxruntime-gpu
sentencepiece
# VLM
# Aucune dépendance Python (utilise urllib)
# Nécessite Ollama installé localement : https://ollama.ai/
# Tests & Qualité (nouveaux)
pytest
pytest-cov
pydantic
structlog
jinja2
matplotlib
```
---
## 9. Configuration Ollama
### Installation
```bash
# Linux
curl -fsSL https://ollama.ai/install.sh | sh
# macOS
brew install ollama
# Windows
# Télécharger depuis https://ollama.ai/download
```
### Téléchargement du modèle
```bash
ollama pull qwen2.5vl:7b
# ou
ollama pull qwen3-vl:8b
```
### Vérification
```bash
# Lister les modèles disponibles
ollama list
# Tester le modèle
ollama run qwen2.5vl:7b
```
### Configuration GPU (optionnel)
Ollama détecte automatiquement le GPU CUDA si disponible.
Vérifier dans les logs :
```bash
ollama serve
# Chercher : "GPU detected: NVIDIA GeForce RTX 5070"
```
---
## 10. Workflow Complet
```
1. Chargement PDF
2. Extraction texte (5 passes)
3. Détection Regex
4. VLM (si PDF scanné)
5. NER (EDS-Pseudo ou CamemBERT)
6. Extraction Trackare
7. Détection contextuelle
8. Consolidation globale
9. Rescan sélectif
10. Redaction PDF (vector ou raster)
11. Génération audit.jsonl
12. Validation post-anonymisation (à implémenter)
13. Certificat de conformité (à implémenter)
```
---
## Conclusion
Le système actuel est **très sophistiqué** avec 5 couches de détection complémentaires. Les principaux axes d'amélioration sont :
1. **Métriques de qualité** : Créer un dataset annoté et mesurer Précision/Rappel/F1
2. **Validation VLM** : Réduire les hallucinations via validation croisée
3. **Optimisation GPU** : Accélérer NER et vérifier support GPU Ollama
4. **Tests de régression** : Suite automatique pour éviter les régressions
5. **Validation post-anonymisation** : Scanner de fuite automatique
La spécification mise à jour reflète maintenant cette architecture réelle.

View File

@@ -0,0 +1,571 @@
# Guide de Démarrage Rapide
## Installation des Dépendances
```bash
# Installer les nouvelles dépendances
pip install pytest pytest-cov pydantic structlog jinja2 matplotlib
# Vérifier l'installation
python -c "import pytest, pydantic, structlog, jinja2, matplotlib; print('✅ Toutes les dépendances sont installées')"
# Vérifier la disponibilité CUDA
python -c "import torch; print(f'CUDA disponible: {torch.cuda.is_available()}'); print(f'GPU: {torch.cuda.get_device_name(0) if torch.cuda.is_available() else \"N/A\"}')"
```
## Préparation de l'Environnement
```bash
# Créer les répertoires nécessaires
mkdir -p tests/ground_truth
mkdir -p tests/unit
mkdir -p tests/regression
mkdir -p reports/quality
mkdir -p evaluation
mkdir -p detectors
mkdir -p tools
mkdir -p docs
mkdir -p config
# Vérifier la structure
tree -L 2 tests/ evaluation/ detectors/ tools/
```
## Phase 1 : Création du Dataset de Test
### Étape 1.1 : Sélectionner les Documents
```bash
# Aller dans le répertoire source
cd "/home/dom/Téléchargements/II-1 Ctrl_T2A_2025_CHCB_DocJustificatifs (1)/"
# Lister tous les PDFs
find . -name "*.pdf" -type f > /tmp/all_pdfs.txt
wc -l /tmp/all_pdfs.txt # Compter le nombre total
# Analyser la répartition par dossier OGC
for dir in */; do
count=$(find "$dir" -name "*.pdf" -type f | wc -l)
echo "$dir: $count PDFs"
done | sort -t: -k2 -n
# Sélectionner manuellement 30 documents :
# - 10 simples (1-2 pages, peu de PII)
# - 15 moyens (3-5 pages, PII variés)
# - 5 complexes (>5 pages, nombreux PII)
# Copier les documents sélectionnés
# Exemple :
cp "257_23209962/FC14.pdf" ~/path/to/project/tests/ground_truth/ogc_257_fc14.pdf
cp "257_23209962/FC16.pdf" ~/path/to/project/tests/ground_truth/ogc_257_fc16.pdf
# ... répéter pour les 30 documents
```
### Étape 1.2 : Créer l'Outil d'Annotation
```bash
# Créer le fichier
cat > tools/annotation_tool.py << 'EOF'
#!/usr/bin/env python3
"""
Outil d'annotation CLI pour créer le dataset de test.
Usage: python tools/annotation_tool.py tests/ground_truth/
"""
import json
from pathlib import Path
import sys
# TODO: Implémenter l'outil d'annotation
# Voir design.md section 2.1.2 pour les spécifications
if __name__ == "__main__":
if len(sys.argv) < 2:
print("Usage: python tools/annotation_tool.py <ground_truth_dir>")
sys.exit(1)
ground_truth_dir = Path(sys.argv[1])
print(f"Annotation des documents dans : {ground_truth_dir}")
# TODO: Implémenter la logique d'annotation
EOF
chmod +x tools/annotation_tool.py
```
### Étape 1.3 : Annoter les Documents
```bash
# Lancer l'outil d'annotation
python tools/annotation_tool.py tests/ground_truth/
# Pour chaque PDF, l'outil doit :
# 1. Extraire et afficher le texte
# 2. Demander de saisir les PII (type, texte, page, contexte)
# 3. Demander les termes médicaux à préserver
# 4. Sauvegarder en JSON
# Format de sortie attendu :
# tests/ground_truth/ogc_257_fc14.pdf
# tests/ground_truth/ogc_257_fc14.annotations.json
```
## Phase 2 : Implémentation de l'Évaluation
### Étape 2.1 : Créer l'Évaluateur de Qualité
```bash
# Créer le fichier
cat > evaluation/quality_evaluator.py << 'EOF'
#!/usr/bin/env python3
"""
Évaluateur de qualité d'anonymisation.
Compare les détections avec les annotations manuelles.
"""
from dataclasses import dataclass
from pathlib import Path
from typing import List, Dict
import json
@dataclass
class EvaluationResult:
true_positives: int
false_positives: int
false_negatives: int
precision: float
recall: float
f1_score: float
missed_pii: List[Dict]
false_detections: List[Dict]
class QualityEvaluator:
def __init__(self, ground_truth_dir: Path):
self.ground_truth_dir = ground_truth_dir
def evaluate(self, pdf_path: Path, audit_path: Path) -> EvaluationResult:
# TODO: Implémenter l'évaluation
# Voir design.md section 2.2.1 pour les spécifications
pass
if __name__ == "__main__":
# TODO: Ajouter CLI
pass
EOF
chmod +x evaluation/quality_evaluator.py
```
### Étape 2.2 : Créer le Scanner de Fuite
```bash
# Créer le fichier
cat > evaluation/leak_scanner.py << 'EOF'
#!/usr/bin/env python3
"""
Scanner de fuite de PII dans les documents anonymisés.
"""
from dataclasses import dataclass
from pathlib import Path
from typing import List, Dict
@dataclass
class LeakReport:
is_safe: bool
leak_count: int
leaks: List[Dict]
class LeakScanner:
def scan(self, anonymized_pdf: Path, original_audit: Path) -> LeakReport:
# TODO: Implémenter le scan
# Voir design.md section 2.2.2 pour les spécifications
pass
if __name__ == "__main__":
# TODO: Ajouter CLI
pass
EOF
chmod +x evaluation/leak_scanner.py
```
### Étape 2.3 : Créer le Benchmark
```bash
# Créer le fichier
cat > evaluation/benchmark.py << 'EOF'
#!/usr/bin/env python3
"""
Benchmark de performance du système d'anonymisation.
"""
from pathlib import Path
import time
import json
class Benchmark:
def __init__(self, test_data_dir: Path):
self.test_data_dir = test_data_dir
def run(self) -> Dict:
# TODO: Implémenter le benchmark
# Voir design.md section 2.2.3 pour les spécifications
pass
if __name__ == "__main__":
# TODO: Ajouter CLI
pass
EOF
chmod +x evaluation/benchmark.py
```
## Phase 3 : Mesure de la Baseline
### Étape 3.1 : Anonymiser les Documents de Test
```bash
# Option 1 : Via GUI
python Pseudonymisation_Gui_V5.py
# Sélectionner le dossier tests/ground_truth/
# Lancer l'anonymisation
# Option 2 : Via CLI (si disponible)
python anonymizer_core_refactored_onnx.py \
tests/ground_truth/*.pdf \
--output tests/ground_truth/anonymized/ \
--hf \
--raster
```
### Étape 3.2 : Évaluer la Baseline
```bash
# Évaluer chaque document
python evaluation/quality_evaluator.py \
--ground-truth tests/ground_truth/ \
--anonymized tests/ground_truth/anonymized/ \
--output reports/baseline_evaluation.json
# Générer le rapport HTML
python evaluation/quality_evaluator.py \
--ground-truth tests/ground_truth/ \
--anonymized tests/ground_truth/anonymized/ \
--output reports/baseline_report.html \
--format html
```
### Étape 3.3 : Scanner les Fuites
```bash
# Scanner tous les documents anonymisés
for pdf in tests/ground_truth/anonymized/*.pdf; do
audit="${pdf%.pdf}.audit.jsonl"
python evaluation/leak_scanner.py \
--anonymized "$pdf" \
--audit "$audit" \
--output "reports/leak_$(basename $pdf .pdf).json"
done
# Générer un rapport consolidé
python evaluation/leak_scanner.py \
--batch tests/ground_truth/anonymized/ \
--output reports/leak_report.html
```
### Étape 3.4 : Benchmarker les Performances
```bash
# Exécuter le benchmark
python evaluation/benchmark.py \
--test-dir tests/ground_truth/ \
--iterations 3 \
--output reports/baseline_benchmark.json
# Afficher les résultats
python evaluation/benchmark.py \
--show reports/baseline_benchmark.json
```
## Phase 4 : Amélioration des Détecteurs
### Étape 4.1 : Créer les Regex Améliorées
```bash
# Créer le fichier
cat > detectors/improved_regex.py << 'EOF'
#!/usr/bin/env python3
"""
Regex améliorées pour la détection de PII.
"""
import re
# Téléphone amélioré (formats fragmentés)
RE_TEL_IMPROVED = re.compile(
r"(?<!\d)"
r"(?:"
r"(?:\+33|0033)\s*[1-9](?:[\s.\-]?\d){8}"
r"|"
r"0[1-9](?:[\s.\-]?\d){8}"
r"|"
r"0[1-9][\s.\-]?\d{1,2}[\s.\-]?\d{1,2}[\s\n]{1,3}\d{1,2}[\s.\-]?\d{1,2}[\s.\-]?\d{1,2}"
r")"
r"(?!\d)",
re.MULTILINE
)
# Email amélioré (domaines médicaux)
RE_EMAIL_IMPROVED = re.compile(
r"\b[A-Za-z0-9._%+-]+"
r"@"
r"(?:"
r"(?:chu|ch|aphp|ap-hm|hospices-civils|clinique|hopital|ehpad)"
r"[\w\-]*\.[a-z]{2,}"
r"|"
r"[A-Za-z0-9.-]+\.[A-Za-z]{2,}"
r")\b",
re.IGNORECASE
)
# TODO: Ajouter les autres regex améliorées
# Voir design.md section 2.3.1 pour les spécifications
EOF
```
### Étape 4.2 : Créer le Détecteur Contextuel
```bash
# Créer le fichier
cat > detectors/contextual.py << 'EOF'
#!/usr/bin/env python3
"""
Détecteur contextuel pour les noms de personnes.
"""
import re
from typing import List, Dict
class ContextualDetector:
def __init__(self):
self.strong_contexts = [
r"(?:Dr\.?|Docteur|Pr\.?|Professeur)\s+{name}",
r"(?:Mme|Madame|M\.|Monsieur)\s+{name}",
r"Patient(?:e)?\s*:\s*{name}",
]
def detect(self, text: str, page: int) -> List[Dict]:
# TODO: Implémenter la détection contextuelle
# Voir design.md section 2.3.2 pour les spécifications
pass
EOF
```
### Étape 4.3 : Créer le Détecteur Hybride
```bash
# Créer le fichier
cat > detectors/hybrid.py << 'EOF'
#!/usr/bin/env python3
"""
Détecteur hybride combinant plusieurs méthodes.
"""
from typing import List, Dict
class HybridDetector:
def __init__(self):
# TODO: Initialiser les détecteurs
pass
def detect(self, text: str, page: int) -> List[Dict]:
# TODO: Implémenter le pipeline hybride
# Voir design.md section 2.3.3 pour les spécifications
pass
EOF
```
## Phase 5 : Tests et Validation
### Étape 5.1 : Créer les Tests Unitaires
```bash
# Créer les fichiers de test
mkdir -p tests/unit
# Tests des regex
cat > tests/unit/test_improved_regex.py << 'EOF'
import pytest
from detectors.improved_regex import RE_TEL_IMPROVED, RE_EMAIL_IMPROVED
class TestImprovedRegex:
@pytest.mark.parametrize("phone,should_match", [
("06 12 34 56 78", True),
("0612345678", True),
("06 12 34\n56 78", True),
("12345678901", False),
])
def test_phone_detection(self, phone, should_match):
match = RE_TEL_IMPROVED.search(phone)
assert (match is not None) == should_match
# TODO: Ajouter plus de tests
EOF
# Exécuter les tests
pytest tests/unit/ -v --cov=detectors
```
### Étape 5.2 : Créer les Tests de Régression
```bash
# Créer le fichier
cat > tests/regression/test_regression.py << 'EOF'
import pytest
from pathlib import Path
from evaluation.quality_evaluator import QualityEvaluator
class TestRegression:
def test_quality_metrics(self):
"""Vérifie que les métriques de qualité sont atteintes"""
evaluator = QualityEvaluator(Path("tests/ground_truth"))
# TODO: Implémenter le test
# Vérifier Rappel >= 99.5%, Précision >= 97%
pass
def test_no_performance_degradation(self):
"""Vérifie qu'il n'y a pas de dégradation de performance"""
# TODO: Implémenter le test
# Vérifier temps < 30s par PDF
pass
EOF
# Exécuter les tests de régression
pytest tests/regression/ -v
```
### Étape 5.3 : Valider sur le Corpus Complet
```bash
# Anonymiser tous les documents
python Pseudonymisation_Gui_V5.py
# Sélectionner : /home/dom/Téléchargements/II-1 Ctrl_T2A_2025_CHCB_DocJustificatifs (1)/
# Lancer l'anonymisation
# Scanner toutes les fuites
python evaluation/leak_scanner.py \
--batch "/home/dom/Téléchargements/II-1 Ctrl_T2A_2025_CHCB_DocJustificatifs (1)/anonymise/" \
--output reports/full_corpus_leak_report.html
# Vérifier qu'aucune fuite critique n'est détectée
grep -i "CRITIQUE" reports/full_corpus_leak_report.html
```
## Commandes Utiles
### Vérifier la Qualité du Code
```bash
# Linter
pylint detectors/ evaluation/ tools/
# Formatter
black detectors/ evaluation/ tools/
# Type checker
mypy detectors/ evaluation/ tools/
# Tout en une fois
pylint detectors/ && black --check detectors/ && mypy detectors/
```
### Générer la Documentation
```bash
# Générer la doc API avec Sphinx (optionnel)
sphinx-apidoc -o docs/api detectors/ evaluation/ tools/
sphinx-build -b html docs/ docs/_build/
# Ou simplement documenter avec des docstrings
python -m pydoc detectors.hybrid
```
### Exporter les Résultats
```bash
# Exporter les métriques en CSV
python evaluation/quality_evaluator.py \
--ground-truth tests/ground_truth/ \
--output reports/metrics.csv \
--format csv
# Exporter les graphiques
python evaluation/quality_evaluator.py \
--ground-truth tests/ground_truth/ \
--output reports/charts/ \
--format charts
```
## Troubleshooting
### Problème : Annotation trop longue
**Solution** : Paralléliser avec 2 annotateurs
```bash
# Annotateur 1 : documents 1-15
python tools/annotation_tool.py tests/ground_truth/ --range 1-15
# Annotateur 2 : documents 16-30
python tools/annotation_tool.py tests/ground_truth/ --range 16-30
```
### Problème : GPU non détecté
**Solution** : Vérifier l'installation CUDA
```bash
# Vérifier CUDA
nvidia-smi
# Vérifier PyTorch CUDA
python -c "import torch; print(torch.cuda.is_available())"
# Réinstaller PyTorch avec CUDA si nécessaire
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118
```
### Problème : VRAM insuffisante
**Solution** : Réduire la taille du batch
```yaml
# Dans config/quality_config.yml
gpu:
batch_size: 8 # Réduire de 16 à 8
max_vram_gb: 8 # Réduire la limite
```
### Problème : Traitement trop lent même avec GPU
**Solution** : Vérifier que le GPU est bien utilisé
```python
# Ajouter du logging dans le code
import torch
print(f"Device utilisé: {torch.cuda.get_device_name(0)}")
print(f"VRAM utilisée: {torch.cuda.memory_allocated() / 1e9:.2f} GB")
```
### Problème : Mémoire RAM insuffisante (peu probable avec 128 GB)
**Solution** : Réduire le nombre de workers
```yaml
# Dans config/quality_config.yml
performance:
max_workers: 4 # Réduire de 8 à 4
```
## Ressources
- **Documentation** : `docs/`
- **Spécifications** : `.kiro/specs/anonymization-quality-optimization/`
- **Tests** : `tests/`
- **Rapports** : `reports/`
## Support
Pour toute question :
1. Consulter `requirements.md` pour les exigences
2. Consulter `design.md` pour l'architecture
3. Consulter `tasks.md` pour le plan détaillé
4. Consulter `SUMMARY.md` pour le résumé exécutif

View File

@@ -0,0 +1,151 @@
# Spec : Optimisation de la Qualité d'Anonymisation
## Vue d'Ensemble
Cette spécification détaille le projet d'optimisation de la qualité d'anonymisation du système de pseudonymisation de documents PDF médicaux.
**Objectif** : Atteindre un équilibre optimal entre rappel (détection des PII) et précision (éviter les faux positifs) pour garantir la conformité RGPD tout en préservant la lisibilité médicale.
## Métriques Cibles
- **Rappel** : ≥ 99.5% (maximum 0.5% de PII manqués)
- **Précision** : ≥ 97% (maximum 3% de faux positifs)
- **F1-Score** : ≥ 0.98
- **Temps de traitement** : < 30 secondes par PDF
## Corpus de Travail
- **Source** : 59 dossiers OGC dans `/home/dom/Téléchargements/II-1 Ctrl_T2A_2025_CHCB_DocJustificatifs (1)/`
- **Sortie existante** : 130 fichiers anonymisés + audits dans `anonymise/`
- **Dataset de test** : 30 documents annotés manuellement (à créer)
## Contraintes
- ✅ Utilisation de documents réels uniquement (pas de mocks)
- ✅ CPU uniquement (pas de GPU)
- ✅ RAM limitée (< 4 GB par processus)
- ✅ Conformité RGPD stricte
## Structure de la Spec
1. **requirements.md** : Exigences fonctionnelles et non-fonctionnelles
2. **design.md** : Architecture technique et composants détaillés
3. **tasks.md** : Plan d'implémentation en 4 phases
## Phases du Projet
### Phase 1 : Mesure et Baseline (2 semaines)
- Création du dataset de test annoté (30 documents)
- Implémentation du système d'évaluation
- Mesure des performances actuelles
### Phase 2 : Amélioration de la Détection (3 semaines)
- Amélioration des regex (téléphones, emails, adresses, NIR)
- Implémentation de la détection contextuelle
- Approche hybride multi-détecteurs
### Phase 3 : Validation et Reporting (1 semaine)
- Validation post-anonymisation
- Génération de rapports de qualité
- Tests de régression automatiques
### Phase 4 : Documentation et Finalisation (3 jours)
- Documentation complète
- Validation finale sur corpus complet
- Livrables
## Livrables Attendus
1. Dataset de test annoté (30+ documents)
2. Système d'évaluation automatique
3. Détecteurs améliorés (regex + contextuel + hybride)
4. Suite de tests de régression
5. Rapports de qualité (HTML + JSON)
6. Documentation (guides + API)
7. Métriques baseline et finales
## Démarrage Rapide
### Prérequis
```bash
# Installer les dépendances
pip install pytest pytest-cov pydantic structlog jinja2 matplotlib
# Créer les répertoires
mkdir -p tests/ground_truth
mkdir -p reports/quality
```
### Étape 1 : Créer le Dataset Annoté
```bash
# Sélectionner 30 documents représentatifs
python tools/select_test_documents.py \
--source "/home/dom/Téléchargements/II-1 Ctrl_T2A_2025_CHCB_DocJustificatifs (1)/" \
--output tests/ground_truth/ \
--count 30
# Annoter les documents
python tools/annotation_tool.py tests/ground_truth/
```
### Étape 2 : Mesurer la Baseline
```bash
# Évaluer le système actuel
python evaluation/quality_evaluator.py \
--ground-truth tests/ground_truth/ \
--output reports/baseline_report.html
# Benchmarker les performances
python evaluation/benchmark.py \
--test-dir tests/ground_truth/ \
--output reports/baseline_benchmark.json
```
### Étape 3 : Implémenter les Améliorations
Suivre les tâches dans `tasks.md` phase par phase.
### Étape 4 : Valider
```bash
# Tests de régression
pytest tests/regression/ --benchmark
# Validation sur corpus complet
python scripts/validate_full_corpus.py \
--source "/home/dom/Téléchargements/II-1 Ctrl_T2A_2025_CHCB_DocJustificatifs (1)/" \
--output reports/final_validation.html
```
## Ressources
- **Documentation** : `docs/`
- **Tests** : `tests/`
- **Configuration** : `config/quality_config.yml`
- **Rapports** : `reports/`
## Contact
Pour toute question sur cette spécification, consulter les documents détaillés :
- `requirements.md` pour les exigences
- `design.md` pour l'architecture
- `tasks.md` pour le plan d'implémentation
## Statut
- [x] Requirements définis
- [x] Design validé
- [x] Tasks planifiées
- [ ] Implémentation en cours
- [ ] Tests validés
- [ ] Documentation complète
- [ ] Livraison finale
---
**Version** : 1.0.0
**Date de création** : 2024-01-15
**Dernière mise à jour** : 2024-01-15

View File

@@ -0,0 +1,321 @@
# Résumé Exécutif - Optimisation de la Qualité d'Anonymisation
## Contexte
Vous disposez d'un système d'anonymisation de documents PDF médicaux qui combine **4 couches de détection** :
**1. Extraction multi-passes** : pdfplumber → pdfminer → PyMuPDF → docTR OCR → tesseract
**2. Détection par regex** : EMAIL, TEL, NIR, IBAN, IPP, FINESS, RPPS, OGC, dates, adresses
**3. VLM (Vision Language Model)** : Ollama avec qwen2.5vl:7b pour analyse visuelle des PDF scannés
- Détecte 20+ catégories de PII visuellement (manuscrit, mal orienté)
- Matching flou pour identifiants numériques manuscrits
- Masquage total des pages manuscrites (< 100 mots OCR)
**4. NER** : EDS-Pseudo (AP-HP, F1=0.97) via edsnlp OU CamemBERT-NER ONNX
**5. Consolidation** : Propagation globale + extraction Trackare + rescan sélectif
**Corpus de travail** : 59 dossiers OGC (130 fichiers PDF) dans `/home/dom/Téléchargements/II-1 Ctrl_T2A_2025_CHCB_DocJustificatifs (1)/`
## Problématique
- ❌ Faux négatifs (PII non détectés) → Risque RGPD
- ❌ Faux positifs (termes médicaux masqués) → Documents illisibles
- ❌ VLM peut halluciner sur pages manuscrites complexes
- ❌ Pas de métriques de qualité mesurables
- ❌ Pas de validation post-anonymisation
- ❌ Pas d'optimisation GPU pour VLM (Ollama local)
## Objectifs
**Métriques cibles** :
- Rappel ≥ 99.5% (max 0.5% de PII manqués)
- Précision ≥ 97% (max 3% de faux positifs)
- F1-Score ≥ 0.98
- Temps < 10s par PDF (avec GPU)
**Matériel disponible** :
- CPU : AMD Ryzen 9 9950X (16 cœurs / 32 threads)
- RAM : 128 GB
- GPU : NVIDIA RTX 5070 (12 GB VRAM)
- CUDA : PyTorch 2.10.0 avec support CUDA
## Solution Proposée
### 1. Mesure (2 semaines)
**Créer un dataset de test annoté** :
- Sélectionner 30 documents représentatifs
- Annoter manuellement tous les PII
- Format JSON standardisé
**Implémenter l'évaluation** :
- Évaluateur de qualité (Précision, Rappel, F1)
- Scanner de fuite (détection PII résiduels)
- Benchmark de performance
**Mesurer la baseline** :
- Évaluer le système actuel
- Identifier les faux négatifs/positifs
- Benchmarker les performances
### 2. Amélioration (3 semaines)
**Regex améliorées** :
- Téléphones fragmentés : `06 12 34\n56 78`
- Emails médicaux : `nom@chu-bordeaux.fr`
- Adresses avec compléments : `12 rue X, Bât. B, Appt. 12`
- NIR avec espaces variables
- Noms avec caractères spéciaux : `O'Brien, Müller`
**Détection contextuelle** :
- Noms après "Dr.", "Patient:", etc.
- Noms en MAJUSCULES (hors stopwords médicaux)
- Filtrage des faux positifs
**Approche hybride** :
- Pipeline en 5 étapes : Regex → VLM (si scanné) → EDS-Pseudo → CamemBERT → Contextuel
- Masquage progressif (éviter doublons)
- Fusion intelligente des résultats
- Validation croisée VLM ↔ NER (anti-hallucination)
- Accélération GPU pour NER et optimisation VLM
- Traitement parallèle de plusieurs PDFs (8-12 workers)
### 3. Validation (1 semaine)
**Validation post-anonymisation** :
- Scanner automatique de fuite
- Vérification métadonnées PDF
- Certificat de conformité
**Tests de régression** :
- Suite automatique sur dataset annoté
- Alerte si dégradation des métriques
**Validation corpus complet** :
- Exécution sur les 59 dossiers OGC
- Vérification 0 fuite critique
- Validation manuelle (échantillon)
### 4. Documentation (3 jours)
- Guide d'annotation
- Guide d'évaluation
- Référence API
- Rapports de qualité
## Architecture Cible
```
PDF → Extraction texte → Détection Hybride → Consolidation → Redaction
(5 passes + GPU) ↓
Validation Post-Anonymisation
Certificat de Conformité
```
**Détection Hybride** :
1. Regex améliorées (formats structurés)
2. VLM optimisé (Ollama qwen2.5vl:7b) - si PDF scanné
3. EDS-Pseudo (noms, contexte médical) - GPU accéléré
4. CamemBERT-NER (fallback) - GPU accéléré
5. Contextuel (patterns linguistiques)
**Optimisations Performance** :
- Accélération CUDA pour modèles NER
- Batch processing optimisé (12 GB VRAM)
- VLM avec prompt amélioré et validation croisée
- Traitement parallèle multi-PDF (16 cœurs)
- Temps cible : < 10s par PDF (textuel), < 30s (scanné avec VLM)
## Livrables
1. ✅ Dataset annoté (30+ documents)
2. ✅ Système d'évaluation (évaluateur + scanner + benchmark)
3. ✅ Détecteurs améliorés (regex + contextuel + hybride)
4. ✅ Tests de régression automatiques
5. ✅ Rapports de qualité (HTML + JSON)
6. ✅ Documentation complète
7. ✅ Métriques baseline et finales
## Planning
| Phase | Durée | Tâches Principales |
|-------|-------|-------------------|
| **Phase 1 : Mesure** | 2 semaines | Dataset annoté, Évaluation, Baseline |
| **Phase 2 : Amélioration** | 3 semaines | Regex, Contextuel, Hybride, GPU optimization |
| **Phase 3 : Validation** | 1 semaine | Post-validation, Tests, Corpus complet |
| **Phase 4 : Documentation** | 3 jours | Guides, API, Rapports |
| **Total** | **7 semaines** | |
## Prochaines Étapes
### Étape 1 : Sélectionner les Documents de Test
```bash
# Analyser le corpus
cd "/home/dom/Téléchargements/II-1 Ctrl_T2A_2025_CHCB_DocJustificatifs (1)/"
find . -name "*.pdf" | wc -l # Compter les PDFs
# Sélectionner 30 documents représentatifs
# - 10 simples (1-2 pages, peu de PII)
# - 15 moyens (3-5 pages, PII variés)
# - 5 complexes (>5 pages, nombreux PII)
# Copier dans tests/ground_truth/
mkdir -p tests/ground_truth
# Copier manuellement les 30 PDFs sélectionnés
```
### Étape 2 : Créer l'Outil d'Annotation
```bash
# Créer le fichier
touch tools/annotation_tool.py
# Implémenter l'outil CLI pour annoter les PDFs
# (voir design.md section 2.1.2 pour les spécifications)
```
### Étape 3 : Annoter les Documents
```bash
# Lancer l'outil d'annotation
python tools/annotation_tool.py tests/ground_truth/
# Pour chaque PDF :
# 1. Afficher le texte page par page
# 2. Saisir les PII (type, texte, contexte)
# 3. Lister les termes médicaux à préserver
# 4. Sauvegarder en JSON
```
### Étape 4 : Implémenter l'Évaluateur
```bash
# Créer le fichier
touch evaluation/quality_evaluator.py
# Implémenter :
# - Classe EvaluationResult
# - Classe QualityEvaluator
# - Méthode evaluate()
# - Calcul Précision/Rappel/F1
# - Génération de rapport
```
### Étape 5 : Mesurer la Baseline
```bash
# Anonymiser les 30 documents annotés
python Pseudonymisation_Gui_V5.py # Ou CLI
# Évaluer
python evaluation/quality_evaluator.py \
--ground-truth tests/ground_truth/ \
--output reports/baseline_report.html
# Analyser les résultats
# - Identifier les faux négatifs
# - Identifier les faux positifs
# - Prioriser les améliorations
```
## Points d'Attention
### Annotation Manuelle
⚠️ **Temps estimé** : 30 documents × 1h = 30 heures
- Prévoir 5 jours dédiés
- Possibilité de paralléliser (2 annotateurs)
- Validation croisée recommandée
### Optimisation GPU
**Accélération disponible** : RTX 5070 avec 12 GB VRAM
- EDS-Pseudo et CamemBERT-NER peuvent utiliser CUDA
- Batch processing optimisé pour réduire le temps de traitement
- Objectif : < 10s par PDF (vs 30s en CPU-only)
- Fallback CPU automatique si GPU indisponible
### Traitement Parallèle
**Puissance CPU** : 16 cœurs / 32 threads
- Traitement simultané de 8-12 PDFs
- Speedup significatif sur corpus complet
- Répartition de charge intelligente
### Faux Négatifs Critiques
⚠️ **Priorité RGPD** : 0 faux négatif = objectif
- Scanner de fuite obligatoire
- Validation post-anonymisation en mode strict
- Double vérification manuelle sur échantillon
### Faux Positifs Médicaux
⚠️ **Lisibilité** : Préserver les termes médicaux
- Enrichir la liste des stopwords
- Validation par expert médical
- Ajustement des seuils de confiance
## Critères de Succès
**Qualité** :
- Rappel ≥ 99.5%
- Précision ≥ 97%
- F1-Score ≥ 0.98
- Taux de documents sûrs ≥ 98%
**Performance** :
- Temps < 10s par PDF (avec GPU)
- Temps < 30s par PDF (fallback CPU)
- RAM < 32 GB par processus
- VRAM < 10 GB
- Pas de dégradation > 20% vs baseline
**Livrables** :
- Dataset annoté créé
- Système d'évaluation fonctionnel
- Tests de régression en place
- Documentation complète
**Validation** :
- 0 fuite critique sur corpus complet
- Validation expert médical (échantillon)
- Amélioration mesurable vs baseline
## Ressources
**Documentation** :
- `requirements.md` : Exigences détaillées
- `design.md` : Architecture technique
- `tasks.md` : Plan d'implémentation
- `README.md` : Vue d'ensemble
**Code** :
- `tools/annotation_tool.py` : Outil d'annotation
- `evaluation/quality_evaluator.py` : Évaluateur
- `evaluation/leak_scanner.py` : Scanner de fuite
- `detectors/improved_regex.py` : Regex améliorées
- `detectors/contextual.py` : Détection contextuelle
- `detectors/hybrid.py` : Approche hybride
**Tests** :
- `tests/unit/` : Tests unitaires
- `tests/regression/` : Tests de régression
- `tests/ground_truth/` : Dataset annoté
**Configuration** :
- `config/quality_config.yml` : Configuration qualité
**Rapports** :
- `reports/baseline_report.html` : Rapport baseline
- `reports/final_report.html` : Rapport final
- `reports/comparison.html` : Comparaison avant/après
---
**Prêt à démarrer ?** Commencez par la Phase 1 : Sélection et annotation des 30 documents de test !

View File

@@ -0,0 +1,912 @@
# Design - Optimisation de la Qualité d'Anonymisation
## 1. Vue d'Ensemble de l'Architecture
### 1.1 Architecture Actuelle (Baseline)
```
┌─────────────────────────────────────────────────────────────┐
│ PDF d'entrée │
└────────────────────────┬────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ EXTRACTION DE TEXTE (5 passes) │
│ pdfplumber → pdfminer → PyMuPDF → docTR OCR → tesseract │
│ + OCR word map (coordonnées normalisées 0→1) │
└────────────────────────┬────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ DÉTECTION PII (4 couches) │
│ ├─ 1. Regex (EMAIL, TEL, NIR, IBAN, etc.) │
│ ├─ 2. VLM Ollama (qwen2.5vl:7b) — si PDF scanné │
│ │ • Analyse visuelle de chaque page (150 DPI) │
│ │ • 20+ catégories PII (manuscrit, mal orienté) │
│ │ • Masquage total si < 100 mots OCR │
│ ├─ 3. NER EDS-Pseudo (13 labels, F1=0.97) │
│ │ ou CamemBERT-NER ONNX (fallback) │
│ └─ 4. Extraction Trackare (champs structurés) │
└────────────────────────┬────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ CONSOLIDATION GLOBALE │
│ Propagation des PII sur toutes les pages │
│ + Noms compagnons + Rescan sélectif │
└────────────────────────┬────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ REDACTION PDF │
│ • Vector (PyMuPDF search_for) │
│ • Raster (OCR word map + matching flou pour VLM) │
│ Génération PDF raster + audit.jsonl │
└─────────────────────────────────────────────────────────────┘
```
**Problèmes identifiés** :
- ❌ Pas de validation post-anonymisation
- ❌ Pas de métriques de qualité
- ❌ VLM peut halluciner (pages manuscrites complexes)
- ❌ Pas d'optimisation GPU pour VLM
- ❌ Pas de tests de régression
---
### 1.2 Architecture Cible (Optimisée)
```
┌─────────────────────────────────────────────────────────────┐
│ PDF d'entrée │
└────────────────────────┬────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ EXTRACTION DE TEXTE (inchangé) │
└────────────────────────┬────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ DÉTECTION HYBRIDE (5 passes + améliorations) │
│ ├─ 1. Regex améliorées (formats structurés) │
│ ├─ 2. VLM optimisé (GPU, prompt amélioré, anti-hallucination) │
│ ├─ 3. EDS-Pseudo (noms, contexte médical) - GPU │
│ ├─ 4. CamemBERT-NER (fallback) - GPU │
│ └─ 5. Détection contextuelle renforcée │
│ │
│ → Masquage progressif pour éviter doublons │
│ → Fusion intelligente des résultats │
│ → Validation croisée VLM ↔ NER pour réduire hallucinations│
└────────────────────────┬────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ CONSOLIDATION GLOBALE (inchangé) │
└────────────────────────┬────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ REDACTION PDF │
└────────────────────────┬────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ VALIDATION POST-ANONYMISATION (NOUVEAU) │
│ ├─ Scanner de fuite PII │
│ ├─ Vérification métadonnées │
│ ├─ Détection hallucinations VLM (cross-check NER) │
│ └─ Certificat de conformité │
└────────────────────────┬────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ ÉVALUATION QUALITÉ (si ground truth disponible) │
│ ├─ Calcul Précision/Rappel/F1 par méthode │
│ ├─ Identification faux positifs/négatifs │
│ └─ Rapport de qualité │
└─────────────────────────────────────────────────────────────┘
```
---
## 2. Composants Détaillés
### 2.1 Dataset de Test Annoté
#### 2.1.1 Structure des Données
**Format d'annotation** :
```json
{
"pdf_path": "OGC_257/FC14.pdf",
"metadata": {
"annotator": "expert_1",
"annotation_date": "2024-01-15",
"document_type": "compte_rendu_hospitalier",
"page_count": 3,
"difficulty": "medium"
},
"annotations": [
{
"id": "ann_001",
"page": 1,
"type": "NOM",
"text": "DUPONT",
"bbox": [100.5, 200.3, 150.2, 220.8],
"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",
"Praticien conseil"
],
"statistics": {
"total_pii": 45,
"by_type": {
"NOM": 12,
"PRENOM": 8,
"TEL": 3,
"EMAIL": 2,
"DATE": 15,
"ADRESSE": 5
}
}
}
```
#### 2.1.2 Outil d'Annotation
**Composant** : `annotation_tool.py`
**Fonctionnalités** :
- Interface CLI pour annoter les PDF
- Extraction automatique du texte + affichage
- Saisie guidée des annotations
- Validation du format JSON
- Export au format standardisé
**Workflow d'annotation** :
1. Sélectionner un PDF du corpus
2. Extraire et afficher le texte page par page
3. Pour chaque PII identifié :
- Saisir le type (NOM, TEL, EMAIL, etc.)
- Saisir le texte exact
- Saisir le contexte (fenêtre de 50 caractères)
- Marquer comme obligatoire/optionnel
- Estimer la difficulté (easy/medium/hard)
4. Lister les termes médicaux à préserver
5. Sauvegarder l'annotation
---
### 2.2 Système d'Évaluation
#### 2.2.1 Évaluateur de Qualité
**Composant** : `quality_evaluator.py`
**Classes principales** :
```python
@dataclass
class EvaluationResult:
true_positives: int
false_positives: int
false_negatives: int
precision: float
recall: float
f1_score: float
missed_pii: List[Dict] # Faux négatifs détaillés
false_detections: List[Dict] # Faux positifs détaillés
by_type: Dict[str, Dict] # Métriques par type de PII
class QualityEvaluator:
def evaluate(self, pdf_path: Path, audit_path: Path) -> EvaluationResult
def compare(self, annotations: List, detected: List) -> tuple
def generate_report(self, results: List[EvaluationResult]) -> str
```
**Algorithme de comparaison** :
1. Charger les annotations manuelles (ground truth)
2. Charger l'audit généré (détections)
3. Normaliser les textes (lowercase, strip)
4. Créer des clés de comparaison : `(page, type, texte_normalisé)`
5. Calculer les intersections :
- TP = annotations ∩ détections
- FN = annotations - détections (PII manqués)
- FP = détections - annotations (sur-détection)
6. Calculer les métriques
7. Générer le rapport détaillé
---
#### 2.2.2 Scanner de Fuite
**Composant** : `leak_scanner.py`
**Classes principales** :
```python
@dataclass
class LeakReport:
is_safe: bool
leak_count: int
leaks: List[Dict]
severity_counts: Dict[str, int]
class LeakScanner:
def scan(self, anonymized_pdf: Path, original_audit: Path) -> LeakReport
def scan_text(self, text: str, original_pii: List) -> List[Dict]
def scan_metadata(self, pdf_path: Path) -> List[Dict]
```
**Algorithme de scan** :
1. Extraire le texte du PDF anonymisé
2. Charger les PII originaux depuis l'audit
3. Vérifier que les PII originaux ne sont plus présents
4. Détecter de nouveaux PII non masqués (regex + NER)
5. Scanner les métadonnées PDF
6. Classer les fuites par sévérité :
- CRITIQUE : PII original présent
- HAUTE : Nouveau PII détecté
- MOYENNE : Métadonnée suspecte
---
#### 2.2.3 Benchmark de Performance
**Composant** : `benchmark.py`
**Métriques collectées** :
- Temps de traitement (total, par page, par étape)
- Utilisation CPU (%)
- Utilisation RAM (MB)
- Métriques de qualité (Précision, Rappel, F1)
- Nombre de PII détectés par type
**Format de sortie** :
```json
{
"benchmark_date": "2024-01-15T10:30:00",
"system_info": {
"cpu": "Intel i7-9700K",
"ram_gb": 16,
"python_version": "3.12.0"
},
"results": [
{
"pdf_path": "OGC_257/FC14.pdf",
"processing_time_s": 12.5,
"time_per_page_s": 4.2,
"cpu_usage_percent": 85.3,
"ram_usage_mb": 1024,
"pii_detected": 45,
"quality_metrics": {
"precision": 0.98,
"recall": 0.995,
"f1_score": 0.987
}
}
],
"summary": {
"avg_time_per_doc": 15.2,
"avg_precision": 0.975,
"avg_recall": 0.992,
"avg_f1": 0.983
}
}
```
---
### 2.3 Détecteurs Améliorés
#### 2.3.1 Regex Améliorées
**Composant** : `improved_regex_detector.py`
**Améliorations par type** :
**A) Téléphones** :
```python
RE_TEL_IMPROVED = re.compile(
r"(?<!\d)"
r"(?:"
# Format international
r"(?:\+33|0033)\s*[1-9](?:[\s.\-]?\d){8}"
r"|"
# Format national
r"0[1-9](?:[\s.\-]?\d){8}"
r"|"
# Format fragmenté (max 3 espaces/retours entre groupes)
r"0[1-9][\s.\-]?\d{1,2}[\s.\-]?\d{1,2}[\s\n]{1,3}\d{1,2}[\s.\-]?\d{1,2}[\s.\-]?\d{1,2}"
r")"
r"(?!\d)",
re.MULTILINE
)
```
**B) Emails** :
```python
RE_EMAIL_IMPROVED = re.compile(
r"\b[A-Za-z0-9._%+-]+"
r"@"
r"(?:"
# Domaines médicaux
r"(?:chu|ch|aphp|ap-hm|hospices-civils|clinique|hopital|ehpad)"
r"[\w\-]*\.[a-z]{2,}"
r"|"
# Domaines génériques
r"[A-Za-z0-9.-]+\.[A-Za-z]{2,}"
r")\b",
re.IGNORECASE
)
```
**C) Adresses** :
```python
RE_ADRESSE_IMPROVED = re.compile(
r"\b"
r"(?:\d{1,4}\s*(?:bis|ter|quater|[A-Z])?\s*,?\s*)?"
r"(?:rue|avenue|boulevard|place|chemin|allée|impasse|route|"
r"résidence|lotissement|cité|hameau|quartier)\s+"
r"(?:de\s+(?:la\s+|l['']\s*|les\s+)?|du\s+|des\s+)?"
r"[A-ZÉÈÀÙÂÊÎÔÛa-zéèàùâêîôûäëïöüç\s\-']{2,}"
r"(?:\s*,?\s*(?:Bât(?:iment)?\.?\s*[A-Z0-9]+|Appt?\.?\s*\d+))?"
,
re.IGNORECASE
)
```
**Tests unitaires** :
- Minimum 20 cas de test par regex
- Cas positifs (doit matcher)
- Cas négatifs (ne doit pas matcher)
- Cas limites (formats rares)
---
#### 2.3.2 Détecteur Contextuel
**Composant** : `contextual_detector.py`
**Stratégie** :
1. Détecter les noms avec contexte fort (haute confiance)
2. Détecter les noms en MAJUSCULES (moyenne confiance)
3. Détecter les noms avec contexte faible (basse confiance)
4. Filtrer les faux positifs via stopwords médicaux
5. Dédupliquer et trier par confiance
**Patterns de contexte** :
```python
STRONG_CONTEXTS = [
r"(?:Dr\.?|Docteur|Pr\.?|Professeur)\s+{name}",
r"(?:Mme|Madame|M\.|Monsieur)\s+{name}",
r"Patient(?:e)?\s*:\s*{name}",
r"Nom\s*:\s*{name}",
r"(?:Rédigé|Validé|Signé)\s+par\s+{name}",
]
WEAK_CONTEXTS = [
r"{name}\s+a\s+(?:examiné|consulté|prescrit)",
r"(?:examen|consultation)\s+(?:de|par)\s+{name}",
]
```
**Niveau de confiance** :
- Contexte fort : 0.95
- MAJUSCULES (hors stopwords) : 0.80
- Contexte faible : 0.60
---
#### 2.3.3 Détecteur Hybride
**Composant** : `hybrid_detector.py`
**Architecture** :
```python
class HybridDetector:
def __init__(self):
self.regex_detector = ImprovedRegexDetector()
self.eds_pseudo = EdsPseudoManager()
self.camembert_ner = NerModelManager()
self.contextual_detector = ContextualDetector()
def detect(self, text: str, page: int) -> List[PiiHit]:
# Étape 1 : Regex (priorité haute)
hits = self.regex_detector.detect(text, page)
masked_text = self._mask_zones(text, hits)
# Étape 2 : EDS-Pseudo
if self.eds_pseudo.is_loaded():
eds_hits = self._detect_with_eds(masked_text, page)
hits.extend(eds_hits)
masked_text = self._mask_zones(masked_text, eds_hits)
# Étape 3 : CamemBERT-NER
if self.camembert_ner.is_loaded():
camembert_hits = self._detect_with_camembert(masked_text, page)
hits.extend(camembert_hits)
masked_text = self._mask_zones(masked_text, camembert_hits)
# Étape 4 : Contextuel
context_hits = self.contextual_detector.detect(masked_text, page)
hits.extend(context_hits)
# Fusion et dédoplication
return self._merge_hits(hits)
```
**Stratégie de fusion** :
- Dédupliquer par position (même zone = même PII)
- En cas de conflit de type, garder le plus spécifique
- Tracer la méthode de détection pour chaque PII
---
### 2.4 Validation Post-Anonymisation
**Composant** : `post_validation.py`
**Workflow** :
```python
def validate_anonymized_pdf(
anonymized_pdf: Path,
original_audit: Path,
strict_mode: bool = True
) -> ValidationResult:
# 1. Scanner les fuites
leak_report = leak_scanner.scan(anonymized_pdf, original_audit)
# 2. Vérifier la lisibilité
readability_score = check_readability(anonymized_pdf)
# 3. Générer le certificat
if leak_report.is_safe and readability_score > 0.7:
certificate = generate_certificate(anonymized_pdf)
return ValidationResult(
is_valid=True,
certificate=certificate,
leak_report=leak_report
)
else:
if strict_mode:
raise ValidationError("Document non conforme")
return ValidationResult(
is_valid=False,
leak_report=leak_report
)
```
**Certificat de conformité** :
```json
{
"certificate_id": "CERT-2024-01-15-001",
"pdf_path": "OGC_257/FC14.redacted_raster.pdf",
"validation_date": "2024-01-15T10:30:00",
"is_compliant": true,
"checks": {
"no_pii_leak": true,
"metadata_clean": true,
"readability_ok": true
},
"validator": "LeakScanner v2.0",
"signature": "sha256:abc123..."
}
```
---
### 2.5 Reporting
**Composant** : `quality_reporter.py`
**Rapport HTML** :
- Vue d'ensemble (métriques globales)
- Graphiques (répartition PII, évolution qualité)
- Tableau détaillé par document
- Liste des faux négatifs (si disponible)
- Liste des faux positifs (si disponible)
- Recommandations d'amélioration
**Template Jinja2** :
```html
<!DOCTYPE html>
<html>
<head>
<title>Rapport de Qualité - Anonymisation</title>
<style>/* CSS moderne */</style>
</head>
<body>
<h1>Rapport de Qualité d'Anonymisation</h1>
<section class="summary">
<h2>Vue d'Ensemble</h2>
<div class="metrics">
<div class="metric">
<span class="value">{{ precision|round(3) }}</span>
<span class="label">Précision</span>
</div>
<div class="metric">
<span class="value">{{ recall|round(3) }}</span>
<span class="label">Rappel</span>
</div>
<div class="metric">
<span class="value">{{ f1_score|round(3) }}</span>
<span class="label">F1-Score</span>
</div>
</div>
</section>
<!-- Graphiques, tableaux, etc. -->
</body>
</html>
```
---
## 3. Flux de Données
### 3.1 Flux d'Annotation
```
PDF réel → Extraction texte → Affichage CLI → Saisie annotations
→ Validation format → Sauvegarde JSON → Dataset annoté
```
### 3.2 Flux d'Évaluation
```
PDF + Annotations → Anonymisation → Audit généré
→ Comparaison → Calcul métriques → Rapport qualité
```
### 3.3 Flux de Validation
```
PDF anonymisé + Audit original → Scanner fuite → Vérification métadonnées
→ Check lisibilité → Certificat conformité (si OK)
```
---
## 4. Décisions Techniques
### 4.1 Choix d'Implémentation
**Langage** : Python 3.12 (existant)
**Bibliothèques** :
- `pytest` : Tests unitaires et de régression
- `pydantic` : Validation des données (annotations, config)
- `structlog` : Logging structuré
- `jinja2` : Génération rapports HTML
- `matplotlib` : Graphiques (léger, pas de dépendance JS)
**Format de données** :
- Annotations : JSON (lisible, éditable)
- Rapports : HTML + JSON (double export)
- Certificats : JSON signé (SHA256)
### 4.2 Optimisations Performance
**Accélération GPU** :
- Utiliser CUDA pour EDS-Pseudo et CamemBERT-NER
- Batch processing optimisé pour 12 GB VRAM
- Batch size dynamique selon la taille des documents
- Fallback CPU automatique si GPU indisponible
**Parallélisation CPU** :
- Traitement parallèle de plusieurs PDFs (ProcessPoolExecutor)
- Nombre de workers optimal : 8-12 (sur 16 cœurs / 32 threads)
- Répartition intelligente de la charge
**Mémoire** :
- Pas de contrainte mémoire (128 GB disponibles)
- Possibilité de charger plusieurs modèles simultanément
- Cache des résultats NER pour paragraphes identiques
**Optimisations supplémentaires** :
- Quantification ONNX des modèles NER (optionnel)
- Préchargement des modèles en mémoire
- Pipeline asynchrone (extraction → détection → redaction)
---
## 5. Interfaces et API
### 5.1 API d'Évaluation
```python
# Évaluer un document
evaluator = QualityEvaluator(ground_truth_dir)
result = evaluator.evaluate(pdf_path, audit_path)
# Évaluer un batch
results = evaluator.evaluate_batch(pdf_list, audit_list)
report = evaluator.generate_report(results)
```
### 5.2 API de Validation
```python
# Valider un document anonymisé
scanner = LeakScanner()
leak_report = scanner.scan(anonymized_pdf, original_audit)
if leak_report.is_safe:
print("✅ Document conforme")
else:
print(f"{leak_report.leak_count} fuites détectées")
```
### 5.3 API de Benchmark
```python
# Benchmarker le système
benchmark = Benchmark(test_data_dir)
results = benchmark.run()
benchmark.export_results("benchmark_results.json")
```
---
## 6. Configuration
### 6.1 Fichier de Configuration
**Fichier** : `config/quality_config.yml`
```yaml
evaluation:
ground_truth_dir: "tests/ground_truth"
min_documents: 30
confidence_thresholds:
regex: 1.0
eds_pseudo: 0.85
camembert: 0.90
contextual: 0.80
validation:
strict_mode: true
scan_metadata: true
readability_threshold: 0.7
detection:
enable_regex: true
enable_eds_pseudo: true
enable_camembert: true
enable_contextual: true
# Accélération GPU
gpu:
enabled: true
device: "cuda" # ou "cpu" pour fallback
batch_size: 16 # Ajuster selon VRAM disponible
max_vram_gb: 10 # Limite de VRAM (12 GB disponibles)
regex:
patterns: [EMAIL, TEL, NIR, IBAN, IPP, FINESS, RPPS, OGC, DATE, ADRESSE]
contextual:
strong_context_confidence: 0.95
uppercase_confidence: 0.80
weak_context_confidence: 0.60
performance:
max_workers: 8 # Traitement parallèle de PDFs (16 cœurs / 32 threads disponibles)
max_ram_gb: 32 # Limite RAM par processus (128 GB disponibles)
enable_cache: true
enable_gpu: true
reporting:
output_format: [html, json]
include_graphs: true
export_false_negatives: true
export_false_positives: true
```
---
## 7. Tests
### 7.1 Tests Unitaires
**Couverture** : ≥ 80% pour les composants critiques
**Tests par composant** :
- `test_regex_improved.py` : Tests exhaustifs des regex
- `test_contextual_detector.py` : Tests de détection contextuelle
- `test_hybrid_detector.py` : Tests d'intégration détecteurs
- `test_quality_evaluator.py` : Tests de calcul métriques
- `test_leak_scanner.py` : Tests de détection de fuites
### 7.2 Tests de Régression
**Suite de tests** : `tests/regression/`
**Workflow** :
1. Charger le dataset annoté (30+ documents)
2. Anonymiser chaque document
3. Évaluer la qualité
4. Vérifier que les métriques respectent les seuils :
- Rappel ≥ 99.5%
- Précision ≥ 97%
- F1-Score ≥ 0.98
5. Alerter si dégradation
**Exécution** :
```bash
pytest tests/regression/ --benchmark
```
---
## 8. Monitoring et Observabilité
### 8.1 Logging Structuré
```python
import structlog
logger = structlog.get_logger()
# Log avec contexte
logger.info("detection_started",
pdf_path=str(pdf_path),
page_count=page_count)
logger.info("pii_detected",
pii_type="NOM",
count=12,
method="eds_pseudo",
confidence=0.95)
```
### 8.2 Métriques Collectées
**Par document** :
- Temps de traitement
- Nombre de PII détectés par type
- Méthode de détection utilisée
- Métriques de qualité (si ground truth)
**Agrégées** :
- Temps moyen par document
- Répartition des PII par type
- Taux de faux positifs/négatifs
- Évolution des métriques dans le temps
---
## 9. Sécurité
### 9.1 Protection des Données
- Pas de logs contenant des PII
- Suppression sécurisée des fichiers temporaires
- Pas de transmission réseau
- Traitement local uniquement
### 9.2 Validation des Entrées
- Validation du format PDF (type MIME)
- Limite de taille (< 100 MB)
- Validation du format JSON (annotations)
- Sanitization des chemins (pas de path traversal)
---
## 10. Déploiement
### 10.1 Structure des Fichiers
```
anonymizer/
├── core/
│ ├── __init__.py
│ ├── pipeline.py (existant)
│ └── ...
├── detectors/
│ ├── __init__.py
│ ├── improved_regex.py (nouveau)
│ ├── contextual.py (nouveau)
│ └── hybrid.py (nouveau)
├── evaluation/
│ ├── __init__.py
│ ├── quality_evaluator.py (nouveau)
│ ├── leak_scanner.py (nouveau)
│ └── benchmark.py (nouveau)
├── tools/
│ ├── __init__.py
│ ├── annotation_tool.py (nouveau)
│ └── quality_reporter.py (nouveau)
└── tests/
├── unit/
├── regression/
└── ground_truth/ (nouveau)
```
### 10.2 Installation
```bash
# Installer les nouvelles dépendances
pip install pytest pytest-cov pydantic structlog jinja2 matplotlib
# Créer les répertoires
mkdir -p tests/ground_truth
mkdir -p reports/quality
# Copier la configuration
cp config/quality_config.yml.example config/quality_config.yml
```
---
## 11. Migration depuis la Version Actuelle
### 11.1 Compatibilité Ascendante
- ✅ API existante inchangée
- ✅ Format d'audit `.jsonl` inchangé
- ✅ Configuration YAML compatible
- ✅ Pas de breaking changes
### 11.2 Activation Progressive
**Phase 1** : Mesure (pas d'impact sur production)
- Créer le dataset annoté
- Implémenter l'évaluateur
- Mesurer la baseline
**Phase 2** : Amélioration (opt-in)
- Implémenter les détecteurs améliorés
- Activer via configuration
- Comparer avec baseline
**Phase 3** : Validation (opt-in)
- Implémenter le scanner de fuite
- Activer en mode non-bloquant
- Valider sur corpus complet
**Phase 4** : Production (opt-out)
- Activer par défaut
- Mode strict optionnel
- Monitoring continu
---
## 12. Livrables Techniques
1. **Code source** :
- `detectors/improved_regex.py`
- `detectors/contextual.py`
- `detectors/hybrid.py`
- `evaluation/quality_evaluator.py`
- `evaluation/leak_scanner.py`
- `evaluation/benchmark.py`
- `tools/annotation_tool.py`
- `tools/quality_reporter.py`
2. **Tests** :
- `tests/unit/test_*.py`
- `tests/regression/test_regression.py`
3. **Documentation** :
- `docs/annotation_guide.md`
- `docs/evaluation_guide.md`
- `docs/api_reference.md`
4. **Configuration** :
- `config/quality_config.yml`
5. **Templates** :
- `templates/quality_report.html`
6. **Dataset** :
- `tests/ground_truth/*.pdf`
- `tests/ground_truth/*.annotations.json`

View File

@@ -0,0 +1,408 @@
# Requirements - Optimisation de la Qualité d'Anonymisation
## 1. Contexte et Objectifs
### 1.1 Contexte Métier
Le système d'anonymisation de documents PDF médicaux doit garantir une conformité RGPD stricte tout en préservant la lisibilité des documents pour un usage médical (recherche, formation, archivage).
**Corpus de travail** :
- 59 dossiers OGC (Opération Gros Calibre) dans `/home/dom/Téléchargements/II-1 Ctrl_T2A_2025_CHCB_DocJustificatifs (1)/`
- 130 fichiers PDF déjà anonymisés avec audits `.audit.jsonl` dans le sous-dossier `anonymise/`
- Documents médicaux réels (comptes-rendus hospitaliers, dossiers patients)
### 1.2 Problématique Actuelle
Le système actuel combine **4 couches de détection** :
**1. Extraction multi-passes (5 méthodes)** :
- pdfplumber → pdfminer → PyMuPDF → docTR OCR → tesseract OCR
**2. Détection par regex** :
- EMAIL, TEL, NIR, IBAN, IPP, FINESS, RPPS, OGC, dates, adresses
- Patterns contextuels (Dr., Patient:, etc.)
- Extraction de champs structurés (Trackare)
**3. VLM (Vision Language Model)** :
- Ollama avec qwen2.5vl:7b pour analyse visuelle des PDF scannés
- Détecte 20+ catégories de PII visuellement (manuscrit, mal orienté)
- Matching flou pour identifiants numériques manuscrits
- Masquage total des pages manuscrites (< 100 mots OCR)
**4. NER (Named Entity Recognition)** :
- EDS-Pseudo (AP-HP, F1=0.97) via edsnlp - 13 labels
- Fallback CamemBERT-NER ONNX
- Appliqué sur le narratif après regex
**5. Consolidation globale** :
- Propagation des PII sur toutes les pages
- Détection de "noms compagnons" (mots adjacents)
- Rescan sélectif des PII critiques
**Problèmes identifiés** :
- Faux négatifs (PII non détectés) → Risque RGPD critique
- Faux positifs (termes médicaux masqués) → Documents illisibles
- Pas de métriques de qualité mesurables
- Pas de validation post-anonymisation
- Pas de ground truth pour évaluer les performances
- VLM peut halluciner sur pages manuscrites complexes
- Pas d'optimisation GPU pour le VLM (Ollama local)
### 1.3 Objectifs de Qualité
**Objectif principal** : Équilibre optimal entre rappel et précision
**Métriques cibles** :
- **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)
**Contraintes matérielles** :
- **CPU** : AMD Ryzen 9 9950X (16 cœurs / 32 threads) - Excellent pour parallélisation
- **RAM** : 128 GB - Aucune contrainte mémoire
- **GPU** : NVIDIA GeForce RTX 5070 (12 GB VRAM) - Accélération NER possible
- **CUDA** : PyTorch 2.10.0 avec CUDA disponible
- Temps de traitement cible : < 10 secondes par PDF (avec GPU)
---
## 2. Exigences Fonctionnelles
### 2.1 Création d'un Dataset de Test Annoté
**REQ-001 : Annotation Manuelle de Documents Réels**
- **Priorité** : CRITIQUE
- **Description** : Créer un corpus de test avec annotations manuelles des PII sur les documents réels existants
- **Critères d'acceptation** :
- Minimum 30 documents PDF annotés (représentatifs des 59 dossiers OGC)
- Annotations au format JSON structuré
- Chaque PII annoté avec : type, texte, page, bbox, contexte, criticité
- Distinction entre PII obligatoires (RGPD) et optionnels
- Termes médicaux à préserver explicitement listés
- **Contraintes** :
- Utiliser uniquement les documents réels du corpus existant
- Pas de données synthétiques ou mockées
- Annotations validées par au moins 2 personnes (inter-annotator agreement)
**REQ-002 : Structure du Dataset de Test**
- **Priorité** : CRITIQUE
- **Description** : Organiser le dataset de test de manière exploitable
- **Critères d'acceptation** :
```
tests/ground_truth/
├── pdf_001.pdf # PDF original
├── pdf_001.annotations.json # Annotations manuelles
├── pdf_002.pdf
├── pdf_002.annotations.json
└── ...
```
- Format d'annotation standardisé et documenté
- Métadonnées : difficulté, type de document, nombre de pages
- Répartition équilibrée : documents simples, moyens, complexes
---
### 2.2 Système d'Évaluation de la Qualité
**REQ-003 : Évaluateur Automatique**
- **Priorité** : CRITIQUE
- **Description** : Outil d'évaluation comparant les détections avec les annotations manuelles
- **Critères d'acceptation** :
- Calcul automatique de : Précision, Rappel, F1-Score
- Identification des faux négatifs (PII manqués) avec contexte
- Identification des faux positifs (sur-détection) avec contexte
- Rapport détaillé par type de PII (NOM, TEL, EMAIL, etc.)
- Rapport détaillé par document
- Export des résultats en JSON et HTML
**REQ-004 : Scanner de Fuite de PII**
- **Priorité** : CRITIQUE
- **Description** : Vérifier qu'aucun PII ne subsiste dans les PDF anonymisés
- **Critères d'acceptation** :
- Extraction du texte du PDF anonymisé (OCR si nécessaire)
- Détection de PII résiduels (regex + NER)
- Vérification que les PII originaux ne sont plus présents
- Scan des métadonnées PDF (author, creator, etc.)
- Rapport de fuite avec niveau de sévérité (CRITIQUE, HAUTE, MOYENNE)
- Validation : document sûr = 0 fuite détectée
**REQ-005 : Benchmark de Performance**
- **Priorité** : HAUTE
- **Description** : Mesurer les performances du système actuel et des améliorations
- **Critères d'acceptation** :
- Temps de traitement par document
- Temps de traitement par page
- Utilisation CPU/RAM
- Métriques de qualité (Précision, Rappel, F1)
- Comparaison avant/après optimisation
- Export des résultats en format tabulaire
---
### 2.3 Amélioration de la Détection
**REQ-006 : Amélioration des Regex**
- **Priorité** : HAUTE
- **Description** : Renforcer les regex pour réduire les faux négatifs
- **Critères d'acceptation** :
- Téléphones fragmentés sur plusieurs lignes détectés
- Emails avec domaines médicaux (chu-, aphp-, etc.) détectés
- Adresses avec compléments (Bât., Appt., etc.) détectées
- NIR avec espaces variables détectés
- Noms avec caractères spéciaux (O'Brien, D'Angelo, Müller) détectés
- Tests unitaires exhaustifs pour chaque regex (≥ 20 cas par pattern)
**REQ-007 : Détection Contextuelle Renforcée**
- **Priorité** : HAUTE
- **Description** : Améliorer la détection des noms par analyse contextuelle
- **Critères d'acceptation** :
- Détection des noms après "Dr.", "Pr.", "Patient:", etc.
- Détection des noms en MAJUSCULES (hors termes médicaux)
- Détection des noms dans les listes virgulées ("Dr. X, Y, DUPONT")
- Détection des noms du personnel ("Aide : Marie-Paule BORDABERRY")
- Filtrage des faux positifs via liste de stopwords médicaux enrichie
- Niveau de confiance associé à chaque détection
**REQ-008 : Approche Hybride Multi-Détecteurs**
- **Priorité** : HAUTE
- **Description** : Combiner plusieurs méthodes de détection en cascade
- **Critères d'acceptation** :
- Pipeline en 5 étapes : Regex → VLM (si scanné) → EDS-Pseudo → CamemBERT-NER → Contextuel
- Masquage progressif pour éviter les doublons
- Fusion intelligente des résultats (dédoplication, résolution de conflits)
- Traçabilité : chaque PII détecté indique la méthode de détection (REGEX, VLM, EDS, NER, CONTEXT)
- Configuration activable/désactivable par méthode
- VLM appliqué uniquement sur PDFs scannés (ocr_used=True)
- Gestion des pages manuscrites (masquage total si < 100 mots OCR)
---
### 2.4 Validation et Reporting
**REQ-009 : Validation Post-Anonymisation**
- **Priorité** : CRITIQUE
- **Description** : Valider automatiquement chaque document anonymisé
- **Critères d'acceptation** :
- Exécution automatique après chaque anonymisation
- Scan de fuite de PII (texte + métadonnées)
- Vérification de la lisibilité (pas trop de masquage)
- Génération d'un certificat de conformité si validation OK
- Blocage de la sortie si fuite détectée (mode strict)
**REQ-010 : Rapport de Qualité Détaillé**
- **Priorité** : HAUTE
- **Description** : Générer un rapport de qualité pour chaque batch traité
- **Critères d'acceptation** :
- Statistiques globales : nombre de documents, PII détectés, temps total
- Métriques de qualité : Précision, Rappel, F1-Score
- Liste des faux négatifs (si dataset annoté disponible)
- Liste des faux positifs (si dataset annoté disponible)
- Répartition des PII par type (graphique)
- Export HTML + JSON
---
### 2.5 Amélioration Continue
**REQ-011 : Tests de Régression Automatiques**
- **Priorité** : HAUTE
- **Description** : Suite de tests automatiques pour éviter les régressions
- **Critères d'acceptation** :
- Exécution sur le dataset de test annoté
- Vérification que les métriques ne se dégradent pas
- Alerte si Rappel < 99.5% ou Précision < 97%
- Intégration possible en CI/CD
- Temps d'exécution < 10 minutes
**REQ-013 : Optimisation et Validation du VLM**
- **Priorité** : HAUTE
- **Description** : Améliorer la fiabilité et les performances du VLM pour les PDF scannés
- **Critères d'acceptation** :
- Prompt VLM optimisé pour réduire les hallucinations
- Validation croisée VLM ↔ NER (rejeter si conflit majeur)
- Seuil de confiance configurable (défaut: 0.5)
- Gestion intelligente des pages manuscrites (seuil OCR configurable)
- Timeout configurable (défaut: 180s)
- Métriques spécifiques VLM : taux d'hallucination, temps par page
- Support GPU pour Ollama si disponible
- Fallback gracieux si Ollama indisponible
**REQ-014 : Amélioration du Matching Flou VLM**
- **Priorité** : MOYENNE
- **Description** : Améliorer le matching des identifiants numériques manuscrits détectés par le VLM
- **Critères d'acceptation** :
- Matching flou basé sur séquences de chiffres (ratio configurable, défaut: 0.7)
- Support des identifiants partiellement lisibles
- Validation par distance de Levenshtein pour les noms
- Tests unitaires avec identifiants manuscrits réels
---
## 3. Exigences Non-Fonctionnelles
### 3.1 Performance
**NFR-001 : Temps de Traitement**
- Temps de traitement : < 10 secondes par PDF (moyenne) avec GPU
- Temps de traitement : < 2 secondes par page avec GPU
- Temps de traitement : < 30 secondes par PDF en mode CPU-only (fallback)
- Pas de dégradation > 20% par rapport à la version actuelle
**NFR-002 : Utilisation des Ressources**
- Utilisation GPU : Accélération CUDA pour les modèles NER (EDS-Pseudo, CamemBERT)
- Utilisation RAM : < 32 GB par processus (128 GB disponibles)
- Utilisation VRAM : < 10 GB (12 GB disponibles sur RTX 5070)
- Support du traitement par lots (batch) avec parallélisation sur 16 cœurs CPU
- Traitement parallèle de plusieurs PDFs simultanément (jusqu'à 8 workers)
### 3.2 Maintenabilité
**NFR-003 : Code Qualité**
- Code modulaire et testable
- Couverture de tests : ≥ 80% pour les fonctions critiques
- Documentation des fonctions (docstrings)
- Type hints Python partout
**NFR-004 : Configuration**
- Configuration externalisée (YAML)
- Activation/désactivation des détecteurs par configuration
- Seuils de confiance configurables
- Pas de valeurs en dur dans le code
### 3.3 Sécurité et Conformité
**NFR-005 : Conformité RGPD**
- Aucun PII ne doit fuiter (rappel ≥ 99.5%)
- Traçabilité complète (audit trail)
- Validation post-anonymisation obligatoire
- Métadonnées PDF nettoyées
**NFR-006 : Sécurité des Données**
- Pas de transmission de données vers des services externes
- Traitement local uniquement
- Pas de logs contenant des PII
- Suppression sécurisée des fichiers temporaires
---
## 4. Critères de Succès
### 4.1 Critères Quantitatifs
**Métriques de qualité** :
- ✅ Rappel ≥ 99.5% sur le dataset de test
- ✅ Précision ≥ 97% sur le dataset de test
- ✅ F1-Score ≥ 0.98 sur le dataset de test
- ✅ Taux de documents sûrs ≥ 98%
**Métriques de performance** :
- ✅ Temps de traitement < 30s par PDF
- ✅ Utilisation RAM < 4 GB
- ✅ Pas de dégradation > 20% vs version actuelle
### 4.2 Critères Qualitatifs
- ✅ Dataset de test annoté créé (≥ 30 documents)
- ✅ Système d'évaluation automatique fonctionnel
- ✅ Scanner de fuite opérationnel
- ✅ Tests de régression en place
- ✅ Documentation complète
### 4.3 Validation Finale
**Test d'acceptation** :
1. Exécuter le système sur les 59 dossiers OGC complets
2. Valider que 0 fuite critique n'est détectée
3. Vérifier que les documents restent lisibles (validation manuelle sur échantillon)
4. Comparer les métriques avec la baseline actuelle
5. Validation par un expert médical (échantillon de 10 documents)
---
## 5. Contraintes et Risques
### 5.1 Contraintes
**Contraintes techniques** :
- GPU NVIDIA RTX 5070 avec CUDA disponible (accélération recommandée)
- Fallback CPU si GPU indisponible
- RAM abondante (128 GB) - pas de contrainte mémoire
- Pas de dépendances externes nécessitant internet en production
**Contraintes métier** :
- Utilisation de documents réels uniquement (pas de mocks)
- Conformité RGPD stricte
- Préservation de la lisibilité médicale
### 5.2 Risques
| Risque | Probabilité | Impact | Mitigation |
|--------|-------------|--------|------------|
| Annotation manuelle trop longue | HAUTE | MOYEN | Prioriser 30 documents représentatifs, automatiser partiellement |
| Faux négatifs résiduels | MOYENNE | CRITIQUE | Validation post-anonymisation obligatoire, scanner de fuite |
| Dégradation des performances | FAIBLE | MOYEN | Benchmark continu, optimisation GPU, parallélisation |
| Sur-masquage (trop de faux positifs) | MOYENNE | MOYEN | Enrichissement liste stopwords, validation manuelle échantillon |
| Saturation VRAM GPU | FAIBLE | FAIBLE | Batch sizing dynamique, fallback CPU si nécessaire |
---
## 6. Dépendances et Prérequis
### 6.1 Dépendances Techniques
**Existantes** :
- Python 3.12
- **VLM** : Ollama (qwen2.5vl:7b ou qwen3-vl:8b) - analyse visuelle
- **NER** : EDS-Pseudo (AP-HP/eds-pseudo-public) via edsnlp
- **NER fallback** : CamemBERT-NER (Jean-Baptiste/camembert-ner) ONNX
- **OCR** : docTR (deep learning) + tesseract (fallback)
- **PDF** : PyMuPDF, pdfplumber, pdfminer.six
- **Runtime** : ONNX Runtime, transformers, optimum
**Nouvelles** :
- `pytest` (tests)
- `pytest-cov` (couverture)
- `pydantic` (validation config)
- `structlog` (logging structuré)
- `jinja2` (rapports HTML)
- `matplotlib` ou `plotly` (graphiques)
### 6.2 Données Requises
- ✅ 59 dossiers OGC existants
- ✅ 130 fichiers anonymisés + audits existants
- ⏳ 30 documents annotés manuellement (à créer)
- ⏳ Liste enrichie de stopwords médicaux (à compléter)
---
## 7. Livrables Attendus
1. **Dataset de test annoté** (30+ documents)
2. **Système d'évaluation automatique** (évaluateur + scanner + benchmark)
3. **Détecteurs améliorés** (regex + contextuel + hybride)
4. **Suite de tests de régression**
5. **Rapports de qualité** (HTML + JSON)
6. **Documentation** (guide d'utilisation, guide d'annotation)
7. **Métriques de baseline** (avant optimisation)
8. **Métriques finales** (après optimisation)
---
## 8. Planning Indicatif
**Phase 1 - Mesure (2 semaines)** :
- Création dataset annoté (30 docs)
- Système d'évaluation
- Métriques baseline
**Phase 2 - Amélioration (3 semaines)** :
- Amélioration regex
- Détection contextuelle
- Approche hybride
**Phase 3 - Validation (1 semaine)** :
- Tests de régression
- Validation sur corpus complet
- Documentation
**Total** : 6 semaines

View File

@@ -0,0 +1,408 @@
# Tasks - Optimisation de la Qualité d'Anonymisation
## Phase 1 : Mesure et Baseline (2 semaines)
### 1.1 Création du Dataset de Test Annoté
- [ ] 1.1.1 Sélectionner 30 documents représentatifs des 59 dossiers OGC
- [ ] 1.1.1.1 Analyser la répartition des documents (types, complexité, taille)
- [ ] 1.1.1.2 Sélectionner 10 documents simples (1-2 pages, peu de PII)
- [ ] 1.1.1.3 Sélectionner 15 documents moyens (3-5 pages, PII variés)
- [ ] 1.1.1.4 Sélectionner 5 documents complexes (>5 pages, nombreux PII)
- [ ] 1.1.1.5 Copier les documents dans `tests/ground_truth/`
- [ ] 1.1.2 Créer l'outil d'annotation CLI
- [ ] 1.1.2.1 Créer `tools/annotation_tool.py`
- [ ] 1.1.2.2 Implémenter l'extraction et affichage du texte
- [ ] 1.1.2.3 Implémenter la saisie guidée des annotations
- [ ] 1.1.2.4 Implémenter la validation du format JSON
- [ ] 1.1.2.5 Implémenter l'export au format standardisé
- [ ] 1.1.2.6 Ajouter la documentation d'utilisation
- [ ] 1.1.3 Annoter les 30 documents sélectionnés
- [ ] 1.1.3.1 Annoter les 10 documents simples
- [ ] 1.1.3.2 Annoter les 15 documents moyens
- [ ] 1.1.3.3 Annoter les 5 documents complexes
- [ ] 1.1.3.4 Valider les annotations (double vérification)
- [ ] 1.1.3.5 Calculer les statistiques du dataset (PII par type, difficulté)
- [ ] 1.1.4 Enrichir la liste des stopwords médicaux
- [ ] 1.1.4.1 Extraire les termes médicaux des 30 documents annotés
- [ ] 1.1.4.2 Identifier les faux positifs actuels (termes masqués à tort)
- [ ] 1.1.4.3 Ajouter les nouveaux termes à `_MEDICAL_STOP_WORDS_SET`
- [ ] 1.1.4.4 Documenter les sources des stopwords
### 1.2 Système d'Évaluation de la Qualité
- [ ] 1.2.1 Implémenter l'évaluateur de qualité
- [ ] 1.2.1.1 Créer `evaluation/quality_evaluator.py`
- [ ] 1.2.1.2 Implémenter la classe `EvaluationResult` (dataclass)
- [ ] 1.2.1.3 Implémenter la classe `QualityEvaluator`
- [ ] 1.2.1.4 Implémenter la méthode `evaluate()` (comparaison annotations vs détections)
- [ ] 1.2.1.5 Implémenter le calcul des métriques (Précision, Rappel, F1)
- [ ] 1.2.1.6 Implémenter l'identification des faux négatifs
- [ ] 1.2.1.7 Implémenter l'identification des faux positifs
- [ ] 1.2.1.8 Implémenter la génération de rapport texte
- [ ] 1.2.1.9 Ajouter les tests unitaires
- [ ] 1.2.2 Implémenter le scanner de fuite
- [ ] 1.2.2.1 Créer `evaluation/leak_scanner.py`
- [ ] 1.2.2.2 Implémenter la classe `LeakReport` (dataclass)
- [ ] 1.2.2.3 Implémenter la classe `LeakScanner`
- [ ] 1.2.2.4 Implémenter `scan_text()` (détection PII résiduels)
- [ ] 1.2.2.5 Implémenter `scan_metadata()` (scan métadonnées PDF)
- [ ] 1.2.2.6 Implémenter la classification par sévérité
- [ ] 1.2.2.7 Implémenter la génération de rapport de fuite
- [ ] 1.2.2.8 Ajouter les tests unitaires
- [ ] 1.2.3 Implémenter le benchmark de performance
- [ ] 1.2.3.1 Créer `evaluation/benchmark.py`
- [ ] 1.2.3.2 Implémenter la collecte des métriques de temps
- [ ] 1.2.3.3 Implémenter la collecte des métriques CPU/RAM
- [ ] 1.2.3.4 Implémenter la collecte des métriques de qualité
- [ ] 1.2.3.5 Implémenter l'export JSON des résultats
- [ ] 1.2.3.6 Implémenter l'affichage tabulaire des résultats
- [ ] 1.2.3.7 Ajouter les tests unitaires
### 1.3 Mesure de la Baseline
- [ ] 1.3.1 Exécuter l'évaluation sur le dataset annoté
- [ ] 1.3.1.1 Anonymiser les 30 documents annotés avec le système actuel
- [ ] 1.3.1.2 Exécuter l'évaluateur sur les 30 documents
- [ ] 1.3.1.3 Générer le rapport de qualité baseline
- [ ] 1.3.1.4 Identifier les faux négatifs critiques
- [ ] 1.3.1.5 Identifier les faux positifs fréquents
- [ ] 1.3.2 Exécuter le benchmark de performance
- [ ] 1.3.2.1 Benchmarker le système actuel sur les 30 documents
- [ ] 1.3.2.2 Mesurer le temps de traitement moyen
- [ ] 1.3.2.3 Mesurer l'utilisation CPU/RAM
- [ ] 1.3.2.4 Exporter les résultats baseline
- [ ] 1.3.3 Analyser les résultats baseline
- [ ] 1.3.3.1 Analyser les types de PII manqués (faux négatifs)
- [ ] 1.3.3.2 Analyser les types de faux positifs
- [ ] 1.3.3.3 Identifier les patterns problématiques
- [ ] 1.3.3.4 Prioriser les améliorations à implémenter
- [ ] 1.3.3.5 Documenter les findings dans un rapport
---
## Phase 2 : Amélioration de la Détection (3 semaines)
### 2.1 Amélioration des Regex
- [ ] 2.1.1 Améliorer la détection des téléphones
- [ ] 2.1.1.1 Créer `detectors/improved_regex.py`
- [ ] 2.1.1.2 Implémenter `RE_TEL_IMPROVED` (formats fragmentés)
- [ ] 2.1.1.3 Ajouter 20+ tests unitaires pour les téléphones
- [ ] 2.1.1.4 Valider sur le dataset annoté
- [ ] 2.1.2 Améliorer la détection des emails
- [ ] 2.1.2.1 Implémenter `RE_EMAIL_IMPROVED` (domaines médicaux)
- [ ] 2.1.2.2 Ajouter 20+ tests unitaires pour les emails
- [ ] 2.1.2.3 Valider sur le dataset annoté
- [ ] 2.1.3 Améliorer la détection des adresses
- [ ] 2.1.3.1 Implémenter `RE_ADRESSE_IMPROVED` (compléments Bât., Appt.)
- [ ] 2.1.3.2 Ajouter 20+ tests unitaires pour les adresses
- [ ] 2.1.3.3 Valider sur le dataset annoté
- [ ] 2.1.4 Améliorer la détection des NIR
- [ ] 2.1.4.1 Implémenter `RE_NIR_IMPROVED` (espaces variables)
- [ ] 2.1.4.2 Ajouter 20+ tests unitaires pour les NIR
- [ ] 2.1.4.3 Valider sur le dataset annoté
- [ ] 2.1.5 Améliorer la détection des noms avec caractères spéciaux
- [ ] 2.1.5.1 Adapter les regex pour O'Brien, D'Angelo, Müller, etc.
- [ ] 2.1.5.2 Ajouter 20+ tests unitaires
- [ ] 2.1.5.3 Valider sur le dataset annoté
- [ ] 2.1.6 Intégrer les regex améliorées
- [ ] 2.1.6.1 Remplacer les regex dans `anonymizer_core_refactored_onnx.py`
- [ ] 2.1.6.2 Exécuter les tests de régression
- [ ] 2.1.6.3 Mesurer l'amélioration (Rappel, Précision)
### 2.2 Détection Contextuelle
- [ ] 2.2.1 Implémenter le détecteur contextuel
- [ ] 2.2.1.1 Créer `detectors/contextual.py`
- [ ] 2.2.1.2 Implémenter la classe `ContextualDetector`
- [ ] 2.2.1.3 Implémenter la détection avec contexte fort
- [ ] 2.2.1.4 Implémenter la détection des noms en MAJUSCULES
- [ ] 2.2.1.5 Implémenter la détection avec contexte faible
- [ ] 2.2.1.6 Implémenter le filtrage via stopwords médicaux
- [ ] 2.2.1.7 Implémenter la dédoplication et tri par confiance
- [ ] 2.2.1.8 Ajouter les tests unitaires
- [ ] 2.2.2 Valider le détecteur contextuel
- [ ] 2.2.2.1 Tester sur le dataset annoté
- [ ] 2.2.2.2 Mesurer le rappel (noms détectés)
- [ ] 2.2.2.3 Mesurer la précision (faux positifs)
- [ ] 2.2.2.4 Ajuster les seuils de confiance si nécessaire
### 2.3 Approche Hybride
- [ ] 2.3.1 Implémenter le détecteur hybride
- [ ] 2.3.1.1 Créer `detectors/hybrid.py`
- [ ] 2.3.1.2 Implémenter la classe `HybridDetector`
- [ ] 2.3.1.3 Implémenter le pipeline en 4 étapes (Regex → EDS → CamemBERT → Contextuel)
- [ ] 2.3.1.4 Implémenter le masquage progressif
- [ ] 2.3.1.5 Implémenter la fusion des résultats
- [ ] 2.3.1.6 Implémenter la traçabilité (méthode de détection)
- [ ] 2.3.1.7 Ajouter les tests d'intégration
- [ ] 2.3.2 Intégrer le détecteur hybride
- [ ] 2.3.2.1 Modifier `anonymizer_core_refactored_onnx.py` pour utiliser `HybridDetector`
- [ ] 2.3.2.2 Ajouter la configuration activable/désactivable par détecteur
- [ ] 2.3.2.3 Exécuter les tests de régression
- [ ] 2.3.2.4 Mesurer l'amélioration globale
- [ ] 2.3.3 Optimiser les performances avec GPU
- [ ] 2.3.3.1 Activer l'accélération CUDA pour EDS-Pseudo
- [ ] 2.3.3.2 Activer l'accélération CUDA pour CamemBERT-NER
- [ ] 2.3.3.3 Implémenter le batch processing optimisé pour GPU
- [ ] 2.3.3.4 Tester différentes tailles de batch (4, 8, 16, 32)
- [ ] 2.3.3.5 Mesurer l'utilisation VRAM et ajuster batch_size
- [ ] 2.3.3.6 Implémenter le fallback CPU automatique si GPU indisponible
- [ ] 2.3.3.7 Profiler le code (cProfile + CUDA profiler)
- [ ] 2.3.3.8 Identifier les goulots d'étranglement
- [ ] 2.3.3.9 Optimiser les parties critiques
- [ ] 2.3.3.10 Vérifier que le temps de traitement est < 10s/PDF avec GPU
- [ ] 2.3.4 Implémenter le traitement parallèle multi-PDF
- [ ] 2.3.4.1 Créer un gestionnaire de pool de workers (ProcessPoolExecutor)
- [ ] 2.3.4.2 Tester avec 4, 8, 12 workers (optimal sur 16 cœurs)
- [ ] 2.3.4.3 Implémenter la répartition de charge intelligente
- [ ] 2.3.4.4 Mesurer le speedup avec parallélisation
- [ ] 2.3.4.5 Gérer les conflits d'accès GPU entre workers
### 2.4 Configuration
- [ ] 2.4.1 Créer le fichier de configuration
- [ ] 2.4.1.1 Créer `config/quality_config.yml`
- [ ] 2.4.1.2 Définir les paramètres d'évaluation
- [ ] 2.4.1.3 Définir les paramètres de validation
- [ ] 2.4.1.4 Définir les paramètres de détection
- [ ] 2.4.1.5 Définir les paramètres GPU (device, batch_size, max_vram)
- [ ] 2.4.1.6 Définir les paramètres VLM (Ollama URL, model, timeout, confidence)
- [ ] 2.4.1.7 Définir les paramètres de performance (max_workers, parallélisation)
- [ ] 2.4.1.8 Définir les paramètres de reporting
- [ ] 2.4.2 Implémenter le chargement de configuration
- [ ] 2.4.2.1 Utiliser `pydantic` pour valider la configuration
- [ ] 2.4.2.2 Créer les modèles de configuration typés
- [ ] 2.4.2.3 Implémenter le chargement depuis YAML
- [ ] 2.4.2.4 Ajouter les tests de validation
### 2.5 Optimisation VLM
- [ ] 2.5.1 Améliorer le prompt VLM
- [ ] 2.5.1.1 Analyser les hallucinations actuelles du VLM
- [ ] 2.5.1.2 Créer un prompt plus précis avec exemples négatifs
- [ ] 2.5.1.3 Ajouter des instructions anti-hallucination
- [ ] 2.5.1.4 Tester sur échantillon de pages manuscrites
- [ ] 2.5.1.5 Mesurer le taux d'hallucination avant/après
- [ ] 2.5.2 Implémenter la validation croisée VLM ↔ NER
- [ ] 2.5.2.1 Créer `detectors/vlm_validator.py`
- [ ] 2.5.2.2 Implémenter la comparaison VLM vs NER
- [ ] 2.5.2.3 Définir les règles de résolution de conflits
- [ ] 2.5.2.4 Rejeter les détections VLM non confirmées (seuil configurable)
- [ ] 2.5.2.5 Logger les conflits pour analyse
- [ ] 2.5.2.6 Ajouter les tests unitaires
- [ ] 2.5.3 Optimiser les performances VLM
- [ ] 2.5.3.1 Vérifier si Ollama supporte GPU (CUDA)
- [ ] 2.5.3.2 Configurer Ollama pour utiliser le GPU si disponible
- [ ] 2.5.3.3 Mesurer le temps de traitement par page (baseline)
- [ ] 2.5.3.4 Optimiser la résolution d'image (trade-off qualité/vitesse)
- [ ] 2.5.3.5 Implémenter un cache des résultats VLM par hash d'image
- [ ] 2.5.3.6 Mesurer le speedup après optimisations
---
## Phase 3 : Validation et Reporting (1 semaine)
### 3.1 Validation Post-Anonymisation
- [ ] 3.1.1 Implémenter la validation post-anonymisation
- [ ] 3.1.1.1 Créer `core/post_validation.py`
- [ ] 3.1.1.2 Implémenter la fonction `validate_anonymized_pdf()`
- [ ] 3.1.1.3 Intégrer le scanner de fuite
- [ ] 3.1.1.4 Implémenter la vérification de lisibilité
- [ ] 3.1.1.5 Implémenter la génération de certificat
- [ ] 3.1.1.6 Implémenter le mode strict (blocage si fuite)
- [ ] 3.1.1.7 Ajouter les tests unitaires
- [ ] 3.1.2 Intégrer la validation dans le pipeline
- [ ] 3.1.2.1 Modifier `anonymizer_core_refactored_onnx.py` pour appeler la validation
- [ ] 3.1.2.2 Ajouter l'option `--validate` en CLI
- [ ] 3.1.2.3 Ajouter l'option dans la GUI
- [ ] 3.1.2.4 Tester sur le dataset annoté
### 3.2 Reporting
- [ ] 3.2.1 Créer le générateur de rapports
- [ ] 3.2.1.1 Créer `tools/quality_reporter.py`
- [ ] 3.2.1.2 Implémenter la classe `QualityReporter`
- [ ] 3.2.1.3 Créer le template HTML (`templates/quality_report.html`)
- [ ] 3.2.1.4 Implémenter la génération de graphiques (matplotlib)
- [ ] 3.2.1.5 Implémenter l'export JSON
- [ ] 3.2.1.6 Implémenter l'export HTML
- [ ] 3.2.1.7 Ajouter les tests unitaires
- [ ] 3.2.2 Générer les rapports de qualité
- [ ] 3.2.2.1 Générer le rapport baseline (avant optimisation)
- [ ] 3.2.2.2 Générer le rapport après optimisation
- [ ] 3.2.2.3 Créer un rapport comparatif (avant/après)
- [ ] 3.2.2.4 Exporter en HTML et JSON
### 3.3 Tests de Régression
- [ ] 3.3.1 Créer la suite de tests de régression
- [ ] 3.3.1.1 Créer `tests/regression/test_regression.py`
- [ ] 3.3.1.2 Implémenter le test de qualité (Rappel ≥ 99.5%, Précision ≥ 97%)
- [ ] 3.3.1.3 Implémenter le test de performance (temps < 30s/PDF)
- [ ] 3.3.1.4 Implémenter le test de non-régression (vs baseline)
- [ ] 3.3.1.5 Configurer pytest pour exécution automatique
- [ ] 3.3.2 Exécuter les tests de régression
- [ ] 3.3.2.1 Exécuter sur le dataset annoté complet
- [ ] 3.3.2.2 Vérifier que tous les tests passent
- [ ] 3.3.2.3 Corriger les régressions si nécessaire
### 3.4 Validation sur Corpus Complet
- [ ] 3.4.1 Exécuter sur les 59 dossiers OGC complets
- [ ] 3.4.1.1 Anonymiser les 130 fichiers avec le système optimisé
- [ ] 3.4.1.2 Exécuter le scanner de fuite sur tous les fichiers
- [ ] 3.4.1.3 Vérifier qu'aucune fuite critique n'est détectée
- [ ] 3.4.1.4 Générer le rapport de qualité global
- [ ] 3.4.2 Validation manuelle (échantillon)
- [ ] 3.4.2.1 Sélectionner 10 documents aléatoires
- [ ] 3.4.2.2 Vérifier manuellement la qualité d'anonymisation
- [ ] 3.4.2.3 Vérifier la lisibilité médicale
- [ ] 3.4.2.4 Documenter les observations
- [ ] 3.4.3 Comparer avec la baseline
- [ ] 3.4.3.1 Comparer les métriques de qualité (Rappel, Précision, F1)
- [ ] 3.4.3.2 Comparer les métriques de performance (temps, CPU, RAM)
- [ ] 3.4.3.3 Calculer le gain d'amélioration
- [ ] 3.4.3.4 Documenter les résultats
---
## Phase 4 : Documentation et Finalisation (3 jours)
### 4.1 Documentation
- [ ] 4.1.1 Créer le guide d'annotation
- [ ] 4.1.1.1 Créer `docs/annotation_guide.md`
- [ ] 4.1.1.2 Documenter le processus d'annotation
- [ ] 4.1.1.3 Documenter le format JSON
- [ ] 4.1.1.4 Ajouter des exemples
- [ ] 4.1.2 Créer le guide d'évaluation
- [ ] 4.1.2.1 Créer `docs/evaluation_guide.md`
- [ ] 4.1.2.2 Documenter l'utilisation de l'évaluateur
- [ ] 4.1.2.3 Documenter l'utilisation du scanner
- [ ] 4.1.2.4 Documenter l'utilisation du benchmark
- [ ] 4.1.2.5 Ajouter des exemples
- [ ] 4.1.3 Créer la référence API
- [ ] 4.1.3.1 Créer `docs/api_reference.md`
- [ ] 4.1.3.2 Documenter les classes principales
- [ ] 4.1.3.3 Documenter les méthodes publiques
- [ ] 4.1.3.4 Ajouter des exemples de code
- [ ] 4.1.4 Mettre à jour le README
- [ ] 4.1.4.1 Ajouter la section "Évaluation de la Qualité"
- [ ] 4.1.4.2 Ajouter les nouvelles dépendances
- [ ] 4.1.4.3 Ajouter les exemples d'utilisation
- [ ] 4.1.4.4 Ajouter les métriques de qualité
### 4.2 Finalisation
- [ ] 4.2.1 Revue de code
- [ ] 4.2.1.1 Vérifier la qualité du code (pylint, black, mypy)
- [ ] 4.2.1.2 Vérifier la couverture de tests (≥ 80%)
- [ ] 4.2.1.3 Vérifier la documentation (docstrings)
- [ ] 4.2.1.4 Corriger les problèmes identifiés
- [ ] 4.2.2 Préparer les livrables
- [ ] 4.2.2.1 Dataset annoté (30+ documents)
- [ ] 4.2.2.2 Code source (détecteurs + évaluation)
- [ ] 4.2.2.3 Tests (unitaires + régression)
- [ ] 4.2.2.4 Documentation (guides + API)
- [ ] 4.2.2.5 Rapports (baseline + optimisé + comparatif)
- [ ] 4.2.2.6 Configuration (`quality_config.yml`)
- [ ] 4.2.3 Validation finale
- [ ] 4.2.3.1 Vérifier que tous les critères de succès sont atteints
- [ ] 4.2.3.2 Vérifier que les métriques cibles sont atteintes (Rappel ≥ 99.5%, Précision ≥ 97%)
- [ ] 4.2.3.3 Vérifier que les performances sont acceptables (< 30s/PDF)
- [ ] 4.2.3.4 Obtenir la validation d'un expert médical (échantillon)
---
## Tâches Optionnelles (si temps disponible)
- [ ]* Implémenter un cache des résultats NER pour améliorer les performances
- [ ]* Implémenter la parallélisation du traitement par lots (déjà inclus dans Phase 2)
- [ ]* Créer une interface web pour l'annotation (alternative à la CLI)
- [ ]* Implémenter l'export des rapports en PDF
- [ ]* Créer un dashboard de monitoring (Grafana/Prometheus)
- [ ]* Implémenter l'analyse automatique des échecs (suggestions d'amélioration)
- [ ]* Fine-tuner EDS-Pseudo sur le dataset annoté
- [ ]* Implémenter un modèle ensemble (vote majoritaire)
- [ ]* Optimiser le batch size dynamiquement selon la VRAM disponible
- [ ]* Implémenter le préchargement asynchrone des modèles NER
- [ ]* Tester d'autres modèles VLM (Qwen3-VL 8B, LLaVA, etc.)
- [ ]* Implémenter un système de feedback utilisateur pour améliorer le VLM
- [ ]* Créer un mode "review" pour valider les détections VLM manuellement
---
## Dépendances entre Tâches
**Critiques** (bloquantes) :
- 1.1 (Dataset annoté) → 1.3 (Baseline) → 2.x (Amélioration) → 3.4 (Validation)
- 1.2.1 (Évaluateur) → 1.3.1 (Évaluation baseline)
- 1.2.2 (Scanner) → 3.1 (Validation post-anonymisation)
- 2.1 + 2.2 + 2.3 (Détecteurs) → 3.3 (Tests régression)
**Parallélisables** :
- 1.2.1 (Évaluateur) || 1.2.2 (Scanner) || 1.2.3 (Benchmark)
- 2.1.1 || 2.1.2 || 2.1.3 || 2.1.4 || 2.1.5 (Regex indépendantes)
- 4.1.1 || 4.1.2 || 4.1.3 (Documentation)
---
## Estimation de Charge
**Phase 1** : 10 jours (2 semaines)
- Annotation : 5 jours (30 docs × 1h = 30h)
- Évaluation : 3 jours
- Baseline : 2 jours
**Phase 2** : 15 jours (3 semaines)
- Regex : 5 jours
- Contextuel : 3 jours
- Hybride : 3 jours
- VLM optimization : 2 jours
- GPU optimization : 1 jour
- Config : 1 jour
**Phase 3** : 5 jours (1 semaine)
- Validation : 2 jours
- Reporting : 1 jour
- Tests régression : 1 jour
- Validation corpus : 1 jour
**Phase 4** : 3 jours
- Documentation : 2 jours
- Finalisation : 1 jour
**Total** : 33 jours (6.6 semaines) ≈ **7 semaines avec marge**