/comprendre

One endpoint. Text in, structured procurement intelligence out. Works with or without Claude Haiku.

What it does

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:

Two modes

WITH Haiku

Claude 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

WITHOUT Haiku

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".

Request

{
  "text": "your procurement text here",
  "factory_id": 3,
  "anthropic": false
}
FieldTypeDefaultDescription
textstringrequiredFree text. Invoice summary, purchase request, delivery note, anything procurement.
factory_idint3Monce factory ID. Affects which Snake models / ref tables are used.
anthropicboolfalseSet 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.

How to prompt it

Invoice control (best prompts)

"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.

Purchase routing (best prompts)

"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).

What the regex fallback can parse

PatternExampleExtracts
Product + qty200 trempes 10mmqty=200, desc="Trempe 10mm"
Prices21.50 EUR, 58€pu_ht=21.50, 58.0
SupplierFacture GlassCorpemetteur="GlassCorp"
Urgencyurgence, stock videurgence="critique"
Productstrempe, feuillete, intercalaire, miroir, joint, float, double/triple vitragedescription + field_type

Response (controle_entrant)

{
  "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
}

Response (routage_sortant)

{
  "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
}

With vs Without Haiku — what changes

Haiku ONHaiku OFF
ExtractionClaude parses context, handles ambiguity, normalizes namesRegex matches quantities + prices + known product keywords
Supplier nameExtracted from context ("facture de GlassCorp" → "GlassCorp SA")Regex after "facture/de/chez" keyword
Line itemsFull structured lines with ref, description, qty, pu, totalMatched products with detected prices (may miss or misalign)
Doc typeClaude detects + Snake confirmsSnake only (from text features)
Price anomalySnake on Haiku-extracted prices — accurateSnake on regex-extracted prices — depends on text format
TotauxClaude extracts brut/remise/TVA/TTCSum of detected line totals, assumes 20% TVA
Flux detectionClaude understands intentKeyword scoring (invoice vs purchase words)
quality_score0.92 / 0.900.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.

EC2 setup: enabling Haiku

Option 1: ANTHROPIC_API_KEY directly

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

Option 2: From your .zshrc AWS_BEARER_TOKEN

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=.

Verify

# 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 examples

Invoice with anomaly

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
  }'

Purchase request

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
  }'

Test without Haiku (always works)

# 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