✨ 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
122 lines
3.9 KiB
JavaScript
122 lines
3.9 KiB
JavaScript
// 🎯 CODE NODE: Парсинг JSON ответов от AI Agent
|
||
// Вход: массив с ответами от AI Agent в JSON формате
|
||
// Выход: структурированные данные для каждого критерия
|
||
|
||
const inputData = $input.all();
|
||
|
||
// Обрабатываем каждый item (ответ на вопрос)
|
||
const results = inputData.map((item, index) => {
|
||
const rawOutput = item.json.output || item.json.response || '';
|
||
|
||
let parsedData = {
|
||
found: false,
|
||
score: 0.0,
|
||
quote: '',
|
||
url: '',
|
||
details: '',
|
||
checked_pages: 0,
|
||
confidence: 'Не найдено'
|
||
};
|
||
|
||
try {
|
||
// Пытаемся распарсить JSON из ответа
|
||
// AI может вернуть JSON в разных форматах, пробуем все варианты
|
||
|
||
// Вариант 1: Чистый JSON
|
||
if (rawOutput.trim().startsWith('{')) {
|
||
parsedData = JSON.parse(rawOutput);
|
||
}
|
||
// Вариант 2: JSON в markdown блоке ```json ... ```
|
||
else if (rawOutput.includes('```json')) {
|
||
const jsonMatch = rawOutput.match(/```json\s*(\{[\s\S]*?\})\s*```/);
|
||
if (jsonMatch) {
|
||
parsedData = JSON.parse(jsonMatch[1]);
|
||
}
|
||
}
|
||
// Вариант 3: JSON где-то в тексте
|
||
else {
|
||
const jsonMatch = rawOutput.match(/\{[\s\S]*?"found"[\s\S]*?\}/);
|
||
if (jsonMatch) {
|
||
parsedData = JSON.parse(jsonMatch[0]);
|
||
}
|
||
}
|
||
} catch (e) {
|
||
// Если не удалось распарсить JSON - пытаемся извлечь данные из текста
|
||
console.log(`Ошибка парсинга JSON для item ${index}: ${e.message}`);
|
||
|
||
// Проверяем наличие позитивных маркеров
|
||
const isFound = rawOutput.includes('✅ ДА') ||
|
||
rawOutput.includes('найдено') ||
|
||
rawOutput.includes('указан') ||
|
||
rawOutput.includes('представлен');
|
||
|
||
const isNotFound = rawOutput.includes('❌ НЕТ') ||
|
||
rawOutput.includes('не найдено') ||
|
||
rawOutput.includes('отсутствует');
|
||
|
||
// Извлекаем цитату
|
||
const quoteMatch = rawOutput.match(/📄 Цитата: "(.+?)"/s) ||
|
||
rawOutput.match(/Цитата: (.+?)(?:\n|$)/);
|
||
const quote = quoteMatch ? quoteMatch[1].trim() : rawOutput.substring(0, 200);
|
||
|
||
// Извлекаем URL
|
||
const urlMatch = rawOutput.match(/🔗 URL: (.+?)(?:\n|$)/) ||
|
||
rawOutput.match(/URL: (.+?)(?:\n|$)/);
|
||
const url = urlMatch ? urlMatch[1].trim() : '';
|
||
|
||
// Оценка
|
||
let score = 0.0;
|
||
let confidence = 'Не найдено';
|
||
|
||
if (isFound && quote && url) {
|
||
score = 1.0;
|
||
confidence = 'Высокая';
|
||
} else if (isFound && quote) {
|
||
score = 0.5;
|
||
confidence = 'Средняя';
|
||
} else if (isNotFound) {
|
||
score = 0.0;
|
||
confidence = 'Не найдено';
|
||
} else {
|
||
score = 0.2;
|
||
confidence = 'Низкая';
|
||
}
|
||
|
||
parsedData = {
|
||
found: isFound,
|
||
score: score,
|
||
quote: quote,
|
||
url: url,
|
||
details: rawOutput.substring(0, 200),
|
||
checked_pages: 0,
|
||
confidence: confidence
|
||
};
|
||
}
|
||
|
||
// Возвращаем структурированные данные
|
||
return {
|
||
json: {
|
||
criterion_id: item.json.id || (index + 1),
|
||
criterion_name: item.json.name || `Критерий ${index + 1}`,
|
||
question: item.json.question || '',
|
||
raw_answer: rawOutput,
|
||
found: parsedData.found,
|
||
score: parsedData.score,
|
||
quote: parsedData.quote || '',
|
||
url: parsedData.url || '',
|
||
details: parsedData.details || '',
|
||
checked_pages: parsedData.checked_pages || 0,
|
||
confidence: parsedData.confidence || 'Не найдено'
|
||
}
|
||
};
|
||
});
|
||
|
||
return results;
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|