IA (ai-kit)
IA (ai-kit)
Module transverse qui sert les autres domaines : OCR factures fournisseur (Achats), enrichissement prospects terrain (CRM ciblage), OCR plaque signalétique constructeur (Assets), cotation CERFA (Rating). Il ne possède pas d'écran métier propre, mais expose une route d'observabilité coûts et un endpoint dev pour déclencher des workflows.
/api/workspace/ai/*. Source de cette page :
docs/17-domain-ai-kit.md et le code sous server/lib/ai/.Vocabulaire & entités
| Terme | Entité / type | Définition |
|---|---|---|
| Provider | AIProvider | Adaptateur d'appel IA (scaleway par défaut, anthropic en alt). |
| Completion | AICompletionRequest / AICompletionResult | Unité d'appel : prompt + options → texte + tokens + coût. |
| Attachment | AIAttachment | Pièce jointe multimodale (image ou PDF base64) transmise au modèle vision. |
| Workflow | string (clé) | Identifiant fonctionnel du pipeline (invoice-ocr-extract, prospect-enrich…). |
| CostEvent | AICostEvent (Prisma) | Ligne d'audit par appel : provider, modèle, tokens, coût USD, statut, durée. |
| Mode | AI_PROVIDER_MODE | fixtures (défaut dev) ou live. En fixtures : réponses canned, aucun crédit consommé. |
Le modèle
AICostEventest dansdocs/04-data-model.md§13. Les DTOs Zod sont dansshared/dto/ai.dto.ts.
Écrans
| Écran | Route | Contenu |
|---|---|---|
| Coûts IA | /workspace/ai/costs | Liste paginée des AICostEvent : workflow, provider, modèle, tokens, coût USD, statut. |
| Agrégats mensuels | via endpoint | KPIs par workflow : nb appels, coût total/moyen, tokens in/out. |
Pas d'écran admin dédié implémenté à ce stade (stub dans la doc cible docs/17-).
Modèle de données (points clés)
AICostEvent: enregistré après chaque appel IA (succès et erreur). Champstatusvautsuccessouerror;errorMessagenon-null en cas d'échec.costUsdest unDecimalPrisma — converti ennumberà la sérialisation (Number(e.costUsd)).triggeredByUserIdest nullable (jobs batch déclenchés sans session user).- Multi-tenant strict :
organizationIdtoujours présent, jamais lu depuis le body.
API
Les deux routes workspace exigent admin.audit:read.
| Méthode | Route | Permission |
|---|---|---|
GET | /api/workspace/ai/costs | admin.audit:read |
GET | /api/workspace/ai/costs/monthly | admin.audit:read |
POST | /api/dev/ai/trigger-workflow | dev uniquement (route non protégée) |
/api/workspace/ai/costsAuth Liste paginée des événements de coût IA pour l'organisation courante.
Query string
invoice-ocr-extract, prospect-enrich…).YYYY-MM.Requête
curl -s "$API/api/workspace/ai/costs?yearMonth=2026-06&workflow=invoice-ocr-extract" \
-H "Cookie: $SESSION"
Réponse
{
"items": [{
"id": "cst_…",
"workflow": "invoice-ocr-extract",
"provider": "scaleway",
"model": "pixtral-12b-2409",
"inputTokens": 800,
"outputTokens": 90,
"costUsd": 0.0009,
"status": "success",
"durationMs": 1420,
"createdAt": "2026-06-10T14:32:00.000Z"
}],
"page": 1,
"pageSize": 20,
"total": 1
}
Workflows implémentés
invoice-ocr-extract — OCR facture fournisseur
Fichier : server/lib/ai/workflows/invoice-ocr-extract.ts
PDF facture → pdfToImageAttachments() → pixtral (vision)
→ parseAiJson() → InvoiceOcrExtractResult → AICostEvent
- Le PDF est rastérisé en images avant l'appel (
pdf-to-images.ts) car pixtral n'ingère pas un PDF brut — repli sur PDF base64 si le rendu échoue. - Appel
AIProvider.completion()avecattachments(multimodal). - Extraction JSON :
vendor,vendorSiret,invoiceNumber,issueDate,dueDate,totalHt,totalTtc. AICostEventcréé dans tous les cas (succès ou erreur).
plate-ocr-extract — OCR plaque signalétique constructeur
Fichier : server/lib/ai/workflows/plate-ocr-extract.ts
Photo d'une plaque → provider vision → serialNumber, manufacturer, model,
voltage, refrigerant, power, dimensions. Même pattern que
invoice-ocr-extract (image base64, pas de rasterisation PDF).
prospect-enrich — Enrichissement Gemini grounded
Fichier : server/lib/ai/workflows/prospect-enrich.ts
nom + adresse → PII masking → Gemini + googleSearch (étape 1 : texte libre)
→ Gemini structured output (étape 2 : JSON)
→ ProspectEnrichmentOutput → AICostEvent (provider: 'google')
- Deux temps obligatoires : Gemini interdit
tool use + sortie structurée JSONdans le même appel (validé live). - Vérification budget IA avant tout appel (
isAiBudgetExhausted) ; lèveAiBudgetExhaustedErrorsi le seuil est atteint. - Cache 15 j sur l'appel (
cachedCall('gemini-enrich', …)). - Sortie :
siret,siren,emails[],openingHours,socialNetworks,description,confidence(0-100). - Requiert
GOOGLE_GENERATIVE_AI_API_KEYen mode live.
call-summary, lead-enrichment, rating-cerfa-extract
Présents en fixtures déterministes (server/lib/ai/providers/fixtures.ts).
Workflows live non encore implémentés pour ces cas (stub spec docs/17-).
Providers
Scaleway (défaut, AI_PROVIDER=scaleway)
Fichier : server/lib/ai/providers/scaleway/index.ts
- Modèle texte :
gpt-oss-120b(variableSCALEWAY_MODEL). - Modèle vision :
pixtral-12b-2409(variableSCALEWAY_VISION_MODEL) — activé automatiquement siattachmentsprésents dans la requête. - Utilise
@ai_kit/core→Agent+scaleway(model)en mode live. - Requiert
SCALEWAY_API_KEY.
Anthropic (alternatif, AI_PROVIDER=anthropic)
Fichier : server/lib/ai/providers/anthropic/index.ts
- Utilise l'API Anthropic avec le modèle configuré.
Gemini (enrichissement ciblage uniquement)
Utilisé exclusivement par prospect-enrich via @ai_kit/core + googleSearch.
Ne passe pas par le registry de providers — appelé directement dans runtime.ts.
Mode fixtures (défaut dev)
AI_PROVIDER_MODE absent ou différent de live → réponses canned dans
server/lib/ai/providers/fixtures.ts. Aucun crédit consommé, latence simulée
20 ms. AICostEvent créé quand même (coût calculé via tarif Anthropic fixtures).
Observabilité
- Langfuse :
traceCompletion()dansserver/lib/ai/observability/langfuse.ts. No-op silencieux siLANGFUSE_PUBLIC_KEY/LANGFUSE_SECRET_KEYabsents. SDK non encore installé (stub Phase 12+). Debug activé viaLANGFUSE_DEBUG=true. AICostEvent: trace permanente en base (persist même en cas d'erreur).
Règles métier
- Budget mensuel : seuil
AI_MONTHLY_BUDGET_USD(défaut 50 USD). Si dépassé :checkBudgetAlert()crée une notificationGENERICpour tous les admins de l'org avec lien/workspace/ai/costs.isAiBudgetExhausted()(sans effet de bord) : verrou préventif avant appel dans les workflows batch (ex.prospect-enrich).
- Multi-tenant strict :
organizationIdtoujours issu de la session, jamais du body. - PII masking :
maskPii()appliqué sur le prompt avant tout envoi externe (prospect-enrich). Emails, téléphones, noms masqués si non nécessaires. - Décisions automatisées : aucune décision impactant un client (refus, suspension) sans validation humaine — toute sortie IA est présentée pour confirmation.
- Hallucinations : les sorties IA sont présentées à l'utilisateur pour validation avant persistance (OCR facture, plaque, enrichissement).
Variables d'environnement
| Variable | Défaut | Usage |
|---|---|---|
AI_PROVIDER | scaleway | Provider actif : scaleway | anthropic. |
AI_PROVIDER_MODE | (absent = fixtures) | live pour activer les vrais appels. |
SCALEWAY_API_KEY | — | Requis en mode live Scaleway. |
SCALEWAY_MODEL | gpt-oss-120b | Modèle texte Scaleway. |
SCALEWAY_VISION_MODEL | pixtral-12b-2409 | Modèle vision Scaleway. |
GOOGLE_GENERATIVE_AI_API_KEY | — | Requis pour prospect-enrich live (Gemini). |
GEMINI_MODEL | gemini-2.5-flash | Modèle Gemini. |
AI_MONTHLY_BUDGET_USD | 50 | Seuil alerte/blocage budget mensuel. |
LANGFUSE_PUBLIC_KEY / LANGFUSE_SECRET_KEY | — | Active les traces Langfuse. |
Administration
Référence technique du domaine Administration — console super-admin, paramètres applicatifs, gestion des organisations, webhooks sortants, audit log et supervision.
Achats
Référence technique du domaine Achats fournisseurs — devis multi-fournisseurs, inbox OCR IA, comparateur, commandes, réception→asset, rapprochement 3 voies et boucle achats↔leasing.