mirror of
https://github.com/R0m1k3/CollectFlow.git
synced 2026-10-11 17:26:32 +02:00
debug(ai): add verbose logging and improved error visibility in batch analyzer
This commit is contained in:
1 parent
c6148b58a4
commit
1cda9cef9d
2 files changed
+37
-15
No files matched your search
@@ -81,13 +81,30 @@ Format attendu:
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
const content = data.choices[0].message.content;
|
||||
const content: string = data.choices?.[0]?.message?.content ?? "";
|
||||
|
||||
// Clean up markdown markers if the model ignored response_format
|
||||
const jsonMatch = content.match(/```json\n([\s\S]*?)\n```/) || content.match(/{[\s\S]*}/);
|
||||
const jsonStr = jsonMatch ? jsonMatch[0].replace(/```json\n|\n```/g, '') : content;
|
||||
console.log("[batch-analyze] Raw LLM response:", content.slice(0, 500));
|
||||
|
||||
if (!content) {
|
||||
return NextResponse.json({ error: "Réponse vide du modèle." }, { status: 500 });
|
||||
}
|
||||
|
||||
// Try to extract JSON block from the response (handles markdown code blocks and raw JSON)
|
||||
let jsonStr = content;
|
||||
const jsonBlock = content.match(/```json\s*([\s\S]*?)\s*```/);
|
||||
if (jsonBlock) {
|
||||
jsonStr = jsonBlock[1];
|
||||
} else {
|
||||
// Look for first { ... } block
|
||||
const start = content.indexOf("{");
|
||||
const end = content.lastIndexOf("}");
|
||||
if (start !== -1 && end !== -1) {
|
||||
jsonStr = content.slice(start, end + 1);
|
||||
}
|
||||
}
|
||||
|
||||
const resultJson = JSON.parse(jsonStr);
|
||||
console.log("[batch-analyze] Parsed results count:", resultJson?.results?.length ?? "N/A");
|
||||
|
||||
return NextResponse.json(resultJson);
|
||||
|
||||
|
||||
@@ -8,13 +8,13 @@ import { ProductRow } from "@/types/grid";
|
||||
|
||||
export function BulkAiAnalyzer() {
|
||||
const [isAnalyzing, setIsAnalyzing] = useState(false);
|
||||
const [progress, setProgress] = useState({ current: 0, total: 0, message: "" });
|
||||
const [progress, setProgress] = useState({ current: 0, total: 0, message: "", errors: 0 });
|
||||
const setDraftGamme = useGridStore(state => state.setDraftGamme);
|
||||
const setInsight = useAiCopilotStore(state => state.setInsight);
|
||||
|
||||
const handleAnalyze = async () => {
|
||||
const { rows } = useGridStore.getState();
|
||||
if (rows.length === 0) return;
|
||||
console.log("[BulkAiAnalyzer] Starting analysis on", rows.length, "rows");
|
||||
|
||||
setIsAnalyzing(true);
|
||||
|
||||
@@ -40,12 +40,12 @@ export function BulkAiAnalyzer() {
|
||||
}
|
||||
}
|
||||
|
||||
setProgress({ current: 0, total: chunks.length, message: "Initialisation..." });
|
||||
setProgress({ current: 0, total: chunks.length, message: "Initialisation...", errors: 0 });
|
||||
|
||||
// Process sequentially
|
||||
let completed = 0;
|
||||
for (const chunk of chunks) {
|
||||
setProgress({ current: completed, total: chunks.length, message: `Analyse du rayon: ${chunk.rayon}` });
|
||||
setProgress(prev => ({ ...prev, current: completed, total: chunks.length, message: `Analyse du rayon: ${chunk.rayon}` }));
|
||||
|
||||
// Simplify payload to save tokens
|
||||
const payloadProducts = chunk.items.map(r => ({
|
||||
@@ -66,35 +66,40 @@ export function BulkAiAnalyzer() {
|
||||
});
|
||||
|
||||
if (!res.ok) {
|
||||
console.error(`Erreur sur le lot ${chunk.rayon}`);
|
||||
const errText = await res.text();
|
||||
console.error(`[BulkAiAnalyzer] Erreur HTTP ${res.status} sur le lot ${chunk.rayon}:`, errText);
|
||||
setProgress(prev => ({ ...prev, errors: prev.errors + 1 }));
|
||||
completed++;
|
||||
continue; // Skip the failed chunk but continue processing
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
const data = await res.json();
|
||||
console.log(`[BulkAiAnalyzer] Response for ${chunk.rayon}:`, data);
|
||||
|
||||
// data.results should be an array
|
||||
if (data && Array.isArray(data.results)) {
|
||||
let applied = 0;
|
||||
data.results.forEach((reco: any) => {
|
||||
if (reco.codein && reco.recommandationGamme) {
|
||||
// Update the gamme draft
|
||||
setDraftGamme(reco.codein, reco.recommandationGamme);
|
||||
// Inject the justification into the AI insight column (with gamme letter prefix)
|
||||
const baseJustification = reco.justificationCourte || "Aucune explication.";
|
||||
const justification = `Gamme ${reco.recommandationGamme} — ${baseJustification}`;
|
||||
setInsight(reco.codein, justification, reco.isDuplicate ?? false);
|
||||
applied++;
|
||||
}
|
||||
});
|
||||
console.log(`[BulkAiAnalyzer] Applied ${applied} recommendations for ${chunk.rayon}`);
|
||||
} else {
|
||||
console.warn(`[BulkAiAnalyzer] Unexpected response shape for ${chunk.rayon}:`, data);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("Failed to parse JSON for chunk", chunk.rayon, e);
|
||||
console.error(`[BulkAiAnalyzer] Failed to parse JSON for chunk ${chunk.rayon}:`, e);
|
||||
}
|
||||
|
||||
completed++;
|
||||
}
|
||||
|
||||
setProgress({ current: completed, total: chunks.length, message: "Analyse terminée avec succès !" });
|
||||
setProgress(prev => ({ ...prev, current: completed, total: chunks.length, message: `Analyse terminée ! (${prev.errors > 0 ? prev.errors + " erreurs" : "succès"})` }));
|
||||
setTimeout(() => {
|
||||
setIsAnalyzing(false);
|
||||
}, 3000);
|
||||
|
||||
Reference in new issue
Block a user