feat: implement AnalysisEngine to generate AI prompts and process responses, incorporating updated product recommendation rules for strict low-score exclusion and critical analysis.

This commit is contained in:
Michael committed 2026-02-23 15:36:49 +01:00
1 parent 7538bf4629
commit 79c611db2c
2 files changed
+28 -25

No files matched your search

@@ -2,22 +2,22 @@ import { ProductAnalysisInput } from "../models/ai-analysis.types";
export class AnalysisEngine { export class AnalysisEngine {
static generateSystemPrompt(): string { static generateSystemPrompt(): string {
return `Tu es Mary, experte en analyse de gammes retail B2B. Ta mission est d'aider un acheteur à arbitrer son assortiment. return `Tu es Mary, experte en analyse de gammes retail B2B. Ta mission est d'aider un acheteur à arbitrer son assortiment avec une rigueur absolue.
HIÉRARCHIE D'ANALYSE (CRITIQUE) : RÈGLES D'OR DE DÉCISION :
1. VALEUR BUSINESS (Priorité Maximale) : Analyse le CA et la Marge brute. Un produit à forte marge ou contribution CA significative doit être protégé, même si les volumes sont faibles. 1. EXCLUSION AUTOMATIQUE (Score < 20) : Tout produit ayant un score global inférieur à 20 doit être recommandé en [Z] (Sortie). C'est une règle de sécurité non négociable.
2. RÉGULARITÉ & SERVICE : Un produit vendu régulièrement (même 1 unité/mois) peut être un "Produit de Service" essentiel pour le client et mérite souvent d'être maintenu en gamme [A]. 2. ANALYSE CRITIQUE SYSTÉMATIQUE (Score >= 20) : Même pour les scores élevés (> 50 ou > 70), ne valide PAS automatiquement le [A]. Tu dois mener une analyse critique basée sur le CA, la Marge et la Quantité.
3. SCORE GLOBAL (Indicateur Secondaire) : Le score est une aide, pas une sentence. Un score < 30 n'implique PAS automatiquement une sortie [Z]. 3. VALIDATION PAR LA VALEUR : Pour recommander [A], le produit doit prouver sa valeur réelle (ex: Marge élevée, CA significatif, ou Régularité de service irréprochable). Si les volumes sont dérisoires et la marge faible, propose [Z] même si le score est correct.
RÈGLES D'OR : RÈGLES DE RÉDACTION :
1. VÉRACITÉ ABSOLUE : Ne déforme JAMAIS les chiffres fournis. 1. VÉRACITÉ : Respecte strictement les chiffres fournis.
2. PAS DE COUPERET : Évite de recommander [Z] uniquement sur la base d'un score faible. 2. SANS COMPLAISANCE : Sois directe. Si un produit est mauvais malgré son score, dis-le.
3. JUSTIFICATION BUSINESS : Précise toujours si la recommandation est basée sur la rentabilité (marge), le service (régularité) ou la performance globale (score). 3. JUSTIFICATION : Base ta réponse sur la rentabilité (marge), le poids business (CA) ou le service (régularité).
Options de recommandation : Options de recommandation :
- [A] - PERMANENT : Rotation régulière ou produit stratégique/marge/service. - [A] - PERMANENT : Produit dont la valeur business ou le service client est prouvé.
- [C] - SAISONNIER : Pics de ventes concentrés, inactivité hors saison. - [C] - SAISONNIER : Pics de ventes concentrés, inactivité hors saison.
- [Z] - SORTIE : Inutilité business prouvée (CA quasi-nul + Marge faible + Score bas + Inactif). - [Z] - SORTIE : Inutilité business (Score < 20 OU CA/Marge/Quantité insuffisants).
Ta réponse doit être courte, directe et sans complaisance. Ta réponse doit être courte, directe et sans complaisance.
Format : "[Recommandation] : [Justification factuelle]"`; Format : "[Recommandation] : [Justification factuelle]"`;
@@ -28,37 +28,30 @@ Format : "[Recommandation] : [Justification factuelle]"`;
.map(([k, v]) => `${k}: ${Math.round(v)}u`) .map(([k, v]) => `${k}: ${Math.round(v)}u`)
.join(", "); .join(", ");
const volumeInfo = `Stats Réelles : ${Math.round(p.totalQuantite)}u sur ${p.storeCount} mag. const volumeInfo = `Volumes : ${Math.round(p.totalQuantite)}u sur ${p.storeCount} mag.`;
Stats Pondérées (Base 2 mag) : ${Math.round(p.weightedTotalQuantite || 0)}u`;
const projectionInfo = p.regularityScore > 0 && p.regularityScore < 12 ? ` const projectionInfo = p.regularityScore > 0 && p.regularityScore < 12 ? `
--- ANALYSE DE POTENTIEL (Produit récent : ${p.regularityScore}/12 mois active) --- --- ANALYSE DE POTENTIEL (Produit récent : ${p.regularityScore}/12 mois active) ---
Projection 12 mois (Run Rate) : ${Math.round(p.projectedTotalQuantite || 0)}u (${(p.projectedTotalCa || 0).toFixed(2)}€)` : ""; Projection 12 mois : ${Math.round(p.projectedTotalQuantite || 0)}u (${(p.projectedTotalCa || 0).toFixed(2)}€)` : "";
const activityAlert = (p.inactivityMonths || 0) > 2 const activityAlert = (p.inactivityMonths || 0) > 2
? `\n⚠️ ALERTE : Inactif depuis ${p.inactivityMonths} mois (Dernière vente: ${p.lastMonthWithSale || "Inconnue"})` ? `\n⚠️ ALERTE : Inactif depuis ${p.inactivityMonths} mois`
: ""; : "";
const benchmarks = `
Benchmarks Rayon ("${p.libelleNiveau2}") :
- Moyenne 1 mag: ${Math.round(p.avgQtyRayon1 || 0)}u | Multi-mag: ${Math.round(p.avgQtyRayon2 || 0)}u`;
return `IDENTITÉ DU PRODUIT : return `IDENTITÉ DU PRODUIT :
- Libellé : "${p.libelle1}" (Ref: ${p.codein}) - Libellé : "${p.libelle1}" (Ref: ${p.codein})
- Rayon : ${p.libelleNiveau2 || "Non classé"} - Rayon : ${p.libelleNiveau2 || "Non classé"}
- Gamme actuelle : ${p.codeGamme ?? "Non définie"} - Gamme actuelle : ${p.codeGamme ?? "Non définie"}
INDICATEURS BUSINESS (PRIORITAIRES) : DONNÉES BUSINESS :
- Marge brute : ${p.tauxMarge.toFixed(1)}% - Marge brute : ${p.tauxMarge.toFixed(1)}%
- Total CA : ${p.totalCa.toFixed(2)}€ - Total CA : ${p.totalCa.toFixed(2)}€
- Régularité des ventes : ${p.regularityScore}/12 mois active
INDICATEURS TECHNIQUES (SECONDAIRES) :
- Score Global App : ${p.score.toFixed(1)}/100 - Score Global App : ${p.score.toFixed(1)}/100
${volumeInfo}${projectionInfo}${activityAlert}${benchmarks} - Régularité : ${p.regularityScore}/12 mois active
${volumeInfo}${projectionInfo}${activityAlert}
- Historique mensuel (Pondéré) : ${monthlySummary} - Historique mensuel (Pondéré) : ${monthlySummary}
Quelle est ta recommandation (A, C ou Z) et pourquoi ?`; Analyse la pertinence business du produit sans aucune complaisance. Quelle est ta recommandation (A, C ou Z) ?`;
} }
static extractRecommendation(content: string): "A" | "C" | "Z" | null { static extractRecommendation(content: string): "A" | "C" | "Z" | null {
+10
View File
@@ -14,6 +14,10 @@ Activation et initialisation de l'Agent Master BMAD.
- [x] Étape 6 : Proposition technique et plan d'implémentation - [x] Étape 6 : Proposition technique et plan d'implémentation
- [x] Étape 7 : Application des modifications dans `analysis-engine.ts` - [x] Étape 7 : Application des modifications dans `analysis-engine.ts`
- [x] Étape 8 : Vérification et validation - [x] Étape 8 : Vérification et validation
- [x] Étape 9 : Relativisation des recommandations (Abandon Benchmarking)
- [x] Étape 10 : Ajustement du seuil de protection (Score < 20)
- [x] Étape 11 : Intégration de l'analyse critique systématique (même score > 50)
- [x] Étape 12 : Validation finale et correction TS
# Progress Log # Progress Log
@@ -28,3 +32,9 @@ Activation et initialisation de l'Agent Master BMAD.
- Déploiement de la nouvelle hiérarchie d'analyse (CA/Marge > Score). - Déploiement de la nouvelle hiérarchie d'analyse (CA/Marge > Score).
- Suppression des seuils de blocage score < 30. - Suppression des seuils de blocage score < 30.
- Mise en avant des "Produits de Service". - Mise en avant des "Produits de Service".
- Michael signale une inflation des recommandations [A] (86 articles).
- Michael demande d'abandonner l'analyse par rayon.
- Mise en place d'une protection stricte : Score < 20 => Sortie [Z] automatique.
- Arbitrage IA maintenu entre 20 et 50 basé sur CA / Marge / Quantité.
- Michael exige une analyse critique systématique même pour les scores > 50.
- Logique finale implémentée et validée (Score < 20 = Z).