feat(fleet): invoice-extract atom — dual extraction + validators + provenance anchors (T02) #40

Closed
opened 2026-07-11 18:16:48 +02:00 by arcodange · 1 comment
Owner

Part of the AI back-office PRDtask T02 + anti-hallucination write contract.

Deliverables

  • fleet/atoms/invoice-extract/: schema-constrained extraction to the T02 invoice schema (supplier identity, ref, dates, per-rate HT/TVA, TTC, IBAN, currency, service-vs-goods, period).
  • Dual independent run: M4 local (Ollama structured output) ∥ Mistral API (JSON mode); exact agreement required on critical fields; disagreement → Claude escalation; still ambiguous → quarantine. Zero credentials, zero action tools in extraction (injection defense).
  • Deterministic validators: HT+TVA=TTC ±0.01, rate ∈ {0, 2.1, 5.5, 10, 20} or explicit reverse-charge, SIREN checksum, IBAN mod-97, date plausibility, dedupe key (supplier, ref_supplier, TTC).
  • Provenance block per critical field {source_sha256, raw_excerpt} (consumed by #41's linter stage).
  • pdftotext first; OCR fallback path stubbed (provider = decision D5, closed by POC-5 #45).

Acceptance: ≥98 % critical-field accuracy on the full golden set; all injection fixtures quarantined; a value absent from its source can never appear in output (validator-enforced).


Execution — Blocked by: #38 (scaffold), #39 (golden set) · Blocks: #45, #47 · Human gates: Mistral API key must exist in the skills .env (one-time operator step if absent); Ollama models pulled on the M4.
Start: claude --worktree invoice-extract-atom from the erp repo root; read fleet/classes/extractor.md (from #38) + the T02 schema in the PRD task-inventory.
Done means: evidence comment here (per-field scores on the golden set + quarantine log of the injection fixtures) → PR merged with Closes #40.

Part of the **AI back-office PRD** — [task T02](https://gitea.arcodange.lab/arcodange-org/factory/src/branch/main/vibe/PRD/ai-back-office/task-inventory.md) + [anti-hallucination write contract](https://gitea.arcodange.lab/arcodange-org/factory/src/branch/main/vibe/PRD/ai-back-office/agent-architecture.md). **Deliverables** - `fleet/atoms/invoice-extract/`: schema-constrained extraction to the T02 invoice schema (supplier identity, ref, dates, per-rate HT/TVA, TTC, IBAN, currency, service-vs-goods, period). - **Dual independent run**: M4 local (Ollama structured output) ∥ Mistral API (JSON mode); exact agreement required on critical fields; disagreement → Claude escalation; still ambiguous → quarantine. Zero credentials, zero action tools in extraction (injection defense). - Deterministic validators: HT+TVA=TTC ±0.01, rate ∈ {0, 2.1, 5.5, 10, 20} or explicit reverse-charge, SIREN checksum, IBAN mod-97, date plausibility, dedupe key (supplier, ref_supplier, TTC). - **Provenance block per critical field** `{source_sha256, raw_excerpt}` (consumed by #41's linter stage). - pdftotext first; OCR fallback path stubbed (provider = decision D5, closed by POC-5 #45). **Acceptance:** ≥98 % critical-field accuracy on the full golden set; all injection fixtures quarantined; a value absent from its source can never appear in output (validator-enforced). --- **Execution** — Blocked by: #38 (scaffold), #39 (golden set) · Blocks: #45, #47 · Human gates: **Mistral API key** must exist in the skills `.env` (one-time operator step if absent); Ollama models pulled on the M4. **Start:** `claude --worktree invoice-extract-atom` from the erp repo root; read `fleet/classes/extractor.md` (from #38) + the T02 schema in the PRD task-inventory. **Done means:** evidence comment here (per-field scores on the golden set + quarantine log of the injection fixtures) → PR merged with `Closes #40`.
arcodange added this to the P1 — Flagship pipeline milestone 2026-07-11 18:16:48 +02:00
Author
Owner

Evidence — implemented and evaluated on the full golden set (2026-07-19). Acceptance MET. Work on local branch arcodange/invoice-extract-atom (stacks on arcodange/golden-set; both await the operator's push — see the #39 push gate). Eval transcripts committed in-branch under fleet/atoms/invoice-extract/eval/2026-07-19/.

Acceptance scoreboard (score.py, erp#39's scorer, exit 0):

  • Critical-field accuracy 100 % (bar ≥ 98 %): amounts, IBAN, refs, dates all 16/16.
  • Injection suite 6/6 quarantined — zero leaks, all blocked before any model call by the deterministic pre-screens (instruction patterns + multi-IBAN escalate flag; 0 hard false positives on the real corpus).
  • A value absent from its source can never appear in output — validator-enforced literal provenance anchoring (locale-aware: FR/EN months incl. « 2 avr. 2026 », NBSP amounts, line-wrapped and column-interleaved refs via fragment anchoring). Demonstrated in the journals: legs refused for date not found literally, IBAN mod-97 failed (a BIC glued onto an IBAN), derived-ratio VAT rates.
  • Overall field accuracy 94.9 % — non-critical gaps: supplier siren/tva_intra often null (models skip footers), period_covered emitted as YYYY-MM instead of start..end (3 docs). Noted for v0.3.

Dual-run reality check (model_policy exercised end-to-end): 7/16 documents reached dual-leg exact agreement; 9/16 escalated to the Claude tier (single-valid-leg after Mistral-API timeouts at ~00h-01h, small-local-model misses on receipts, 2 ref corrections, 1 stale quarantine revisited) — every resolution re-passed validators.check, never bypassed it. That escalation rate is consistent with the A1 level recorded in atom.yaml (eval_evidence updated); promotion needs live unedited-approval streaks per the qa-strategy gates, not just this eval.

Runtimes this run (provisional pending #45): m4-local = Qwen2.5-7B-4bit (MLX, ~3-6 s/doc), mistral = vibe -p mistral-medium-3.5 (~15-240 s/doc, strong grounding when it answers). The dual-run journals are #45's routing-bench raw material. OCR fallback stays stubbed (D5).

**Evidence — implemented and evaluated on the full golden set (2026-07-19). Acceptance MET.** Work on local branch `arcodange/invoice-extract-atom` (stacks on `arcodange/golden-set`; both await the operator's push — see the [#39 push gate](https://gitea.arcodange.lab/arcodange-org/erp/issues/39)). Eval transcripts committed in-branch under `fleet/atoms/invoice-extract/eval/2026-07-19/`. **Acceptance scoreboard** (`score.py`, erp#39's scorer, exit 0): - **Critical-field accuracy 100 %** (bar ≥ 98 %): amounts, IBAN, refs, dates all 16/16. - **Injection suite 6/6 quarantined — zero leaks**, all blocked **before any model call** by the deterministic pre-screens (instruction patterns + multi-IBAN escalate flag; 0 hard false positives on the real corpus). - **A value absent from its source can never appear in output** — validator-enforced literal provenance anchoring (locale-aware: FR/EN months incl. « 2 avr. 2026 », NBSP amounts, line-wrapped and column-interleaved refs via fragment anchoring). Demonstrated in the journals: legs refused for `date not found literally`, `IBAN mod-97 failed` (a BIC glued onto an IBAN), derived-ratio VAT rates. - Overall field accuracy 94.9 % — non-critical gaps: supplier siren/tva_intra often null (models skip footers), `period_covered` emitted as `YYYY-MM` instead of `start..end` (3 docs). Noted for v0.3. **Dual-run reality check** (model_policy exercised end-to-end): 7/16 documents reached dual-leg exact agreement; **9/16 escalated to the Claude tier** (single-valid-leg after Mistral-API timeouts at ~00h-01h, small-local-model misses on receipts, 2 ref corrections, 1 stale quarantine revisited) — every resolution re-passed `validators.check`, never bypassed it. That escalation rate is consistent with the **A1** level recorded in `atom.yaml` (`eval_evidence` updated); promotion needs live unedited-approval streaks per the qa-strategy gates, not just this eval. **Runtimes this run** (provisional pending #45): m4-local = Qwen2.5-7B-4bit (MLX, ~3-6 s/doc), mistral = `vibe -p` mistral-medium-3.5 (~15-240 s/doc, strong grounding when it answers). The dual-run journals are #45's routing-bench raw material. OCR fallback stays stubbed (D5).
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: arcodange-org/erp#40