Files
rpa_vision_v3/docs/BENCH_SAFETY_CHECKS_2026-05-06.md
Dom 0a02a6ec9c
Some checks failed
tests / Lint (ruff + black) (push) Successful in 15s
tests / Tests unitaires (sans GPU) (push) Failing after 14s
tests / Tests sécurité (critique) (push) Has been skipped
feat(qw4): bench rigoureux LLM safety_checks → gemma4:latest par défaut
Bench 5 modèles × 5 scénarios × cold+warm sur RTX 5070 :
- gemma4:latest : warm 2.9s, JSON 92%, détection 46% → gagnant
- qwen2.5vl:7b : warm 6.6s, détection 23% (trop lent)
- qwen2.5vl:3b : warm 2.0s, détection 8% (vérifie pour vérifier)
- medgemma:4b : warm 0.5s, détection 0% (refuse de signaler) → mauvais
  défaut initial, corrigé
- qwen3-vl:8b : 0% JSON valide (ignore format=json Ollama) → écarté

Modifications safety_checks_provider.py :
- RPA_SAFETY_CHECKS_LLM_MODEL défaut: medgemma:4b → gemma4:latest
- RPA_SAFETY_CHECKS_LLM_TIMEOUT_S défaut: 5 → 7 (warm 2.9s + marge)

Doc complète : docs/BENCH_SAFETY_CHECKS_2026-05-06.md
Script : tools/bench_safety_checks_models.py (reproductible, ~10-15 min)

Limite assumée : 46% de détection. À présenter en démo comme aide médecin,
pas certification. Amélioration V2 = prompt plus dirigé sur champs à vérifier.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 09:23:09 +02:00

96 lines
4.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Bench QW4 safety_checks — sélection du LLM contextuel
**Date** : 2026-05-06
**Contexte** : QW4 du sprint mai. La fonction `_call_llm_for_contextual_checks`
appelle Ollama avec un screenshot + prompt court pour générer 0-3 checks de
vérification supplémentaires que l'humain doit acquitter avant la reprise
d'un replay en pause supervisée (`safety_level=medical_critical`).
## Méthodologie
- **5 scénarios** : screenshots synthétiques de dossiers patient avec UNE
anomalie volontaire chacun (date de naissance aberrante, IPP incohérent,
diagnostic vide, code CIM inadapté à l'âge, forfait incohérent avec durée).
- **5 candidats** : `gemma4:latest`, `qwen3-vl:8b`, `qwen2.5vl:7b`,
`qwen2.5vl:3b`, `medgemma:4b`.
- **Protocole par modèle** : déchargement VRAM (keep_alive=0 sur tous les
modèles loaded) → 1er appel = cold start chronométré → 4 autres screenshots
× 3 runs = 12 mesures warm.
- **Métriques** : cold start, warm avg, warm p95, % JSON valide, % détection
(anomalie cible présente dans label/evidence d'au moins un check renvoyé).
- **Script** : `tools/bench_safety_checks_models.py`.
## Résultats
| Modèle | Cold (s) | Warm avg (s) | Warm p95 (s) | JSON | Détection |
|---|---:|---:|---:|---:|---:|
| `gemma4:latest` | 10.6 | **2.9** | 3.4 | 92% (12/13) | **46% (6/13)** |
| `qwen3-vl:8b` | 5.6 | — | — | **0%** (0/12) | 0% (0/12) |
| `qwen2.5vl:7b` | 9.4 | 6.6 | 8.1 | 100% (13/13) | 23% (3/13) |
| `qwen2.5vl:3b` | 6.0 | 2.0 | 2.5 | 100% (13/13) | 8% (1/13) |
| `medgemma:4b` | 2.0 | 0.5 | 0.7 | 100% (13/13) | **0%** (0/13) |
## Lecture
- **`medgemma:4b` retourne systématiquement `[]`** sur les 13 mesures.
Trop obéissant à "Si rien d'inhabituel à signaler, retourne []", refuse
de pointer ne serait-ce qu'une date 1900-01-01. **Mauvais choix par défaut**
malgré sa rapidité et sa spécialisation médicale revendiquée.
- **`qwen3-vl:8b` ignore `format=json` Ollama** : 0 réponse parsable. À écarter
pour cette tâche tant que le tooling Ollama / le modèle ne convergent pas.
- **`qwen2.5vl:7b`** détecte mais 2× plus lent (warm 6.6s) que gemma4 et tend
à inventer des anomalies de format de date qui ne sont pas la vraie cible.
- **`qwen2.5vl:3b`** rapide mais détection 8% — il "vérifie pour vérifier"
(renvoie souvent "vérification de la date de naissance" même quand la date
est correcte).
- **`gemma4:latest` gagne** : meilleur taux de détection (46%) ET deuxième
meilleur warm (2.9s). Tend à raisonner cohérence motif/diagnostic plutôt
que valeurs aberrantes brutes.
## Détail détection par scénario
| Scénario | gemma4 | qwen2.5vl:7b | qwen2.5vl:3b | medgemma:4b |
|---|:---:|:---:|:---:|:---:|
| Date naissance aberrante (1900) | ❌ | ✅ | ✅ | ❌ |
| IPP incohérent (`ABC@@##XYZ`) | ❌ | ❌ | ❌ | ❌ |
| Diagnostic principal vide | ✅ | ❌ | ❌ | ❌ |
| Code CIM inadapté à l'âge | ✅ | ❌ | ❌ | ❌ |
| Forfait UHCD vs durée 1h | ❌ | ❌ | ❌ | ❌ |
Aucun modèle ne détecte les 5 scénarios. **L'IPP corrompu et le forfait
incohérent ne sont détectés par personne** — ces anomalies demanderaient
soit un prompt plus dirigé (liste explicite des champs à vérifier), soit
un modèle plus large.
## Décision
- **Défaut serveur** : `RPA_SAFETY_CHECKS_LLM_MODEL=gemma4:latest`
- **Timeout** : `RPA_SAFETY_CHECKS_LLM_TIMEOUT_S=7` (warm 2.9s + marge)
- **Persistance VRAM** : `OLLAMA_KEEP_ALIVE=24h` recommandé pour éviter le
cold start de 10s en démo
Modifications appliquées dans `agent_v0/server_v1/safety_checks_provider.py`.
## Limites & travail futur
1. **46% de détection est faible** : à présenter comme aide au médecin, pas
comme certification. Le médecin reste le décideur.
2. **Prompt actuel trop générique** : un prompt qui liste explicitement les
champs à vérifier (DDN, IPP, diagnostic, forfait, cohérence âge/diagnostic)
donnerait probablement de meilleurs résultats. À mesurer en V2.
3. **Bench sur 5 anomalies seulement** : à étendre dès qu'on a un corpus de
vrais dossiers Easily Assure avec anomalies confirmées par Pauline / Amina.
4. **Pas de test sur des dossiers SANS anomalie** (faux positifs) : à ajouter.
5. **Pas de bench des modèles cloud** (gemma3:27b-cloud, deepseek, gpt-oss)
par contrainte 100% local — mais à explorer si on lève cette contrainte
pour les checks contextuels (qui ne contiennent pas de PII si on
anonymise les screenshots).
## Reproductibilité
```bash
cd /home/dom/ai/rpa_vision_v3
.venv/bin/python tools/bench_safety_checks_models.py
# (BENCH_TIMEOUT=60 par défaut, ~10-15 min sur RTX 5070)
```