POST /comprendre

Genesis — everything you need to know to call this endpoint

1. What it does

/comprendre takes raw unstructured text (an email body, a pasted message, anything) and returns a full classification: email type, client, product lines, delivery info, and an explainable audit trail.

It always returns a response. If the LLM (Claude Haiku via Bedrock) is available, extraction is high quality. If not, a keyword/regex fallback extracts what it can. In both cases, Snake SAT classification runs on the extracted features.

Raw text in
Extraction (Haiku OR keyword fallback)
13 boolean/categorical features
Snake SAT classification (10 models, always runs)
JSON response with prediction + probability + XAI audit

2. How to call it

POST /comprendre
Content-Type: application/json

{
  "text": "your email or message text here",
  "factory_id": 3,
  "anthropic": false
}
FieldTypeRequiredDefaultDescription
textstringyesThe raw text to classify. Email body, pasted message, any unstructured French text about glass products.
factory_idintno3Monce factory ID. Options: 1 (VIT), 3 (Monce), 4 (VIP), 9 (Euro), 10 (TGVI).
anthropicboolnofalseSet to true to enable Claude Haiku extraction. Default uses keyword/regex extraction only — no LLM, no API key needed.

curl examples

# Default (Snake only, no LLM, instant)
curl -X POST https://emailclassifier.aws.monce.ai/comprendre \
  -H "Content-Type: application/json" \
  -d '{"text": "Bonjour, merci de nous livrer 200 feuillete 44.2 clair 1000x2000. Livraison le 25/04 sur chantier Lille."}'

# With Haiku extraction (needs API key on EC2)
curl -X POST https://emailclassifier.aws.monce.ai/comprendre \
  -H "Content-Type: application/json" \
  -d '{"text": "Bonjour, merci de nous livrer 200 feuillete 44.2 clair 1000x2000.", "anthropic": true}'

# Devis (default mode)
curl -X POST https://emailclassifier.aws.monce.ai/comprendre \
  -H "Content-Type: application/json" \
  -d '{"text": "Pourriez-vous nous faire un prix pour 100 trempes 10mm?"}'

# Relance (default mode)
curl -X POST https://emailclassifier.aws.monce.ai/comprendre \
  -H "Content-Type: application/json" \
  -d '{"text": "Toujours en attente de la commande #4521. Ca fait 2 semaines de retard."}'

3. What comes back

{
  "factory_id": 3,
  "version": "v0.2.0",
  "mock": false,                          // false = Haiku, true = keyword fallback
  "classification": {
    "Prediction": "Commande",             // top class
    "Probability": {                      // all 5 classes, sums to ~1.0
      "Commande": 0.99,
      "Devis": 0.01,
      "Relance": 0.0,
      "Spam": 0.0,
      "Autre": 0.0
    },
    "method": "snake_sat",                // always snake_sat
    "tier": 1
  },
  "client": {
    "match": "Verreries du Nord",         // detected company name (or null)
    "numero_client": "CLI-07329",         // mock ID from domain hash
    "confidence": 0.95,
    "method": "snake_sat",
    "contact": "Jean Dupont"              // extracted contact name
  },
  "lignes": [                             // product lines extracted from text
    {
      "ligne": 1,
      "texte_brut": "200 feuillete 44.2 clair 1000x2000",
      "qty": 200,
      "dims": "1000x2000",
      "article": {
        "num_article": "31939",           // mock article ID
        "denomination": "Feuillete 44.2 clair",
        "confidence": 0.68,
        "method": "snake_sat",
        "tier": 1,
        "field_type": null                // or "intercalaire"/"remplissage"
      }
    }
  ],
  "delai_demande": "2026-04-25",          // delivery date if mentioned
  "lieu_livraison": "chantier Lille",      // delivery location if mentioned
  "quality_score": 0.69,                   // avg confidence across all matches
  "latency_ms": 2305,                     // total server time
  "xai": {
    "classification_audit": "...",         // full Snake audit for email type
    "client_audit": "...",                 // how client was identified
    "lignes_audit": ["L1: ...", "L2: ..."],// per-line matching audit
    "actions_suggerees": [                 // recommended next steps
      "Creer commande ERP avec lignes produit extraites",
      "Confirmer delai 2026-04-25 avec logistique"
    ]
  }
}

4. The mock and anthropic fields

anthropic is the input flag. mock is the output flag. Together they tell you what happened.

Request anthropicResponse mockWhat ranLatency
false (default) true Keyword extraction + Snake SAT <10ms
true false Claude Haiku extraction + Snake SAT 1.5–3s
true true Haiku failed → keyword fallback + Snake SAT ~5s (timeout + fallback)

Default is keyword + Snake. No API key, no network, no cost. Snake does the classification with real SAT models. This is the mode the EC2 runs in out of the box.

With anthropic=true: Claude Haiku extracts richer features from natural language before Snake classifies. Better at understanding context, synonyms, implicit meaning. Requires AWS_BEARER_TOKEN_BEDROCK on the EC2.

5. Two modes in detail

Mode A: Default anthropic=false

When: Default. No flag needed. No API key needed.

What happens: Keyword/regex extraction runs locally. Detects quantities, dimensions, dates, product keywords, tone markers, urgency words. Builds the 13 features. Snake classifies.

Latency: <10ms total. Pure local computation.

Cost: Zero. No network calls, no API usage.

