Spaces:
Sleeping
Sleeping
File size: 3,432 Bytes
0ec8c7c 79c5a92 628ec36 0ec8c7c 469b970 e6a627d f86ee93 46f9a7a d14861f e6a627d f86ee93 79c5a92 8db634a f86ee93 0ec8c7c 35d8bd5 d14861f 6a25ae8 d14861f f86ee93 628ec36 0ec8c7c 628ec36 d14861f 0ec8c7c 628ec36 0ec8c7c 628ec36 d14861f 0ec8c7c d14861f 0ec8c7c 79c5a92 d897af7 d14861f 0ec8c7c f86ee93 d14861f f86ee93 bbb4e4b f86ee93 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | /** engine/classifier.js V101.0 - Hybrid Vision Integration */
const { routeWithLLM } = require('../services/llmService');
const { downloadFile } = require('../services/storageService');
const { processImageUpload } = require('./imageProcessor');
const KEYWORDS = {
reset: ['reset', 'ืืชืื', 'ืืืคืืก', 'ืจืืกื', 'ืชืคืจืื'],
cart: ['ืขืืื', 'ืกืืืื', 'ืืื ืื ืืืฆื', 'ืืื ืืฆื'],
checkout: ['ืชืืจืื', 'ืืฆืขืช ืืืืจ', 'ืืฉืื', 'ืืฉืืื', 'ืฆ\'ืง ืืืื', 'checkout']
};
async function classify(text, session) {
const safeText = String(text || "");
const t = safeText.toLowerCase().trim();
// 1. Technical Fast Paths
if (t.startsWith('system_')) return { intent: 'system_action', action: t, raw_text: safeText };
if (KEYWORDS.reset.some(k => t.includes(k)) && t.split(' ').length <= 4) return { intent: 'reset' };
if (KEYWORDS.cart.some(k => t.includes(k))) return { intent: 'show_cart' };
// 2. LLM / Compiler Pipeline
try {
let imageBuffer = null;
let technicalMetadata = null;
if (safeText.includes('[IMAGE_UPLOADED:')) {
const match = safeText.match(/\[IMAGE_UPLOADED:\s*([^\]]+)\]/);
if (match) {
try {
imageBuffer = await downloadFile(match[1].trim());
// LAYER 1: The Code is Judge (Deterministic physical measurement)
technicalMetadata = await processImageUpload(imageBuffer);
session.lastImageMetadata = technicalMetadata; // Persist for context
} catch (e) {
console.error("โ [VISION ERROR]:", e.message);
}
}
}
const extraction = await routeWithLLM(safeText, session, imageBuffer);
extraction.raw_text = safeText;
extraction.technicalMetadata = technicalMetadata;
// --- Spec v5.7.4: Deterministic Semantic Closure Gate ---
// Calculate closure intent and confirmation flag heuristically
let closureScore = 0;
let isConfirmed = false;
const positiveClosureSignals = ["ืืฉืืจ", "ืืื ืืืฉืื", "ืกืืืจ", "ืชื ืืฆืขื", "ืืขืืื", "ืืืืืง", "ืืื", "ืชืชืงืื", "ืฉืื ืืืงืื", "ืืืฉื", "ืืกืืจ", "ืืืื"];
const conditionSignals = ["ืืื", "ืืืฅ ื", "ืืืื", "ืืฉื ืืช", "ืจืืข", "ืฉื ื", "ืชืืืืฃ", "ืืืงืื"];
const hasPositiveSignal = positiveClosureSignals.some(s => t.includes(s));
const hasCondition = conditionSignals.some(s => t.includes(s));
if (hasPositiveSignal && !hasCondition && extraction.intent !== 'update' && extraction.intent !== 'reset') {
closureScore = 0.9;
isConfirmed = true;
} else if (hasCondition || extraction.intent === 'update') {
closureScore = 0.0;
isConfirmed = false;
}
extraction.closure_intent_score = closureScore;
extraction.confirmation_flag = isConfirmed;
return extraction;
} catch (e) {
console.error("Classifier Error:", e);
return {
intent: "chat",
answer_text: "ืกืืืื, ืื ื ืืืื ืงืืฉื ืงืื ืืขืืืื. ื ืกื ืฉืื?",
products_detected: [],
parameters_detected: []
};
}
}
module.exports = { classifyMessage: classify }; |