From 0067738df6bc217d7692c6bac313a93186f1d83d Mon Sep 17 00:00:00 2001 From: Domi31tls Date: Mon, 2 Mar 2026 09:52:49 +0100 Subject: [PATCH] =?UTF-8?q?spec:=20Architecture=20compl=C3=A8te=20avec=20V?= =?UTF-8?q?LM=20(5=20couches=20d=C3=A9tection)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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 --- .../.config.kiro | 7 + .../ARCHITECTURE_REELLE.md | 473 +++++++++ .../QUICKSTART.md | 571 +++++++++++ .../README.md | 151 +++ .../SUMMARY.md | 321 ++++++ .../design.md | 912 ++++++++++++++++++ .../requirements.md | 408 ++++++++ .../tasks.md | 408 ++++++++ 8 files changed, 3251 insertions(+) create mode 100644 .kiro/specs/anonymization-quality-optimization/.config.kiro create mode 100644 .kiro/specs/anonymization-quality-optimization/ARCHITECTURE_REELLE.md create mode 100644 .kiro/specs/anonymization-quality-optimization/QUICKSTART.md create mode 100644 .kiro/specs/anonymization-quality-optimization/README.md create mode 100644 .kiro/specs/anonymization-quality-optimization/SUMMARY.md create mode 100644 .kiro/specs/anonymization-quality-optimization/design.md create mode 100644 .kiro/specs/anonymization-quality-optimization/requirements.md create mode 100644 .kiro/specs/anonymization-quality-optimization/tasks.md diff --git a/.kiro/specs/anonymization-quality-optimization/.config.kiro b/.kiro/specs/anonymization-quality-optimization/.config.kiro new file mode 100644 index 0000000..a50c383 --- /dev/null +++ b/.kiro/specs/anonymization-quality-optimization/.config.kiro @@ -0,0 +1,7 @@ +{ + "specType": "feature", + "workflowType": "requirements-first", + "featureName": "anonymization-quality-optimization", + "createdAt": "2024-01-15T10:00:00Z", + "version": "1.0.0" +} diff --git a/.kiro/specs/anonymization-quality-optimization/ARCHITECTURE_REELLE.md b/.kiro/specs/anonymization-quality-optimization/ARCHITECTURE_REELLE.md new file mode 100644 index 0000000..f647a28 --- /dev/null +++ b/.kiro/specs/anonymization-quality-optimization/ARCHITECTURE_REELLE.md @@ -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. diff --git a/.kiro/specs/anonymization-quality-optimization/QUICKSTART.md b/.kiro/specs/anonymization-quality-optimization/QUICKSTART.md new file mode 100644 index 0000000..8dcc6d2 --- /dev/null +++ b/.kiro/specs/anonymization-quality-optimization/QUICKSTART.md @@ -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 ") + 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"(? 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 diff --git a/.kiro/specs/anonymization-quality-optimization/README.md b/.kiro/specs/anonymization-quality-optimization/README.md new file mode 100644 index 0000000..d06de30 --- /dev/null +++ b/.kiro/specs/anonymization-quality-optimization/README.md @@ -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 diff --git a/.kiro/specs/anonymization-quality-optimization/SUMMARY.md b/.kiro/specs/anonymization-quality-optimization/SUMMARY.md new file mode 100644 index 0000000..acd1605 --- /dev/null +++ b/.kiro/specs/anonymization-quality-optimization/SUMMARY.md @@ -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 ! diff --git a/.kiro/specs/anonymization-quality-optimization/design.md b/.kiro/specs/anonymization-quality-optimization/design.md new file mode 100644 index 0000000..39f6816 --- /dev/null +++ b/.kiro/specs/anonymization-quality-optimization/design.md @@ -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"(? 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 + + + + Rapport de Qualité - Anonymisation + + + +

Rapport de Qualité d'Anonymisation

+ +
+

Vue d'Ensemble

+
+
+ {{ precision|round(3) }} + Précision +
+
+ {{ recall|round(3) }} + Rappel +
+
+ {{ f1_score|round(3) }} + F1-Score +
+
+
+ + + + +``` + +--- + +## 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` diff --git a/.kiro/specs/anonymization-quality-optimization/requirements.md b/.kiro/specs/anonymization-quality-optimization/requirements.md new file mode 100644 index 0000000..ed78108 --- /dev/null +++ b/.kiro/specs/anonymization-quality-optimization/requirements.md @@ -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 diff --git a/.kiro/specs/anonymization-quality-optimization/tasks.md b/.kiro/specs/anonymization-quality-optimization/tasks.md new file mode 100644 index 0000000..3cf8f00 --- /dev/null +++ b/.kiro/specs/anonymization-quality-optimization/tasks.md @@ -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**