From 2b7e7bc1f4187b5f70ebd4058e7662a80fe8e91c Mon Sep 17 00:00:00 2001 From: Michael SCHAL Date: Thu, 19 Mar 2026 09:50:28 +0100 Subject: [PATCH] feat: Introduce AI analysis engine with detailed system prompt and user message generation for product recommendations, and add an OpenRouter client. --- src/app/(dashboard)/grid/loading.tsx | 39 +++++++++++++++++++ .../ai-copilot/business/analysis-engine.ts | 3 +- .../ai-copilot/data/open-router-client.ts | 11 ++++++ 3 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 src/app/(dashboard)/grid/loading.tsx diff --git a/src/app/(dashboard)/grid/loading.tsx b/src/app/(dashboard)/grid/loading.tsx new file mode 100644 index 0000000..4d3b3df --- /dev/null +++ b/src/app/(dashboard)/grid/loading.tsx @@ -0,0 +1,39 @@ +export default function GridLoading() { + return ( +
+
+ {/* Spinner */} +
+
+
+ +
+ + Chargement des données + + + Récupération des articles et calcul des scores... + +
+
+
+ ); +} diff --git a/src/features/ai-copilot/business/analysis-engine.ts b/src/features/ai-copilot/business/analysis-engine.ts index a51ceba..d45d18f 100644 --- a/src/features/ai-copilot/business/analysis-engine.ts +++ b/src/features/ai-copilot/business/analysis-engine.ts @@ -46,8 +46,9 @@ PROMOUVOIR (Z → A) : Le verdict pré-calculé est Z, MAIS : DÉGRADER (A → Z) : Le verdict pré-calculé est A, MAIS : • Tendance en effondrement (H2/H1 < 0.4) • ET aucune réception récente - • ET score < 55 + • ET score < 55 ⚠️ SI LE SCORE EST ≥ 55, TU NE PEUX JAMAIS DÉGRADER EN Z → Les 3 conditions doivent être remplies SIMULTANÉMENT. + → Un score élevé (≥ 55) INTERDIT toute dégradation, quelle que soit la tendance. Si AUCUNE condition d'ajustement n'est remplie → CONFIRME le verdict pré-calculé. diff --git a/src/features/ai-copilot/data/open-router-client.ts b/src/features/ai-copilot/data/open-router-client.ts index ba8d7f2..3a94403 100644 --- a/src/features/ai-copilot/data/open-router-client.ts +++ b/src/features/ai-copilot/data/open-router-client.ts @@ -86,6 +86,17 @@ export class OpenRouterClient { // Ré-appliquer le garde-fou pour la reco extraite du texte. if (!ruleApplies && (reco === "B" || reco === "C" || reco === "D")) reco = "A"; } + + // Garde-fou anti-dégradation : l'IA ne peut PAS dégrader A → Z + // si le score pré-calculé est ≥ 55 (sauf si règle manager). + // Corrige les hallucinations du LLM qui ignore la condition "score < 55". + const preScore = p.scoring?.score ?? p.score ?? 0; + const preVerdict = p.scoring?.verdict ?? (preScore >= 45 ? "A" : "Z"); + if (!ruleApplies && preVerdict === "A" && reco === "Z" && preScore >= 55) { + console.warn(`[AI Guardrail] Blocked A→Z degradation for ${p.codein} (score ${preScore} ≥ 55)`); + reco = "A"; + cleanInsight += " [Garde-fou : score élevé, dégradation bloquée]"; + } } catch (e) { console.error("Failed to parse AI JSON response:", content, e); // Fallback to text parsing