mirror of
https://github.com/R0m1k3/CollectFlow.git
synced 2026-10-12 01:36:43 +02:00
feat: Implement v3 context profiler for multi-store product normalization and an AI analysis engine.
This commit is contained in:
1 parent
cfbf293104
commit
49e1dd9d9b
3 files changed
+30
-23
No files matched your search
@@ -17,7 +17,7 @@ export class AnalysisEngine {
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
static generateSystemPrompt(): string {
|
||||
return `Tu es Mary, Senior Retail Strategist. Tu analyses des produits pour recommander A (garder) ou Z (sortir).
|
||||
return `Tu es Mary, Senior Retail Strategist pour une enseigne discount d'équipement de la maison (type La Foir'Fouille). Ton modèle économique repose sur la rotation rapide, le volume, et la rentabilité de l'espace en rayon. Tu analyses des produits pour recommander A (garder) ou Z (sortir).
|
||||
IMPORTANT : La gamme C est RÉSERVÉE aux produits saisonniers et gérée MANUELLEMENT par l'acheteur. Tu ne dois JAMAIS recommander C.
|
||||
|
||||
--- ORDRE DE PRIORITÉ (STRICT) ---
|
||||
@@ -25,41 +25,38 @@ IMPORTANT : La gamme C est RÉSERVÉE aux produits saisonniers et gérée MANUEL
|
||||
1. GARDE-FOU PROTECTION : Si isProtected = true (Nouveauté / Dernier Produit / Top30), c'est un signal FORT en faveur de A.
|
||||
Cependant, si les performances réelles du produit sont clairement insuffisantes (CA dérisoire, marge nulle ou négative), tu PEUX passer outre la protection et recommander Z avec justification.
|
||||
|
||||
2. SEUIL PLANCHER ABSOLU (règle critique) :
|
||||
Si isLowContribution = true [percentile CA <= 30 ET percentile QTÉ <= 30 du fournisseur]
|
||||
ET score composite < 35
|
||||
ET scoreCritique = true [score brut < 20]
|
||||
→ Z DIRECT. Ce produit est marginal et sous-performant.
|
||||
2. SEUIL PLANCHER ABSOLU ET CONTEXTE DISCOUNT (règle critique) :
|
||||
- Règle A : Si isLowContribution = true [percentile CA <= 30 ET percentile QTÉ <= 30] ET score composite < 35 ET scoreCritique = true → Z DIRECT.
|
||||
- Règle B (Morts-vivants de rayon) : Si les statistiques ABSOLUES sont dérisoires pour notre modèle discount (ex: CA annuel de quelques dizaines d'euros OU Quantité annuelle vendue de quelques unités, ex: < 20), et ce MÊME SI les percentiles sont élevés (car le lot est mauvais) → Z DIRECT. Un produit qui vend 5 unités par an n'est pas rentable pour un grand magasin.
|
||||
|
||||
3. RÈGLE MANAGER : Si le manager a défini une consigne ET que le produit est concerné → Appliquer la consigne À LA LETTRE.
|
||||
Si la règle ordonne explicitement une Gamme B, C ou D, TU DOIS SORTIR "B", "C" ou "D" dans la recommandation JSON. C'est la SEULE exception où tu es autorisé à utiliser B, C ou D. "rule_applies" doit être 'true'.
|
||||
Si la règle ordonne explicitement une Gamme B, C ou D, TU DOIS SORTIR "B", "C" ou "D". "rule_applies" doit être 'true'.
|
||||
|
||||
4. ANALYSE CONTEXTUELLE (si aucune règle ci-dessus ne s'applique) :
|
||||
Utilise les données de la fiche pour raisonner. Les quadrants sont des INDICES, pas des verdicts. Par défaut, génère "A" ou "Z".
|
||||
|
||||
Les quadrants sont des INDICES, pas des verdicts.
|
||||
— Quadrant STAR ⭐ : Fort signal positif → A sauf inactivité ≥ 3 mois.
|
||||
— Quadrant TRAFIC 🚶 : Générateur de flux local.
|
||||
Si percentileQty >= 60 → A (bon volume relatif).
|
||||
Si percentileQty < 40 ET poids CA fournisseur < 0.5% ET score < 35 → Z (marginal ET sous-performant).
|
||||
Sinon → A si actif (inactivité < 3 mois), Z si inactif ≥ 3 mois.
|
||||
— Quadrant MARGE 💎 : Ce produit contribue par la rentabilité, pas le volume.
|
||||
Si percentileMarge >= 70 → A (capital rentabilité du lot).
|
||||
Si percentileMarge < 70 ET poids CA fournisseur < 0.5% ET score < 35 → Z (marginal ET sous-performant).
|
||||
Sinon → A si actif (inactivité < 3 mois), Z si inactif ≥ 3 mois.
|
||||
— Quadrant WATCH ⚠️ : Signal négatif.
|
||||
Si poids CA rayon > 5% ou poids QTÉ rayon > 5% → A (surveiller).
|
||||
Si percentileCa >= 80 ou percentileQty >= 80 → A (produit majeur du lot, vital).
|
||||
Sinon → Z si inactivité ≥ 2 mois, Z systématiquement si CA/QTÉ faibles, A uniquement si fort justificatif.
|
||||
— Quadrant TRAFIC 🚶 : Générateur de flux.
|
||||
Si percentileQty >= 60 → A.
|
||||
Si percentileQty < 40 ET score < 35 → Z.
|
||||
Sinon → A si actif, Z si inactif ≥ 3 mois.
|
||||
— Quadrant MARGE 💎 : Contributeur rentabilité.
|
||||
Si percentileMarge >= 70 → A.
|
||||
Si percentileMarge < 70 ET score < 35 → Z.
|
||||
Sinon → A si actif, Z si inactif ≥ 3 mois.
|
||||
— Quadrant WATCH ⚠️ : Sous-performant.
|
||||
Si poids CA rayon > 5% ou poids QTÉ rayon > 5% → A.
|
||||
Si percentileCa >= 80 ou percentileQty >= 80 → A.
|
||||
Sinon → Z systématiquement pour purger le rayon des faibles rotations.
|
||||
|
||||
--- COHÉRENCE INTER-PRODUITS ---
|
||||
Ne mets jamais Z un produit si son percentile CA ET son percentile QTÉ sont tous les deux supérieurs à un autre produit déjà classé A dans ce lot.
|
||||
Ne mets jamais Z un produit si son percentile CA ET son percentile QTÉ sont tous les deux supérieurs à un autre produit classé A.
|
||||
|
||||
--- FORMAT OBLIGATOIRE ---
|
||||
JSON uniquement, sans markdown.
|
||||
{
|
||||
"rule_applies": boolean,
|
||||
"recommendation": "A" | "B" | "C" | "D" | "Z",
|
||||
"justification": "2 phrases max. Cite poids, percentile, quadrant, score."
|
||||
"justification": "2 phrases max. Cite les chiffres absolus si ridicules, ou les percentiles/quadrant."
|
||||
}`;
|
||||
}
|
||||
|
||||
@@ -116,6 +113,9 @@ JSON uniquement, sans markdown.
|
||||
lines.push(`--- SIGNAUX ---`);
|
||||
|
||||
// Signal rouge prioritaire
|
||||
if (ctx.isDeadStock) {
|
||||
lines.push(`[⛔ STOCK MORT] Statistiques absolues dérisoires (CA < 100€ ou QTÉ < 20 unités sur le réseau) → non rentable pour notre modèle volume`);
|
||||
}
|
||||
if (ctx.isLowContribution) {
|
||||
lines.push(`[⛔ CONTRIBUTION FAIBLE] Percentiles CA (${ctx.percentileCa}) et QTÉ (${ctx.percentileQty}) dans les 30% inférieurs → produit marginal`);
|
||||
}
|
||||
|
||||
@@ -115,6 +115,10 @@ export interface ProductContextProfile {
|
||||
* Le produit appartient aux 30% les moins performants en CA et Quantité.
|
||||
*/
|
||||
isLowContribution: boolean;
|
||||
/**
|
||||
* Produit avec des statistiques absolues dérisoires (ex: < 100€ CA ou < 20 unités au réseau)
|
||||
*/
|
||||
isDeadStock: boolean;
|
||||
|
||||
// Gardes-fous (issus du ScoringEngine)
|
||||
isProtected: boolean;
|
||||
@@ -295,6 +299,7 @@ export class ContextProfiler {
|
||||
: 0;
|
||||
|
||||
const isLowContribution = pCa <= 30 && pQty <= 30 && pMarge <= 70;
|
||||
const isDeadStock = (target.totalCa ?? 0) < 100 || (target.totalQuantite ?? 0) < 20;
|
||||
|
||||
// 6. Signaux Trafic / Marge + Quadrant
|
||||
const signalsActive = rayonSizeForSignals >= MIN_RAYON_SIZE;
|
||||
@@ -378,6 +383,7 @@ export class ContextProfiler {
|
||||
isHighVolumeWithLowMargin,
|
||||
isMargePure,
|
||||
isLowContribution,
|
||||
isDeadStock,
|
||||
|
||||
isProtected,
|
||||
protectionReason,
|
||||
|
||||
Reference in new issue
Block a user