// 🎯 CODE NODE: Проверка регулярными выражениями // Размести эту ноду ПОСЛЕ AI Agent // Она улучшит оценку, если найдёт точные форматы (ИНН, телефоны, email) // Получаем данные от AI Agent const aiResult = $input.item.json; // Получаем текст из chunks (должен быть в контексте) // Если у тебя есть отдельная нода для получения chunks - используй её // Иначе - нужно сделать дополнительный запрос к PostgreSQL const hotelText = $('Postgres1').all().map(item => item.json.text).join(' '); // Регулярные выражения для каждого критерия const regexPatterns = { 1: { // ИНН, ОГРН patterns: [ /\b\d{10}\b/g, // ИНН юр.лица (10 цифр) /\b\d{12}\b/g, // ИНН ИП (12 цифр) /\b\d{13}\b/g, // ОГРН (13 цифр) /\b\d{15}\b/g, // ОГРНИП (15 цифр) /инн\s*:?\s*\d{10,12}/gi, /огрн\s*:?\s*\d{13}/gi ], weight: 1.0 }, 2: { // Адрес patterns: [ /\d{6}.*?ул\./gi, /ул\.\s*[А-Яа-яёЁA-Za-z\s]+,?\s*\d+/gi, /\d{6},?\s*г\.\s*[А-Яа-яёЁ-]+/gi ], weight: 1.0 }, 3: { // Контакты patterns: [ /(?:\+7|8)\s*\(?\d{3,5}\)?\s*\d{1,3}[-\s]?\d{2}[-\s]?\d{2}/g, // Телефон /[\w\.-]+@[\w\.-]+\.\w{2,}/g // Email ], weight: 1.0 }, 4: { // Режим работы patterns: [ /(?:с|с\s+)\d{1,2}(?::|\.)\d{2}\s*(?:до|по)\s*\d{1,2}(?::|\.)\d{2}/gi, /круглосуточно/gi, /24\s*[/\-]\s*7/g ], weight: 1.0 }, 5: { // 152-ФЗ patterns: [ /152[-\s]?фз/gi, /политика\s+в\s+отношении\s+обработки\s+персональных\s+данных/gi ], weight: 1.0 }, 7: { // Договор-оферта patterns: [ /публичная\s+оферта/gi, /договор.*?оказани.*?услуг/gi, /пользовательское\s+соглашение/gi ], weight: 1.0 }, 9: { // Цены patterns: [ /\d+\s*(?:руб|₽)/g, /(?:от|цена|стоимость)\s*\d+/gi ], weight: 0.8 }, 12: { // Онлайн-бронирование patterns: [ /забронировать/gi, /форма\s+(?:заявки|бронирования)/gi ], weight: 0.8 } }; // Функция проверки паттернов function checkPatterns(text, patterns) { const matches = []; for (const pattern of patterns) { const found = text.match(pattern); if (found) { matches.push(...found.slice(0, 3)); // Макс 3 совпадения на паттерн } } return matches; } // Проверяем текущий критерий const criterionId = aiResult.criterion_id || aiResult.id; const regexConfig = regexPatterns[criterionId]; let regexScore = 0.0; let regexMatches = []; if (regexConfig && hotelText) { regexMatches = checkPatterns(hotelText, regexConfig.patterns); if (regexMatches.length > 0) { regexScore = regexConfig.weight; } } // ГИБРИДНАЯ ОЦЕНКА: берём максимум из AI и регулярок const aiScore = parseFloat(aiResult.score) || 0.0; const finalScore = Math.max(aiScore, regexScore); // Определяем метод, который дал результат let method = 'Не найдено'; if (finalScore > 0) { if (aiScore > regexScore) { method = 'AI Agent'; } else if (regexScore > aiScore) { method = 'Регулярные выражения'; } else { method = 'AI Agent + Регулярки'; } } // Возвращаем улучшенный результат return { json: { criterion_id: criterionId, criterion_name: aiResult.criterion_name || aiResult.name, question: aiResult.question, // Результаты AI Agent ai_score: aiScore, ai_found: aiResult.found, ai_quote: aiResult.quote || '', ai_url: aiResult.url || '', // Результаты регулярок regex_score: regexScore, regex_matches: regexMatches.slice(0, 5), // Макс 5 совпадений regex_found: regexMatches.length > 0, // Итоговая оценка final_score: finalScore, method: method, confidence: finalScore >= 0.8 ? 'Высокая' : finalScore >= 0.5 ? 'Средняя' : finalScore >= 0.3 ? 'Низкая' : 'Не найдено', // Для отчёта quote: aiResult.quote || (regexMatches.length > 0 ? `Найдено: ${regexMatches[0]}` : ''), url: aiResult.url || '', details: aiResult.details || '' } };