Pourquoi ce module
Claude Opus 4.8 traite les PDFs et images nativement : multi-pages, OCR serveur Anthropic intégré, mise en page préservée, extraction jusqu'à 32 MB par PDF. Le marché des outils d'extraction documentaire (Docsumo, Rossum) vaut 2,5 Md€ en 2026, mais la majorité des cas BtoB (factures, contrats, rapports) ne nécessite pas ML custom — la vision Claude, combinée à JSON schema strict et tool use, résout 95 % des besoins production.
Ce module vous transforme en expert extraction documentaire serverless : vous lisez un PDF de 30 pages, en extrayez 500 lignes de facture avec TVA et totaux, validez le JSON et l'exportez en CSV, le tout en < 5 secondes.

@image.png charge le fichier (Read), Claude voit et décrit le contenu. Même principe pour un PDF — base de l'extraction documentaire de ce module.Prérequis : avoir une clé API Anthropic, maîtriser JSON schema et les bases du tool use (modules J1–J3), avoir lu la documentation vision d'Anthropic.
Objectifs pédagogiques
À l'issue de ce module, vous serez capable de :
- Charger et traiter des PDFs multi-pages (jusqu'à 100 pages) avec OCR serveur transparent, sans dépendre d'une API OCR externe
- Extraire du JSON structuré d'un PDF avec un schéma Zod/Pydantic strict, validation côté client, taux de précision 97+%
- Coder une skill
/facture-extractqui lit une facture PDF (même scannée), extrait lignes + TVA + totaux, valide et pousse en CSV - Coder une skill
/contrat-analyzequi parcourt un contrat multi-pages, marque les clauses critiques (prix, date, parties, durée), cite les pages source - Concevoir une stratégie de résolution : Opus 4.7/4.8 accepte jusqu'à 2576 px sur le grand côté (haute résolution, coords pixel-exactes) ; ~1568 px reste le sweet spot coût/perf à viser par downscaling quand la fidélité n'est pas critique (limite 5 MB/image après base64)
- Orchestrer vision + tool use : utiliser Claude pour le parsing visuel, valider avec un schéma JSON, en cas d'erreur, redemander un refinement au modèle
Plan détaillé
- Capacités vision Anthropic : PDF natif, OCR, formats, limites
- Limites critiques : taille, pages, résolution, coûts
- Downscaling et compression — best practices
- Pattern extraction structurée : vision + JSON schema
- Validation côté client : Zod/Pydantic
- Skill
/facture-extract: démo complète - Skill
/contrat-analyze: citation de pages source - Tool use vision : refinement itératif
- Tableaux et diagrammes : document understanding avancé
- Atelier : pipeline PDF → JSON → CSV
Capacités vision Anthropic
PDF support natif (depuis mai 2024)
Format : application/pdf, jusqu'à 100 pages par requête, jusqu'à 32 MB par PDF.
⚠️ Limites à revérifier : les plafonds de pages et de résolution évoluent avec les modèles. Les modèles récents (Opus 4.7+) acceptent des PDF plus volumineux et des images de résolution plus élevée que les valeurs historiques citées ici. Confirmez les limites en vigueur sur docs.claude.com avant de dimensionner un pipeline.
Avantages vs upload image séquentiellement :
| Approche | Latence | Coûts tokens | Limites |
|---|---|---|---|
| PDF natif (1 requête) | 2-3s pour 50 pages | ~2000 tokens pour 50p | Max 100 pages |
| Images séquentielles (50 requêtes) | 8-10s | ~3500 tokens (overhead requête) | Pas de contexte cross-page |
| Tesseract OCR local + texte | 15-20s | Réduit mais latence haute | Textes multi-colonne cassés |
Qui utiliser quand :
- PDF natif : extraction rapide, 1-100 pages, budget tokens OK
- Images séquentielles : > 100 pages, besoin de paralléléiser, contexte par page silo
- Tesseract local : données sensibles (RGPD), offline, mais OCR qualité médiane
Formats et limites
Formats supportés : PDF (natif), PNG, JPG, WebP, GIF (transparence + animation OK).
Tailles max par asset :
- Image : 5 MB après base64 (~6,67 MB brut)
- PDF : 32 MB brut
- Total requête : 200 MB (tous assets + texte)
Résolution (Opus 4.7 / 4.8) :
- Max haute résolution : 2576 px sur le grand côté (depuis Opus 4.7). Les coordonnées renvoyées par le modèle sont 1:1 avec les pixels (plus de recalage d'échelle). Activation automatique, aucun beta header requis.
- Sweet spot coût/perf : ~1568 px sur le grand côté (recommandé quand la pleine résolution n'apporte rien)
- Min lisibilité : ~512 px (OCR dégradé)
⚠️ Ne downscalez pas par réflexe. Une image pleine résolution sur Opus 4.7/4.8 peut coûter jusqu'à ~4784 image tokens (≈ 3× l'ancien plafond ~1600), mais pour de l'extraction fine (petits caractères, tampons, tableaux denses, manuscrit) la haute résolution augmente nettement la précision. Ramenez à ~1568 px uniquement quand la fidélité n'est pas critique.
Astuce : une facture de 800×1000 en JPG compressé = 120 KB, après base64 = 160 KB. Pas de souci. Une capture d'écran 3000×2000 non compressée = 8 MB ; compressée en WebP = 1,5 MB. À faire.
OCR natif vs approches legacy
L'OCR d'Anthropic est côté serveur, transparent, inclus dans le coût vision :
Ancienne approche (2023):
PDF → upload → Tesseract local (15s) → texte → Claude → JSON
Nouvelle approche (2024+):
PDF → Claude vision directement → JSON
(OCR serveur Anthropic inclus, 2-3s end-to-end)
Gain : -80 % latence, zéro dépendance OCR, OCR qualité supérieure (gère multilingue, sans serif, dégradé).
Limites critiques et stratégies
Limite 1 : 100 pages max par requête
Une facture = 1 page. Un contrat = 30 pages. Un rapport annuel = 150 pages.
Stratégie si > 100 pages :
async function extractLargeDoc(pdfPath: string) {
const numPages = await getPageCount(pdfPath);
const chunks = Math.ceil(numPages / 100);
for (let i = 0; i < chunks; i++) {
const startPage = i * 100 + 1;
const endPage = Math.min((i + 1) * 100, numPages);
const chunk = await extractPages(pdfPath, startPage, endPage);
results.push(...chunk);
}
return mergeResults(results); // Déduplique chevauchements
}
Limite 2 : 5 MB par image après base64
Une facture JPG scannée = ~2-3 MB décompressée, `450 KB après JPEG compression normal, OK. Une capture d'écran 4K sans compression = 15 MB, trop lourd.
Downscaling TypeScript :
import sharp from "sharp";
async function downscaleImage(filePath: string): Promise<Buffer> {
const metadata = await sharp(filePath).metadata();
// Optimisation COÛT : ramène à 1568px sur le grand côté.
// Le plafond réel d'Opus 4.7/4.8 est 2576px — vise TARGET=2576 si la fidélité prime
// (petits caractères, tableaux denses). Ici on optimise le coût.
const TARGET = 1568;
const scale = Math.min(
TARGET / (metadata.width ?? 1),
TARGET / (metadata.height ?? 1)
);
if (scale < 1) {
return sharp(filePath)
.resize(
Math.round((metadata.width ?? 1) * scale),
Math.round((metadata.height ?? 1) * scale),
{ fit: "inside", withoutEnlargement: true }
)
.jpeg({ quality: 85, progressive: true })
.toBuffer();
}
return fs.readFileSync(filePath);
}
// Avant vision call :
const imageBase64 = (await downscaleImage("facture.jpg")).toString("base64");
Limite 3 : Coûts tokens
Vision a un coût en image tokens :
- Formule : ⌈largeur / 28⌉ × ⌈hauteur / 28⌉ tokens visuels (chaque patch 28×28 pixels = 1 token)
- Sans overhead fixe (exemple : 200×200 px = 64 tokens, 1000×1000 px = 1296 tokens)
Facturation :
- Facture 1 page optimisée (1568×2000) = ~300 tokens
- Contrat 30 pages PDF = ~9000 tokens
- 1 million factures/mois = ~300M tokens/mois ≈ 700-2100 € selon le modèle (Haiku 4.5 à Sonnet 4.6 ; ou 350-1050 € avec batch processing 50 % discount, prix API juin 2026)
ROI : Automatiser 1000 factures/mois en-maison ≈ 40 heures FTE, coût ~2000 € vs 150 € en API = 13× ROI.
Pattern extraction structurée

@…png charge l'image (Read), Claude voit le tableau et ses barres, puis renvoie un JSON conforme au schéma demandé (valeurs lues à l'écran). Même chaîne pour une facture, un contrat ou un graphique scanné.Vision + JSON schema strict
Le pattern gold standard pour l'extraction est :
Voici l'architecture complète du pipeline extraction visuelle → JSON validé → application métier :
Chargement du schéma…
Vision lit le document → Claude raisonne sur la mise en page
→ Claude génère JSON conforme au schéma → Client valide
Schéma exemple (Zod TypeScript) :
import { z } from "zod";
const InvoiceSchema = z.object({
invoiceNumber: z.string().min(1),
date: z.string().date(),
dueDate: z.string().date(),
vendor: z.object({
name: z.string(),
address: z.string(),
taxId: z.string().regex(/^FR[0-9]{11}$/)
}),
customer: z.object({
name: z.string(),
address: z.string(),
taxId: z.string().optional()
}),
lineItems: z.array(
z.object({
description: z.string(),
quantity: z.number().positive(),
unitPrice: z.number().nonnegative(),
taxRate: z.number().min(0).max(1),
amount: z.number().nonnegative()
})
),
subtotal: z.number().nonnegative(),
taxAmount: z.number().nonnegative(),
totalDue: z.number().positive(),
pageNumber: z.number().min(1),
sourceHash: z.string().describe("SHA256 of original PDF for audit")
});
type Invoice = z.infer<typeof InvoiceSchema>;
Appel vision + refinement
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic();
// Note : pour des PDF réutilisés ou volumineux en production, préférez la Files API
// (uploader une fois, réutiliser `file_id` au lieu de renvoyer le base64 à chaque appel) :
// const f = await client.beta.files.upload({ file: ... });
// source: { type: "file", file_id: f.id }
// Le base64 ci-dessous reste pratique pour les fichiers ponctuels.
async function extractInvoice(pdfPath: string): Promise<Invoice> {
const pdfBase64 = fs.readFileSync(pdfPath).toString("base64");
const response = await client.messages.create({
model: "claude-opus-4-8",
max_tokens: 2048,
messages: [
{
role: "user",
content: [
{
type: "document",
source: {
type: "base64",
media_type: "application/pdf",
data: pdfBase64
}
},
{
type: "text",
text: `Extrait le JSON de cette facture en respectant strictement ce schéma:\n${JSON.stringify(InvoiceSchema)}\n\nRéponds UNIQUEMENT avec du JSON valide, pas d'explication.`
}
]
}
]
});
const jsonText = response.content[0].type === "text" ? response.content[0].text : "";
const parsed = JSON.parse(jsonText);
// Valide et lève si invalide
return InvoiceSchema.parse(parsed);
}
💡 Mieux : structured outputs natifs. Plutôt que « Réponds UNIQUEMENT en JSON » +
JSON.parse(qui peut échouer), contraignez la génération au schéma — le JSON est garanti conforme, sans boucle de refinement pour cause de JSON malformé. (Le mécanisme des structured outputs —output_config.format, contraintes supportées, prefills retirés — est traité à fond dans M3 ; ici on l'applique à l'extraction vision.)import { zodOutputFormat } from "@anthropic-ai/sdk/helpers/zod"; const res = await client.messages.parse({ model: "claude-opus-4-8", max_tokens: 2048, messages: [{ role: "user", content: [ { type: "document", source: { type: "base64", media_type: "application/pdf", data: pdfBase64 } }, { type: "text", text: "Extrais cette facture." }, ]}], output_config: { format: zodOutputFormat(InvoiceSchema) }, }); const invoice = res.parsed_output; // déjà typé Invoice, garanti conforme au schémaLe SDK retire automatiquement les contraintes Zod non supportées par les structured outputs (
.regex(),.min()/.max()numériques,.date()) du schéma envoyé et les revalide côté client. La boucle de refinement ci-dessous reste utile pour les erreurs métier (montants incohérents, total ≠ somme des lignes), pas pour le JSON malformé.
En cas d'erreur de parsing (ou de validation métier) :
async function extractInvoiceWithRefinement(
pdfPath: string,
maxRetries: number = 2
): Promise<Invoice> {
for (let attempt = 0; attempt <= maxRetries; attempt++) {
try {
return await extractInvoice(pdfPath);
} catch (error) {
if (attempt === maxRetries) throw error;
// Refinement : redemande au modèle de corriger
const retry = await client.messages.create({
model: "claude-opus-4-8",
max_tokens: 2048,
messages: [
{
role: "user",
content: [
{
type: "document",
source: { type: "base64", media_type: "application/pdf", data: pdfBase64 }
},
{
type: "text",
text: `ERREUR: ${error.message}\n\nRée-examine la facture. Ton dernier JSON était invalide car: [détail]. Corrige-le et valide: ${JSON.stringify(InvoiceSchema)}`
}
]
}
]
});
}
}
}
Skill /facture-extract
Structure complète d'une skill d'extraction facture.
Architecture (~/.claude/skills/facture-extract/) :
facture-extract/
├── SKILL.md # orchestration
├── VALIDATION.md # schéma Zod complet
├── EXAMPLES.md # 3 factures réelles (anonymisées)
└── tests/
├── golden_facture_1.pdf
├── golden_facture_1.json
└── integration.test.ts
SKILL.md (extrait) :
---
name: facture-extract
description: PDF facture → JSON validé + CSV
allowed-tools:
- Bash(cat, jq, csv)
argument-hint: <PDF_PATH>
model: claude-opus-4-8
---
## Phases
### Phase 1 — Downscale et base64
Si image > 1568px ou > 5 MB, compresse via Sharp.
### Phase 2 — Vision extraction
Appelle Claude vision sur le PDF. Schéma strict (Zod).
### Phase 3 — Validation
Valide le JSON via Zod. Si erreur, refinement.
### Phase 4 — CSV export
Génère CSV (headers: invoiceNumber, vendor, amount, tax, date).
## Input
PDF facture, n'importe quel format ou scan.
## Output
- JSON structuré (validé)
- CSV ligne pour import en base
- Audit: source hash + timestamp
Démo exécution :
/facture-extract ~/Downloads/Acme_Invoice_2026-05-03.pdf
# Sortie :
# ✓ Downscale: 2400×3200 → 1568×2090
# ✓ Vision: 342 tokens consommés
# ✓ JSON validé: 1 facture, 18 lignes
# ✓ CSV créé: facture_acme_20260503.csv
# {
# "invoiceNumber": "INV-2026-0547",
# "vendor": { "name": "ACME Corp", ... },
# "totalDue": 4850.50,
# "taxAmount": 845.67,
# ...
# }
Skill /contrat-analyze
Pour les contrats multi-pages, le besoin est différent : pas une simple extraction, mais annotation + citation de pages source.
Voici comment structurer le workflow d'analyse de contrats multi-pages :
Chargement du schéma…
Architecture :
contrat-analyze/
├── SKILL.md
├── CLAUSES.md # 30 types de clauses identifiées
└── EXAMPLES.md # contrat 15p annoté
Phases :
1. Vision lit tout le contrat (jusqu'à 100p)
2. Identifie : parties, dates, montants, durée, résiliation, IP
3. Pour chaque clause critique → cite la page source exacte
4. Génère JSON + Markdown annotée
Schéma de sortie :
const ContractClauseSchema = z.object({
type: z.enum([
"parties",
"effective_date",
"term_months",
"price",
"payment_terms",
"termination",
"ip_ownership",
"confidentiality",
"liability_cap",
"governing_law"
]),
text: z.string(),
pageNumbers: z.array(z.number()),
severity: z.enum(["critical", "important", "reference"]),
redFlag: z.string().optional().describe("Risque légal détecté")
});
const ContractAnalysisSchema = z.object({
documentName: z.string(),
totalPages: z.number(),
parties: z.array(z.string()),
startDate: z.string().date(),
endDate: z.string().date().optional(),
estimatedValue: z.number().optional(),
clauses: z.array(ContractClauseSchema),
summary: z.string().max(500)
});
Démo :
/contrat-analyze ~/contrats/SLA_Provider_2026.pdf
# ✓ 12 pages traitées
# Parties: "Acme Inc", "Tech Consulting SARL"
# ✓ Dates extraites: 2026-05-01 → 2027-04-30
# ✓ Montant: 150 000 € (p. 3)
# ✓ Clauses critiques:
# - Résiliation anticipée (p. 8) [RED FLAG: délai 15j vs norme 30j]
# - Limitation responsabilité: 50k€ max (p. 11)
# - Loi applicable: droit français (p. 12)
Tableaux et diagrammes
Tableau extraction
Les tableaux PDF donnent du fil à retordre à l'OCR classique. Vision Anthropic les détecte et les structure bien.
Pattern :
const TableCellSchema = z.object({
row: z.number(),
col: z.number(),
text: z.string(),
isHeader: z.boolean()
});
const TableExtractionSchema = z.object({
pageNumber: z.number(),
tableIndex: z.number(),
rows: z.number(),
cols: z.number(),
cells: z.array(TableCellSchema),
markdown: z.string().describe("Rendu markdown du tableau")
});
async function extractTable(pdfPath: string, tableNumber: number = 0) {
// Vision lit le PDF
// Identifie les tableaux par structure visuelle (cellules, bordures)
// Extrait en JSON structuré
// Convertit en Markdown pour réédition
}
Diagrammes (flowchart, architecture)
Vision détecte les formes, flèches, texte dans les diagrams. Utile pour :
- Architectures système (data lineage)
- Flowcharts process (compliance docs)
- Organigrammes (org charts)
Pattern :
const DiagramElementSchema = z.object({
id: z.string(),
type: z.enum(["box", "circle", "diamond", "arrow", "text"]),
label: z.string(),
connections: z.array(z.string()).describe("IDs des éléments connectés")
});
const DiagramSchema = z.object({
pageNumber: z.number(),
elements: z.array(DiagramElementSchema),
interpretation: z.string().describe("Explication du diagramme en prose")
});
Vision + JSON schema = reconstruction visuelle → texte → back to structure.
Atelier : pipeline PDF → JSON → CSV (60 min)
Livrable :
- Skill
/facture-extractexécutable - Zod schema validant sur 5 factures test
- CSV exporté, importable en Excel
- Audit trail (hash PDF + timestamp)
Tâches :
-
Downscaling (15 min)
- Prendre 3 factures : PDF natif, JPG scan, PNG screenshot
- Tester downscale via Sharp
- Vérifier taille finale < 5 MB
-
Schema + validation (20 min)
- Écrire Zod schema complet pour 1 facture
- Parser 3 factures, relever différences de structure
- Adapter schema (champs optionnels, alternatives)
-
Vision call + refinement (15 min)
- Appeler Claude vision sur les 3 factures
- Traiter erreurs parsing (retry logic)
- Afficher taux de précision (champs extraits / champs attendus)
-
CSV export + validation (10 min)
- Générer CSV avec headers corrects
- Importer dans un tableur (Excel, Sheets)
- Vérifier montants, TVA, dates
Document understanding avancé
Au-delà des factures simples, vous rencontrez :
| Type de doc | Défi visuel | Pattern |
|---|---|---|
| Factures multi-colonnes | Colonnes pas alignées | Vision détecte colonnes → extrait par colonne |
| Contrats scannés dégradés | OCR peu lisible | Refinement + prompt pour "lis même si flou" |
| Tableaux imbriqués | Limites de cellules invisibles | Vision détecte via espaces, aligne |
| Diagrammes + texte mix | Éléments superposés | Deux passes : d'abord shapes, puis texte OCR |
| Formules mathématiques | LaTeX/MathML | Vision interprète, générer comme "x + 2y = 5" |
Guideline : si un humain ne peut pas lire, vision non plus. Mais si lisible pour humain, vision le fait 97 % du temps.
Pour aller plus loin
- 📖 Anthropic — Vision guide
- 📖 Anthropic — PDF support & OCR
- 🛠 Sharp — image processing — librairie recommandée pour downscale TypeScript
- 🛠 Zod — TypeScript schema validation — validation post-extraction
- 📦 instructor-js — structured output pour TypeScript (alternative Zod)
- 🎯 Modules complémentaires : M3 Hallucination mitigation (validation extraction), M5 Long-context strategies (contrats > 100p), M11 ROI mesurable (ROI automatisation doc)
Récapitulatif
À retenir absolument :
- PDF natif = 100 pages max, 32 MB max, OCR transparent (côté Anthropic)
- Downscale à 1568×1568 pour l'efficacité, compresse agressivement
- JSON schema strict + refinement itératif = 97%+ précision
- Vision + tool use = citez les pages source (audit trail critique)
- Coûts : 1000 factures = 150 € API vs 400 € FTE, ROI immédiat