Spaces:
Sleeping
Sleeping
| /** 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 }; |