ordinarthur 2f96238efe
All checks were successful
Build & Deploy API / build-and-deploy (push) Successful in 1m21s
feat(ocr): throttle --delay-ms + script generate-expected pour ground truth
Améliorations sur la commande de bench OCR validée avec 5 factures
réelles via Mistral (100 % accuracy obtenue sur l'échantillon test) :

  - Option `--delay-ms` (default 1500 ms) entre 2 appels provider pour
    éviter le rate limit Mistral (1300 free tier ≈ 1 req/s). Permet de
    benchmark les 27 factures sans HTTP 429.
  - Script `e2e/fixtures/invoices/generate-expected.mjs` qui parse les
    PDFs via `pdftotext -layout` (poppler-utils) et génère
    automatiquement les <name>.expected.json :
      • Numéro F2026-XXXX
      • Dates DD/MM/YYYY ou format long ("21 avril 2026")
      • Montant TTC en cents (gère séparateur milliers "2 775,02")
      • clientName en gérant 3 templates :
          - "DOIT : <Nom>"
          - "Facturé à :" en colonne droite
          - "ADRESSÉE À ... ÉCHÉANCE" côte à côte
    Re-générable, idempotent (skip si .expected.json existe déjà).

Le .gitignore du dossier reste sur `*` exclude pour ne pas commit les
PDFs (cohérent avec assets/test-invoices/ déjà ignoré racine), mais
autorise le script `generate-expected.mjs` (reproductible, sans secret).

Workflow utilisateur :
  1. Pose tes PDFs dans e2e/fixtures/invoices/
  2. `node generate-expected.mjs` génère les ground truth en lot
  3. Vérifie/corrige à la main si besoin (parser pas 100 % parfait sur
     tous les templates exotiques)
  4. `OCR_PROVIDER=mistral pnpm ocr:validate` lance le bench réel

Résultat baseline observé sur 5 factures Mistral en mode réel :
  - clientName     5/5  (100 %)
  - clientEmail    5/5  (100 %)
  - numero         5/5  (100 %)
  - amountTtcCents 5/5  (100 %)
  - issueDate      5/5  (100 %)
  - dueDate        5/5  (100 %)
  - Latence moyenne : 3,1 s / facture

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-18 16:05:37 +02:00
..

Fixtures OCR — factures réelles pour bench provider

Dossier de référence pour la commande node ace ocr:validate qui mesure la qualité d'extraction OCR (Mock, Mistral, ou autre futur provider) sur un set de factures réelles avec ground truth.

Comment ajouter une facture

  1. Dépose ton PDF dans ce dossier : ma-facture.pdf (ou .png, .jpg).
  2. Crée à côté ma-facture.expected.json avec les valeurs lisibles à l'œil sur la facture :
{
  "expected": {
    "clientName": "Boulangerie Martin SARL",
    "clientEmail": "compta@boulangerie-martin.fr",
    "numero": "F-2024-0042",
    "amountTtcCents": 124000,
    "issueDate": "2024-04-15",
    "dueDate": "2024-05-15"
  },
  "notes": "facture B2B classique, en-tête simple"
}

Champs :

Champ Format Note
clientName String Le nom de la société/personne facturée. Variantes acceptées via similarité Jaccard ≥ 85 % (tokens) — utile si l'OCR rate un "SARL" final.
clientEmail String OR null null si pas d'email sur la facture.
numero String Tel qu'imprimé. Comparaison case-insensitive trim.
amountTtcCents Integer Montant TTC en centimes. Comparaison exacte (la précision financière compte).
issueDate YYYY-MM-DD Comparaison au jour près.
dueDate YYYY-MM-DD Idem.

Le champ notes est libre, ignoré par la commande — pratique pour documenter "facture avec logo qui couvre 30 % du haut", "facture manuscrite scannée", etc.

Comment lancer le bench

# Avec le provider courant (.env) — par défaut "mock"
pnpm --filter @rubis/api exec node ace ocr:validate

# Forcer Mistral (vrai OCR — coûte des tokens API)
OCR_PROVIDER=mistral MISTRAL_API_KEY=sk-... \
  pnpm --filter @rubis/api exec node ace ocr:validate

# Avec un dossier custom + rapport JSON
node ace ocr:validate --fixtures-dir=./other-pdfs --out=report.json

Lecture du résultat

La commande affiche :

  • Pour chaque facture : check par champ (✓/✗) avec expected vs got + confidence du provider
  • Sommaire : nombre de factures 100 % match, accuracy globale champs, latence moyenne
  • Précision par champ : pour chaque type (amount, dueDate, clientName…), le ratio de matches

Exit code 1 si une facture a échoué → utile en CI pour bloquer un déploiement OCR si la qualité a chuté.

Diversité du set

Pour un bench représentatif, viser au moins :

  • 5 factures B2B (en-tête société, SIRET, TVA, montant rond)
  • 5 factures de prestation (taux horaire, jours, multilignes)
  • 2-3 factures avec spécificités (sous-totaux multiples, devises mixtes, scan basse qualité)
  • 1 facture mauvaise : floue, manuscrite, photo prise à la volée — pour mesurer le worst case et calibrer la confidence du provider

Les vraies factures peuvent contenir des infos sensibles — ne pas commit dans le repo public. Le .gitignore exclut ce dossier par défaut (cf. e2e/fixtures/invoices/.gitignore).

Cibler un seuil de qualité

Calibrage suggéré V1 (à ajuster après premier run réel) :

  • amountTtcCents : ≥ 98 % d'accuracy (zéro tolérance sur l'argent)
  • dueDate / issueDate : ≥ 95 %
  • numero : ≥ 95 %
  • clientName : ≥ 90 % (avec fuzzy)
  • clientEmail : ≥ 80 % (souvent absent → null fréquent)

En-dessous, soit améliorer le provider (prompt Mistral, post-processing), soit baisser la confiance affichée à l'user dans le SPA (badge "à vérifier" sur les drafts).