pini-print-bot / engine /validator.js
dotandru's picture
V2.2.7 SUPER NUCLEAR: Total Ghost Scrub and Size Fix
ae54989
Raw
History Blame Contribute Delete
5.21 kB
/** engine/validator.js V94.1 - Syntax Fixed */
const fs = require('fs');
const path = require('path');
let productsDB = {};
try {
productsDB = JSON.parse(fs.readFileSync(path.join(__dirname, '../db/products.json'), 'utf8'));
} catch (e) {
console.error("Failed loading products.json in validator");
}
const VALID_PRODUCTS = new Set(Object.keys(productsDB));
const PRODUCT_KEYWORDS_MAP = {
'ืคื•ืกื˜ืจ': 'poster', 'poster': 'poster',
'ืคืœื™ื™ืจ': 'flyer', 'flyer': 'flyer',
'ื—ื•ื‘ืจ': 'booklet', 'ืกืคืจ': 'booklet', 'ืงื˜ืœื•ื’': 'booklet', 'booklet': 'booklet',
'ืžื“ื‘ืง': 'sticker', 'sticker': 'sticker',
'ืกืงื•ื“ื™ืงืก': 'scodix', 'scodix': 'scodix', 'ืคื•ื™ืœ': 'scodix',
'ืืœื•ืงื•ื‘ื•ื ื“': 'alucobond', 'alucobond': 'alucobond', 'ืฉืœื˜': 'alucobond',
'ื’ืœื™ืœ': 'roll_stickers', 'roll_stickers': 'roll_stickers'
};
function validateLLMResult(llmResult, userText, session) {
let result = { ...llmResult };
const text = userText.toLowerCase();
if (!result.mapped_params) result.mapped_params = {};
// Product Detection Override
const detectedProductsSet = new Set();
Object.keys(PRODUCT_KEYWORDS_MAP).forEach(keyword => {
if (text.includes(keyword)) {
detectedProductsSet.add(PRODUCT_KEYWORDS_MAP[keyword]);
}
});
const detectedProducts = Array.from(detectedProductsSet);
const hasNumber = /\d/.test(text);
if (detectedProducts.length > 0 && hasNumber) {
if (result.intent !== 'quote' || !result.product) {
console.log(`๐Ÿ›ก๏ธ [VALIDATOR] Force-Switching to QUOTE. Found: ${detectedProducts.join(', ')}`); // โœ… ืชื•ืงืŸ!
result.intent = 'quote';
if (!result.product) {
result.product = detectedProducts[0];
}
}
result.allDetectedProducts = detectedProducts;
}
// ืฉืืจ ื”ืงื•ื“ ื ืฉืืจ ืื•ืชื• ื“ื‘ืจ...
const updateKeywords = ["ืชืฉื ื”", "ืชื—ืœื™ืฃ", "ืขื“ื›ืŸ", "ื›ืžื•ืช", "ืœ-", "ืœืžืขืœื”", "ืœืžื˜ื”", "ื‘ืžืงื•ื", "update", "qty", "change", "replace", "fix"];
if (updateKeywords.some(k => text.includes(k))) {
result.intent = 'update';
}
const sizeMatch = text.match(/(\d+\.\d+|\d+)\s*(?:x|X|\*|ืขืœ)\s*(\d+\.\d+|\d+)/);
if (sizeMatch) {
result.mapped_params.size = `${sizeMatch[1]}x${sizeMatch[2]}`;
console.log(`๐Ÿ›ก๏ธ [VALIDATOR] Detected Size with Decimals: ${result.mapped_params.size}`);
if (result.intent === 'chat') result.intent = 'update';
}
// --- PHASE 1.3 UAT Hotfix: Alucobond vs Office Intercept ---
if (text.includes('ืืœื•ืงื•ื‘ื•ื ื“') || text.includes('alucobond')) {
if (result.product === 'office') {
console.log(`\x1b[33m๐Ÿ›ก๏ธ [X-RAY VALIDATOR] Intercepted LLM hallucination: Swapped 'office' for 'alucobond'\x1b[0m`);
result.product = 'alucobond';
result.intent = 'quote';
}
}
if (text.includes('ื›ืจื•ืžื•')) {
if (text.includes('300')) result.mapped_params.paper_type = 'chromo_300';
else result.mapped_params.paper_type = 'chromo_130';
if (result.intent === 'chat') result.intent = 'update';
}
if (text.includes('ืžื˜')) {
result.mapped_params.paper_type = 'matte_350';
if (result.intent === 'chat') result.intent = 'update';
}
if (text.includes("ื‘ืœื™") || text.includes("ืœืœื")) {
if (result.intent === 'chat') result.intent = 'update';
}
if (/^\d+$/.test(text.trim()) && result.intent === 'chat') {
result.intent = 'update';
}
// --- PHASE 1.3 Anti-Hallucination: Confidence Gate ---
if (result.confidence !== undefined && result.confidence < 0.85) {
console.log(`\x1b[31m๐Ÿ›ก๏ธ [X-RAY VALIDATOR] Confidence Gate Blocked: ${result.confidence} is below 0.85 threshold.\x1b[0m`);
result.intent = 'chat';
result.product = null;
result.answer_text = "ืื ื™ ืœื ืœื’ืžืจื™ ื‘ื˜ื•ื— ื‘ื›ื•ื•ื ืชืš, ืืคืฉืจ ืœื ืกื— ืฉื•ื‘?";
}
// --- PHASE 1.3 Anti-Hallucination: Product Whitelist ---
if (result.product && !VALID_PRODUCTS.has(result.product)) {
console.log(`\x1b[31m๐Ÿ›ก๏ธ [X-RAY VALIDATOR] Product Whitelist Blocked: '${result.product}' does not exist in DB.\x1b[0m`);
result.intent = 'chat';
result.product = null;
result.answer_text = "ืœืฆืขืจื™ ืื™ืŸ ืœื ื• ืืช ื”ืžื•ืฆืจ ื”ื–ื” ื›ืจื’ืข ื‘ืžืขืจื›ืช. ืœื—ื–ื•ืจ ืœืชืคืจื™ื˜?";
}
// --- PHASE 1.3 Anti-Hallucination: Quantity Clamp ---
if (result.mapped_params && result.mapped_params.qty !== undefined) {
const rawQty = parseInt(result.mapped_params.qty);
if (!isNaN(rawQty)) {
// ื”ื’ื‘ืœืช ืžื™ื ื™ืžื•ื ื•ืžืงืกื™ืžื•ื ืื’ืจืกื™ื‘ื™ืช (1 ืขื“ 100,000)
const clampedQty = Math.max(1, Math.min(rawQty, 100000));
if (rawQty !== clampedQty) {
console.log(`\x1b[33m๐Ÿ›ก๏ธ [X-RAY VALIDATOR] Quantity Clamped from ${rawQty} to ${clampedQty}.\x1b[0m`);
}
result.mapped_params.qty = clampedQty;
}
}
return result;
}
module.exports = { validateLLMResult };