diff --git a/src/main/java/kz/konturai/parser/dto/MarketingAnalysisV3Result.java b/src/main/java/kz/konturai/parser/dto/MarketingAnalysisV3Result.java index e580b56..76a7ba6 100644 --- a/src/main/java/kz/konturai/parser/dto/MarketingAnalysisV3Result.java +++ b/src/main/java/kz/konturai/parser/dto/MarketingAnalysisV3Result.java @@ -138,9 +138,10 @@ public class MarketingAnalysisV3Result { @Data public static class UserPositioning { - private RadarMetrics radarChart; - private String status; - private List gaps; + private RadarMetrics marketMetrics; + private RadarMetrics userMetrics; + private String mode; + private List strategicFocus; } @Data diff --git a/src/main/java/kz/konturai/parser/service/MarketingAnalysisV3Service.java b/src/main/java/kz/konturai/parser/service/MarketingAnalysisV3Service.java index 3a3e94a..bb66b0f 100644 --- a/src/main/java/kz/konturai/parser/service/MarketingAnalysisV3Service.java +++ b/src/main/java/kz/konturai/parser/service/MarketingAnalysisV3Service.java @@ -236,16 +236,18 @@ public class MarketingAnalysisV3Service { private String buildKazakhstanSystemPrompt() { return """ - РОЛЬ: Ты — Chief Data Officer и Стратег Big 4 (PwC, BCG) по рынку Казахстана. - ЗАДАЧА: Сгенерировать глубокий, Data-Driven "Marketing Analysis v4.0" в строгом JSON формате. - + РОЛЬ: Ты — Chief Data Officer и Senior Стратег Big 4 (PwC, McKinsey), эксперт по рынку Казахстана. + Твоя задача — не просто сгенерировать JSON, а подготовить ИДЕАЛЬНЫЙ датасет для интерактивного аналитического дашборда на фронтенде (React/Vue). + От твоих данных будут строиться реальные графики (Radar, Scatter, Pie, Line charts). Данные должны быть математически корректны и логически связаны. + КРИТИЧЕСКИЕ ПРАВИЛА (ANTI-HALLUCINATION PROTOCOL): - 1. ТОЛЬКО РЕАЛЬНЫЕ ДАННЫЕ: Вся аналитика строится на переданном SEARCH EVIDENCE. - 2. РЕАЛЬНЫЕ КОНКУРЕНТЫ: В блоке `3_competitor_map` ОБЯЗАНО быть строго от 5 до 10 РЕАЛЬНЫХ компаний из предоставленных данных. Ровно 3 — ЗАПРЕЩЕНО. - 3. ПОЛНАЯ РУСИФИКАЦИЯ: Все текстовые значения статусов, уровней и трендов (businessStage, competitionLevel, demandTrend, intensityLabel, status) СТРОГО на русском языке. Запрещено копировать английские слова (JUST_STARTING, HIGH, STABLE, NONE) из DTO. Переводи их по смыслу (Например: 'На старте', 'Высокая', 'Стабильный', 'Отсутствует'). - 4. ОЦИФРОВКА И ТИПЫ ДАННЫХ: Возвращай строго те типы данных, которые указаны в шаблоне. Если указано число (0 или 0.0), возвращай число, а не строку. - 5. СВЯЗЬ СО СТРАТЕГИЕЙ: Твой анализ — это фундамент для будущего SMM-Scoring Model. - 6. НИКАКИХ NULL: Заполни абсолютно все поля JSON. Если точной цифры нет, примени метод Ферми и сделай экстраполяцию, характерную для рынка РК. + 1. АБСОЛЮТНАЯ РУСИФИКАЦИЯ: Все статусы, уровни, тренды и перечисления (businessStage, competitionLevel, demandTrend, intensityLabel) СТРОГО НА РУССКОМ ЯЗЫКЕ. Никаких 'JUST_STARTING', 'HIGH', 'NONE'. + 2. ГЕОГРАФИЯ И ГОРОДА: Ты ОБЯЗАН включить КАЖДЫЙ город, переданный в запросе, в блоки аналитики (1_market_landscape и 2_geo_structure). Пропуск даже одного города — критический провал системы. + 3. КОНКУРЕНТЫ: В блоке `3_competitor_map` ОБЯЗАНО быть строго от 5 до 10 реально существующих компаний из SEARCH EVIDENCE. Ровно 3 — ЗАПРЕЩЕНО. + 4. ЧИСЛА, А НЕ СЛОВА: Если фронт ждет int или double (например, avgMonthlySearches, avgCycleDays), выдавай СТРОГО числа. Никаких слов "высокая" или "короткий". + 5. НИКАКИХ NULL И ПУСТОТ: Заполни абсолютно все поля. Используй экстраполяцию рынка РК (Kaspi, 2GIS, менталитет), если точных данных нет. + 6. ЛОГИКА ГРАФИКОВ: Суммы процентов (например, в content_profile или starDistribution) должны давать ровно 100%. + 7. РЕАЛИСТИЧНОСТЬ ДАННЫХ (КРИТИЧНО): Избегай круглых чисел и ленивых средних значений (типа ровно 50% или везде 0). Генерируй реалистичный математический разброс для показателей, основываясь на данных парсинга. """; } @@ -271,42 +273,55 @@ public class MarketingAnalysisV3Service { РАЗВЕДДАННЫЕ (SEARCH EVIDENCE): %s - ИНСТРУКЦИИ ПО СЕКЦИЯМ (СТРОГО): - СТРОГО ИСПОЛЬЗУЙ ВСЕ ГОРОДА, КОТОРЫЕ ТЕБЕ ОТПРАВЛЯЮТ, ПРЯМ ВСЕ - [0_executive_summary] - - Все статусы СТРОГО на русском. - - averageNicheEr: Верни число (double, например 0.05). + ОБЯЗАТЕЛЬНЫЕ ЦЕЛЕВЫЕ ГОРОДА (СТРОГО ИСПОЛЬЗУЙ ВСЕ ГОРОДА В АНАЛИЗЕ!): %s - [1_market_landscape] и [2_geo_structure] - - ОБЯЗАТЕЛЬНО выведи метрики распределения для КАЖДОГО из этих городов: %s. Пропуск любого города — критическая ошибка. + ИНСТРУКЦИИ ДЛЯ ПОДГОТОВКИ ДАННЫХ К ДАШБОРДУ (СТРОГО): - [3_competitor_map] - - ОБЯЗАНО быть строго от 5 до 10 РЕАЛЬНЫХ компаний. - - Рассчитай реалистичный ER (от 0.01 до 0.08). + [0_executive_summary] -> Виджеты KPI + - Все текстовые поля (businessStage, geography, competitionLevel, demandTrend) СТРОГО НА РУССКОМ. + - averageNicheEr: верни реалистичное число (double, например 0.045). - [4_content_profile] - - Сумма всех ContentPercent должна быть ровно 100.0. - - avgTextLengthCharacters: Верни конкретное число символов (int, например 400). - - ctaUsagePercent: Верни процент использования призывов (double, например 85.0). + [1_market_landscape] -> Pie Chart (Платформы) и Heatmap (Города) + - Распредели игроков по платформам адекватно. + - В cityDistribution ОБЯЗАТЕЛЬНО укажи распределение по КАЖДОМУ целевому городу. - [6_reputation_analysis] - - avgOwnerResponseTimeHours: Верни среднее время ответа в часах (int, например 2 или 24). + [2_geo_structure] -> Сравнительная гистограмма + - В cityComparison ОБЯЗАНЫ быть ВСЕ целевые города с метриками. - [7_behavioral_pattern] - - Все показатели верни в процентах (double, например 45.0). - - avgCycleDays: Верни цикл сделки в днях (int, например 7). + [3_competitor_map] -> Scatter Plot (Пузырьковая диаграмма) + - СТРОГО 5-10 РЕАЛЬНЫХ конкурентов. Меньше 5 недопустимо. + - ER, followers, postsPerMonth должны быть числовыми и реалистичными. - [8_search_demand] - - avgMonthlySearches: Верни число поисковых запросов в месяц (int, например 15000). - - seasonality: 12 объектов. Поле "period" СТРОГО на русском (Январь, Февраль...). + [4_content_profile] -> Donut Chart + - Сумма всех Percent строго 100.0. Сделай реалистичный разброс (например 35, 20, 15, 25, 5). + - avgTextLengthCharacters: верни число символов (int, например 350). + - ctaUsagePercent: процент постов с призывом (double, например 85.5). - [9_user_positioning] - - status: СТРОГО на русском (например 'Отсутствует', 'Действующий'). + [5_competition_intensity] -> Gauge Chart (Спидометр) + - ciiIndex: 0-100. + - intensityLabel: СТРОГО НА РУССКОМ (например "Высокая", "Свободный рынок"). - [11_smm_strategy_rationale] - - МИНИМУМ 50 СЛОВ. Обоснуй стратегию на основе реальных данных из блоков 5 и 7. + [6_reputation_analysis] -> Bar Chart (Рейтинги) + - starDistribution: сумма долей строго 100.0. Имитируй реальные отзывы (много 5, немного 1, почти нет 2 и 3). + - avgOwnerResponseTimeHours: часы (int, например 2 или 24). - ЭТАЛОННЫЙ JSON: + [7_behavioral_pattern] -> Горизонтальный Bar Chart и Карточки + - Показатели (promoUsagePercent и т.д.) верни в процентах (double, 0.0 - 100.0). Сделай цифры разными и реалистичными. + - avgCycleDays: цикл сделки в днях (int, например 7). + + [8_search_demand] -> Line Chart (Сезонность) + - avgMonthlySearches: точное число запросов (int, например 15000). Никаких слов! + - seasonality: ровно 12 объектов. Периоды строго на русском (Январь, Февраль...). + + [9_user_positioning] -> Radar Chart (Паутинка) - ВАЖНАЯ ЛОГИКА: + - Если DTO smmStatus == "NONE": поле mode СТРОГО "BENCHMARK". userMetrics везде 0. marketMetrics заполни РЕАЛЬНЫМИ средними требованиями ниши (от 0 до 100, с разбросом, например activity 75, engagement 45, reputation 80). + - Если DTO smmStatus != "NONE": поле mode СТРОГО "COMPARISON". Оцени userMetrics на основе данных, marketMetrics — реалистичное среднее по рынку. + - strategicFocus: Напиши 3 конкретных шага (стратегический фокус). + + [10_structured_conclusions] & [11_smm_strategy_rationale] -> Текстовые выводы + - МИНИМУМ 50 СЛОВ в блоке 11. Обоснуй SMM стратегию глубоко, опираясь на конкретные числа из графиков. + + ЭТАЛОННЫЙ JSON (СТРОГО СОБЛЮДАЙ ФОРМАТ, КЛЮЧИ И ТИПЫ ДАННЫХ): %s """.formatted(requestJson, evidenceJson, targetCities, schemaTemplate); } catch (Exception e) { @@ -318,18 +333,18 @@ public class MarketingAnalysisV3Service { return """ { "0_executive_summary": { - "businessStage": "СТРОГО НА РУССКОМ", - "geography": "СТРОГО НА РУССКОМ", + "businessStage": "СТРОГО НА РУССКОМ (например: 'На этапе запуска', 'Действующий бизнес')", + "geography": "СТРОГО НА РУССКОМ (например: 'Один город', 'Вся страна')", "activeCompetitors": 0, - "competitionLevel": "СТРОГО НА РУССКОМ", + "competitionLevel": "СТРОГО НА РУССКОМ (например: 'Высокий', 'Средний')", "averageNicheEr": 0.0, "averageRating": 0.0, - "demandTrend": "СТРОГО НА РУССКОМ", + "demandTrend": "СТРОГО НА РУССКОМ (например: 'Растущий', 'Стабильный')", "keyFigures": ["string", "string", "string"] }, "1_market_landscape": { "activePlayersByPlatform": {"Instagram": 0, "TikTok": 0, "GoogleMaps": 0}, - "cityDistribution": {"Almaty": 0}, + "cityDistribution": {"Город 1": 0, "Город 2": 0}, "nicheReputationLevel": 0.0 }, "2_geo_structure": { @@ -361,7 +376,7 @@ public class MarketingAnalysisV3Service { }, "5_competition_intensity": { "ciiIndex": 0, - "intensityLabel": "СТРОГО НА РУССКОМ", + "intensityLabel": "СТРОГО НА РУССКОМ (например: 'Высокая плотность')", "contributingFactors": ["string"] }, "6_reputation_analysis": { @@ -398,18 +413,13 @@ public class MarketingAnalysisV3Service { "relatedQueries": ["string"] }, "9_user_positioning": { - "radarChart": { - "activity": 0, - "engagement": 0, - "video": 0, - "reputation": 0, - "frequency": 0 - }, - "status": "СТРОГО НА РУССКОМ", - "gaps": ["string"] + "marketMetrics": {"activity": 0, "engagement": 0, "video": 0, "reputation": 0, "frequency": 0}, + "userMetrics": {"activity": 0, "engagement": 0, "video": 0, "reputation": 0, "frequency": 0}, + "mode": "BENCHMARK или COMPARISON", + "strategicFocus": ["string", "string", "string"] }, "10_structured_conclusions": ["string", "string", "string"], - "11_smm_strategy_rationale": "string" + "11_smm_strategy_rationale": "МИНИМУМ 50 СЛОВ. Экспертный текст, связывающий данные графиков с выбором SMM." } """; }