🚀 Full project sync: Hotels RAG & Audit System
✨ Major Features: - Complete RAG system for hotel website analysis - Hybrid audit with BGE-M3 embeddings + Natasha NER - Universal horizontal Excel reports with dashboards - Multi-region processing (SPb, Orel, Chukotka, Kamchatka) 📊 Completed Regions: - Орловская область: 100% (36/36) - Чукотский АО: 100% (4/4) - г. Санкт-Петербург: 93% (893/960) - Камчатский край: 87% (89/102) 🔧 Infrastructure: - PostgreSQL with pgvector extension - BGE-M3 embeddings API - Browserless for web scraping - N8N workflows for automation - S3/Nextcloud file storage 📝 Documentation: - Complete DB schemas - API documentation - Setup guides - Status reports
This commit is contained in:
160
n8n_code_check_regex.js
Normal file
160
n8n_code_check_regex.js
Normal file
@@ -0,0 +1,160 @@
|
||||
// 🎯 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 || ''
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user