One endpoint. Text in, structured procurement intelligence out. Works with or without Claude Haiku.
POST /comprendre takes casual French text about procurement — an invoice summary, a purchase request, a delivery note description — and returns structured analysis with Snake SAT classification.
It auto-detects the flux:
controle_entrant → doc type, line-by-line price anomaly, arithmetic check, decisionroutage_sortant → article matching, supplier routing, urgencyClaude Haiku extracts structured JSON from free text. Understands context, handles ambiguity, normalizes descriptions.
Quality: 0.92 (controle) / 0.90 (routage)
Latency: ~1.2s
Requires: ANTHROPIC_API_KEY in environment
Regex fallback parser extracts quantities, prices, product names, supplier. Snake doc_type model detects document type.
Quality: 0.65 (controle) / 0.55 (routage)
Latency: ~5ms
Requires: Nothing. Always works.
The response always tells you which mode was used: "haiku": true/false and "extraction_method": "claude_haiku" | "regex_fallback".
{
"text": "your procurement text here",
"factory_id": 3,
"anthropic": false
}
| Field | Type | Default | Description |
|---|---|---|---|
text | string | required | Free text. Invoice summary, purchase request, delivery note, anything procurement. |
factory_id | int | 3 | Monce factory ID. Affects which Snake models / ref tables are used. |
anthropic | bool | false | Set to true to enable Claude Haiku extraction. When false (default), uses regex + Snake only — no external API call, no API key needed, ~5ms. |
Default behavior: anthropic=false. The endpoint runs entirely on Snake models + regex. Fast, free, always works. Set anthropic=true when you want Haiku's contextual understanding for messy or ambiguous text.
"Facture GlassCorp, 200 trempes 10mm a 21.50 EUR et 150 feuilletes 44.2 a 58 EUR. Normalement c'est 21 EUR et 54 EUR. Total 13305 EUR HT."
Mention: supplier name, quantities, unit prices, expected prices. The more numbers, the better the anomaly detection.
"Facture FA-2026-0891 de GlassCorp SA. 3 lignes: VS-TMP10 Trempe 10mm x200 a 21.50, VS-FEU442 Feuil 44.2 x150 a 58.33, VS-INT16N Intercalaire 16mm x80 a 3.20. Total HT 13305.50, remise 3%, TVA 20%."
More structured = better extraction. Haiku handles both casual and formal equally well. Regex needs numbers and product keywords.
"On a besoin de 500 trempes 10mm urgence pour lundi, stock vide. Et aussi 200 intercalaires TGI 16mm."
Mention: quantities, product descriptions, urgency keywords (urgence/urgent/ASAP/stock vide/lundi/demain).
| Pattern | Example | Extracts |
|---|---|---|
| Product + qty | 200 trempes 10mm | qty=200, desc="Trempe 10mm" |
| Prices | 21.50 EUR, 58€ | pu_ht=21.50, 58.0 |
| Supplier | Facture GlassCorp | emetteur="GlassCorp" |
| Urgency | urgence, stock vide | urgence="critique" |
| Products | trempe, feuillete, intercalaire, miroir, joint, float, double/triple vitrage | description + field_type |
{
"factory_id": 3,
"version": "v19.364.0410",
"flux": "controle_entrant",
"haiku": true,
"extraction_method": "claude_haiku",
"document": {
"type": {"Prediction": "Facture", "Probability": {...}, "method": "snake_sat"},
"numero": "FA-2026-0891",
"date": "2026-04-05"
},
"fournisseur": {"match": "GlassCorp SA", "numero_fournisseur": "pending_snake_api", ...},
"controle_lignes": [
{
"ligne": 1,
"ref_fournisseur": "VS-TMP10",
"ref_interne": {"num_article": "pending_snake_api", "denomination": "Trempe 10mm clair", ...},
"controle_prix": {
"pu_facture": 21.50,
"pu_commande": 21.00,
"ecart_commande": "+2.4%",
"anomalie": {"Prediction": "Normal", "Probability": {...}}
},
"controle_qty": {"qty_facture": 200, "ecart": 0, "anomalie": "Conforme"},
"controle_calcul": {"coherent": true}
},
{
"ligne": 2,
"controle_prix": {
"pu_facture": 58.33,
"pu_commande": 54.00,
"ecart_commande": "+8.0%",
"anomalie": {"Prediction": "Alerte", "Probability": {...}}
}
}
],
"controle_totaux": {"verification_globale": "OK"},
"synthese": {
"anomalies": 1,
"alertes": [{"type": "prix", "ligne": 2, "detail": "..."}],
"decision": {"Prediction": "Verifier", "actions": ["..."]}
},
"xai": {
"doc_type_audit": "Snake SAT audit trail...",
"prix_audit": "L1: ... Normal. L2: ... Alerte.",
"decision_audit": "Verifier: 1 anomalie(s)."
},
"quality_score": 0.92,
"latency_ms": 1250
}
{
"factory_id": 3,
"version": "v19.364.0410",
"flux": "routage_sortant",
"haiku": false,
"extraction_method": "regex_fallback",
"articles_demandes": [
{"texte_brut": "500 Trempe 10mm", "article": {"num_article": "pending_snake_api", ...}, "qty": 500}
],
"routage_fournisseurs": [],
"proposition_commande": {"fournisseur": "pending_snake_api", "total_estime_ht": 12500.0, ...},
"quality_score": 0.55,
"latency_ms": 4
}
| Haiku ON | Haiku OFF | |
|---|---|---|
| Extraction | Claude parses context, handles ambiguity, normalizes names | Regex matches quantities + prices + known product keywords |
| Supplier name | Extracted from context ("facture de GlassCorp" → "GlassCorp SA") | Regex after "facture/de/chez" keyword |
| Line items | Full structured lines with ref, description, qty, pu, total | Matched products with detected prices (may miss or misalign) |
| Doc type | Claude detects + Snake confirms | Snake only (from text features) |
| Price anomaly | Snake on Haiku-extracted prices — accurate | Snake on regex-extracted prices — depends on text format |
| Totaux | Claude extracts brut/remise/TVA/TTC | Sum of detected line totals, assumes 20% TVA |
| Flux detection | Claude understands intent | Keyword scoring (invoice vs purchase words) |
| quality_score | 0.92 / 0.90 | 0.65 / 0.55 |
| Latency | ~1.2s | ~5ms |
Key insight: Without Haiku, the Snake models still classify correctly — they see the same features. The quality drop is entirely in extraction precision, not classification accuracy. If your text is well-structured with clear numbers, regex + Snake gets you 80% of the way.
ssh -i ~/.ssh/vlm-extraction-key.pem ubuntu@13.38.32.93 # Add key to environment file echo 'ANTHROPIC_API_KEY=sk-ant-api03-...' | sudo tee -a /opt/procurement/.env # Restart service sudo systemctl restart procurement
If your .zshrc exports AWS_BEARER_TOKEN or ANTHROPIC_API_KEY, forward it to the EC2:
# From your local machine — push the key from your shell environment ssh -i ~/.ssh/vlm-extraction-key.pem ubuntu@13.38.32.93 \ "echo 'ANTHROPIC_API_KEY=$ANTHROPIC_API_KEY' | sudo tee -a /opt/procurement/.env && \ sudo systemctl restart procurement"
The $ANTHROPIC_API_KEY expands locally from your .zshrc before the SSH command runs. The key gets written to the EC2's /opt/procurement/.env, which the systemd service reads via EnvironmentFile=.
# Quick test — should show "haiku": true
curl -s https://procurementclassifier.aws.monce.ai/comprendre \
-H 'Content-Type: application/json' \
-d '{"text": "Facture 200 trempes 10mm a 21.50 EUR"}' | python3 -m json.tool | grep haiku
curl -s https://procurementclassifier.aws.monce.ai/comprendre \
-H 'Content-Type: application/json' \
-d '{
"text": "Facture GlassCorp, 200 trempes 10mm a 21.50 EUR et 150 feuilletes 44.2 a 58 EUR. Normalement 21 et 54 EUR.",
"factory_id": 3
}'
curl -s https://procurementclassifier.aws.monce.ai/comprendre \
-H 'Content-Type: application/json' \
-d '{
"text": "On a besoin de 500 trempes 10mm urgence pour lundi, stock vide. Et 200 intercalaires TGI 16mm.",
"factory_id": 3
}'
# Even without API key, this returns a viable response
# with regex extraction + Snake classification
curl -s https://procurementclassifier.aws.monce.ai/comprendre \
-H 'Content-Type: application/json' \
-d '{"text": "500 trempes 10mm a 22 EUR, 100 intercalaires 16mm a 3.50 EUR"}'
Charles Dana — Monce SAS — 2026