Accuracy: Good for structured text with explicit quantities, bullet points, glass product names. Misses nuance and implicit meaning. The Snake models carry the classification — as long as the keyword extraction catches the right boolean features, the prediction is correct.

Mode B: Haiku enabled anthropic=true

When: "anthropic": true in request AND AWS_BEARER_TOKEN_BEDROCK is set on EC2.

What happens: The full text is sent to Claude Haiku 4.5 with a structured extraction prompt. Claude returns JSON with expediteur, intention, lignes_articles, delai, lieu_livraison, ton, urgence. This JSON is then parsed into 13 features that feed Snake.

Latency: 1.5–3s (dominated by Haiku round-trip to Bedrock eu-west-3).

Accuracy: High. Claude handles synonyms ("livrer" = "expedier" = "envoyer"), implicit quantities, ambiguous phrasing. The 13 features are reliably extracted even from messy text.

Fallback chain: eu-west-3 → us-west-2 → us-east-1. If all three Bedrock regions fail, falls through to Mode B.

6. The 13 features (what Snake sees)

Regardless of extraction mode, the same 13 features are computed and fed to Snake:

#FeatureTypeHow it's computed
1has_quantityboolAny product line has qty ≠ null
2has_product_refboolText contains ref/BC/CMD/PO/# patterns
3has_dimensionsboolAny product line has dims (LxH)
4has_priceboolText contains prix/tarif/devis/cotation
5has_attachment_pdfboolAttachments list contains .pdf
6has_delivery_datebooldelai_demande is not null
7toncat"formel" or "informel"
8has_greetingboolBody starts with Bonjour/Madame/Salut/...
9nb_product_linesintCount of extracted product lines
10has_urgency_wordsboolText contains urgent/asap/critique/...
11has_complaint_wordsboolText contains reclamation/casse/probleme/...
12has_question_markboolBody or subject contains "?"
13domain_knownboolSender domain is not gmail/yahoo/free

7. How to prompt it

/comprendre is designed for raw text — no structure needed. But you'll get better results with more signal:

Best results (most signal)

{
  "text": "De: jean.dupont@verreriesdunord.fr\nObjet: Commande feuillete\n\nBonjour,\nMerci de nous livrer :\n- 200 pieces feuillete 44.2 clair 1000x2000\n- 50 trempe 10mm 800x1200\nLivraison 25/04 chantier Lille.\nCordialement, Jean Dupont"
}

Include sender email, subject, bullet-point lines, quantities, dimensions, dates, signature. Haiku extracts everything; even the fallback catches most of it.

Good results (natural text)

{
  "text": "Bonjour, je voudrais commander 50 vitrages feuillete 44.2 pour le chantier de Lyon, livraison avant fin avril svp."
}

Natural sentence. Haiku gets it all. Fallback catches "commander" (intention), "50" (qty), "feuillete 44.2" (product), "fin avril" (date), "chantier de Lyon" (location).

Minimal (still works)

{
  "text": "200 feuillete 44.2 1000x2000"
}

Telegram-style. Both modes detect quantity + product + dimensions. Classification works but confidence is lower (no intention keywords, no greeting, no delivery date).

Edge cases

// Empty text: returns "Autre" with low confidence
{"text": ""}

// Non-glass text: returns "Autre" or "Spam"
{"text": "Buy cheap watches online!!!"}

// Pure question: returns "Devis"
{"text": "Quel est votre prix pour du trempe 10mm?"}

8. EC2 environment setup

The API key controls which mode runs. Set it in /home/ubuntu/emailclassifier/.env:

# Bedrock token (preferred — works with eu-west-3 Bedrock gateway)
AWS_BEARER_TOKEN_BEDROCK=ABSK...your_token...

# Or direct Anthropic key (if using direct API instead of Bedrock)
# ANTHROPIC_API_KEY=sk-ant-...

The systemd service loads this via EnvironmentFile=/home/ubuntu/emailclassifier/.env. After changing, restart:

sudo systemctl restart emailclassifier

To test without Haiku (force fallback mode): temporarily clear the .env file. All requests will use keyword extraction and return mock=true.

9. Response guarantees

GuaranteeAlwaysNotes
Returns 200 with valid JSONyesUnless text field is missing (422)
classification.Prediction is one of 5 classesyesCommande/Devis/Relance/Spam/Autre
classification.Probability sums to ~1.0yesRounding may cause ±0.01
xai audit trail presentyesSnake audit in both modes
lignes populateddependsEmpty if no products detected in text
client.match populateddependsRequires email or company in text
delai_demande populateddependsOnly if a date is mentioned
Latency < 5syesHaiku: 1.5-3s, fallback: <10ms

10. Downstream integration

# Python
import requests
r = requests.post("https://emailclassifier.aws.monce.ai/comprendre",
                  json={"text": email_body, "factory_id": 3})
result = r.json()

if result["classification"]["Prediction"] == "Commande":
    create_erp_order(result["lignes"], result["client"])
elif result["classification"]["Prediction"] == "Devis":
    generate_quote(result["lignes"])

# Check extraction quality
if result["mock"]:
    flag_for_manual_review(result)
# JavaScript (Outlook add-in)
const res = await fetch("https://emailclassifier.aws.monce.ai/comprendre", {
  method: "POST",
  headers: {"Content-Type": "application/json"},
  body: JSON.stringify({text: emailBody, factory_id: 3})
});
const data = await res.json();
showClassification(data.classification.Prediction, data.xai);