Spaces:
Running
CLAUDE.md — Picarones
Plateforme de benchmark OCR/HTR pour documents patrimoniaux. Repo : github.com/maribakulj/Picarones HuggingFace Space : huggingface.co/spaces/Ma-Ri-Ba-Ku/Picarones (Docker, port 7860)
Setup
pip install -e ".[dev,web]" # IMPORTANT : toujours inclure [web] pour les tests
pytest tests/ -q --tb=short # lancer les tests
picarones demo --output rapport.html # rapport démo sans moteur installé
picarones serve --port 8080 # interface web locale
Mise à jour Codespace complète :
git pull && pip install -e ".[dev,web]" && picarones demo --output rapport_demo.html && picarones serve --port 8080
Architecture
picarones/
├── cli.py # CLI Click : run, metrics, engines, info, demo, serve, import, history, robustness
├── fixtures.py # Données de test fictives (documents médiévaux)
├── core/
│ ├── corpus.py # Chargement corpus (dossier local, ALTO XML, PAGE XML)
│ ├── metrics.py # CER, WER, MER, WIL (via jiwer)
│ ├── normalization.py # Profils : nfc, caseless, minimal, medieval_french, early_modern_french,
│ │ # medieval_latin, early_modern_english, medieval_english
│ ├── statistics.py # Bootstrap CI 95%, Wilcoxon (scipy optionnel), corrélations
│ ├── runner.py # Orchestrateur benchmark (ThreadPool IO-bound, ProcessPool CPU-bound)
│ ├── results.py # Modèles de données DocumentResult, BenchmarkResults + export JSON
│ ├── confusion.py # Matrice de confusion unicode
│ ├── char_scores.py # Scores ligatures (fi, fl, œ, æ, ꝑ…) et diacritiques
│ ├── taxonomy.py # Taxonomie erreurs 9 classes (confusion visuelle, abréviation…)
│ ├── structure.py # Analyse structurelle (blocs, lignes, mots)
│ ├── image_quality.py # Métriques qualité image (contraste, bruit, résolution…)
│ ├── difficulty.py # Score difficulté intrinsèque par document
│ ├── hallucination.py # Détection hallucinations VLM (score ancrage, ratio longueur)
│ ├── line_metrics.py # Distribution erreurs par ligne (Gini, percentiles)
│ ├── history.py # Suivi longitudinal SQLite
│ └── robustness.py # Analyse robustesse (bruit, flou, rotation, résolution)
├── engines/
│ ├── base.py # BaseEngine avec execution_mode ("io" ou "cpu")
│ ├── tesseract.py # execution_mode = "cpu"
│ ├── pero_ocr.py # execution_mode = "cpu"
│ ├── mistral_ocr.py # endpoint /v1/ocr dédié (pas chat/completions)
│ ├── google_vision.py
│ └── azure_doc_intel.py
├── llm/
│ ├── base.py
│ ├── mistral_adapter.py # POST /v1/chat/completions — BUG ACTIF : sortie vide à corriger
│ ├── openai_adapter.py
│ ├── anthropic_adapter.py
│ └── ollama_adapter.py
├── pipelines/
│ ├── base.py # OCRLLMPipeline — BUG ACTIF : résultats 0/0 documents
│ └── over_normalization.py
├── prompts/ # 8 fichiers .txt FR+EN
│ ├── medieval_french.txt
│ ├── medieval_french_zero_shot.txt
│ ├── early_modern_french.txt
│ ├── early_modern_french_zero_shot.txt
│ ├── medieval_english.txt
│ ├── early_modern_english.txt
│ ├── medieval_latin.txt
│ └── zero_shot.txt
├── report/
│ ├── generator.py # Rapport HTML auto-contenu (Chart.js + diff2html)
│ └── diff_utils.py
├── web/
│ └── app.py # FastAPI, SSE, upload corpus ZIP, endpoints modèles dynamiques
└── importers/
├── iiif.py
├── htr_united.py
├── huggingface.py
├── gallica.py
└── escriptorium.py
Bugs actifs à corriger en priorité
🔴 BUG CRITIQUE — Pipeline OCR+LLM sortie vide
Symptôme : le pipeline tesseract → mistral:ministral-3b-latest s'exécute (15s de traitement
visible dans les logs) mais produit une sortie vide "" pour chaque document. Le rapport affiche
CER 100% avec "Aucune sortie" et 0/0 documents.
Localisation probable :
picarones/llm/mistral_adapter.py: vérifier quechoices[0].message.contentest bien extraitpicarones/pipelines/base.py: vérifier queresult.hypothesisest bien mis à jour après l'appel LLM, et que les DocumentResult sont bien collectés par le runner- Le modèle
ministral-3b-latestsupporte bienPOST /v1/chat/completions
À faire : ajouter des logs DEBUG (prompt envoyé tronqué, statut HTTP, contenu brut réponse) pour diagnostiquer sans modifier le comportement.
🟡 CI — python-multipart
Symptôme : 114 tests ERROR car python-multipart absent lors de l'import de web/app.py.
Fix : dans .github/workflows/ci.yml, remplacer pip install -e ".[dev]" par
pip install -e ".[dev,web]".
🟡 Tests fixtures post-Sprint 10
5 tests échouent : counts de moteurs (4→5) et flag is_pipeline pour gpt-4o-vision.
🟡 Test Windows SQLite
TestCLIHistory::test_history_empty_db — PermissionError sur Windows (fichier encore ouvert
lors du os.unlink). À corriger avec try/except autour du unlink.
🟡 Test HuggingFace language filter
TestHuggingFaceImporter::test_search_language_filter — assertion sur ds.language.
Règles importantes — ne pas toucher
- Ne jamais retirer
python-multipartdes dépendances : FastAPI vérifie sa présence à l'import du module (décoration@app.postavecUploadFile), pas à l'exécution. Ça casse tous les tests web au setup. - Ne jamais mettre
except Exception: pass: remplacer parlogger.warning("[module] fonctionnalité dégradée : %s", e). - Toujours utiliser
logger.warningavec message explicite quand une fonctionnalité optionnelle échoue (confusion, taxonomy, structure, image_quality, etc.). - Les profils de normalisation sont dans
picarones/core/normalization.py— l'endpoint/api/normalization/profilesdoit les lire dynamiquement depuis ce fichier, pas depuis une liste statique.
Variables d'environnement
# Clés API LLM (configurées dans HuggingFace Space Settings → Variables and secrets)
MISTRAL_API_KEY=...
OPENAI_API_KEY=sk-...
ANTHROPIC_API_KEY=sk-ant-...
# OCR cloud (optionnel)
GOOGLE_APPLICATION_CREDENTIALS=/path/to/creds.json
AZURE_DOC_INTEL_ENDPOINT=https://...
AZURE_DOC_INTEL_KEY=...
Pipelines OCR+LLM — modes
| Mode | Description |
|---|---|
| zero_shot | Le LLM reçoit l'image directement et transcrit sans OCR préalable (VLM) |
| post_correction_texte | OCR → texte brut → LLM corrige le texte (modèles texte seul) |
| post_correction_image_texte | OCR → LLM reçoit image + texte brut pour correction (VLM) |
ministral-3b-latest = modèle texte pur → utiliser mode post_correction_texte uniquement.
CI/CD
- CI GitHub Actions :
.github/workflows/ci.yml— Python 3.11/3.12, Linux/macOS/Windows - Sync HuggingFace :
.github/workflows/sync_to_huggingface.yml— push auto sur main (nécessite secretHF_TOKENdans GitHub Settings → Secrets → Actions) - HuggingFace Space : Docker sur port 7860
Sprints réalisés
| Sprint | Contenu |
|---|---|
| 1 | Structure Python, Tesseract, Pero OCR, CER/WER, CLI |
| 2 | Rapport HTML v1 (Chart.js, diff coloré, galerie) |
| 3 | Pipelines OCR+LLM (3 modes), GPT-4o/Claude/Mistral/Ollama, prompts versionnés |
| 4 | Adaptateurs API OCR (Mistral OCR, Google Vision, Azure), import IIIF, CER diplomatique |
| 5 | Métriques avancées (unicode, ligatures, structure, qualité image, taxonomie 9 classes) |
| 6 | Interface web FastAPI, HTR-United/HuggingFace, bilingue FR/EN, upload ZIP |
| 7 | Rapport HTML v2 (Wilcoxon, bootstrap, clustering, score difficulté, URL stateful, CSV) |
| 8 | eScriptorium, Gallica API, suivi longitudinal SQLite, analyse robustesse |
| 9 | Documentation, packaging, Docker, CI/CD GitHub Actions, PyInstaller, version 1.0.0-Beta |
| 10 | Distribution erreurs par ligne (Gini, percentiles), détection hallucinations VLM |
| 11 | Internationalisation FR/EN, profils normalisation anglais (early_modern, medieval, secretary_hand) |
| 12 | Upload ZIP depuis navigateur, filtrage fichiers macOS ._*, profils exclusion caractères, sélecteur modèles dynamique |
| 13 | Nettoyage pyproject.toml, exceptions silencieuses → warnings, parallélisation runner (ThreadPool/ProcessPool), timeout par doc, résultats partiels NDJSON, validation statistique Wilcoxon |
Contexte développement
- Environnement : GitHub Codespaces (
/workspaces/Picarones), Python 3.12 - Tests : ~1020 tests (après sprint 13)
- Branche active :
main(ouclaude/setup-picarones-project-FKKnsselon le contexte) - Transcript de la conversation de développement :
/mnt/transcripts/2026-03-11-14-01-41-picarones-ocr-bench-project.txt