spec: Architecture complète avec VLM (5 couches détection)
- Ajout documentation VLM (Ollama qwen2.5vl:7b) - Pipeline complet: Regex → VLM → EDS-Pseudo → CamemBERT → Contextuel - Nouvelles exigences REQ-013/REQ-014 pour optimisation VLM - Tâches Phase 2.5: amélioration prompt, validation croisée, perf - Document ARCHITECTURE_REELLE.md avec détails complets - Matériel: AMD Ryzen 9 9950X, 128GB RAM, RTX 5070 12GB - Objectifs: Rappel ≥99.5%, Précision ≥97%, F1 ≥0.98
This commit is contained in:
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"specType": "feature",
|
||||||
|
"workflowType": "requirements-first",
|
||||||
|
"featureName": "anonymization-quality-optimization",
|
||||||
|
"createdAt": "2024-01-15T10:00:00Z",
|
||||||
|
"version": "1.0.0"
|
||||||
|
}
|
||||||
@@ -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.
|
||||||
571
.kiro/specs/anonymization-quality-optimization/QUICKSTART.md
Normal file
571
.kiro/specs/anonymization-quality-optimization/QUICKSTART.md
Normal file
@@ -0,0 +1,571 @@
|
|||||||
|
# Guide de Démarrage Rapide
|
||||||
|
|
||||||
|
## Installation des Dépendances
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Installer les nouvelles dépendances
|
||||||
|
pip install pytest pytest-cov pydantic structlog jinja2 matplotlib
|
||||||
|
|
||||||
|
# Vérifier l'installation
|
||||||
|
python -c "import pytest, pydantic, structlog, jinja2, matplotlib; print('✅ Toutes les dépendances sont installées')"
|
||||||
|
|
||||||
|
# Vérifier la disponibilité CUDA
|
||||||
|
python -c "import torch; print(f'CUDA disponible: {torch.cuda.is_available()}'); print(f'GPU: {torch.cuda.get_device_name(0) if torch.cuda.is_available() else \"N/A\"}')"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Préparation de l'Environnement
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Créer les répertoires nécessaires
|
||||||
|
mkdir -p tests/ground_truth
|
||||||
|
mkdir -p tests/unit
|
||||||
|
mkdir -p tests/regression
|
||||||
|
mkdir -p reports/quality
|
||||||
|
mkdir -p evaluation
|
||||||
|
mkdir -p detectors
|
||||||
|
mkdir -p tools
|
||||||
|
mkdir -p docs
|
||||||
|
mkdir -p config
|
||||||
|
|
||||||
|
# Vérifier la structure
|
||||||
|
tree -L 2 tests/ evaluation/ detectors/ tools/
|
||||||
|
```
|
||||||
|
|
||||||
|
## Phase 1 : Création du Dataset de Test
|
||||||
|
|
||||||
|
### Étape 1.1 : Sélectionner les Documents
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Aller dans le répertoire source
|
||||||
|
cd "/home/dom/Téléchargements/II-1 Ctrl_T2A_2025_CHCB_DocJustificatifs (1)/"
|
||||||
|
|
||||||
|
# Lister tous les PDFs
|
||||||
|
find . -name "*.pdf" -type f > /tmp/all_pdfs.txt
|
||||||
|
wc -l /tmp/all_pdfs.txt # Compter le nombre total
|
||||||
|
|
||||||
|
# Analyser la répartition par dossier OGC
|
||||||
|
for dir in */; do
|
||||||
|
count=$(find "$dir" -name "*.pdf" -type f | wc -l)
|
||||||
|
echo "$dir: $count PDFs"
|
||||||
|
done | sort -t: -k2 -n
|
||||||
|
|
||||||
|
# Sélectionner manuellement 30 documents :
|
||||||
|
# - 10 simples (1-2 pages, peu de PII)
|
||||||
|
# - 15 moyens (3-5 pages, PII variés)
|
||||||
|
# - 5 complexes (>5 pages, nombreux PII)
|
||||||
|
|
||||||
|
# Copier les documents sélectionnés
|
||||||
|
# Exemple :
|
||||||
|
cp "257_23209962/FC14.pdf" ~/path/to/project/tests/ground_truth/ogc_257_fc14.pdf
|
||||||
|
cp "257_23209962/FC16.pdf" ~/path/to/project/tests/ground_truth/ogc_257_fc16.pdf
|
||||||
|
# ... répéter pour les 30 documents
|
||||||
|
```
|
||||||
|
|
||||||
|
### Étape 1.2 : Créer l'Outil d'Annotation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Créer le fichier
|
||||||
|
cat > tools/annotation_tool.py << 'EOF'
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Outil d'annotation CLI pour créer le dataset de test.
|
||||||
|
Usage: python tools/annotation_tool.py tests/ground_truth/
|
||||||
|
"""
|
||||||
|
import json
|
||||||
|
from pathlib import Path
|
||||||
|
import sys
|
||||||
|
|
||||||
|
# TODO: Implémenter l'outil d'annotation
|
||||||
|
# Voir design.md section 2.1.2 pour les spécifications
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
if len(sys.argv) < 2:
|
||||||
|
print("Usage: python tools/annotation_tool.py <ground_truth_dir>")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
ground_truth_dir = Path(sys.argv[1])
|
||||||
|
print(f"Annotation des documents dans : {ground_truth_dir}")
|
||||||
|
# TODO: Implémenter la logique d'annotation
|
||||||
|
EOF
|
||||||
|
|
||||||
|
chmod +x tools/annotation_tool.py
|
||||||
|
```
|
||||||
|
|
||||||
|
### Étape 1.3 : Annoter les Documents
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Lancer l'outil d'annotation
|
||||||
|
python tools/annotation_tool.py tests/ground_truth/
|
||||||
|
|
||||||
|
# Pour chaque PDF, l'outil doit :
|
||||||
|
# 1. Extraire et afficher le texte
|
||||||
|
# 2. Demander de saisir les PII (type, texte, page, contexte)
|
||||||
|
# 3. Demander les termes médicaux à préserver
|
||||||
|
# 4. Sauvegarder en JSON
|
||||||
|
|
||||||
|
# Format de sortie attendu :
|
||||||
|
# tests/ground_truth/ogc_257_fc14.pdf
|
||||||
|
# tests/ground_truth/ogc_257_fc14.annotations.json
|
||||||
|
```
|
||||||
|
|
||||||
|
## Phase 2 : Implémentation de l'Évaluation
|
||||||
|
|
||||||
|
### Étape 2.1 : Créer l'Évaluateur de Qualité
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Créer le fichier
|
||||||
|
cat > evaluation/quality_evaluator.py << 'EOF'
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Évaluateur de qualité d'anonymisation.
|
||||||
|
Compare les détections avec les annotations manuelles.
|
||||||
|
"""
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import List, Dict
|
||||||
|
import json
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class EvaluationResult:
|
||||||
|
true_positives: int
|
||||||
|
false_positives: int
|
||||||
|
false_negatives: int
|
||||||
|
precision: float
|
||||||
|
recall: float
|
||||||
|
f1_score: float
|
||||||
|
missed_pii: List[Dict]
|
||||||
|
false_detections: List[Dict]
|
||||||
|
|
||||||
|
class QualityEvaluator:
|
||||||
|
def __init__(self, ground_truth_dir: Path):
|
||||||
|
self.ground_truth_dir = ground_truth_dir
|
||||||
|
|
||||||
|
def evaluate(self, pdf_path: Path, audit_path: Path) -> EvaluationResult:
|
||||||
|
# TODO: Implémenter l'évaluation
|
||||||
|
# Voir design.md section 2.2.1 pour les spécifications
|
||||||
|
pass
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# TODO: Ajouter CLI
|
||||||
|
pass
|
||||||
|
EOF
|
||||||
|
|
||||||
|
chmod +x evaluation/quality_evaluator.py
|
||||||
|
```
|
||||||
|
|
||||||
|
### Étape 2.2 : Créer le Scanner de Fuite
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Créer le fichier
|
||||||
|
cat > evaluation/leak_scanner.py << 'EOF'
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Scanner de fuite de PII dans les documents anonymisés.
|
||||||
|
"""
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import List, Dict
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class LeakReport:
|
||||||
|
is_safe: bool
|
||||||
|
leak_count: int
|
||||||
|
leaks: List[Dict]
|
||||||
|
|
||||||
|
class LeakScanner:
|
||||||
|
def scan(self, anonymized_pdf: Path, original_audit: Path) -> LeakReport:
|
||||||
|
# TODO: Implémenter le scan
|
||||||
|
# Voir design.md section 2.2.2 pour les spécifications
|
||||||
|
pass
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# TODO: Ajouter CLI
|
||||||
|
pass
|
||||||
|
EOF
|
||||||
|
|
||||||
|
chmod +x evaluation/leak_scanner.py
|
||||||
|
```
|
||||||
|
|
||||||
|
### Étape 2.3 : Créer le Benchmark
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Créer le fichier
|
||||||
|
cat > evaluation/benchmark.py << 'EOF'
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Benchmark de performance du système d'anonymisation.
|
||||||
|
"""
|
||||||
|
from pathlib import Path
|
||||||
|
import time
|
||||||
|
import json
|
||||||
|
|
||||||
|
class Benchmark:
|
||||||
|
def __init__(self, test_data_dir: Path):
|
||||||
|
self.test_data_dir = test_data_dir
|
||||||
|
|
||||||
|
def run(self) -> Dict:
|
||||||
|
# TODO: Implémenter le benchmark
|
||||||
|
# Voir design.md section 2.2.3 pour les spécifications
|
||||||
|
pass
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# TODO: Ajouter CLI
|
||||||
|
pass
|
||||||
|
EOF
|
||||||
|
|
||||||
|
chmod +x evaluation/benchmark.py
|
||||||
|
```
|
||||||
|
|
||||||
|
## Phase 3 : Mesure de la Baseline
|
||||||
|
|
||||||
|
### Étape 3.1 : Anonymiser les Documents de Test
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Option 1 : Via GUI
|
||||||
|
python Pseudonymisation_Gui_V5.py
|
||||||
|
# Sélectionner le dossier tests/ground_truth/
|
||||||
|
# Lancer l'anonymisation
|
||||||
|
|
||||||
|
# Option 2 : Via CLI (si disponible)
|
||||||
|
python anonymizer_core_refactored_onnx.py \
|
||||||
|
tests/ground_truth/*.pdf \
|
||||||
|
--output tests/ground_truth/anonymized/ \
|
||||||
|
--hf \
|
||||||
|
--raster
|
||||||
|
```
|
||||||
|
|
||||||
|
### Étape 3.2 : Évaluer la Baseline
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Évaluer chaque document
|
||||||
|
python evaluation/quality_evaluator.py \
|
||||||
|
--ground-truth tests/ground_truth/ \
|
||||||
|
--anonymized tests/ground_truth/anonymized/ \
|
||||||
|
--output reports/baseline_evaluation.json
|
||||||
|
|
||||||
|
# Générer le rapport HTML
|
||||||
|
python evaluation/quality_evaluator.py \
|
||||||
|
--ground-truth tests/ground_truth/ \
|
||||||
|
--anonymized tests/ground_truth/anonymized/ \
|
||||||
|
--output reports/baseline_report.html \
|
||||||
|
--format html
|
||||||
|
```
|
||||||
|
|
||||||
|
### Étape 3.3 : Scanner les Fuites
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Scanner tous les documents anonymisés
|
||||||
|
for pdf in tests/ground_truth/anonymized/*.pdf; do
|
||||||
|
audit="${pdf%.pdf}.audit.jsonl"
|
||||||
|
python evaluation/leak_scanner.py \
|
||||||
|
--anonymized "$pdf" \
|
||||||
|
--audit "$audit" \
|
||||||
|
--output "reports/leak_$(basename $pdf .pdf).json"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Générer un rapport consolidé
|
||||||
|
python evaluation/leak_scanner.py \
|
||||||
|
--batch tests/ground_truth/anonymized/ \
|
||||||
|
--output reports/leak_report.html
|
||||||
|
```
|
||||||
|
|
||||||
|
### Étape 3.4 : Benchmarker les Performances
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Exécuter le benchmark
|
||||||
|
python evaluation/benchmark.py \
|
||||||
|
--test-dir tests/ground_truth/ \
|
||||||
|
--iterations 3 \
|
||||||
|
--output reports/baseline_benchmark.json
|
||||||
|
|
||||||
|
# Afficher les résultats
|
||||||
|
python evaluation/benchmark.py \
|
||||||
|
--show reports/baseline_benchmark.json
|
||||||
|
```
|
||||||
|
|
||||||
|
## Phase 4 : Amélioration des Détecteurs
|
||||||
|
|
||||||
|
### Étape 4.1 : Créer les Regex Améliorées
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Créer le fichier
|
||||||
|
cat > detectors/improved_regex.py << 'EOF'
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Regex améliorées pour la détection de PII.
|
||||||
|
"""
|
||||||
|
import re
|
||||||
|
|
||||||
|
# Téléphone amélioré (formats fragmentés)
|
||||||
|
RE_TEL_IMPROVED = re.compile(
|
||||||
|
r"(?<!\d)"
|
||||||
|
r"(?:"
|
||||||
|
r"(?:\+33|0033)\s*[1-9](?:[\s.\-]?\d){8}"
|
||||||
|
r"|"
|
||||||
|
r"0[1-9](?:[\s.\-]?\d){8}"
|
||||||
|
r"|"
|
||||||
|
r"0[1-9][\s.\-]?\d{1,2}[\s.\-]?\d{1,2}[\s\n]{1,3}\d{1,2}[\s.\-]?\d{1,2}[\s.\-]?\d{1,2}"
|
||||||
|
r")"
|
||||||
|
r"(?!\d)",
|
||||||
|
re.MULTILINE
|
||||||
|
)
|
||||||
|
|
||||||
|
# Email amélioré (domaines médicaux)
|
||||||
|
RE_EMAIL_IMPROVED = re.compile(
|
||||||
|
r"\b[A-Za-z0-9._%+-]+"
|
||||||
|
r"@"
|
||||||
|
r"(?:"
|
||||||
|
r"(?:chu|ch|aphp|ap-hm|hospices-civils|clinique|hopital|ehpad)"
|
||||||
|
r"[\w\-]*\.[a-z]{2,}"
|
||||||
|
r"|"
|
||||||
|
r"[A-Za-z0-9.-]+\.[A-Za-z]{2,}"
|
||||||
|
r")\b",
|
||||||
|
re.IGNORECASE
|
||||||
|
)
|
||||||
|
|
||||||
|
# TODO: Ajouter les autres regex améliorées
|
||||||
|
# Voir design.md section 2.3.1 pour les spécifications
|
||||||
|
EOF
|
||||||
|
```
|
||||||
|
|
||||||
|
### Étape 4.2 : Créer le Détecteur Contextuel
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Créer le fichier
|
||||||
|
cat > detectors/contextual.py << 'EOF'
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Détecteur contextuel pour les noms de personnes.
|
||||||
|
"""
|
||||||
|
import re
|
||||||
|
from typing import List, Dict
|
||||||
|
|
||||||
|
class ContextualDetector:
|
||||||
|
def __init__(self):
|
||||||
|
self.strong_contexts = [
|
||||||
|
r"(?:Dr\.?|Docteur|Pr\.?|Professeur)\s+{name}",
|
||||||
|
r"(?:Mme|Madame|M\.|Monsieur)\s+{name}",
|
||||||
|
r"Patient(?:e)?\s*:\s*{name}",
|
||||||
|
]
|
||||||
|
|
||||||
|
def detect(self, text: str, page: int) -> List[Dict]:
|
||||||
|
# TODO: Implémenter la détection contextuelle
|
||||||
|
# Voir design.md section 2.3.2 pour les spécifications
|
||||||
|
pass
|
||||||
|
EOF
|
||||||
|
```
|
||||||
|
|
||||||
|
### Étape 4.3 : Créer le Détecteur Hybride
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Créer le fichier
|
||||||
|
cat > detectors/hybrid.py << 'EOF'
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Détecteur hybride combinant plusieurs méthodes.
|
||||||
|
"""
|
||||||
|
from typing import List, Dict
|
||||||
|
|
||||||
|
class HybridDetector:
|
||||||
|
def __init__(self):
|
||||||
|
# TODO: Initialiser les détecteurs
|
||||||
|
pass
|
||||||
|
|
||||||
|
def detect(self, text: str, page: int) -> List[Dict]:
|
||||||
|
# TODO: Implémenter le pipeline hybride
|
||||||
|
# Voir design.md section 2.3.3 pour les spécifications
|
||||||
|
pass
|
||||||
|
EOF
|
||||||
|
```
|
||||||
|
|
||||||
|
## Phase 5 : Tests et Validation
|
||||||
|
|
||||||
|
### Étape 5.1 : Créer les Tests Unitaires
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Créer les fichiers de test
|
||||||
|
mkdir -p tests/unit
|
||||||
|
|
||||||
|
# Tests des regex
|
||||||
|
cat > tests/unit/test_improved_regex.py << 'EOF'
|
||||||
|
import pytest
|
||||||
|
from detectors.improved_regex import RE_TEL_IMPROVED, RE_EMAIL_IMPROVED
|
||||||
|
|
||||||
|
class TestImprovedRegex:
|
||||||
|
@pytest.mark.parametrize("phone,should_match", [
|
||||||
|
("06 12 34 56 78", True),
|
||||||
|
("0612345678", True),
|
||||||
|
("06 12 34\n56 78", True),
|
||||||
|
("12345678901", False),
|
||||||
|
])
|
||||||
|
def test_phone_detection(self, phone, should_match):
|
||||||
|
match = RE_TEL_IMPROVED.search(phone)
|
||||||
|
assert (match is not None) == should_match
|
||||||
|
|
||||||
|
# TODO: Ajouter plus de tests
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Exécuter les tests
|
||||||
|
pytest tests/unit/ -v --cov=detectors
|
||||||
|
```
|
||||||
|
|
||||||
|
### Étape 5.2 : Créer les Tests de Régression
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Créer le fichier
|
||||||
|
cat > tests/regression/test_regression.py << 'EOF'
|
||||||
|
import pytest
|
||||||
|
from pathlib import Path
|
||||||
|
from evaluation.quality_evaluator import QualityEvaluator
|
||||||
|
|
||||||
|
class TestRegression:
|
||||||
|
def test_quality_metrics(self):
|
||||||
|
"""Vérifie que les métriques de qualité sont atteintes"""
|
||||||
|
evaluator = QualityEvaluator(Path("tests/ground_truth"))
|
||||||
|
# TODO: Implémenter le test
|
||||||
|
# Vérifier Rappel >= 99.5%, Précision >= 97%
|
||||||
|
pass
|
||||||
|
|
||||||
|
def test_no_performance_degradation(self):
|
||||||
|
"""Vérifie qu'il n'y a pas de dégradation de performance"""
|
||||||
|
# TODO: Implémenter le test
|
||||||
|
# Vérifier temps < 30s par PDF
|
||||||
|
pass
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Exécuter les tests de régression
|
||||||
|
pytest tests/regression/ -v
|
||||||
|
```
|
||||||
|
|
||||||
|
### Étape 5.3 : Valider sur le Corpus Complet
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Anonymiser tous les documents
|
||||||
|
python Pseudonymisation_Gui_V5.py
|
||||||
|
# Sélectionner : /home/dom/Téléchargements/II-1 Ctrl_T2A_2025_CHCB_DocJustificatifs (1)/
|
||||||
|
# Lancer l'anonymisation
|
||||||
|
|
||||||
|
# Scanner toutes les fuites
|
||||||
|
python evaluation/leak_scanner.py \
|
||||||
|
--batch "/home/dom/Téléchargements/II-1 Ctrl_T2A_2025_CHCB_DocJustificatifs (1)/anonymise/" \
|
||||||
|
--output reports/full_corpus_leak_report.html
|
||||||
|
|
||||||
|
# Vérifier qu'aucune fuite critique n'est détectée
|
||||||
|
grep -i "CRITIQUE" reports/full_corpus_leak_report.html
|
||||||
|
```
|
||||||
|
|
||||||
|
## Commandes Utiles
|
||||||
|
|
||||||
|
### Vérifier la Qualité du Code
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Linter
|
||||||
|
pylint detectors/ evaluation/ tools/
|
||||||
|
|
||||||
|
# Formatter
|
||||||
|
black detectors/ evaluation/ tools/
|
||||||
|
|
||||||
|
# Type checker
|
||||||
|
mypy detectors/ evaluation/ tools/
|
||||||
|
|
||||||
|
# Tout en une fois
|
||||||
|
pylint detectors/ && black --check detectors/ && mypy detectors/
|
||||||
|
```
|
||||||
|
|
||||||
|
### Générer la Documentation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Générer la doc API avec Sphinx (optionnel)
|
||||||
|
sphinx-apidoc -o docs/api detectors/ evaluation/ tools/
|
||||||
|
sphinx-build -b html docs/ docs/_build/
|
||||||
|
|
||||||
|
# Ou simplement documenter avec des docstrings
|
||||||
|
python -m pydoc detectors.hybrid
|
||||||
|
```
|
||||||
|
|
||||||
|
### Exporter les Résultats
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Exporter les métriques en CSV
|
||||||
|
python evaluation/quality_evaluator.py \
|
||||||
|
--ground-truth tests/ground_truth/ \
|
||||||
|
--output reports/metrics.csv \
|
||||||
|
--format csv
|
||||||
|
|
||||||
|
# Exporter les graphiques
|
||||||
|
python evaluation/quality_evaluator.py \
|
||||||
|
--ground-truth tests/ground_truth/ \
|
||||||
|
--output reports/charts/ \
|
||||||
|
--format charts
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Problème : Annotation trop longue
|
||||||
|
|
||||||
|
**Solution** : Paralléliser avec 2 annotateurs
|
||||||
|
```bash
|
||||||
|
# Annotateur 1 : documents 1-15
|
||||||
|
python tools/annotation_tool.py tests/ground_truth/ --range 1-15
|
||||||
|
|
||||||
|
# Annotateur 2 : documents 16-30
|
||||||
|
python tools/annotation_tool.py tests/ground_truth/ --range 16-30
|
||||||
|
```
|
||||||
|
|
||||||
|
### Problème : GPU non détecté
|
||||||
|
|
||||||
|
**Solution** : Vérifier l'installation CUDA
|
||||||
|
```bash
|
||||||
|
# Vérifier CUDA
|
||||||
|
nvidia-smi
|
||||||
|
|
||||||
|
# Vérifier PyTorch CUDA
|
||||||
|
python -c "import torch; print(torch.cuda.is_available())"
|
||||||
|
|
||||||
|
# Réinstaller PyTorch avec CUDA si nécessaire
|
||||||
|
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118
|
||||||
|
```
|
||||||
|
|
||||||
|
### Problème : VRAM insuffisante
|
||||||
|
|
||||||
|
**Solution** : Réduire la taille du batch
|
||||||
|
```yaml
|
||||||
|
# Dans config/quality_config.yml
|
||||||
|
gpu:
|
||||||
|
batch_size: 8 # Réduire de 16 à 8
|
||||||
|
max_vram_gb: 8 # Réduire la limite
|
||||||
|
```
|
||||||
|
|
||||||
|
### Problème : Traitement trop lent même avec GPU
|
||||||
|
|
||||||
|
**Solution** : Vérifier que le GPU est bien utilisé
|
||||||
|
```python
|
||||||
|
# Ajouter du logging dans le code
|
||||||
|
import torch
|
||||||
|
print(f"Device utilisé: {torch.cuda.get_device_name(0)}")
|
||||||
|
print(f"VRAM utilisée: {torch.cuda.memory_allocated() / 1e9:.2f} GB")
|
||||||
|
```
|
||||||
|
|
||||||
|
### Problème : Mémoire RAM insuffisante (peu probable avec 128 GB)
|
||||||
|
|
||||||
|
**Solution** : Réduire le nombre de workers
|
||||||
|
```yaml
|
||||||
|
# Dans config/quality_config.yml
|
||||||
|
performance:
|
||||||
|
max_workers: 4 # Réduire de 8 à 4
|
||||||
|
```
|
||||||
|
|
||||||
|
## Ressources
|
||||||
|
|
||||||
|
- **Documentation** : `docs/`
|
||||||
|
- **Spécifications** : `.kiro/specs/anonymization-quality-optimization/`
|
||||||
|
- **Tests** : `tests/`
|
||||||
|
- **Rapports** : `reports/`
|
||||||
|
|
||||||
|
## Support
|
||||||
|
|
||||||
|
Pour toute question :
|
||||||
|
1. Consulter `requirements.md` pour les exigences
|
||||||
|
2. Consulter `design.md` pour l'architecture
|
||||||
|
3. Consulter `tasks.md` pour le plan détaillé
|
||||||
|
4. Consulter `SUMMARY.md` pour le résumé exécutif
|
||||||
151
.kiro/specs/anonymization-quality-optimization/README.md
Normal file
151
.kiro/specs/anonymization-quality-optimization/README.md
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
# Spec : Optimisation de la Qualité d'Anonymisation
|
||||||
|
|
||||||
|
## Vue d'Ensemble
|
||||||
|
|
||||||
|
Cette spécification détaille le projet d'optimisation de la qualité d'anonymisation du système de pseudonymisation de documents PDF médicaux.
|
||||||
|
|
||||||
|
**Objectif** : Atteindre un équilibre optimal entre rappel (détection des PII) et précision (éviter les faux positifs) pour garantir la conformité RGPD tout en préservant la lisibilité médicale.
|
||||||
|
|
||||||
|
## Métriques Cibles
|
||||||
|
|
||||||
|
- **Rappel** : ≥ 99.5% (maximum 0.5% de PII manqués)
|
||||||
|
- **Précision** : ≥ 97% (maximum 3% de faux positifs)
|
||||||
|
- **F1-Score** : ≥ 0.98
|
||||||
|
- **Temps de traitement** : < 30 secondes par PDF
|
||||||
|
|
||||||
|
## Corpus de Travail
|
||||||
|
|
||||||
|
- **Source** : 59 dossiers OGC dans `/home/dom/Téléchargements/II-1 Ctrl_T2A_2025_CHCB_DocJustificatifs (1)/`
|
||||||
|
- **Sortie existante** : 130 fichiers anonymisés + audits dans `anonymise/`
|
||||||
|
- **Dataset de test** : 30 documents annotés manuellement (à créer)
|
||||||
|
|
||||||
|
## Contraintes
|
||||||
|
|
||||||
|
- ✅ Utilisation de documents réels uniquement (pas de mocks)
|
||||||
|
- ✅ CPU uniquement (pas de GPU)
|
||||||
|
- ✅ RAM limitée (< 4 GB par processus)
|
||||||
|
- ✅ Conformité RGPD stricte
|
||||||
|
|
||||||
|
## Structure de la Spec
|
||||||
|
|
||||||
|
1. **requirements.md** : Exigences fonctionnelles et non-fonctionnelles
|
||||||
|
2. **design.md** : Architecture technique et composants détaillés
|
||||||
|
3. **tasks.md** : Plan d'implémentation en 4 phases
|
||||||
|
|
||||||
|
## Phases du Projet
|
||||||
|
|
||||||
|
### Phase 1 : Mesure et Baseline (2 semaines)
|
||||||
|
- Création du dataset de test annoté (30 documents)
|
||||||
|
- Implémentation du système d'évaluation
|
||||||
|
- Mesure des performances actuelles
|
||||||
|
|
||||||
|
### Phase 2 : Amélioration de la Détection (3 semaines)
|
||||||
|
- Amélioration des regex (téléphones, emails, adresses, NIR)
|
||||||
|
- Implémentation de la détection contextuelle
|
||||||
|
- Approche hybride multi-détecteurs
|
||||||
|
|
||||||
|
### Phase 3 : Validation et Reporting (1 semaine)
|
||||||
|
- Validation post-anonymisation
|
||||||
|
- Génération de rapports de qualité
|
||||||
|
- Tests de régression automatiques
|
||||||
|
|
||||||
|
### Phase 4 : Documentation et Finalisation (3 jours)
|
||||||
|
- Documentation complète
|
||||||
|
- Validation finale sur corpus complet
|
||||||
|
- Livrables
|
||||||
|
|
||||||
|
## Livrables Attendus
|
||||||
|
|
||||||
|
1. Dataset de test annoté (30+ documents)
|
||||||
|
2. Système d'évaluation automatique
|
||||||
|
3. Détecteurs améliorés (regex + contextuel + hybride)
|
||||||
|
4. Suite de tests de régression
|
||||||
|
5. Rapports de qualité (HTML + JSON)
|
||||||
|
6. Documentation (guides + API)
|
||||||
|
7. Métriques baseline et finales
|
||||||
|
|
||||||
|
## Démarrage Rapide
|
||||||
|
|
||||||
|
### Prérequis
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Installer les dépendances
|
||||||
|
pip install pytest pytest-cov pydantic structlog jinja2 matplotlib
|
||||||
|
|
||||||
|
# Créer les répertoires
|
||||||
|
mkdir -p tests/ground_truth
|
||||||
|
mkdir -p reports/quality
|
||||||
|
```
|
||||||
|
|
||||||
|
### Étape 1 : Créer le Dataset Annoté
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Sélectionner 30 documents représentatifs
|
||||||
|
python tools/select_test_documents.py \
|
||||||
|
--source "/home/dom/Téléchargements/II-1 Ctrl_T2A_2025_CHCB_DocJustificatifs (1)/" \
|
||||||
|
--output tests/ground_truth/ \
|
||||||
|
--count 30
|
||||||
|
|
||||||
|
# Annoter les documents
|
||||||
|
python tools/annotation_tool.py tests/ground_truth/
|
||||||
|
```
|
||||||
|
|
||||||
|
### Étape 2 : Mesurer la Baseline
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Évaluer le système actuel
|
||||||
|
python evaluation/quality_evaluator.py \
|
||||||
|
--ground-truth tests/ground_truth/ \
|
||||||
|
--output reports/baseline_report.html
|
||||||
|
|
||||||
|
# Benchmarker les performances
|
||||||
|
python evaluation/benchmark.py \
|
||||||
|
--test-dir tests/ground_truth/ \
|
||||||
|
--output reports/baseline_benchmark.json
|
||||||
|
```
|
||||||
|
|
||||||
|
### Étape 3 : Implémenter les Améliorations
|
||||||
|
|
||||||
|
Suivre les tâches dans `tasks.md` phase par phase.
|
||||||
|
|
||||||
|
### Étape 4 : Valider
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Tests de régression
|
||||||
|
pytest tests/regression/ --benchmark
|
||||||
|
|
||||||
|
# Validation sur corpus complet
|
||||||
|
python scripts/validate_full_corpus.py \
|
||||||
|
--source "/home/dom/Téléchargements/II-1 Ctrl_T2A_2025_CHCB_DocJustificatifs (1)/" \
|
||||||
|
--output reports/final_validation.html
|
||||||
|
```
|
||||||
|
|
||||||
|
## Ressources
|
||||||
|
|
||||||
|
- **Documentation** : `docs/`
|
||||||
|
- **Tests** : `tests/`
|
||||||
|
- **Configuration** : `config/quality_config.yml`
|
||||||
|
- **Rapports** : `reports/`
|
||||||
|
|
||||||
|
## Contact
|
||||||
|
|
||||||
|
Pour toute question sur cette spécification, consulter les documents détaillés :
|
||||||
|
- `requirements.md` pour les exigences
|
||||||
|
- `design.md` pour l'architecture
|
||||||
|
- `tasks.md` pour le plan d'implémentation
|
||||||
|
|
||||||
|
## Statut
|
||||||
|
|
||||||
|
- [x] Requirements définis
|
||||||
|
- [x] Design validé
|
||||||
|
- [x] Tasks planifiées
|
||||||
|
- [ ] Implémentation en cours
|
||||||
|
- [ ] Tests validés
|
||||||
|
- [ ] Documentation complète
|
||||||
|
- [ ] Livraison finale
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Version** : 1.0.0
|
||||||
|
**Date de création** : 2024-01-15
|
||||||
|
**Dernière mise à jour** : 2024-01-15
|
||||||
321
.kiro/specs/anonymization-quality-optimization/SUMMARY.md
Normal file
321
.kiro/specs/anonymization-quality-optimization/SUMMARY.md
Normal file
@@ -0,0 +1,321 @@
|
|||||||
|
# Résumé Exécutif - Optimisation de la Qualité d'Anonymisation
|
||||||
|
|
||||||
|
## Contexte
|
||||||
|
|
||||||
|
Vous disposez d'un système d'anonymisation de documents PDF médicaux qui combine **4 couches de détection** :
|
||||||
|
|
||||||
|
**1. Extraction multi-passes** : pdfplumber → pdfminer → PyMuPDF → docTR OCR → tesseract
|
||||||
|
|
||||||
|
**2. Détection par regex** : EMAIL, TEL, NIR, IBAN, IPP, FINESS, RPPS, OGC, dates, adresses
|
||||||
|
|
||||||
|
**3. VLM (Vision Language Model)** : Ollama avec qwen2.5vl:7b pour analyse visuelle des PDF scannés
|
||||||
|
- Détecte 20+ catégories de PII visuellement (manuscrit, mal orienté)
|
||||||
|
- Matching flou pour identifiants numériques manuscrits
|
||||||
|
- Masquage total des pages manuscrites (< 100 mots OCR)
|
||||||
|
|
||||||
|
**4. NER** : EDS-Pseudo (AP-HP, F1=0.97) via edsnlp OU CamemBERT-NER ONNX
|
||||||
|
|
||||||
|
**5. Consolidation** : Propagation globale + extraction Trackare + rescan sélectif
|
||||||
|
|
||||||
|
**Corpus de travail** : 59 dossiers OGC (130 fichiers PDF) dans `/home/dom/Téléchargements/II-1 Ctrl_T2A_2025_CHCB_DocJustificatifs (1)/`
|
||||||
|
|
||||||
|
## Problématique
|
||||||
|
|
||||||
|
- ❌ Faux négatifs (PII non détectés) → Risque RGPD
|
||||||
|
- ❌ Faux positifs (termes médicaux masqués) → Documents illisibles
|
||||||
|
- ❌ VLM peut halluciner sur pages manuscrites complexes
|
||||||
|
- ❌ Pas de métriques de qualité mesurables
|
||||||
|
- ❌ Pas de validation post-anonymisation
|
||||||
|
- ❌ Pas d'optimisation GPU pour VLM (Ollama local)
|
||||||
|
|
||||||
|
## Objectifs
|
||||||
|
|
||||||
|
**Métriques cibles** :
|
||||||
|
- Rappel ≥ 99.5% (max 0.5% de PII manqués)
|
||||||
|
- Précision ≥ 97% (max 3% de faux positifs)
|
||||||
|
- F1-Score ≥ 0.98
|
||||||
|
- Temps < 10s par PDF (avec GPU)
|
||||||
|
|
||||||
|
**Matériel disponible** :
|
||||||
|
- CPU : AMD Ryzen 9 9950X (16 cœurs / 32 threads)
|
||||||
|
- RAM : 128 GB
|
||||||
|
- GPU : NVIDIA RTX 5070 (12 GB VRAM)
|
||||||
|
- CUDA : PyTorch 2.10.0 avec support CUDA
|
||||||
|
|
||||||
|
## Solution Proposée
|
||||||
|
|
||||||
|
### 1. Mesure (2 semaines)
|
||||||
|
|
||||||
|
**Créer un dataset de test annoté** :
|
||||||
|
- Sélectionner 30 documents représentatifs
|
||||||
|
- Annoter manuellement tous les PII
|
||||||
|
- Format JSON standardisé
|
||||||
|
|
||||||
|
**Implémenter l'évaluation** :
|
||||||
|
- Évaluateur de qualité (Précision, Rappel, F1)
|
||||||
|
- Scanner de fuite (détection PII résiduels)
|
||||||
|
- Benchmark de performance
|
||||||
|
|
||||||
|
**Mesurer la baseline** :
|
||||||
|
- Évaluer le système actuel
|
||||||
|
- Identifier les faux négatifs/positifs
|
||||||
|
- Benchmarker les performances
|
||||||
|
|
||||||
|
### 2. Amélioration (3 semaines)
|
||||||
|
|
||||||
|
**Regex améliorées** :
|
||||||
|
- Téléphones fragmentés : `06 12 34\n56 78`
|
||||||
|
- Emails médicaux : `nom@chu-bordeaux.fr`
|
||||||
|
- Adresses avec compléments : `12 rue X, Bât. B, Appt. 12`
|
||||||
|
- NIR avec espaces variables
|
||||||
|
- Noms avec caractères spéciaux : `O'Brien, Müller`
|
||||||
|
|
||||||
|
**Détection contextuelle** :
|
||||||
|
- Noms après "Dr.", "Patient:", etc.
|
||||||
|
- Noms en MAJUSCULES (hors stopwords médicaux)
|
||||||
|
- Filtrage des faux positifs
|
||||||
|
|
||||||
|
**Approche hybride** :
|
||||||
|
- Pipeline en 5 étapes : Regex → VLM (si scanné) → EDS-Pseudo → CamemBERT → Contextuel
|
||||||
|
- Masquage progressif (éviter doublons)
|
||||||
|
- Fusion intelligente des résultats
|
||||||
|
- Validation croisée VLM ↔ NER (anti-hallucination)
|
||||||
|
- Accélération GPU pour NER et optimisation VLM
|
||||||
|
- Traitement parallèle de plusieurs PDFs (8-12 workers)
|
||||||
|
|
||||||
|
### 3. Validation (1 semaine)
|
||||||
|
|
||||||
|
**Validation post-anonymisation** :
|
||||||
|
- Scanner automatique de fuite
|
||||||
|
- Vérification métadonnées PDF
|
||||||
|
- Certificat de conformité
|
||||||
|
|
||||||
|
**Tests de régression** :
|
||||||
|
- Suite automatique sur dataset annoté
|
||||||
|
- Alerte si dégradation des métriques
|
||||||
|
|
||||||
|
**Validation corpus complet** :
|
||||||
|
- Exécution sur les 59 dossiers OGC
|
||||||
|
- Vérification 0 fuite critique
|
||||||
|
- Validation manuelle (échantillon)
|
||||||
|
|
||||||
|
### 4. Documentation (3 jours)
|
||||||
|
|
||||||
|
- Guide d'annotation
|
||||||
|
- Guide d'évaluation
|
||||||
|
- Référence API
|
||||||
|
- Rapports de qualité
|
||||||
|
|
||||||
|
## Architecture Cible
|
||||||
|
|
||||||
|
```
|
||||||
|
PDF → Extraction texte → Détection Hybride → Consolidation → Redaction
|
||||||
|
(5 passes + GPU) ↓
|
||||||
|
Validation Post-Anonymisation
|
||||||
|
↓
|
||||||
|
Certificat de Conformité
|
||||||
|
```
|
||||||
|
|
||||||
|
**Détection Hybride** :
|
||||||
|
1. Regex améliorées (formats structurés)
|
||||||
|
2. VLM optimisé (Ollama qwen2.5vl:7b) - si PDF scanné
|
||||||
|
3. EDS-Pseudo (noms, contexte médical) - GPU accéléré
|
||||||
|
4. CamemBERT-NER (fallback) - GPU accéléré
|
||||||
|
5. Contextuel (patterns linguistiques)
|
||||||
|
|
||||||
|
**Optimisations Performance** :
|
||||||
|
- Accélération CUDA pour modèles NER
|
||||||
|
- Batch processing optimisé (12 GB VRAM)
|
||||||
|
- VLM avec prompt amélioré et validation croisée
|
||||||
|
- Traitement parallèle multi-PDF (16 cœurs)
|
||||||
|
- Temps cible : < 10s par PDF (textuel), < 30s (scanné avec VLM)
|
||||||
|
|
||||||
|
## Livrables
|
||||||
|
|
||||||
|
1. ✅ Dataset annoté (30+ documents)
|
||||||
|
2. ✅ Système d'évaluation (évaluateur + scanner + benchmark)
|
||||||
|
3. ✅ Détecteurs améliorés (regex + contextuel + hybride)
|
||||||
|
4. ✅ Tests de régression automatiques
|
||||||
|
5. ✅ Rapports de qualité (HTML + JSON)
|
||||||
|
6. ✅ Documentation complète
|
||||||
|
7. ✅ Métriques baseline et finales
|
||||||
|
|
||||||
|
## Planning
|
||||||
|
|
||||||
|
| Phase | Durée | Tâches Principales |
|
||||||
|
|-------|-------|-------------------|
|
||||||
|
| **Phase 1 : Mesure** | 2 semaines | Dataset annoté, Évaluation, Baseline |
|
||||||
|
| **Phase 2 : Amélioration** | 3 semaines | Regex, Contextuel, Hybride, GPU optimization |
|
||||||
|
| **Phase 3 : Validation** | 1 semaine | Post-validation, Tests, Corpus complet |
|
||||||
|
| **Phase 4 : Documentation** | 3 jours | Guides, API, Rapports |
|
||||||
|
| **Total** | **7 semaines** | |
|
||||||
|
|
||||||
|
## Prochaines Étapes
|
||||||
|
|
||||||
|
### Étape 1 : Sélectionner les Documents de Test
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Analyser le corpus
|
||||||
|
cd "/home/dom/Téléchargements/II-1 Ctrl_T2A_2025_CHCB_DocJustificatifs (1)/"
|
||||||
|
find . -name "*.pdf" | wc -l # Compter les PDFs
|
||||||
|
|
||||||
|
# Sélectionner 30 documents représentatifs
|
||||||
|
# - 10 simples (1-2 pages, peu de PII)
|
||||||
|
# - 15 moyens (3-5 pages, PII variés)
|
||||||
|
# - 5 complexes (>5 pages, nombreux PII)
|
||||||
|
|
||||||
|
# Copier dans tests/ground_truth/
|
||||||
|
mkdir -p tests/ground_truth
|
||||||
|
# Copier manuellement les 30 PDFs sélectionnés
|
||||||
|
```
|
||||||
|
|
||||||
|
### Étape 2 : Créer l'Outil d'Annotation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Créer le fichier
|
||||||
|
touch tools/annotation_tool.py
|
||||||
|
|
||||||
|
# Implémenter l'outil CLI pour annoter les PDFs
|
||||||
|
# (voir design.md section 2.1.2 pour les spécifications)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Étape 3 : Annoter les Documents
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Lancer l'outil d'annotation
|
||||||
|
python tools/annotation_tool.py tests/ground_truth/
|
||||||
|
|
||||||
|
# Pour chaque PDF :
|
||||||
|
# 1. Afficher le texte page par page
|
||||||
|
# 2. Saisir les PII (type, texte, contexte)
|
||||||
|
# 3. Lister les termes médicaux à préserver
|
||||||
|
# 4. Sauvegarder en JSON
|
||||||
|
```
|
||||||
|
|
||||||
|
### Étape 4 : Implémenter l'Évaluateur
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Créer le fichier
|
||||||
|
touch evaluation/quality_evaluator.py
|
||||||
|
|
||||||
|
# Implémenter :
|
||||||
|
# - Classe EvaluationResult
|
||||||
|
# - Classe QualityEvaluator
|
||||||
|
# - Méthode evaluate()
|
||||||
|
# - Calcul Précision/Rappel/F1
|
||||||
|
# - Génération de rapport
|
||||||
|
```
|
||||||
|
|
||||||
|
### Étape 5 : Mesurer la Baseline
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Anonymiser les 30 documents annotés
|
||||||
|
python Pseudonymisation_Gui_V5.py # Ou CLI
|
||||||
|
|
||||||
|
# Évaluer
|
||||||
|
python evaluation/quality_evaluator.py \
|
||||||
|
--ground-truth tests/ground_truth/ \
|
||||||
|
--output reports/baseline_report.html
|
||||||
|
|
||||||
|
# Analyser les résultats
|
||||||
|
# - Identifier les faux négatifs
|
||||||
|
# - Identifier les faux positifs
|
||||||
|
# - Prioriser les améliorations
|
||||||
|
```
|
||||||
|
|
||||||
|
## Points d'Attention
|
||||||
|
|
||||||
|
### Annotation Manuelle
|
||||||
|
|
||||||
|
⚠️ **Temps estimé** : 30 documents × 1h = 30 heures
|
||||||
|
- Prévoir 5 jours dédiés
|
||||||
|
- Possibilité de paralléliser (2 annotateurs)
|
||||||
|
- Validation croisée recommandée
|
||||||
|
|
||||||
|
### Optimisation GPU
|
||||||
|
|
||||||
|
✅ **Accélération disponible** : RTX 5070 avec 12 GB VRAM
|
||||||
|
- EDS-Pseudo et CamemBERT-NER peuvent utiliser CUDA
|
||||||
|
- Batch processing optimisé pour réduire le temps de traitement
|
||||||
|
- Objectif : < 10s par PDF (vs 30s en CPU-only)
|
||||||
|
- Fallback CPU automatique si GPU indisponible
|
||||||
|
|
||||||
|
### Traitement Parallèle
|
||||||
|
|
||||||
|
✅ **Puissance CPU** : 16 cœurs / 32 threads
|
||||||
|
- Traitement simultané de 8-12 PDFs
|
||||||
|
- Speedup significatif sur corpus complet
|
||||||
|
- Répartition de charge intelligente
|
||||||
|
|
||||||
|
### Faux Négatifs Critiques
|
||||||
|
|
||||||
|
⚠️ **Priorité RGPD** : 0 faux négatif = objectif
|
||||||
|
- Scanner de fuite obligatoire
|
||||||
|
- Validation post-anonymisation en mode strict
|
||||||
|
- Double vérification manuelle sur échantillon
|
||||||
|
|
||||||
|
### Faux Positifs Médicaux
|
||||||
|
|
||||||
|
⚠️ **Lisibilité** : Préserver les termes médicaux
|
||||||
|
- Enrichir la liste des stopwords
|
||||||
|
- Validation par expert médical
|
||||||
|
- Ajustement des seuils de confiance
|
||||||
|
|
||||||
|
## Critères de Succès
|
||||||
|
|
||||||
|
✅ **Qualité** :
|
||||||
|
- Rappel ≥ 99.5%
|
||||||
|
- Précision ≥ 97%
|
||||||
|
- F1-Score ≥ 0.98
|
||||||
|
- Taux de documents sûrs ≥ 98%
|
||||||
|
|
||||||
|
✅ **Performance** :
|
||||||
|
- Temps < 10s par PDF (avec GPU)
|
||||||
|
- Temps < 30s par PDF (fallback CPU)
|
||||||
|
- RAM < 32 GB par processus
|
||||||
|
- VRAM < 10 GB
|
||||||
|
- Pas de dégradation > 20% vs baseline
|
||||||
|
|
||||||
|
✅ **Livrables** :
|
||||||
|
- Dataset annoté créé
|
||||||
|
- Système d'évaluation fonctionnel
|
||||||
|
- Tests de régression en place
|
||||||
|
- Documentation complète
|
||||||
|
|
||||||
|
✅ **Validation** :
|
||||||
|
- 0 fuite critique sur corpus complet
|
||||||
|
- Validation expert médical (échantillon)
|
||||||
|
- Amélioration mesurable vs baseline
|
||||||
|
|
||||||
|
## Ressources
|
||||||
|
|
||||||
|
**Documentation** :
|
||||||
|
- `requirements.md` : Exigences détaillées
|
||||||
|
- `design.md` : Architecture technique
|
||||||
|
- `tasks.md` : Plan d'implémentation
|
||||||
|
- `README.md` : Vue d'ensemble
|
||||||
|
|
||||||
|
**Code** :
|
||||||
|
- `tools/annotation_tool.py` : Outil d'annotation
|
||||||
|
- `evaluation/quality_evaluator.py` : Évaluateur
|
||||||
|
- `evaluation/leak_scanner.py` : Scanner de fuite
|
||||||
|
- `detectors/improved_regex.py` : Regex améliorées
|
||||||
|
- `detectors/contextual.py` : Détection contextuelle
|
||||||
|
- `detectors/hybrid.py` : Approche hybride
|
||||||
|
|
||||||
|
**Tests** :
|
||||||
|
- `tests/unit/` : Tests unitaires
|
||||||
|
- `tests/regression/` : Tests de régression
|
||||||
|
- `tests/ground_truth/` : Dataset annoté
|
||||||
|
|
||||||
|
**Configuration** :
|
||||||
|
- `config/quality_config.yml` : Configuration qualité
|
||||||
|
|
||||||
|
**Rapports** :
|
||||||
|
- `reports/baseline_report.html` : Rapport baseline
|
||||||
|
- `reports/final_report.html` : Rapport final
|
||||||
|
- `reports/comparison.html` : Comparaison avant/après
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Prêt à démarrer ?** Commencez par la Phase 1 : Sélection et annotation des 30 documents de test !
|
||||||
912
.kiro/specs/anonymization-quality-optimization/design.md
Normal file
912
.kiro/specs/anonymization-quality-optimization/design.md
Normal file
@@ -0,0 +1,912 @@
|
|||||||
|
# Design - Optimisation de la Qualité d'Anonymisation
|
||||||
|
|
||||||
|
## 1. Vue d'Ensemble de l'Architecture
|
||||||
|
|
||||||
|
### 1.1 Architecture Actuelle (Baseline)
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ PDF d'entrée │
|
||||||
|
└────────────────────────┬────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ EXTRACTION DE TEXTE (5 passes) │
|
||||||
|
│ pdfplumber → pdfminer → PyMuPDF → docTR OCR → tesseract │
|
||||||
|
│ + OCR word map (coordonnées normalisées 0→1) │
|
||||||
|
└────────────────────────┬────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ DÉTECTION PII (4 couches) │
|
||||||
|
│ ├─ 1. Regex (EMAIL, TEL, NIR, IBAN, etc.) │
|
||||||
|
│ ├─ 2. VLM Ollama (qwen2.5vl:7b) — si PDF scanné │
|
||||||
|
│ │ • Analyse visuelle de chaque page (150 DPI) │
|
||||||
|
│ │ • 20+ catégories PII (manuscrit, mal orienté) │
|
||||||
|
│ │ • Masquage total si < 100 mots OCR │
|
||||||
|
│ ├─ 3. NER EDS-Pseudo (13 labels, F1=0.97) │
|
||||||
|
│ │ ou CamemBERT-NER ONNX (fallback) │
|
||||||
|
│ └─ 4. Extraction Trackare (champs structurés) │
|
||||||
|
└────────────────────────┬────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ CONSOLIDATION GLOBALE │
|
||||||
|
│ Propagation des PII sur toutes les pages │
|
||||||
|
│ + Noms compagnons + Rescan sélectif │
|
||||||
|
└────────────────────────┬────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ REDACTION PDF │
|
||||||
|
│ • Vector (PyMuPDF search_for) │
|
||||||
|
│ • Raster (OCR word map + matching flou pour VLM) │
|
||||||
|
│ Génération PDF raster + audit.jsonl │
|
||||||
|
└─────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
**Problèmes identifiés** :
|
||||||
|
- ❌ Pas de validation post-anonymisation
|
||||||
|
- ❌ Pas de métriques de qualité
|
||||||
|
- ❌ VLM peut halluciner (pages manuscrites complexes)
|
||||||
|
- ❌ Pas d'optimisation GPU pour VLM
|
||||||
|
- ❌ Pas de tests de régression
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 1.2 Architecture Cible (Optimisée)
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ PDF d'entrée │
|
||||||
|
└────────────────────────┬────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ EXTRACTION DE TEXTE (inchangé) │
|
||||||
|
└────────────────────────┬────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ DÉTECTION HYBRIDE (5 passes + améliorations) │
|
||||||
|
│ ├─ 1. Regex améliorées (formats structurés) │
|
||||||
|
│ ├─ 2. VLM optimisé (GPU, prompt amélioré, anti-hallucination) │
|
||||||
|
│ ├─ 3. EDS-Pseudo (noms, contexte médical) - GPU │
|
||||||
|
│ ├─ 4. CamemBERT-NER (fallback) - GPU │
|
||||||
|
│ └─ 5. Détection contextuelle renforcée │
|
||||||
|
│ │
|
||||||
|
│ → Masquage progressif pour éviter doublons │
|
||||||
|
│ → Fusion intelligente des résultats │
|
||||||
|
│ → Validation croisée VLM ↔ NER pour réduire hallucinations│
|
||||||
|
└────────────────────────┬────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ CONSOLIDATION GLOBALE (inchangé) │
|
||||||
|
└────────────────────────┬────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ REDACTION PDF │
|
||||||
|
└────────────────────────┬────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ VALIDATION POST-ANONYMISATION (NOUVEAU) │
|
||||||
|
│ ├─ Scanner de fuite PII │
|
||||||
|
│ ├─ Vérification métadonnées │
|
||||||
|
│ ├─ Détection hallucinations VLM (cross-check NER) │
|
||||||
|
│ └─ Certificat de conformité │
|
||||||
|
└────────────────────────┬────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ ÉVALUATION QUALITÉ (si ground truth disponible) │
|
||||||
|
│ ├─ Calcul Précision/Rappel/F1 par méthode │
|
||||||
|
│ ├─ Identification faux positifs/négatifs │
|
||||||
|
│ └─ Rapport de qualité │
|
||||||
|
└─────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Composants Détaillés
|
||||||
|
|
||||||
|
### 2.1 Dataset de Test Annoté
|
||||||
|
|
||||||
|
#### 2.1.1 Structure des Données
|
||||||
|
|
||||||
|
**Format d'annotation** :
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"pdf_path": "OGC_257/FC14.pdf",
|
||||||
|
"metadata": {
|
||||||
|
"annotator": "expert_1",
|
||||||
|
"annotation_date": "2024-01-15",
|
||||||
|
"document_type": "compte_rendu_hospitalier",
|
||||||
|
"page_count": 3,
|
||||||
|
"difficulty": "medium"
|
||||||
|
},
|
||||||
|
"annotations": [
|
||||||
|
{
|
||||||
|
"id": "ann_001",
|
||||||
|
"page": 1,
|
||||||
|
"type": "NOM",
|
||||||
|
"text": "DUPONT",
|
||||||
|
"bbox": [100.5, 200.3, 150.2, 220.8],
|
||||||
|
"context": "Dr. DUPONT a examiné le patient",
|
||||||
|
"mandatory": true,
|
||||||
|
"difficulty": "easy",
|
||||||
|
"detection_method_expected": ["regex", "ner", "contextual"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"medical_terms_to_preserve": [
|
||||||
|
"Médecin DIM",
|
||||||
|
"Service de cardiologie",
|
||||||
|
"Praticien conseil"
|
||||||
|
],
|
||||||
|
"statistics": {
|
||||||
|
"total_pii": 45,
|
||||||
|
"by_type": {
|
||||||
|
"NOM": 12,
|
||||||
|
"PRENOM": 8,
|
||||||
|
"TEL": 3,
|
||||||
|
"EMAIL": 2,
|
||||||
|
"DATE": 15,
|
||||||
|
"ADRESSE": 5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2.1.2 Outil d'Annotation
|
||||||
|
|
||||||
|
**Composant** : `annotation_tool.py`
|
||||||
|
|
||||||
|
**Fonctionnalités** :
|
||||||
|
- Interface CLI pour annoter les PDF
|
||||||
|
- Extraction automatique du texte + affichage
|
||||||
|
- Saisie guidée des annotations
|
||||||
|
- Validation du format JSON
|
||||||
|
- Export au format standardisé
|
||||||
|
|
||||||
|
**Workflow d'annotation** :
|
||||||
|
1. Sélectionner un PDF du corpus
|
||||||
|
2. Extraire et afficher le texte page par page
|
||||||
|
3. Pour chaque PII identifié :
|
||||||
|
- Saisir le type (NOM, TEL, EMAIL, etc.)
|
||||||
|
- Saisir le texte exact
|
||||||
|
- Saisir le contexte (fenêtre de 50 caractères)
|
||||||
|
- Marquer comme obligatoire/optionnel
|
||||||
|
- Estimer la difficulté (easy/medium/hard)
|
||||||
|
4. Lister les termes médicaux à préserver
|
||||||
|
5. Sauvegarder l'annotation
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 2.2 Système d'Évaluation
|
||||||
|
|
||||||
|
#### 2.2.1 Évaluateur de Qualité
|
||||||
|
|
||||||
|
**Composant** : `quality_evaluator.py`
|
||||||
|
|
||||||
|
**Classes principales** :
|
||||||
|
```python
|
||||||
|
@dataclass
|
||||||
|
class EvaluationResult:
|
||||||
|
true_positives: int
|
||||||
|
false_positives: int
|
||||||
|
false_negatives: int
|
||||||
|
precision: float
|
||||||
|
recall: float
|
||||||
|
f1_score: float
|
||||||
|
missed_pii: List[Dict] # Faux négatifs détaillés
|
||||||
|
false_detections: List[Dict] # Faux positifs détaillés
|
||||||
|
by_type: Dict[str, Dict] # Métriques par type de PII
|
||||||
|
|
||||||
|
class QualityEvaluator:
|
||||||
|
def evaluate(self, pdf_path: Path, audit_path: Path) -> EvaluationResult
|
||||||
|
def compare(self, annotations: List, detected: List) -> tuple
|
||||||
|
def generate_report(self, results: List[EvaluationResult]) -> str
|
||||||
|
```
|
||||||
|
|
||||||
|
**Algorithme de comparaison** :
|
||||||
|
1. Charger les annotations manuelles (ground truth)
|
||||||
|
2. Charger l'audit généré (détections)
|
||||||
|
3. Normaliser les textes (lowercase, strip)
|
||||||
|
4. Créer des clés de comparaison : `(page, type, texte_normalisé)`
|
||||||
|
5. Calculer les intersections :
|
||||||
|
- TP = annotations ∩ détections
|
||||||
|
- FN = annotations - détections (PII manqués)
|
||||||
|
- FP = détections - annotations (sur-détection)
|
||||||
|
6. Calculer les métriques
|
||||||
|
7. Générer le rapport détaillé
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### 2.2.2 Scanner de Fuite
|
||||||
|
|
||||||
|
**Composant** : `leak_scanner.py`
|
||||||
|
|
||||||
|
**Classes principales** :
|
||||||
|
```python
|
||||||
|
@dataclass
|
||||||
|
class LeakReport:
|
||||||
|
is_safe: bool
|
||||||
|
leak_count: int
|
||||||
|
leaks: List[Dict]
|
||||||
|
severity_counts: Dict[str, int]
|
||||||
|
|
||||||
|
class LeakScanner:
|
||||||
|
def scan(self, anonymized_pdf: Path, original_audit: Path) -> LeakReport
|
||||||
|
def scan_text(self, text: str, original_pii: List) -> List[Dict]
|
||||||
|
def scan_metadata(self, pdf_path: Path) -> List[Dict]
|
||||||
|
```
|
||||||
|
|
||||||
|
**Algorithme de scan** :
|
||||||
|
1. Extraire le texte du PDF anonymisé
|
||||||
|
2. Charger les PII originaux depuis l'audit
|
||||||
|
3. Vérifier que les PII originaux ne sont plus présents
|
||||||
|
4. Détecter de nouveaux PII non masqués (regex + NER)
|
||||||
|
5. Scanner les métadonnées PDF
|
||||||
|
6. Classer les fuites par sévérité :
|
||||||
|
- CRITIQUE : PII original présent
|
||||||
|
- HAUTE : Nouveau PII détecté
|
||||||
|
- MOYENNE : Métadonnée suspecte
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### 2.2.3 Benchmark de Performance
|
||||||
|
|
||||||
|
**Composant** : `benchmark.py`
|
||||||
|
|
||||||
|
**Métriques collectées** :
|
||||||
|
- Temps de traitement (total, par page, par étape)
|
||||||
|
- Utilisation CPU (%)
|
||||||
|
- Utilisation RAM (MB)
|
||||||
|
- Métriques de qualité (Précision, Rappel, F1)
|
||||||
|
- Nombre de PII détectés par type
|
||||||
|
|
||||||
|
**Format de sortie** :
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"benchmark_date": "2024-01-15T10:30:00",
|
||||||
|
"system_info": {
|
||||||
|
"cpu": "Intel i7-9700K",
|
||||||
|
"ram_gb": 16,
|
||||||
|
"python_version": "3.12.0"
|
||||||
|
},
|
||||||
|
"results": [
|
||||||
|
{
|
||||||
|
"pdf_path": "OGC_257/FC14.pdf",
|
||||||
|
"processing_time_s": 12.5,
|
||||||
|
"time_per_page_s": 4.2,
|
||||||
|
"cpu_usage_percent": 85.3,
|
||||||
|
"ram_usage_mb": 1024,
|
||||||
|
"pii_detected": 45,
|
||||||
|
"quality_metrics": {
|
||||||
|
"precision": 0.98,
|
||||||
|
"recall": 0.995,
|
||||||
|
"f1_score": 0.987
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"summary": {
|
||||||
|
"avg_time_per_doc": 15.2,
|
||||||
|
"avg_precision": 0.975,
|
||||||
|
"avg_recall": 0.992,
|
||||||
|
"avg_f1": 0.983
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 2.3 Détecteurs Améliorés
|
||||||
|
|
||||||
|
#### 2.3.1 Regex Améliorées
|
||||||
|
|
||||||
|
**Composant** : `improved_regex_detector.py`
|
||||||
|
|
||||||
|
**Améliorations par type** :
|
||||||
|
|
||||||
|
**A) Téléphones** :
|
||||||
|
```python
|
||||||
|
RE_TEL_IMPROVED = re.compile(
|
||||||
|
r"(?<!\d)"
|
||||||
|
r"(?:"
|
||||||
|
# Format international
|
||||||
|
r"(?:\+33|0033)\s*[1-9](?:[\s.\-]?\d){8}"
|
||||||
|
r"|"
|
||||||
|
# Format national
|
||||||
|
r"0[1-9](?:[\s.\-]?\d){8}"
|
||||||
|
r"|"
|
||||||
|
# Format fragmenté (max 3 espaces/retours entre groupes)
|
||||||
|
r"0[1-9][\s.\-]?\d{1,2}[\s.\-]?\d{1,2}[\s\n]{1,3}\d{1,2}[\s.\-]?\d{1,2}[\s.\-]?\d{1,2}"
|
||||||
|
r")"
|
||||||
|
r"(?!\d)",
|
||||||
|
re.MULTILINE
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
**B) Emails** :
|
||||||
|
```python
|
||||||
|
RE_EMAIL_IMPROVED = re.compile(
|
||||||
|
r"\b[A-Za-z0-9._%+-]+"
|
||||||
|
r"@"
|
||||||
|
r"(?:"
|
||||||
|
# Domaines médicaux
|
||||||
|
r"(?:chu|ch|aphp|ap-hm|hospices-civils|clinique|hopital|ehpad)"
|
||||||
|
r"[\w\-]*\.[a-z]{2,}"
|
||||||
|
r"|"
|
||||||
|
# Domaines génériques
|
||||||
|
r"[A-Za-z0-9.-]+\.[A-Za-z]{2,}"
|
||||||
|
r")\b",
|
||||||
|
re.IGNORECASE
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
**C) Adresses** :
|
||||||
|
```python
|
||||||
|
RE_ADRESSE_IMPROVED = re.compile(
|
||||||
|
r"\b"
|
||||||
|
r"(?:\d{1,4}\s*(?:bis|ter|quater|[A-Z])?\s*,?\s*)?"
|
||||||
|
r"(?:rue|avenue|boulevard|place|chemin|allée|impasse|route|"
|
||||||
|
r"résidence|lotissement|cité|hameau|quartier)\s+"
|
||||||
|
r"(?:de\s+(?:la\s+|l['']\s*|les\s+)?|du\s+|des\s+)?"
|
||||||
|
r"[A-ZÉÈÀÙÂÊÎÔÛa-zéèàùâêîôûäëïöüç\s\-']{2,}"
|
||||||
|
r"(?:\s*,?\s*(?:Bât(?:iment)?\.?\s*[A-Z0-9]+|Appt?\.?\s*\d+))?"
|
||||||
|
,
|
||||||
|
re.IGNORECASE
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Tests unitaires** :
|
||||||
|
- Minimum 20 cas de test par regex
|
||||||
|
- Cas positifs (doit matcher)
|
||||||
|
- Cas négatifs (ne doit pas matcher)
|
||||||
|
- Cas limites (formats rares)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### 2.3.2 Détecteur Contextuel
|
||||||
|
|
||||||
|
**Composant** : `contextual_detector.py`
|
||||||
|
|
||||||
|
**Stratégie** :
|
||||||
|
1. Détecter les noms avec contexte fort (haute confiance)
|
||||||
|
2. Détecter les noms en MAJUSCULES (moyenne confiance)
|
||||||
|
3. Détecter les noms avec contexte faible (basse confiance)
|
||||||
|
4. Filtrer les faux positifs via stopwords médicaux
|
||||||
|
5. Dédupliquer et trier par confiance
|
||||||
|
|
||||||
|
**Patterns de contexte** :
|
||||||
|
```python
|
||||||
|
STRONG_CONTEXTS = [
|
||||||
|
r"(?:Dr\.?|Docteur|Pr\.?|Professeur)\s+{name}",
|
||||||
|
r"(?:Mme|Madame|M\.|Monsieur)\s+{name}",
|
||||||
|
r"Patient(?:e)?\s*:\s*{name}",
|
||||||
|
r"Nom\s*:\s*{name}",
|
||||||
|
r"(?:Rédigé|Validé|Signé)\s+par\s+{name}",
|
||||||
|
]
|
||||||
|
|
||||||
|
WEAK_CONTEXTS = [
|
||||||
|
r"{name}\s+a\s+(?:examiné|consulté|prescrit)",
|
||||||
|
r"(?:examen|consultation)\s+(?:de|par)\s+{name}",
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
**Niveau de confiance** :
|
||||||
|
- Contexte fort : 0.95
|
||||||
|
- MAJUSCULES (hors stopwords) : 0.80
|
||||||
|
- Contexte faible : 0.60
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### 2.3.3 Détecteur Hybride
|
||||||
|
|
||||||
|
**Composant** : `hybrid_detector.py`
|
||||||
|
|
||||||
|
**Architecture** :
|
||||||
|
```python
|
||||||
|
class HybridDetector:
|
||||||
|
def __init__(self):
|
||||||
|
self.regex_detector = ImprovedRegexDetector()
|
||||||
|
self.eds_pseudo = EdsPseudoManager()
|
||||||
|
self.camembert_ner = NerModelManager()
|
||||||
|
self.contextual_detector = ContextualDetector()
|
||||||
|
|
||||||
|
def detect(self, text: str, page: int) -> List[PiiHit]:
|
||||||
|
# Étape 1 : Regex (priorité haute)
|
||||||
|
hits = self.regex_detector.detect(text, page)
|
||||||
|
masked_text = self._mask_zones(text, hits)
|
||||||
|
|
||||||
|
# Étape 2 : EDS-Pseudo
|
||||||
|
if self.eds_pseudo.is_loaded():
|
||||||
|
eds_hits = self._detect_with_eds(masked_text, page)
|
||||||
|
hits.extend(eds_hits)
|
||||||
|
masked_text = self._mask_zones(masked_text, eds_hits)
|
||||||
|
|
||||||
|
# Étape 3 : CamemBERT-NER
|
||||||
|
if self.camembert_ner.is_loaded():
|
||||||
|
camembert_hits = self._detect_with_camembert(masked_text, page)
|
||||||
|
hits.extend(camembert_hits)
|
||||||
|
masked_text = self._mask_zones(masked_text, camembert_hits)
|
||||||
|
|
||||||
|
# Étape 4 : Contextuel
|
||||||
|
context_hits = self.contextual_detector.detect(masked_text, page)
|
||||||
|
hits.extend(context_hits)
|
||||||
|
|
||||||
|
# Fusion et dédoplication
|
||||||
|
return self._merge_hits(hits)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Stratégie de fusion** :
|
||||||
|
- Dédupliquer par position (même zone = même PII)
|
||||||
|
- En cas de conflit de type, garder le plus spécifique
|
||||||
|
- Tracer la méthode de détection pour chaque PII
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 2.4 Validation Post-Anonymisation
|
||||||
|
|
||||||
|
**Composant** : `post_validation.py`
|
||||||
|
|
||||||
|
**Workflow** :
|
||||||
|
```python
|
||||||
|
def validate_anonymized_pdf(
|
||||||
|
anonymized_pdf: Path,
|
||||||
|
original_audit: Path,
|
||||||
|
strict_mode: bool = True
|
||||||
|
) -> ValidationResult:
|
||||||
|
# 1. Scanner les fuites
|
||||||
|
leak_report = leak_scanner.scan(anonymized_pdf, original_audit)
|
||||||
|
|
||||||
|
# 2. Vérifier la lisibilité
|
||||||
|
readability_score = check_readability(anonymized_pdf)
|
||||||
|
|
||||||
|
# 3. Générer le certificat
|
||||||
|
if leak_report.is_safe and readability_score > 0.7:
|
||||||
|
certificate = generate_certificate(anonymized_pdf)
|
||||||
|
return ValidationResult(
|
||||||
|
is_valid=True,
|
||||||
|
certificate=certificate,
|
||||||
|
leak_report=leak_report
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
if strict_mode:
|
||||||
|
raise ValidationError("Document non conforme")
|
||||||
|
return ValidationResult(
|
||||||
|
is_valid=False,
|
||||||
|
leak_report=leak_report
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Certificat de conformité** :
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"certificate_id": "CERT-2024-01-15-001",
|
||||||
|
"pdf_path": "OGC_257/FC14.redacted_raster.pdf",
|
||||||
|
"validation_date": "2024-01-15T10:30:00",
|
||||||
|
"is_compliant": true,
|
||||||
|
"checks": {
|
||||||
|
"no_pii_leak": true,
|
||||||
|
"metadata_clean": true,
|
||||||
|
"readability_ok": true
|
||||||
|
},
|
||||||
|
"validator": "LeakScanner v2.0",
|
||||||
|
"signature": "sha256:abc123..."
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 2.5 Reporting
|
||||||
|
|
||||||
|
**Composant** : `quality_reporter.py`
|
||||||
|
|
||||||
|
**Rapport HTML** :
|
||||||
|
- Vue d'ensemble (métriques globales)
|
||||||
|
- Graphiques (répartition PII, évolution qualité)
|
||||||
|
- Tableau détaillé par document
|
||||||
|
- Liste des faux négatifs (si disponible)
|
||||||
|
- Liste des faux positifs (si disponible)
|
||||||
|
- Recommandations d'amélioration
|
||||||
|
|
||||||
|
**Template Jinja2** :
|
||||||
|
```html
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Rapport de Qualité - Anonymisation</title>
|
||||||
|
<style>/* CSS moderne */</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Rapport de Qualité d'Anonymisation</h1>
|
||||||
|
|
||||||
|
<section class="summary">
|
||||||
|
<h2>Vue d'Ensemble</h2>
|
||||||
|
<div class="metrics">
|
||||||
|
<div class="metric">
|
||||||
|
<span class="value">{{ precision|round(3) }}</span>
|
||||||
|
<span class="label">Précision</span>
|
||||||
|
</div>
|
||||||
|
<div class="metric">
|
||||||
|
<span class="value">{{ recall|round(3) }}</span>
|
||||||
|
<span class="label">Rappel</span>
|
||||||
|
</div>
|
||||||
|
<div class="metric">
|
||||||
|
<span class="value">{{ f1_score|round(3) }}</span>
|
||||||
|
<span class="label">F1-Score</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- Graphiques, tableaux, etc. -->
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Flux de Données
|
||||||
|
|
||||||
|
### 3.1 Flux d'Annotation
|
||||||
|
|
||||||
|
```
|
||||||
|
PDF réel → Extraction texte → Affichage CLI → Saisie annotations
|
||||||
|
→ Validation format → Sauvegarde JSON → Dataset annoté
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.2 Flux d'Évaluation
|
||||||
|
|
||||||
|
```
|
||||||
|
PDF + Annotations → Anonymisation → Audit généré
|
||||||
|
→ Comparaison → Calcul métriques → Rapport qualité
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.3 Flux de Validation
|
||||||
|
|
||||||
|
```
|
||||||
|
PDF anonymisé + Audit original → Scanner fuite → Vérification métadonnées
|
||||||
|
→ Check lisibilité → Certificat conformité (si OK)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Décisions Techniques
|
||||||
|
|
||||||
|
### 4.1 Choix d'Implémentation
|
||||||
|
|
||||||
|
**Langage** : Python 3.12 (existant)
|
||||||
|
|
||||||
|
**Bibliothèques** :
|
||||||
|
- `pytest` : Tests unitaires et de régression
|
||||||
|
- `pydantic` : Validation des données (annotations, config)
|
||||||
|
- `structlog` : Logging structuré
|
||||||
|
- `jinja2` : Génération rapports HTML
|
||||||
|
- `matplotlib` : Graphiques (léger, pas de dépendance JS)
|
||||||
|
|
||||||
|
**Format de données** :
|
||||||
|
- Annotations : JSON (lisible, éditable)
|
||||||
|
- Rapports : HTML + JSON (double export)
|
||||||
|
- Certificats : JSON signé (SHA256)
|
||||||
|
|
||||||
|
### 4.2 Optimisations Performance
|
||||||
|
|
||||||
|
**Accélération GPU** :
|
||||||
|
- Utiliser CUDA pour EDS-Pseudo et CamemBERT-NER
|
||||||
|
- Batch processing optimisé pour 12 GB VRAM
|
||||||
|
- Batch size dynamique selon la taille des documents
|
||||||
|
- Fallback CPU automatique si GPU indisponible
|
||||||
|
|
||||||
|
**Parallélisation CPU** :
|
||||||
|
- Traitement parallèle de plusieurs PDFs (ProcessPoolExecutor)
|
||||||
|
- Nombre de workers optimal : 8-12 (sur 16 cœurs / 32 threads)
|
||||||
|
- Répartition intelligente de la charge
|
||||||
|
|
||||||
|
**Mémoire** :
|
||||||
|
- Pas de contrainte mémoire (128 GB disponibles)
|
||||||
|
- Possibilité de charger plusieurs modèles simultanément
|
||||||
|
- Cache des résultats NER pour paragraphes identiques
|
||||||
|
|
||||||
|
**Optimisations supplémentaires** :
|
||||||
|
- Quantification ONNX des modèles NER (optionnel)
|
||||||
|
- Préchargement des modèles en mémoire
|
||||||
|
- Pipeline asynchrone (extraction → détection → redaction)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Interfaces et API
|
||||||
|
|
||||||
|
### 5.1 API d'Évaluation
|
||||||
|
|
||||||
|
```python
|
||||||
|
# Évaluer un document
|
||||||
|
evaluator = QualityEvaluator(ground_truth_dir)
|
||||||
|
result = evaluator.evaluate(pdf_path, audit_path)
|
||||||
|
|
||||||
|
# Évaluer un batch
|
||||||
|
results = evaluator.evaluate_batch(pdf_list, audit_list)
|
||||||
|
report = evaluator.generate_report(results)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5.2 API de Validation
|
||||||
|
|
||||||
|
```python
|
||||||
|
# Valider un document anonymisé
|
||||||
|
scanner = LeakScanner()
|
||||||
|
leak_report = scanner.scan(anonymized_pdf, original_audit)
|
||||||
|
|
||||||
|
if leak_report.is_safe:
|
||||||
|
print("✅ Document conforme")
|
||||||
|
else:
|
||||||
|
print(f"❌ {leak_report.leak_count} fuites détectées")
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5.3 API de Benchmark
|
||||||
|
|
||||||
|
```python
|
||||||
|
# Benchmarker le système
|
||||||
|
benchmark = Benchmark(test_data_dir)
|
||||||
|
results = benchmark.run()
|
||||||
|
benchmark.export_results("benchmark_results.json")
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Configuration
|
||||||
|
|
||||||
|
### 6.1 Fichier de Configuration
|
||||||
|
|
||||||
|
**Fichier** : `config/quality_config.yml`
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
evaluation:
|
||||||
|
ground_truth_dir: "tests/ground_truth"
|
||||||
|
min_documents: 30
|
||||||
|
confidence_thresholds:
|
||||||
|
regex: 1.0
|
||||||
|
eds_pseudo: 0.85
|
||||||
|
camembert: 0.90
|
||||||
|
contextual: 0.80
|
||||||
|
|
||||||
|
validation:
|
||||||
|
strict_mode: true
|
||||||
|
scan_metadata: true
|
||||||
|
readability_threshold: 0.7
|
||||||
|
|
||||||
|
detection:
|
||||||
|
enable_regex: true
|
||||||
|
enable_eds_pseudo: true
|
||||||
|
enable_camembert: true
|
||||||
|
enable_contextual: true
|
||||||
|
|
||||||
|
# Accélération GPU
|
||||||
|
gpu:
|
||||||
|
enabled: true
|
||||||
|
device: "cuda" # ou "cpu" pour fallback
|
||||||
|
batch_size: 16 # Ajuster selon VRAM disponible
|
||||||
|
max_vram_gb: 10 # Limite de VRAM (12 GB disponibles)
|
||||||
|
|
||||||
|
regex:
|
||||||
|
patterns: [EMAIL, TEL, NIR, IBAN, IPP, FINESS, RPPS, OGC, DATE, ADRESSE]
|
||||||
|
|
||||||
|
contextual:
|
||||||
|
strong_context_confidence: 0.95
|
||||||
|
uppercase_confidence: 0.80
|
||||||
|
weak_context_confidence: 0.60
|
||||||
|
|
||||||
|
performance:
|
||||||
|
max_workers: 8 # Traitement parallèle de PDFs (16 cœurs / 32 threads disponibles)
|
||||||
|
max_ram_gb: 32 # Limite RAM par processus (128 GB disponibles)
|
||||||
|
enable_cache: true
|
||||||
|
enable_gpu: true
|
||||||
|
|
||||||
|
reporting:
|
||||||
|
output_format: [html, json]
|
||||||
|
include_graphs: true
|
||||||
|
export_false_negatives: true
|
||||||
|
export_false_positives: true
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Tests
|
||||||
|
|
||||||
|
### 7.1 Tests Unitaires
|
||||||
|
|
||||||
|
**Couverture** : ≥ 80% pour les composants critiques
|
||||||
|
|
||||||
|
**Tests par composant** :
|
||||||
|
- `test_regex_improved.py` : Tests exhaustifs des regex
|
||||||
|
- `test_contextual_detector.py` : Tests de détection contextuelle
|
||||||
|
- `test_hybrid_detector.py` : Tests d'intégration détecteurs
|
||||||
|
- `test_quality_evaluator.py` : Tests de calcul métriques
|
||||||
|
- `test_leak_scanner.py` : Tests de détection de fuites
|
||||||
|
|
||||||
|
### 7.2 Tests de Régression
|
||||||
|
|
||||||
|
**Suite de tests** : `tests/regression/`
|
||||||
|
|
||||||
|
**Workflow** :
|
||||||
|
1. Charger le dataset annoté (30+ documents)
|
||||||
|
2. Anonymiser chaque document
|
||||||
|
3. Évaluer la qualité
|
||||||
|
4. Vérifier que les métriques respectent les seuils :
|
||||||
|
- Rappel ≥ 99.5%
|
||||||
|
- Précision ≥ 97%
|
||||||
|
- F1-Score ≥ 0.98
|
||||||
|
5. Alerter si dégradation
|
||||||
|
|
||||||
|
**Exécution** :
|
||||||
|
```bash
|
||||||
|
pytest tests/regression/ --benchmark
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. Monitoring et Observabilité
|
||||||
|
|
||||||
|
### 8.1 Logging Structuré
|
||||||
|
|
||||||
|
```python
|
||||||
|
import structlog
|
||||||
|
|
||||||
|
logger = structlog.get_logger()
|
||||||
|
|
||||||
|
# Log avec contexte
|
||||||
|
logger.info("detection_started",
|
||||||
|
pdf_path=str(pdf_path),
|
||||||
|
page_count=page_count)
|
||||||
|
|
||||||
|
logger.info("pii_detected",
|
||||||
|
pii_type="NOM",
|
||||||
|
count=12,
|
||||||
|
method="eds_pseudo",
|
||||||
|
confidence=0.95)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 8.2 Métriques Collectées
|
||||||
|
|
||||||
|
**Par document** :
|
||||||
|
- Temps de traitement
|
||||||
|
- Nombre de PII détectés par type
|
||||||
|
- Méthode de détection utilisée
|
||||||
|
- Métriques de qualité (si ground truth)
|
||||||
|
|
||||||
|
**Agrégées** :
|
||||||
|
- Temps moyen par document
|
||||||
|
- Répartition des PII par type
|
||||||
|
- Taux de faux positifs/négatifs
|
||||||
|
- Évolution des métriques dans le temps
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. Sécurité
|
||||||
|
|
||||||
|
### 9.1 Protection des Données
|
||||||
|
|
||||||
|
- Pas de logs contenant des PII
|
||||||
|
- Suppression sécurisée des fichiers temporaires
|
||||||
|
- Pas de transmission réseau
|
||||||
|
- Traitement local uniquement
|
||||||
|
|
||||||
|
### 9.2 Validation des Entrées
|
||||||
|
|
||||||
|
- Validation du format PDF (type MIME)
|
||||||
|
- Limite de taille (< 100 MB)
|
||||||
|
- Validation du format JSON (annotations)
|
||||||
|
- Sanitization des chemins (pas de path traversal)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10. Déploiement
|
||||||
|
|
||||||
|
### 10.1 Structure des Fichiers
|
||||||
|
|
||||||
|
```
|
||||||
|
anonymizer/
|
||||||
|
├── core/
|
||||||
|
│ ├── __init__.py
|
||||||
|
│ ├── pipeline.py (existant)
|
||||||
|
│ └── ...
|
||||||
|
├── detectors/
|
||||||
|
│ ├── __init__.py
|
||||||
|
│ ├── improved_regex.py (nouveau)
|
||||||
|
│ ├── contextual.py (nouveau)
|
||||||
|
│ └── hybrid.py (nouveau)
|
||||||
|
├── evaluation/
|
||||||
|
│ ├── __init__.py
|
||||||
|
│ ├── quality_evaluator.py (nouveau)
|
||||||
|
│ ├── leak_scanner.py (nouveau)
|
||||||
|
│ └── benchmark.py (nouveau)
|
||||||
|
├── tools/
|
||||||
|
│ ├── __init__.py
|
||||||
|
│ ├── annotation_tool.py (nouveau)
|
||||||
|
│ └── quality_reporter.py (nouveau)
|
||||||
|
└── tests/
|
||||||
|
├── unit/
|
||||||
|
├── regression/
|
||||||
|
└── ground_truth/ (nouveau)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 10.2 Installation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Installer les nouvelles dépendances
|
||||||
|
pip install pytest pytest-cov pydantic structlog jinja2 matplotlib
|
||||||
|
|
||||||
|
# Créer les répertoires
|
||||||
|
mkdir -p tests/ground_truth
|
||||||
|
mkdir -p reports/quality
|
||||||
|
|
||||||
|
# Copier la configuration
|
||||||
|
cp config/quality_config.yml.example config/quality_config.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 11. Migration depuis la Version Actuelle
|
||||||
|
|
||||||
|
### 11.1 Compatibilité Ascendante
|
||||||
|
|
||||||
|
- ✅ API existante inchangée
|
||||||
|
- ✅ Format d'audit `.jsonl` inchangé
|
||||||
|
- ✅ Configuration YAML compatible
|
||||||
|
- ✅ Pas de breaking changes
|
||||||
|
|
||||||
|
### 11.2 Activation Progressive
|
||||||
|
|
||||||
|
**Phase 1** : Mesure (pas d'impact sur production)
|
||||||
|
- Créer le dataset annoté
|
||||||
|
- Implémenter l'évaluateur
|
||||||
|
- Mesurer la baseline
|
||||||
|
|
||||||
|
**Phase 2** : Amélioration (opt-in)
|
||||||
|
- Implémenter les détecteurs améliorés
|
||||||
|
- Activer via configuration
|
||||||
|
- Comparer avec baseline
|
||||||
|
|
||||||
|
**Phase 3** : Validation (opt-in)
|
||||||
|
- Implémenter le scanner de fuite
|
||||||
|
- Activer en mode non-bloquant
|
||||||
|
- Valider sur corpus complet
|
||||||
|
|
||||||
|
**Phase 4** : Production (opt-out)
|
||||||
|
- Activer par défaut
|
||||||
|
- Mode strict optionnel
|
||||||
|
- Monitoring continu
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 12. Livrables Techniques
|
||||||
|
|
||||||
|
1. **Code source** :
|
||||||
|
- `detectors/improved_regex.py`
|
||||||
|
- `detectors/contextual.py`
|
||||||
|
- `detectors/hybrid.py`
|
||||||
|
- `evaluation/quality_evaluator.py`
|
||||||
|
- `evaluation/leak_scanner.py`
|
||||||
|
- `evaluation/benchmark.py`
|
||||||
|
- `tools/annotation_tool.py`
|
||||||
|
- `tools/quality_reporter.py`
|
||||||
|
|
||||||
|
2. **Tests** :
|
||||||
|
- `tests/unit/test_*.py`
|
||||||
|
- `tests/regression/test_regression.py`
|
||||||
|
|
||||||
|
3. **Documentation** :
|
||||||
|
- `docs/annotation_guide.md`
|
||||||
|
- `docs/evaluation_guide.md`
|
||||||
|
- `docs/api_reference.md`
|
||||||
|
|
||||||
|
4. **Configuration** :
|
||||||
|
- `config/quality_config.yml`
|
||||||
|
|
||||||
|
5. **Templates** :
|
||||||
|
- `templates/quality_report.html`
|
||||||
|
|
||||||
|
6. **Dataset** :
|
||||||
|
- `tests/ground_truth/*.pdf`
|
||||||
|
- `tests/ground_truth/*.annotations.json`
|
||||||
408
.kiro/specs/anonymization-quality-optimization/requirements.md
Normal file
408
.kiro/specs/anonymization-quality-optimization/requirements.md
Normal file
@@ -0,0 +1,408 @@
|
|||||||
|
# Requirements - Optimisation de la Qualité d'Anonymisation
|
||||||
|
|
||||||
|
## 1. Contexte et Objectifs
|
||||||
|
|
||||||
|
### 1.1 Contexte Métier
|
||||||
|
Le système d'anonymisation de documents PDF médicaux doit garantir une conformité RGPD stricte tout en préservant la lisibilité des documents pour un usage médical (recherche, formation, archivage).
|
||||||
|
|
||||||
|
**Corpus de travail** :
|
||||||
|
- 59 dossiers OGC (Opération Gros Calibre) dans `/home/dom/Téléchargements/II-1 Ctrl_T2A_2025_CHCB_DocJustificatifs (1)/`
|
||||||
|
- 130 fichiers PDF déjà anonymisés avec audits `.audit.jsonl` dans le sous-dossier `anonymise/`
|
||||||
|
- Documents médicaux réels (comptes-rendus hospitaliers, dossiers patients)
|
||||||
|
|
||||||
|
### 1.2 Problématique Actuelle
|
||||||
|
Le système actuel combine **4 couches de détection** :
|
||||||
|
|
||||||
|
**1. Extraction multi-passes (5 méthodes)** :
|
||||||
|
- pdfplumber → pdfminer → PyMuPDF → docTR OCR → tesseract OCR
|
||||||
|
|
||||||
|
**2. Détection par regex** :
|
||||||
|
- EMAIL, TEL, NIR, IBAN, IPP, FINESS, RPPS, OGC, dates, adresses
|
||||||
|
- Patterns contextuels (Dr., Patient:, etc.)
|
||||||
|
- Extraction de champs structurés (Trackare)
|
||||||
|
|
||||||
|
**3. VLM (Vision Language Model)** :
|
||||||
|
- Ollama avec qwen2.5vl:7b pour analyse visuelle des PDF scannés
|
||||||
|
- Détecte 20+ catégories de PII visuellement (manuscrit, mal orienté)
|
||||||
|
- Matching flou pour identifiants numériques manuscrits
|
||||||
|
- Masquage total des pages manuscrites (< 100 mots OCR)
|
||||||
|
|
||||||
|
**4. NER (Named Entity Recognition)** :
|
||||||
|
- EDS-Pseudo (AP-HP, F1=0.97) via edsnlp - 13 labels
|
||||||
|
- Fallback CamemBERT-NER ONNX
|
||||||
|
- Appliqué sur le narratif après regex
|
||||||
|
|
||||||
|
**5. Consolidation globale** :
|
||||||
|
- Propagation des PII sur toutes les pages
|
||||||
|
- Détection de "noms compagnons" (mots adjacents)
|
||||||
|
- Rescan sélectif des PII critiques
|
||||||
|
|
||||||
|
**Problèmes identifiés** :
|
||||||
|
- Faux négatifs (PII non détectés) → Risque RGPD critique
|
||||||
|
- Faux positifs (termes médicaux masqués) → Documents illisibles
|
||||||
|
- Pas de métriques de qualité mesurables
|
||||||
|
- Pas de validation post-anonymisation
|
||||||
|
- Pas de ground truth pour évaluer les performances
|
||||||
|
- VLM peut halluciner sur pages manuscrites complexes
|
||||||
|
- Pas d'optimisation GPU pour le VLM (Ollama local)
|
||||||
|
|
||||||
|
### 1.3 Objectifs de Qualité
|
||||||
|
|
||||||
|
**Objectif principal** : Équilibre optimal entre rappel et précision
|
||||||
|
|
||||||
|
**Métriques cibles** :
|
||||||
|
- **Rappel (Recall)** : ≥ 99.5% (maximum 0.5% de PII manqués)
|
||||||
|
- **Précision (Precision)** : ≥ 97% (maximum 3% de faux positifs)
|
||||||
|
- **F1-Score** : ≥ 0.98
|
||||||
|
- **Taux de documents sûrs** : ≥ 98% (documents avec 0 faux négatif)
|
||||||
|
|
||||||
|
**Contraintes matérielles** :
|
||||||
|
- **CPU** : AMD Ryzen 9 9950X (16 cœurs / 32 threads) - Excellent pour parallélisation
|
||||||
|
- **RAM** : 128 GB - Aucune contrainte mémoire
|
||||||
|
- **GPU** : NVIDIA GeForce RTX 5070 (12 GB VRAM) - Accélération NER possible
|
||||||
|
- **CUDA** : PyTorch 2.10.0 avec CUDA disponible
|
||||||
|
- Temps de traitement cible : < 10 secondes par PDF (avec GPU)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Exigences Fonctionnelles
|
||||||
|
|
||||||
|
### 2.1 Création d'un Dataset de Test Annoté
|
||||||
|
|
||||||
|
**REQ-001 : Annotation Manuelle de Documents Réels**
|
||||||
|
- **Priorité** : CRITIQUE
|
||||||
|
- **Description** : Créer un corpus de test avec annotations manuelles des PII sur les documents réels existants
|
||||||
|
- **Critères d'acceptation** :
|
||||||
|
- Minimum 30 documents PDF annotés (représentatifs des 59 dossiers OGC)
|
||||||
|
- Annotations au format JSON structuré
|
||||||
|
- Chaque PII annoté avec : type, texte, page, bbox, contexte, criticité
|
||||||
|
- Distinction entre PII obligatoires (RGPD) et optionnels
|
||||||
|
- Termes médicaux à préserver explicitement listés
|
||||||
|
- **Contraintes** :
|
||||||
|
- Utiliser uniquement les documents réels du corpus existant
|
||||||
|
- Pas de données synthétiques ou mockées
|
||||||
|
- Annotations validées par au moins 2 personnes (inter-annotator agreement)
|
||||||
|
|
||||||
|
**REQ-002 : Structure du Dataset de Test**
|
||||||
|
- **Priorité** : CRITIQUE
|
||||||
|
- **Description** : Organiser le dataset de test de manière exploitable
|
||||||
|
- **Critères d'acceptation** :
|
||||||
|
```
|
||||||
|
tests/ground_truth/
|
||||||
|
├── pdf_001.pdf # PDF original
|
||||||
|
├── pdf_001.annotations.json # Annotations manuelles
|
||||||
|
├── pdf_002.pdf
|
||||||
|
├── pdf_002.annotations.json
|
||||||
|
└── ...
|
||||||
|
```
|
||||||
|
- Format d'annotation standardisé et documenté
|
||||||
|
- Métadonnées : difficulté, type de document, nombre de pages
|
||||||
|
- Répartition équilibrée : documents simples, moyens, complexes
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 2.2 Système d'Évaluation de la Qualité
|
||||||
|
|
||||||
|
**REQ-003 : Évaluateur Automatique**
|
||||||
|
- **Priorité** : CRITIQUE
|
||||||
|
- **Description** : Outil d'évaluation comparant les détections avec les annotations manuelles
|
||||||
|
- **Critères d'acceptation** :
|
||||||
|
- Calcul automatique de : Précision, Rappel, F1-Score
|
||||||
|
- Identification des faux négatifs (PII manqués) avec contexte
|
||||||
|
- Identification des faux positifs (sur-détection) avec contexte
|
||||||
|
- Rapport détaillé par type de PII (NOM, TEL, EMAIL, etc.)
|
||||||
|
- Rapport détaillé par document
|
||||||
|
- Export des résultats en JSON et HTML
|
||||||
|
|
||||||
|
**REQ-004 : Scanner de Fuite de PII**
|
||||||
|
- **Priorité** : CRITIQUE
|
||||||
|
- **Description** : Vérifier qu'aucun PII ne subsiste dans les PDF anonymisés
|
||||||
|
- **Critères d'acceptation** :
|
||||||
|
- Extraction du texte du PDF anonymisé (OCR si nécessaire)
|
||||||
|
- Détection de PII résiduels (regex + NER)
|
||||||
|
- Vérification que les PII originaux ne sont plus présents
|
||||||
|
- Scan des métadonnées PDF (author, creator, etc.)
|
||||||
|
- Rapport de fuite avec niveau de sévérité (CRITIQUE, HAUTE, MOYENNE)
|
||||||
|
- Validation : document sûr = 0 fuite détectée
|
||||||
|
|
||||||
|
**REQ-005 : Benchmark de Performance**
|
||||||
|
- **Priorité** : HAUTE
|
||||||
|
- **Description** : Mesurer les performances du système actuel et des améliorations
|
||||||
|
- **Critères d'acceptation** :
|
||||||
|
- Temps de traitement par document
|
||||||
|
- Temps de traitement par page
|
||||||
|
- Utilisation CPU/RAM
|
||||||
|
- Métriques de qualité (Précision, Rappel, F1)
|
||||||
|
- Comparaison avant/après optimisation
|
||||||
|
- Export des résultats en format tabulaire
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 2.3 Amélioration de la Détection
|
||||||
|
|
||||||
|
**REQ-006 : Amélioration des Regex**
|
||||||
|
- **Priorité** : HAUTE
|
||||||
|
- **Description** : Renforcer les regex pour réduire les faux négatifs
|
||||||
|
- **Critères d'acceptation** :
|
||||||
|
- Téléphones fragmentés sur plusieurs lignes détectés
|
||||||
|
- Emails avec domaines médicaux (chu-, aphp-, etc.) détectés
|
||||||
|
- Adresses avec compléments (Bât., Appt., etc.) détectées
|
||||||
|
- NIR avec espaces variables détectés
|
||||||
|
- Noms avec caractères spéciaux (O'Brien, D'Angelo, Müller) détectés
|
||||||
|
- Tests unitaires exhaustifs pour chaque regex (≥ 20 cas par pattern)
|
||||||
|
|
||||||
|
**REQ-007 : Détection Contextuelle Renforcée**
|
||||||
|
- **Priorité** : HAUTE
|
||||||
|
- **Description** : Améliorer la détection des noms par analyse contextuelle
|
||||||
|
- **Critères d'acceptation** :
|
||||||
|
- Détection des noms après "Dr.", "Pr.", "Patient:", etc.
|
||||||
|
- Détection des noms en MAJUSCULES (hors termes médicaux)
|
||||||
|
- Détection des noms dans les listes virgulées ("Dr. X, Y, DUPONT")
|
||||||
|
- Détection des noms du personnel ("Aide : Marie-Paule BORDABERRY")
|
||||||
|
- Filtrage des faux positifs via liste de stopwords médicaux enrichie
|
||||||
|
- Niveau de confiance associé à chaque détection
|
||||||
|
|
||||||
|
**REQ-008 : Approche Hybride Multi-Détecteurs**
|
||||||
|
- **Priorité** : HAUTE
|
||||||
|
- **Description** : Combiner plusieurs méthodes de détection en cascade
|
||||||
|
- **Critères d'acceptation** :
|
||||||
|
- Pipeline en 5 étapes : Regex → VLM (si scanné) → EDS-Pseudo → CamemBERT-NER → Contextuel
|
||||||
|
- Masquage progressif pour éviter les doublons
|
||||||
|
- Fusion intelligente des résultats (dédoplication, résolution de conflits)
|
||||||
|
- Traçabilité : chaque PII détecté indique la méthode de détection (REGEX, VLM, EDS, NER, CONTEXT)
|
||||||
|
- Configuration activable/désactivable par méthode
|
||||||
|
- VLM appliqué uniquement sur PDFs scannés (ocr_used=True)
|
||||||
|
- Gestion des pages manuscrites (masquage total si < 100 mots OCR)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 2.4 Validation et Reporting
|
||||||
|
|
||||||
|
**REQ-009 : Validation Post-Anonymisation**
|
||||||
|
- **Priorité** : CRITIQUE
|
||||||
|
- **Description** : Valider automatiquement chaque document anonymisé
|
||||||
|
- **Critères d'acceptation** :
|
||||||
|
- Exécution automatique après chaque anonymisation
|
||||||
|
- Scan de fuite de PII (texte + métadonnées)
|
||||||
|
- Vérification de la lisibilité (pas trop de masquage)
|
||||||
|
- Génération d'un certificat de conformité si validation OK
|
||||||
|
- Blocage de la sortie si fuite détectée (mode strict)
|
||||||
|
|
||||||
|
**REQ-010 : Rapport de Qualité Détaillé**
|
||||||
|
- **Priorité** : HAUTE
|
||||||
|
- **Description** : Générer un rapport de qualité pour chaque batch traité
|
||||||
|
- **Critères d'acceptation** :
|
||||||
|
- Statistiques globales : nombre de documents, PII détectés, temps total
|
||||||
|
- Métriques de qualité : Précision, Rappel, F1-Score
|
||||||
|
- Liste des faux négatifs (si dataset annoté disponible)
|
||||||
|
- Liste des faux positifs (si dataset annoté disponible)
|
||||||
|
- Répartition des PII par type (graphique)
|
||||||
|
- Export HTML + JSON
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 2.5 Amélioration Continue
|
||||||
|
|
||||||
|
**REQ-011 : Tests de Régression Automatiques**
|
||||||
|
- **Priorité** : HAUTE
|
||||||
|
- **Description** : Suite de tests automatiques pour éviter les régressions
|
||||||
|
- **Critères d'acceptation** :
|
||||||
|
- Exécution sur le dataset de test annoté
|
||||||
|
- Vérification que les métriques ne se dégradent pas
|
||||||
|
- Alerte si Rappel < 99.5% ou Précision < 97%
|
||||||
|
- Intégration possible en CI/CD
|
||||||
|
- Temps d'exécution < 10 minutes
|
||||||
|
|
||||||
|
**REQ-013 : Optimisation et Validation du VLM**
|
||||||
|
- **Priorité** : HAUTE
|
||||||
|
- **Description** : Améliorer la fiabilité et les performances du VLM pour les PDF scannés
|
||||||
|
- **Critères d'acceptation** :
|
||||||
|
- Prompt VLM optimisé pour réduire les hallucinations
|
||||||
|
- Validation croisée VLM ↔ NER (rejeter si conflit majeur)
|
||||||
|
- Seuil de confiance configurable (défaut: 0.5)
|
||||||
|
- Gestion intelligente des pages manuscrites (seuil OCR configurable)
|
||||||
|
- Timeout configurable (défaut: 180s)
|
||||||
|
- Métriques spécifiques VLM : taux d'hallucination, temps par page
|
||||||
|
- Support GPU pour Ollama si disponible
|
||||||
|
- Fallback gracieux si Ollama indisponible
|
||||||
|
|
||||||
|
**REQ-014 : Amélioration du Matching Flou VLM**
|
||||||
|
- **Priorité** : MOYENNE
|
||||||
|
- **Description** : Améliorer le matching des identifiants numériques manuscrits détectés par le VLM
|
||||||
|
- **Critères d'acceptation** :
|
||||||
|
- Matching flou basé sur séquences de chiffres (ratio configurable, défaut: 0.7)
|
||||||
|
- Support des identifiants partiellement lisibles
|
||||||
|
- Validation par distance de Levenshtein pour les noms
|
||||||
|
- Tests unitaires avec identifiants manuscrits réels
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Exigences Non-Fonctionnelles
|
||||||
|
|
||||||
|
### 3.1 Performance
|
||||||
|
|
||||||
|
**NFR-001 : Temps de Traitement**
|
||||||
|
- Temps de traitement : < 10 secondes par PDF (moyenne) avec GPU
|
||||||
|
- Temps de traitement : < 2 secondes par page avec GPU
|
||||||
|
- Temps de traitement : < 30 secondes par PDF en mode CPU-only (fallback)
|
||||||
|
- Pas de dégradation > 20% par rapport à la version actuelle
|
||||||
|
|
||||||
|
**NFR-002 : Utilisation des Ressources**
|
||||||
|
- Utilisation GPU : Accélération CUDA pour les modèles NER (EDS-Pseudo, CamemBERT)
|
||||||
|
- Utilisation RAM : < 32 GB par processus (128 GB disponibles)
|
||||||
|
- Utilisation VRAM : < 10 GB (12 GB disponibles sur RTX 5070)
|
||||||
|
- Support du traitement par lots (batch) avec parallélisation sur 16 cœurs CPU
|
||||||
|
- Traitement parallèle de plusieurs PDFs simultanément (jusqu'à 8 workers)
|
||||||
|
|
||||||
|
### 3.2 Maintenabilité
|
||||||
|
|
||||||
|
**NFR-003 : Code Qualité**
|
||||||
|
- Code modulaire et testable
|
||||||
|
- Couverture de tests : ≥ 80% pour les fonctions critiques
|
||||||
|
- Documentation des fonctions (docstrings)
|
||||||
|
- Type hints Python partout
|
||||||
|
|
||||||
|
**NFR-004 : Configuration**
|
||||||
|
- Configuration externalisée (YAML)
|
||||||
|
- Activation/désactivation des détecteurs par configuration
|
||||||
|
- Seuils de confiance configurables
|
||||||
|
- Pas de valeurs en dur dans le code
|
||||||
|
|
||||||
|
### 3.3 Sécurité et Conformité
|
||||||
|
|
||||||
|
**NFR-005 : Conformité RGPD**
|
||||||
|
- Aucun PII ne doit fuiter (rappel ≥ 99.5%)
|
||||||
|
- Traçabilité complète (audit trail)
|
||||||
|
- Validation post-anonymisation obligatoire
|
||||||
|
- Métadonnées PDF nettoyées
|
||||||
|
|
||||||
|
**NFR-006 : Sécurité des Données**
|
||||||
|
- Pas de transmission de données vers des services externes
|
||||||
|
- Traitement local uniquement
|
||||||
|
- Pas de logs contenant des PII
|
||||||
|
- Suppression sécurisée des fichiers temporaires
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Critères de Succès
|
||||||
|
|
||||||
|
### 4.1 Critères Quantitatifs
|
||||||
|
|
||||||
|
**Métriques de qualité** :
|
||||||
|
- ✅ Rappel ≥ 99.5% sur le dataset de test
|
||||||
|
- ✅ Précision ≥ 97% sur le dataset de test
|
||||||
|
- ✅ F1-Score ≥ 0.98 sur le dataset de test
|
||||||
|
- ✅ Taux de documents sûrs ≥ 98%
|
||||||
|
|
||||||
|
**Métriques de performance** :
|
||||||
|
- ✅ Temps de traitement < 30s par PDF
|
||||||
|
- ✅ Utilisation RAM < 4 GB
|
||||||
|
- ✅ Pas de dégradation > 20% vs version actuelle
|
||||||
|
|
||||||
|
### 4.2 Critères Qualitatifs
|
||||||
|
|
||||||
|
- ✅ Dataset de test annoté créé (≥ 30 documents)
|
||||||
|
- ✅ Système d'évaluation automatique fonctionnel
|
||||||
|
- ✅ Scanner de fuite opérationnel
|
||||||
|
- ✅ Tests de régression en place
|
||||||
|
- ✅ Documentation complète
|
||||||
|
|
||||||
|
### 4.3 Validation Finale
|
||||||
|
|
||||||
|
**Test d'acceptation** :
|
||||||
|
1. Exécuter le système sur les 59 dossiers OGC complets
|
||||||
|
2. Valider que 0 fuite critique n'est détectée
|
||||||
|
3. Vérifier que les documents restent lisibles (validation manuelle sur échantillon)
|
||||||
|
4. Comparer les métriques avec la baseline actuelle
|
||||||
|
5. Validation par un expert médical (échantillon de 10 documents)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Contraintes et Risques
|
||||||
|
|
||||||
|
### 5.1 Contraintes
|
||||||
|
|
||||||
|
**Contraintes techniques** :
|
||||||
|
- GPU NVIDIA RTX 5070 avec CUDA disponible (accélération recommandée)
|
||||||
|
- Fallback CPU si GPU indisponible
|
||||||
|
- RAM abondante (128 GB) - pas de contrainte mémoire
|
||||||
|
- Pas de dépendances externes nécessitant internet en production
|
||||||
|
|
||||||
|
**Contraintes métier** :
|
||||||
|
- Utilisation de documents réels uniquement (pas de mocks)
|
||||||
|
- Conformité RGPD stricte
|
||||||
|
- Préservation de la lisibilité médicale
|
||||||
|
|
||||||
|
### 5.2 Risques
|
||||||
|
|
||||||
|
| Risque | Probabilité | Impact | Mitigation |
|
||||||
|
|--------|-------------|--------|------------|
|
||||||
|
| Annotation manuelle trop longue | HAUTE | MOYEN | Prioriser 30 documents représentatifs, automatiser partiellement |
|
||||||
|
| Faux négatifs résiduels | MOYENNE | CRITIQUE | Validation post-anonymisation obligatoire, scanner de fuite |
|
||||||
|
| Dégradation des performances | FAIBLE | MOYEN | Benchmark continu, optimisation GPU, parallélisation |
|
||||||
|
| Sur-masquage (trop de faux positifs) | MOYENNE | MOYEN | Enrichissement liste stopwords, validation manuelle échantillon |
|
||||||
|
| Saturation VRAM GPU | FAIBLE | FAIBLE | Batch sizing dynamique, fallback CPU si nécessaire |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Dépendances et Prérequis
|
||||||
|
|
||||||
|
### 6.1 Dépendances Techniques
|
||||||
|
|
||||||
|
**Existantes** :
|
||||||
|
- Python 3.12
|
||||||
|
- **VLM** : Ollama (qwen2.5vl:7b ou qwen3-vl:8b) - analyse visuelle
|
||||||
|
- **NER** : EDS-Pseudo (AP-HP/eds-pseudo-public) via edsnlp
|
||||||
|
- **NER fallback** : CamemBERT-NER (Jean-Baptiste/camembert-ner) ONNX
|
||||||
|
- **OCR** : docTR (deep learning) + tesseract (fallback)
|
||||||
|
- **PDF** : PyMuPDF, pdfplumber, pdfminer.six
|
||||||
|
- **Runtime** : ONNX Runtime, transformers, optimum
|
||||||
|
|
||||||
|
**Nouvelles** :
|
||||||
|
- `pytest` (tests)
|
||||||
|
- `pytest-cov` (couverture)
|
||||||
|
- `pydantic` (validation config)
|
||||||
|
- `structlog` (logging structuré)
|
||||||
|
- `jinja2` (rapports HTML)
|
||||||
|
- `matplotlib` ou `plotly` (graphiques)
|
||||||
|
|
||||||
|
### 6.2 Données Requises
|
||||||
|
|
||||||
|
- ✅ 59 dossiers OGC existants
|
||||||
|
- ✅ 130 fichiers anonymisés + audits existants
|
||||||
|
- ⏳ 30 documents annotés manuellement (à créer)
|
||||||
|
- ⏳ Liste enrichie de stopwords médicaux (à compléter)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Livrables Attendus
|
||||||
|
|
||||||
|
1. **Dataset de test annoté** (30+ documents)
|
||||||
|
2. **Système d'évaluation automatique** (évaluateur + scanner + benchmark)
|
||||||
|
3. **Détecteurs améliorés** (regex + contextuel + hybride)
|
||||||
|
4. **Suite de tests de régression**
|
||||||
|
5. **Rapports de qualité** (HTML + JSON)
|
||||||
|
6. **Documentation** (guide d'utilisation, guide d'annotation)
|
||||||
|
7. **Métriques de baseline** (avant optimisation)
|
||||||
|
8. **Métriques finales** (après optimisation)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. Planning Indicatif
|
||||||
|
|
||||||
|
**Phase 1 - Mesure (2 semaines)** :
|
||||||
|
- Création dataset annoté (30 docs)
|
||||||
|
- Système d'évaluation
|
||||||
|
- Métriques baseline
|
||||||
|
|
||||||
|
**Phase 2 - Amélioration (3 semaines)** :
|
||||||
|
- Amélioration regex
|
||||||
|
- Détection contextuelle
|
||||||
|
- Approche hybride
|
||||||
|
|
||||||
|
**Phase 3 - Validation (1 semaine)** :
|
||||||
|
- Tests de régression
|
||||||
|
- Validation sur corpus complet
|
||||||
|
- Documentation
|
||||||
|
|
||||||
|
**Total** : 6 semaines
|
||||||
408
.kiro/specs/anonymization-quality-optimization/tasks.md
Normal file
408
.kiro/specs/anonymization-quality-optimization/tasks.md
Normal file
@@ -0,0 +1,408 @@
|
|||||||
|
# Tasks - Optimisation de la Qualité d'Anonymisation
|
||||||
|
|
||||||
|
## Phase 1 : Mesure et Baseline (2 semaines)
|
||||||
|
|
||||||
|
### 1.1 Création du Dataset de Test Annoté
|
||||||
|
|
||||||
|
- [ ] 1.1.1 Sélectionner 30 documents représentatifs des 59 dossiers OGC
|
||||||
|
- [ ] 1.1.1.1 Analyser la répartition des documents (types, complexité, taille)
|
||||||
|
- [ ] 1.1.1.2 Sélectionner 10 documents simples (1-2 pages, peu de PII)
|
||||||
|
- [ ] 1.1.1.3 Sélectionner 15 documents moyens (3-5 pages, PII variés)
|
||||||
|
- [ ] 1.1.1.4 Sélectionner 5 documents complexes (>5 pages, nombreux PII)
|
||||||
|
- [ ] 1.1.1.5 Copier les documents dans `tests/ground_truth/`
|
||||||
|
|
||||||
|
- [ ] 1.1.2 Créer l'outil d'annotation CLI
|
||||||
|
- [ ] 1.1.2.1 Créer `tools/annotation_tool.py`
|
||||||
|
- [ ] 1.1.2.2 Implémenter l'extraction et affichage du texte
|
||||||
|
- [ ] 1.1.2.3 Implémenter la saisie guidée des annotations
|
||||||
|
- [ ] 1.1.2.4 Implémenter la validation du format JSON
|
||||||
|
- [ ] 1.1.2.5 Implémenter l'export au format standardisé
|
||||||
|
- [ ] 1.1.2.6 Ajouter la documentation d'utilisation
|
||||||
|
|
||||||
|
- [ ] 1.1.3 Annoter les 30 documents sélectionnés
|
||||||
|
- [ ] 1.1.3.1 Annoter les 10 documents simples
|
||||||
|
- [ ] 1.1.3.2 Annoter les 15 documents moyens
|
||||||
|
- [ ] 1.1.3.3 Annoter les 5 documents complexes
|
||||||
|
- [ ] 1.1.3.4 Valider les annotations (double vérification)
|
||||||
|
- [ ] 1.1.3.5 Calculer les statistiques du dataset (PII par type, difficulté)
|
||||||
|
|
||||||
|
- [ ] 1.1.4 Enrichir la liste des stopwords médicaux
|
||||||
|
- [ ] 1.1.4.1 Extraire les termes médicaux des 30 documents annotés
|
||||||
|
- [ ] 1.1.4.2 Identifier les faux positifs actuels (termes masqués à tort)
|
||||||
|
- [ ] 1.1.4.3 Ajouter les nouveaux termes à `_MEDICAL_STOP_WORDS_SET`
|
||||||
|
- [ ] 1.1.4.4 Documenter les sources des stopwords
|
||||||
|
|
||||||
|
### 1.2 Système d'Évaluation de la Qualité
|
||||||
|
|
||||||
|
- [ ] 1.2.1 Implémenter l'évaluateur de qualité
|
||||||
|
- [ ] 1.2.1.1 Créer `evaluation/quality_evaluator.py`
|
||||||
|
- [ ] 1.2.1.2 Implémenter la classe `EvaluationResult` (dataclass)
|
||||||
|
- [ ] 1.2.1.3 Implémenter la classe `QualityEvaluator`
|
||||||
|
- [ ] 1.2.1.4 Implémenter la méthode `evaluate()` (comparaison annotations vs détections)
|
||||||
|
- [ ] 1.2.1.5 Implémenter le calcul des métriques (Précision, Rappel, F1)
|
||||||
|
- [ ] 1.2.1.6 Implémenter l'identification des faux négatifs
|
||||||
|
- [ ] 1.2.1.7 Implémenter l'identification des faux positifs
|
||||||
|
- [ ] 1.2.1.8 Implémenter la génération de rapport texte
|
||||||
|
- [ ] 1.2.1.9 Ajouter les tests unitaires
|
||||||
|
|
||||||
|
- [ ] 1.2.2 Implémenter le scanner de fuite
|
||||||
|
- [ ] 1.2.2.1 Créer `evaluation/leak_scanner.py`
|
||||||
|
- [ ] 1.2.2.2 Implémenter la classe `LeakReport` (dataclass)
|
||||||
|
- [ ] 1.2.2.3 Implémenter la classe `LeakScanner`
|
||||||
|
- [ ] 1.2.2.4 Implémenter `scan_text()` (détection PII résiduels)
|
||||||
|
- [ ] 1.2.2.5 Implémenter `scan_metadata()` (scan métadonnées PDF)
|
||||||
|
- [ ] 1.2.2.6 Implémenter la classification par sévérité
|
||||||
|
- [ ] 1.2.2.7 Implémenter la génération de rapport de fuite
|
||||||
|
- [ ] 1.2.2.8 Ajouter les tests unitaires
|
||||||
|
|
||||||
|
- [ ] 1.2.3 Implémenter le benchmark de performance
|
||||||
|
- [ ] 1.2.3.1 Créer `evaluation/benchmark.py`
|
||||||
|
- [ ] 1.2.3.2 Implémenter la collecte des métriques de temps
|
||||||
|
- [ ] 1.2.3.3 Implémenter la collecte des métriques CPU/RAM
|
||||||
|
- [ ] 1.2.3.4 Implémenter la collecte des métriques de qualité
|
||||||
|
- [ ] 1.2.3.5 Implémenter l'export JSON des résultats
|
||||||
|
- [ ] 1.2.3.6 Implémenter l'affichage tabulaire des résultats
|
||||||
|
- [ ] 1.2.3.7 Ajouter les tests unitaires
|
||||||
|
|
||||||
|
### 1.3 Mesure de la Baseline
|
||||||
|
|
||||||
|
- [ ] 1.3.1 Exécuter l'évaluation sur le dataset annoté
|
||||||
|
- [ ] 1.3.1.1 Anonymiser les 30 documents annotés avec le système actuel
|
||||||
|
- [ ] 1.3.1.2 Exécuter l'évaluateur sur les 30 documents
|
||||||
|
- [ ] 1.3.1.3 Générer le rapport de qualité baseline
|
||||||
|
- [ ] 1.3.1.4 Identifier les faux négatifs critiques
|
||||||
|
- [ ] 1.3.1.5 Identifier les faux positifs fréquents
|
||||||
|
|
||||||
|
- [ ] 1.3.2 Exécuter le benchmark de performance
|
||||||
|
- [ ] 1.3.2.1 Benchmarker le système actuel sur les 30 documents
|
||||||
|
- [ ] 1.3.2.2 Mesurer le temps de traitement moyen
|
||||||
|
- [ ] 1.3.2.3 Mesurer l'utilisation CPU/RAM
|
||||||
|
- [ ] 1.3.2.4 Exporter les résultats baseline
|
||||||
|
|
||||||
|
- [ ] 1.3.3 Analyser les résultats baseline
|
||||||
|
- [ ] 1.3.3.1 Analyser les types de PII manqués (faux négatifs)
|
||||||
|
- [ ] 1.3.3.2 Analyser les types de faux positifs
|
||||||
|
- [ ] 1.3.3.3 Identifier les patterns problématiques
|
||||||
|
- [ ] 1.3.3.4 Prioriser les améliorations à implémenter
|
||||||
|
- [ ] 1.3.3.5 Documenter les findings dans un rapport
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 2 : Amélioration de la Détection (3 semaines)
|
||||||
|
|
||||||
|
### 2.1 Amélioration des Regex
|
||||||
|
|
||||||
|
- [ ] 2.1.1 Améliorer la détection des téléphones
|
||||||
|
- [ ] 2.1.1.1 Créer `detectors/improved_regex.py`
|
||||||
|
- [ ] 2.1.1.2 Implémenter `RE_TEL_IMPROVED` (formats fragmentés)
|
||||||
|
- [ ] 2.1.1.3 Ajouter 20+ tests unitaires pour les téléphones
|
||||||
|
- [ ] 2.1.1.4 Valider sur le dataset annoté
|
||||||
|
|
||||||
|
- [ ] 2.1.2 Améliorer la détection des emails
|
||||||
|
- [ ] 2.1.2.1 Implémenter `RE_EMAIL_IMPROVED` (domaines médicaux)
|
||||||
|
- [ ] 2.1.2.2 Ajouter 20+ tests unitaires pour les emails
|
||||||
|
- [ ] 2.1.2.3 Valider sur le dataset annoté
|
||||||
|
|
||||||
|
- [ ] 2.1.3 Améliorer la détection des adresses
|
||||||
|
- [ ] 2.1.3.1 Implémenter `RE_ADRESSE_IMPROVED` (compléments Bât., Appt.)
|
||||||
|
- [ ] 2.1.3.2 Ajouter 20+ tests unitaires pour les adresses
|
||||||
|
- [ ] 2.1.3.3 Valider sur le dataset annoté
|
||||||
|
|
||||||
|
- [ ] 2.1.4 Améliorer la détection des NIR
|
||||||
|
- [ ] 2.1.4.1 Implémenter `RE_NIR_IMPROVED` (espaces variables)
|
||||||
|
- [ ] 2.1.4.2 Ajouter 20+ tests unitaires pour les NIR
|
||||||
|
- [ ] 2.1.4.3 Valider sur le dataset annoté
|
||||||
|
|
||||||
|
- [ ] 2.1.5 Améliorer la détection des noms avec caractères spéciaux
|
||||||
|
- [ ] 2.1.5.1 Adapter les regex pour O'Brien, D'Angelo, Müller, etc.
|
||||||
|
- [ ] 2.1.5.2 Ajouter 20+ tests unitaires
|
||||||
|
- [ ] 2.1.5.3 Valider sur le dataset annoté
|
||||||
|
|
||||||
|
- [ ] 2.1.6 Intégrer les regex améliorées
|
||||||
|
- [ ] 2.1.6.1 Remplacer les regex dans `anonymizer_core_refactored_onnx.py`
|
||||||
|
- [ ] 2.1.6.2 Exécuter les tests de régression
|
||||||
|
- [ ] 2.1.6.3 Mesurer l'amélioration (Rappel, Précision)
|
||||||
|
|
||||||
|
### 2.2 Détection Contextuelle
|
||||||
|
|
||||||
|
- [ ] 2.2.1 Implémenter le détecteur contextuel
|
||||||
|
- [ ] 2.2.1.1 Créer `detectors/contextual.py`
|
||||||
|
- [ ] 2.2.1.2 Implémenter la classe `ContextualDetector`
|
||||||
|
- [ ] 2.2.1.3 Implémenter la détection avec contexte fort
|
||||||
|
- [ ] 2.2.1.4 Implémenter la détection des noms en MAJUSCULES
|
||||||
|
- [ ] 2.2.1.5 Implémenter la détection avec contexte faible
|
||||||
|
- [ ] 2.2.1.6 Implémenter le filtrage via stopwords médicaux
|
||||||
|
- [ ] 2.2.1.7 Implémenter la dédoplication et tri par confiance
|
||||||
|
- [ ] 2.2.1.8 Ajouter les tests unitaires
|
||||||
|
|
||||||
|
- [ ] 2.2.2 Valider le détecteur contextuel
|
||||||
|
- [ ] 2.2.2.1 Tester sur le dataset annoté
|
||||||
|
- [ ] 2.2.2.2 Mesurer le rappel (noms détectés)
|
||||||
|
- [ ] 2.2.2.3 Mesurer la précision (faux positifs)
|
||||||
|
- [ ] 2.2.2.4 Ajuster les seuils de confiance si nécessaire
|
||||||
|
|
||||||
|
### 2.3 Approche Hybride
|
||||||
|
|
||||||
|
- [ ] 2.3.1 Implémenter le détecteur hybride
|
||||||
|
- [ ] 2.3.1.1 Créer `detectors/hybrid.py`
|
||||||
|
- [ ] 2.3.1.2 Implémenter la classe `HybridDetector`
|
||||||
|
- [ ] 2.3.1.3 Implémenter le pipeline en 4 étapes (Regex → EDS → CamemBERT → Contextuel)
|
||||||
|
- [ ] 2.3.1.4 Implémenter le masquage progressif
|
||||||
|
- [ ] 2.3.1.5 Implémenter la fusion des résultats
|
||||||
|
- [ ] 2.3.1.6 Implémenter la traçabilité (méthode de détection)
|
||||||
|
- [ ] 2.3.1.7 Ajouter les tests d'intégration
|
||||||
|
|
||||||
|
- [ ] 2.3.2 Intégrer le détecteur hybride
|
||||||
|
- [ ] 2.3.2.1 Modifier `anonymizer_core_refactored_onnx.py` pour utiliser `HybridDetector`
|
||||||
|
- [ ] 2.3.2.2 Ajouter la configuration activable/désactivable par détecteur
|
||||||
|
- [ ] 2.3.2.3 Exécuter les tests de régression
|
||||||
|
- [ ] 2.3.2.4 Mesurer l'amélioration globale
|
||||||
|
|
||||||
|
- [ ] 2.3.3 Optimiser les performances avec GPU
|
||||||
|
- [ ] 2.3.3.1 Activer l'accélération CUDA pour EDS-Pseudo
|
||||||
|
- [ ] 2.3.3.2 Activer l'accélération CUDA pour CamemBERT-NER
|
||||||
|
- [ ] 2.3.3.3 Implémenter le batch processing optimisé pour GPU
|
||||||
|
- [ ] 2.3.3.4 Tester différentes tailles de batch (4, 8, 16, 32)
|
||||||
|
- [ ] 2.3.3.5 Mesurer l'utilisation VRAM et ajuster batch_size
|
||||||
|
- [ ] 2.3.3.6 Implémenter le fallback CPU automatique si GPU indisponible
|
||||||
|
- [ ] 2.3.3.7 Profiler le code (cProfile + CUDA profiler)
|
||||||
|
- [ ] 2.3.3.8 Identifier les goulots d'étranglement
|
||||||
|
- [ ] 2.3.3.9 Optimiser les parties critiques
|
||||||
|
- [ ] 2.3.3.10 Vérifier que le temps de traitement est < 10s/PDF avec GPU
|
||||||
|
|
||||||
|
- [ ] 2.3.4 Implémenter le traitement parallèle multi-PDF
|
||||||
|
- [ ] 2.3.4.1 Créer un gestionnaire de pool de workers (ProcessPoolExecutor)
|
||||||
|
- [ ] 2.3.4.2 Tester avec 4, 8, 12 workers (optimal sur 16 cœurs)
|
||||||
|
- [ ] 2.3.4.3 Implémenter la répartition de charge intelligente
|
||||||
|
- [ ] 2.3.4.4 Mesurer le speedup avec parallélisation
|
||||||
|
- [ ] 2.3.4.5 Gérer les conflits d'accès GPU entre workers
|
||||||
|
|
||||||
|
### 2.4 Configuration
|
||||||
|
|
||||||
|
- [ ] 2.4.1 Créer le fichier de configuration
|
||||||
|
- [ ] 2.4.1.1 Créer `config/quality_config.yml`
|
||||||
|
- [ ] 2.4.1.2 Définir les paramètres d'évaluation
|
||||||
|
- [ ] 2.4.1.3 Définir les paramètres de validation
|
||||||
|
- [ ] 2.4.1.4 Définir les paramètres de détection
|
||||||
|
- [ ] 2.4.1.5 Définir les paramètres GPU (device, batch_size, max_vram)
|
||||||
|
- [ ] 2.4.1.6 Définir les paramètres VLM (Ollama URL, model, timeout, confidence)
|
||||||
|
- [ ] 2.4.1.7 Définir les paramètres de performance (max_workers, parallélisation)
|
||||||
|
- [ ] 2.4.1.8 Définir les paramètres de reporting
|
||||||
|
|
||||||
|
- [ ] 2.4.2 Implémenter le chargement de configuration
|
||||||
|
- [ ] 2.4.2.1 Utiliser `pydantic` pour valider la configuration
|
||||||
|
- [ ] 2.4.2.2 Créer les modèles de configuration typés
|
||||||
|
- [ ] 2.4.2.3 Implémenter le chargement depuis YAML
|
||||||
|
- [ ] 2.4.2.4 Ajouter les tests de validation
|
||||||
|
|
||||||
|
### 2.5 Optimisation VLM
|
||||||
|
|
||||||
|
- [ ] 2.5.1 Améliorer le prompt VLM
|
||||||
|
- [ ] 2.5.1.1 Analyser les hallucinations actuelles du VLM
|
||||||
|
- [ ] 2.5.1.2 Créer un prompt plus précis avec exemples négatifs
|
||||||
|
- [ ] 2.5.1.3 Ajouter des instructions anti-hallucination
|
||||||
|
- [ ] 2.5.1.4 Tester sur échantillon de pages manuscrites
|
||||||
|
- [ ] 2.5.1.5 Mesurer le taux d'hallucination avant/après
|
||||||
|
|
||||||
|
- [ ] 2.5.2 Implémenter la validation croisée VLM ↔ NER
|
||||||
|
- [ ] 2.5.2.1 Créer `detectors/vlm_validator.py`
|
||||||
|
- [ ] 2.5.2.2 Implémenter la comparaison VLM vs NER
|
||||||
|
- [ ] 2.5.2.3 Définir les règles de résolution de conflits
|
||||||
|
- [ ] 2.5.2.4 Rejeter les détections VLM non confirmées (seuil configurable)
|
||||||
|
- [ ] 2.5.2.5 Logger les conflits pour analyse
|
||||||
|
- [ ] 2.5.2.6 Ajouter les tests unitaires
|
||||||
|
|
||||||
|
- [ ] 2.5.3 Optimiser les performances VLM
|
||||||
|
- [ ] 2.5.3.1 Vérifier si Ollama supporte GPU (CUDA)
|
||||||
|
- [ ] 2.5.3.2 Configurer Ollama pour utiliser le GPU si disponible
|
||||||
|
- [ ] 2.5.3.3 Mesurer le temps de traitement par page (baseline)
|
||||||
|
- [ ] 2.5.3.4 Optimiser la résolution d'image (trade-off qualité/vitesse)
|
||||||
|
- [ ] 2.5.3.5 Implémenter un cache des résultats VLM par hash d'image
|
||||||
|
- [ ] 2.5.3.6 Mesurer le speedup après optimisations
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 3 : Validation et Reporting (1 semaine)
|
||||||
|
|
||||||
|
### 3.1 Validation Post-Anonymisation
|
||||||
|
|
||||||
|
- [ ] 3.1.1 Implémenter la validation post-anonymisation
|
||||||
|
- [ ] 3.1.1.1 Créer `core/post_validation.py`
|
||||||
|
- [ ] 3.1.1.2 Implémenter la fonction `validate_anonymized_pdf()`
|
||||||
|
- [ ] 3.1.1.3 Intégrer le scanner de fuite
|
||||||
|
- [ ] 3.1.1.4 Implémenter la vérification de lisibilité
|
||||||
|
- [ ] 3.1.1.5 Implémenter la génération de certificat
|
||||||
|
- [ ] 3.1.1.6 Implémenter le mode strict (blocage si fuite)
|
||||||
|
- [ ] 3.1.1.7 Ajouter les tests unitaires
|
||||||
|
|
||||||
|
- [ ] 3.1.2 Intégrer la validation dans le pipeline
|
||||||
|
- [ ] 3.1.2.1 Modifier `anonymizer_core_refactored_onnx.py` pour appeler la validation
|
||||||
|
- [ ] 3.1.2.2 Ajouter l'option `--validate` en CLI
|
||||||
|
- [ ] 3.1.2.3 Ajouter l'option dans la GUI
|
||||||
|
- [ ] 3.1.2.4 Tester sur le dataset annoté
|
||||||
|
|
||||||
|
### 3.2 Reporting
|
||||||
|
|
||||||
|
- [ ] 3.2.1 Créer le générateur de rapports
|
||||||
|
- [ ] 3.2.1.1 Créer `tools/quality_reporter.py`
|
||||||
|
- [ ] 3.2.1.2 Implémenter la classe `QualityReporter`
|
||||||
|
- [ ] 3.2.1.3 Créer le template HTML (`templates/quality_report.html`)
|
||||||
|
- [ ] 3.2.1.4 Implémenter la génération de graphiques (matplotlib)
|
||||||
|
- [ ] 3.2.1.5 Implémenter l'export JSON
|
||||||
|
- [ ] 3.2.1.6 Implémenter l'export HTML
|
||||||
|
- [ ] 3.2.1.7 Ajouter les tests unitaires
|
||||||
|
|
||||||
|
- [ ] 3.2.2 Générer les rapports de qualité
|
||||||
|
- [ ] 3.2.2.1 Générer le rapport baseline (avant optimisation)
|
||||||
|
- [ ] 3.2.2.2 Générer le rapport après optimisation
|
||||||
|
- [ ] 3.2.2.3 Créer un rapport comparatif (avant/après)
|
||||||
|
- [ ] 3.2.2.4 Exporter en HTML et JSON
|
||||||
|
|
||||||
|
### 3.3 Tests de Régression
|
||||||
|
|
||||||
|
- [ ] 3.3.1 Créer la suite de tests de régression
|
||||||
|
- [ ] 3.3.1.1 Créer `tests/regression/test_regression.py`
|
||||||
|
- [ ] 3.3.1.2 Implémenter le test de qualité (Rappel ≥ 99.5%, Précision ≥ 97%)
|
||||||
|
- [ ] 3.3.1.3 Implémenter le test de performance (temps < 30s/PDF)
|
||||||
|
- [ ] 3.3.1.4 Implémenter le test de non-régression (vs baseline)
|
||||||
|
- [ ] 3.3.1.5 Configurer pytest pour exécution automatique
|
||||||
|
|
||||||
|
- [ ] 3.3.2 Exécuter les tests de régression
|
||||||
|
- [ ] 3.3.2.1 Exécuter sur le dataset annoté complet
|
||||||
|
- [ ] 3.3.2.2 Vérifier que tous les tests passent
|
||||||
|
- [ ] 3.3.2.3 Corriger les régressions si nécessaire
|
||||||
|
|
||||||
|
### 3.4 Validation sur Corpus Complet
|
||||||
|
|
||||||
|
- [ ] 3.4.1 Exécuter sur les 59 dossiers OGC complets
|
||||||
|
- [ ] 3.4.1.1 Anonymiser les 130 fichiers avec le système optimisé
|
||||||
|
- [ ] 3.4.1.2 Exécuter le scanner de fuite sur tous les fichiers
|
||||||
|
- [ ] 3.4.1.3 Vérifier qu'aucune fuite critique n'est détectée
|
||||||
|
- [ ] 3.4.1.4 Générer le rapport de qualité global
|
||||||
|
|
||||||
|
- [ ] 3.4.2 Validation manuelle (échantillon)
|
||||||
|
- [ ] 3.4.2.1 Sélectionner 10 documents aléatoires
|
||||||
|
- [ ] 3.4.2.2 Vérifier manuellement la qualité d'anonymisation
|
||||||
|
- [ ] 3.4.2.3 Vérifier la lisibilité médicale
|
||||||
|
- [ ] 3.4.2.4 Documenter les observations
|
||||||
|
|
||||||
|
- [ ] 3.4.3 Comparer avec la baseline
|
||||||
|
- [ ] 3.4.3.1 Comparer les métriques de qualité (Rappel, Précision, F1)
|
||||||
|
- [ ] 3.4.3.2 Comparer les métriques de performance (temps, CPU, RAM)
|
||||||
|
- [ ] 3.4.3.3 Calculer le gain d'amélioration
|
||||||
|
- [ ] 3.4.3.4 Documenter les résultats
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 4 : Documentation et Finalisation (3 jours)
|
||||||
|
|
||||||
|
### 4.1 Documentation
|
||||||
|
|
||||||
|
- [ ] 4.1.1 Créer le guide d'annotation
|
||||||
|
- [ ] 4.1.1.1 Créer `docs/annotation_guide.md`
|
||||||
|
- [ ] 4.1.1.2 Documenter le processus d'annotation
|
||||||
|
- [ ] 4.1.1.3 Documenter le format JSON
|
||||||
|
- [ ] 4.1.1.4 Ajouter des exemples
|
||||||
|
|
||||||
|
- [ ] 4.1.2 Créer le guide d'évaluation
|
||||||
|
- [ ] 4.1.2.1 Créer `docs/evaluation_guide.md`
|
||||||
|
- [ ] 4.1.2.2 Documenter l'utilisation de l'évaluateur
|
||||||
|
- [ ] 4.1.2.3 Documenter l'utilisation du scanner
|
||||||
|
- [ ] 4.1.2.4 Documenter l'utilisation du benchmark
|
||||||
|
- [ ] 4.1.2.5 Ajouter des exemples
|
||||||
|
|
||||||
|
- [ ] 4.1.3 Créer la référence API
|
||||||
|
- [ ] 4.1.3.1 Créer `docs/api_reference.md`
|
||||||
|
- [ ] 4.1.3.2 Documenter les classes principales
|
||||||
|
- [ ] 4.1.3.3 Documenter les méthodes publiques
|
||||||
|
- [ ] 4.1.3.4 Ajouter des exemples de code
|
||||||
|
|
||||||
|
- [ ] 4.1.4 Mettre à jour le README
|
||||||
|
- [ ] 4.1.4.1 Ajouter la section "Évaluation de la Qualité"
|
||||||
|
- [ ] 4.1.4.2 Ajouter les nouvelles dépendances
|
||||||
|
- [ ] 4.1.4.3 Ajouter les exemples d'utilisation
|
||||||
|
- [ ] 4.1.4.4 Ajouter les métriques de qualité
|
||||||
|
|
||||||
|
### 4.2 Finalisation
|
||||||
|
|
||||||
|
- [ ] 4.2.1 Revue de code
|
||||||
|
- [ ] 4.2.1.1 Vérifier la qualité du code (pylint, black, mypy)
|
||||||
|
- [ ] 4.2.1.2 Vérifier la couverture de tests (≥ 80%)
|
||||||
|
- [ ] 4.2.1.3 Vérifier la documentation (docstrings)
|
||||||
|
- [ ] 4.2.1.4 Corriger les problèmes identifiés
|
||||||
|
|
||||||
|
- [ ] 4.2.2 Préparer les livrables
|
||||||
|
- [ ] 4.2.2.1 Dataset annoté (30+ documents)
|
||||||
|
- [ ] 4.2.2.2 Code source (détecteurs + évaluation)
|
||||||
|
- [ ] 4.2.2.3 Tests (unitaires + régression)
|
||||||
|
- [ ] 4.2.2.4 Documentation (guides + API)
|
||||||
|
- [ ] 4.2.2.5 Rapports (baseline + optimisé + comparatif)
|
||||||
|
- [ ] 4.2.2.6 Configuration (`quality_config.yml`)
|
||||||
|
|
||||||
|
- [ ] 4.2.3 Validation finale
|
||||||
|
- [ ] 4.2.3.1 Vérifier que tous les critères de succès sont atteints
|
||||||
|
- [ ] 4.2.3.2 Vérifier que les métriques cibles sont atteintes (Rappel ≥ 99.5%, Précision ≥ 97%)
|
||||||
|
- [ ] 4.2.3.3 Vérifier que les performances sont acceptables (< 30s/PDF)
|
||||||
|
- [ ] 4.2.3.4 Obtenir la validation d'un expert médical (échantillon)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Tâches Optionnelles (si temps disponible)
|
||||||
|
|
||||||
|
- [ ]* Implémenter un cache des résultats NER pour améliorer les performances
|
||||||
|
- [ ]* Implémenter la parallélisation du traitement par lots (déjà inclus dans Phase 2)
|
||||||
|
- [ ]* Créer une interface web pour l'annotation (alternative à la CLI)
|
||||||
|
- [ ]* Implémenter l'export des rapports en PDF
|
||||||
|
- [ ]* Créer un dashboard de monitoring (Grafana/Prometheus)
|
||||||
|
- [ ]* Implémenter l'analyse automatique des échecs (suggestions d'amélioration)
|
||||||
|
- [ ]* Fine-tuner EDS-Pseudo sur le dataset annoté
|
||||||
|
- [ ]* Implémenter un modèle ensemble (vote majoritaire)
|
||||||
|
- [ ]* Optimiser le batch size dynamiquement selon la VRAM disponible
|
||||||
|
- [ ]* Implémenter le préchargement asynchrone des modèles NER
|
||||||
|
- [ ]* Tester d'autres modèles VLM (Qwen3-VL 8B, LLaVA, etc.)
|
||||||
|
- [ ]* Implémenter un système de feedback utilisateur pour améliorer le VLM
|
||||||
|
- [ ]* Créer un mode "review" pour valider les détections VLM manuellement
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Dépendances entre Tâches
|
||||||
|
|
||||||
|
**Critiques** (bloquantes) :
|
||||||
|
- 1.1 (Dataset annoté) → 1.3 (Baseline) → 2.x (Amélioration) → 3.4 (Validation)
|
||||||
|
- 1.2.1 (Évaluateur) → 1.3.1 (Évaluation baseline)
|
||||||
|
- 1.2.2 (Scanner) → 3.1 (Validation post-anonymisation)
|
||||||
|
- 2.1 + 2.2 + 2.3 (Détecteurs) → 3.3 (Tests régression)
|
||||||
|
|
||||||
|
**Parallélisables** :
|
||||||
|
- 1.2.1 (Évaluateur) || 1.2.2 (Scanner) || 1.2.3 (Benchmark)
|
||||||
|
- 2.1.1 || 2.1.2 || 2.1.3 || 2.1.4 || 2.1.5 (Regex indépendantes)
|
||||||
|
- 4.1.1 || 4.1.2 || 4.1.3 (Documentation)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Estimation de Charge
|
||||||
|
|
||||||
|
**Phase 1** : 10 jours (2 semaines)
|
||||||
|
- Annotation : 5 jours (30 docs × 1h = 30h)
|
||||||
|
- Évaluation : 3 jours
|
||||||
|
- Baseline : 2 jours
|
||||||
|
|
||||||
|
**Phase 2** : 15 jours (3 semaines)
|
||||||
|
- Regex : 5 jours
|
||||||
|
- Contextuel : 3 jours
|
||||||
|
- Hybride : 3 jours
|
||||||
|
- VLM optimization : 2 jours
|
||||||
|
- GPU optimization : 1 jour
|
||||||
|
- Config : 1 jour
|
||||||
|
|
||||||
|
**Phase 3** : 5 jours (1 semaine)
|
||||||
|
- Validation : 2 jours
|
||||||
|
- Reporting : 1 jour
|
||||||
|
- Tests régression : 1 jour
|
||||||
|
- Validation corpus : 1 jour
|
||||||
|
|
||||||
|
**Phase 4** : 3 jours
|
||||||
|
- Documentation : 2 jours
|
||||||
|
- Finalisation : 1 jour
|
||||||
|
|
||||||
|
**Total** : 33 jours (6.6 semaines) ≈ **7 semaines avec marge**
|
||||||
Reference in New Issue
Block a user