This commit is contained in:
root
2025-12-19 00:08:27 +05:00
parent b140fe35f5
commit 1422d7ddc1
@@ -40,6 +40,9 @@ public class MarketingAnalysisService {
@Value("${openai.model.name.text:gpt-4o}")
private String textModelName;
@Value("${openai.model.name:gpt-4o-mini}")
private String miniModelName;
public MarketingAnalysisService(
MarketingAnalysisRepository repository,
OpenAIAnalyticsService openAIAnalyticsService,
@@ -1407,6 +1410,722 @@ public class MarketingAnalysisService {
}
}
/**
* Подготавливает контекстный JSON для конкретного раздела отчета.
* Извлекает только релевантные данные для экономии токенов.
*
* @param fullJson Полный JSON анализа
* @param section Название раздела (summary, product, market, audience,
* competitors, swot, channels, funnel, positioning, content,
* strategy)
* @return Контекстный JSON с базовыми полями и специфичными для раздела данными
*/
private Map<String, Object> prepareSectionContext(Map<String, Object> fullJson, String section) {
Map<String, Object> context = new HashMap<>();
// Всегда включаем базовые поля
if (fullJson.containsKey("product")) {
context.put("product", fullJson.get("product"));
}
if (fullJson.containsKey("businessNiche")) {
context.put("businessNiche", fullJson.get("businessNiche"));
}
if (fullJson.containsKey("goal")) {
context.put("goal", fullJson.get("goal"));
}
if (fullJson.containsKey("regions")) {
context.put("regions", fullJson.get("regions"));
}
if (fullJson.containsKey("detailLevel")) {
context.put("detailLevel", fullJson.get("detailLevel"));
}
// Добавляем специфичные данные для каждого раздела
switch (section) {
case "summary":
// Для резюме достаточно базовых полей + meta если есть
if (fullJson.containsKey("meta")) {
context.put("meta", fullJson.get("meta"));
}
break;
case "product":
// Для продукта добавляем позиционирование и УТП если есть
if (fullJson.containsKey("positioning")) {
context.put("positioning", fullJson.get("positioning"));
}
if (fullJson.containsKey("valueProposition")) {
context.put("valueProposition", fullJson.get("valueProposition"));
}
break;
case "market":
if (fullJson.containsKey("seasonality")) {
context.put("seasonality", fullJson.get("seasonality"));
}
if (fullJson.containsKey("market")) {
context.put("market", fullJson.get("market"));
}
break;
case "audience":
if (fullJson.containsKey("audienceSegments")) {
context.put("audienceSegments", fullJson.get("audienceSegments"));
}
break;
case "competitors":
if (fullJson.containsKey("competitors")) {
context.put("competitors", fullJson.get("competitors"));
}
if (fullJson.containsKey("comparisonTable")) {
context.put("comparisonTable", fullJson.get("comparisonTable"));
}
if (fullJson.containsKey("swotCompetitors")) {
context.put("swotCompetitors", fullJson.get("swotCompetitors"));
}
if (fullJson.containsKey("marketShareChart")) {
context.put("marketShareChart", fullJson.get("marketShareChart"));
}
break;
case "swot":
if (fullJson.containsKey("swot")) {
context.put("swot", fullJson.get("swot"));
}
break;
case "channels":
if (fullJson.containsKey("channels")) {
context.put("channels", fullJson.get("channels"));
}
if (fullJson.containsKey("channelsPotential")) {
context.put("channelsPotential", fullJson.get("channelsPotential"));
}
break;
case "funnel":
if (fullJson.containsKey("funnel")) {
context.put("funnel", fullJson.get("funnel"));
}
if (fullJson.containsKey("conversionFunnel")) {
context.put("conversionFunnel", fullJson.get("conversionFunnel"));
}
break;
case "positioning":
if (fullJson.containsKey("positioning")) {
context.put("positioning", fullJson.get("positioning"));
}
if (fullJson.containsKey("valueProposition")) {
context.put("valueProposition", fullJson.get("valueProposition"));
}
break;
case "content":
if (fullJson.containsKey("contentRecommendations")) {
context.put("contentRecommendations", fullJson.get("contentRecommendations"));
}
break;
case "strategy":
// Для итоговой стратегии включаем все ключевые данные
if (fullJson.containsKey("swot")) {
context.put("swot", fullJson.get("swot"));
}
if (fullJson.containsKey("channels")) {
context.put("channels", fullJson.get("channels"));
}
if (fullJson.containsKey("funnel")) {
context.put("funnel", fullJson.get("funnel"));
}
if (fullJson.containsKey("positioning")) {
context.put("positioning", fullJson.get("positioning"));
}
if (fullJson.containsKey("valueProposition")) {
context.put("valueProposition", fullJson.get("valueProposition"));
}
if (fullJson.containsKey("contentRecommendations")) {
context.put("contentRecommendations", fullJson.get("contentRecommendations"));
}
break;
}
return context;
}
/**
* Генерирует раздел I: Краткое резюме
*/
private String genSectionSummary(Map<String, Object> contextJson) {
try {
String jsonString = objectMapper.writeValueAsString(contextJson);
StringBuilder promptBuilder = new StringBuilder();
promptBuilder.append("Ты — высокооплачиваемый бизнес-консультант и маркетинговый аналитик.\n\n");
promptBuilder
.append("На основе следующего JSON напиши РАЗДЕЛ I (Краткое резюме) маркетингового отчета.\n\n");
promptBuilder.append("ТРЕБОВАНИЯ:\n");
promptBuilder.append("1. Объем: минимум 500-700 слов\n");
promptBuilder.append("2. Стиль: деловой, убедительный для владельца бизнеса\n");
promptBuilder.append("3. Глубина: аналитические инсайты с практическими выводами\n");
promptBuilder.append("4. Данные: используй ТОЛЬКО данные из JSON, не выдумывай цифры\n\n");
promptBuilder.append("СТРУКТУРА РАЗДЕЛА:\n");
promptBuilder.append("I. Краткое резюме\n\n");
promptBuilder.append("Опиши:\n");
promptBuilder.append("- Что за бизнес (ниша, продукт/услуга)\n");
promptBuilder.append("- Какую цель преследует бизнес на 6-12 месяцев\n");
promptBuilder.append("- Ключевые выводы из анализа (3-4 главных инсайта)\n");
promptBuilder.append("- Общую оценку потенциала и перспектив\n\n");
promptBuilder.append("ВАЖНО:\n");
promptBuilder.append("- Начинай сразу с заголовка \"I. Краткое резюме\"\n");
promptBuilder.append("- Не добавляй вступления или заключения\n");
promptBuilder.append("- Пиши так, чтобы отчет был полезен для принятия бизнес-решений\n\n");
promptBuilder.append("JSON ДАННЫЕ:\n");
promptBuilder.append(jsonString);
String result = openAIAnalyticsService.generateWithInstructionWithModel(
jsonString, promptBuilder.toString(), "ru", miniModelName);
if (result == null || result.trim().isEmpty()) {
logger.warn("genSectionSummary: AI returned empty result");
return "I. Краткое резюме\n\nНе удалось сгенерировать раздел.";
}
logger.info("genSectionSummary: Section generated successfully. Length: {} chars", result.length());
return result;
} catch (Exception e) {
logger.error("genSectionSummary: Error generating section: {}", e.getMessage(), e);
return "I. Краткое резюме\n\nОшибка при генерации раздела: " + e.getMessage();
}
}
/**
* Генерирует раздел II: Анализ продукта
*/
private String genSectionProduct(Map<String, Object> contextJson) {
try {
String jsonString = objectMapper.writeValueAsString(contextJson);
StringBuilder promptBuilder = new StringBuilder();
promptBuilder.append("Ты — высокооплачиваемый бизнес-консультант и маркетинговый аналитик.\n\n");
promptBuilder
.append("На основе следующего JSON напиши РАЗДЕЛ II (Анализ продукта) маркетингового отчета.\n\n");
promptBuilder.append("ТРЕБОВАНИЯ:\n");
promptBuilder.append("1. Объем: минимум 500-700 слов\n");
promptBuilder.append("2. Стиль: деловой, убедительный для владельца бизнеса\n");
promptBuilder.append("3. Глубина: аналитические инсайты с практическими выводами\n");
promptBuilder.append("4. Данные: используй ТОЛЬКО данные из JSON, не выдумывай цифры\n\n");
promptBuilder.append("СТРУКТУРА РАЗДЕЛА:\n");
promptBuilder.append("II. Анализ продукта\n\n");
promptBuilder.append("Детально проанализируй:\n");
promptBuilder.append("- Особенности продукта/услуги, его уникальные характеристики\n");
promptBuilder.append("- Позиционирование на рынке\n");
promptBuilder.append("- Уникальное торговое предложение (УТП)\n");
promptBuilder.append("- Тренды в нише и как продукт им соответствует\n");
promptBuilder.append("- Преимущества и недостатки продукта\n");
promptBuilder.append("- Потенциал для развития и масштабирования\n\n");
promptBuilder.append("ВАЖНО:\n");
promptBuilder.append("- Начинай сразу с заголовка \"II. Анализ продукта\"\n");
promptBuilder.append("- Не добавляй вступления или заключения\n");
promptBuilder.append("- Используй данные из полей product, businessNiche, positioning, valueProposition\n");
promptBuilder.append("- Пиши максимально подробно, анализируй тренды\n\n");
promptBuilder.append("JSON ДАННЫЕ:\n");
promptBuilder.append(jsonString);
String result = openAIAnalyticsService.generateWithInstructionWithModel(
jsonString, promptBuilder.toString(), "ru", miniModelName);
if (result == null || result.trim().isEmpty()) {
logger.warn("genSectionProduct: AI returned empty result");
return "II. Анализ продукта\n\nНе удалось сгенерировать раздел.";
}
logger.info("genSectionProduct: Section generated successfully. Length: {} chars", result.length());
return result;
} catch (Exception e) {
logger.error("genSectionProduct: Error generating section: {}", e.getMessage(), e);
return "II. Анализ продукта\n\nОшибка при генерации раздела: " + e.getMessage();
}
}
/**
* Генерирует раздел III: Анализ рынка и сезонности
*/
private String genSectionMarket(Map<String, Object> contextJson) {
try {
String jsonString = objectMapper.writeValueAsString(contextJson);
StringBuilder promptBuilder = new StringBuilder();
promptBuilder.append("Ты — высокооплачиваемый бизнес-консультант и маркетинговый аналитик.\n\n");
promptBuilder.append(
"На основе следующего JSON напиши РАЗДЕЛ III (Анализ рынка и сезонности) маркетингового отчета.\n\n");
promptBuilder.append("ТРЕБОВАНИЯ:\n");
promptBuilder.append("1. Объем: минимум 500-700 слов\n");
promptBuilder.append("2. Стиль: деловой, убедительный для владельца бизнеса\n");
promptBuilder.append("3. Глубина: аналитические инсайты с практическими выводами\n");
promptBuilder.append("4. Данные: используй ТОЛЬКО данные из JSON, не выдумывай цифры\n\n");
promptBuilder.append("СТРУКТУРА РАЗДЕЛА:\n");
promptBuilder.append("III. Анализ рынка и сезонности\n\n");
promptBuilder.append("Детально проанализируй:\n");
promptBuilder.append("- Рынок Казахстана в данной нише, его размер и динамику\n");
promptBuilder.append("- Макроэкономические факторы, влияющие на нишу\n");
promptBuilder.append("- Тренды и изменения в отрасли\n");
promptBuilder.append("- Сезонные колебания спроса (используй данные из поля seasonality)\n");
promptBuilder.append("- Как сезонность влияет на кэшфлоу бизнеса\n");
promptBuilder.append("- Конкретные рекомендации по работе с сезонностью (акции, планирование)\n\n");
promptBuilder.append("КРИТИЧНО - ВСТАВКА ГРАФИКА:\n");
promptBuilder.append(
"1. В логичном месте раздела (после описания сезонности) вставь плейсхолдер [[CHART_SEASONALITY]] на отдельной строке\n");
promptBuilder.append(
"2. ПЕРЕД графиком напиши вводный абзац (2-3 предложения), начинающийся с: \"Анализ данных на графике ниже показывает...\"\n");
promptBuilder.append(
"3. ПОСЛЕ графика напиши интерпретацию данных (2-3 предложения), начинающуюся с: \"Из этих показателей следует, что...\"\n\n");
promptBuilder.append("ВАЖНО:\n");
promptBuilder.append("- Начинай сразу с заголовка \"III. Анализ рынка и сезонности\"\n");
promptBuilder.append("- Не добавляй вступления или заключения\n");
promptBuilder.append("- Используй данные из полей seasonality, market, regions\n");
promptBuilder.append("- Пиши максимально подробно, анализируй тренды\n\n");
promptBuilder.append("JSON ДАННЫЕ:\n");
promptBuilder.append(jsonString);
String result = openAIAnalyticsService.generateWithInstructionWithModel(
jsonString, promptBuilder.toString(), "ru", textModelName);
if (result == null || result.trim().isEmpty()) {
logger.warn("genSectionMarket: AI returned empty result");
return "III. Анализ рынка и сезонности\n\nНе удалось сгенерировать раздел.";
}
logger.info("genSectionMarket: Section generated successfully. Length: {} chars", result.length());
return result;
} catch (Exception e) {
logger.error("genSectionMarket: Error generating section: {}", e.getMessage(), e);
return "III. Анализ рынка и сезонности\n\nОшибка при генерации раздела: " + e.getMessage();
}
}
/**
* Генерирует раздел IV: Анализ целевой аудитории
*/
private String genSectionAudience(Map<String, Object> contextJson) {
try {
String jsonString = objectMapper.writeValueAsString(contextJson);
StringBuilder promptBuilder = new StringBuilder();
promptBuilder.append("Ты — высокооплачиваемый бизнес-консультант и маркетинговый аналитик.\n\n");
promptBuilder.append(
"На основе следующего JSON напиши РАЗДЕЛ IV (Анализ целевой аудитории) маркетингового отчета.\n\n");
promptBuilder.append("ТРЕБОВАНИЯ:\n");
promptBuilder.append("1. Объем: минимум 500-700 слов\n");
promptBuilder.append("2. Стиль: деловой, убедительный для владельца бизнеса\n");
promptBuilder.append("3. Глубина: аналитические инсайты с практическими выводами\n");
promptBuilder.append("4. Данные: используй ТОЛЬКО данные из JSON, не выдумывай цифры\n\n");
promptBuilder.append("СТРУКТУРА РАЗДЕЛА:\n");
promptBuilder.append("IV. Анализ целевой аудитории\n\n");
promptBuilder.append("Детально проанализируй КАЖДЫЙ сегмент из audienceSegments:\n");
promptBuilder.append("- Демографические характеристики (возраст, пол, доход)\n");
promptBuilder.append("- Психографический портрет (потребности, мотивация, ценности)\n");
promptBuilder.append(
"- Customer Journey Map для каждого сегмента (этапы от первого контакта до покупки и лояльности)\n");
promptBuilder.append("- Ключевые потребности и боли сегмента\n");
promptBuilder.append("- Как продукт решает проблемы каждого сегмента\n");
promptBuilder.append("- Рекомендации по коммуникации с каждым сегментом\n\n");
promptBuilder.append("КРИТИЧНО - ВСТАВКА ГРАФИКА:\n");
promptBuilder.append(
"1. В логичном месте раздела (после описания сегментов) вставь плейсхолдер [[CHART_AUDIENCE]] на отдельной строке\n");
promptBuilder.append(
"2. ПЕРЕД графиком напиши вводный абзац (2-3 предложения), начинающийся с: \"Анализ данных на графике ниже показывает...\"\n");
promptBuilder.append(
"3. ПОСЛЕ графика напиши интерпретацию данных (2-3 предложения), начинающуюся с: \"Из этих показателей следует, что...\"\n\n");
promptBuilder.append("ВАЖНО:\n");
promptBuilder.append("- Начинай сразу с заголовка \"IV. Анализ целевой аудитории\"\n");
promptBuilder.append("- Не добавляй вступления или заключения\n");
promptBuilder.append("- Используй данные из поля audienceSegments\n");
promptBuilder.append("- Для каждого сегмента создай детальный портрет клиента\n\n");
promptBuilder.append("JSON ДАННЫЕ:\n");
promptBuilder.append(jsonString);
String result = openAIAnalyticsService.generateWithInstructionWithModel(
jsonString, promptBuilder.toString(), "ru", textModelName);
if (result == null || result.trim().isEmpty()) {
logger.warn("genSectionAudience: AI returned empty result");
return "IV. Анализ целевой аудитории\n\nНе удалось сгенерировать раздел.";
}
logger.info("genSectionAudience: Section generated successfully. Length: {} chars", result.length());
return result;
} catch (Exception e) {
logger.error("genSectionAudience: Error generating section: {}", e.getMessage(), e);
return "IV. Анализ целевой аудитории\n\nОшибка при генерации раздела: " + e.getMessage();
}
}
/**
* Генерирует раздел V: Анализ конкурентов
*/
private String genSectionCompetitors(Map<String, Object> contextJson) {
try {
String jsonString = objectMapper.writeValueAsString(contextJson);
StringBuilder promptBuilder = new StringBuilder();
promptBuilder.append("Ты — высокооплачиваемый бизнес-консультант и маркетинговый аналитик.\n\n");
promptBuilder.append(
"На основе следующего JSON напиши РАЗДЕЛ V (Анализ конкурентов) маркетингового отчета.\n\n");
promptBuilder.append("ТРЕБОВАНИЯ:\n");
promptBuilder.append("1. Объем: минимум 500-700 слов\n");
promptBuilder.append("2. Стиль: деловой, убедительный для владельца бизнеса\n");
promptBuilder.append("3. Глубина: аналитические инсайты с практическими выводами\n");
promptBuilder.append("4. Данные: используй ТОЛЬКО данные из JSON, не выдумывай цифры\n\n");
promptBuilder.append("СТРУКТУРА РАЗДЕЛА:\n");
promptBuilder.append("V. Анализ конкурентов\n\n");
promptBuilder.append("Детально проанализируй:\n");
promptBuilder.append("- Позиции каждого конкурента на рынке (используй данные из competitors)\n");
promptBuilder.append("- Сильные и слабые стороны конкурентов (из comparisonTable и swotCompetitors)\n");
promptBuilder.append("- Стратегии конкурентов (ценовая политика, каналы продвижения)\n");
promptBuilder.append(
"- Контент-воронки конкурентов: какие типы контента они используют на каждом этапе воронки, какие каналы задействуют, какие месседжи доносят\n");
promptBuilder.append("- Глубокое сравнение нашего бренда с конкурентами (используй comparisonTable)\n");
promptBuilder.append("- Рекомендации по дифференциации и конкурентным преимуществам\n\n");
promptBuilder.append("КРИТИЧНО - ВСТАВКА ГРАФИКА:\n");
promptBuilder.append(
"1. В логичном месте раздела (после анализа конкурентов) вставь плейсхолдер [[CHART_COMPETITORS]] на отдельной строке\n");
promptBuilder.append(
"2. ПЕРЕД графиком напиши вводный абзац (2-3 предложения), начинающийся с: \"Анализ данных на графике ниже показывает...\"\n");
promptBuilder.append(
"3. ПОСЛЕ графика напиши интерпретацию данных (2-3 предложения), начинающуюся с: \"Из этих показателей следует, что...\"\n\n");
promptBuilder.append("ВАЖНО:\n");
promptBuilder.append("- Начинай сразу с заголовка \"V. Анализ конкурентов\"\n");
promptBuilder.append("- Не добавляй вступления или заключения\n");
promptBuilder.append(
"- Используй данные из полей competitors, comparisonTable, swotCompetitors, marketShareChart\n");
promptBuilder.append("- Делай глубокие сравнения нашего бренда с конкурентами\n\n");
promptBuilder.append("JSON ДАННЫЕ:\n");
promptBuilder.append(jsonString);
String result = openAIAnalyticsService.generateWithInstructionWithModel(
jsonString, promptBuilder.toString(), "ru", textModelName);
if (result == null || result.trim().isEmpty()) {
logger.warn("genSectionCompetitors: AI returned empty result");
return "V. Анализ конкурентов\n\nНе удалось сгенерировать раздел.";
}
logger.info("genSectionCompetitors: Section generated successfully. Length: {} chars", result.length());
return result;
} catch (Exception e) {
logger.error("genSectionCompetitors: Error generating section: {}", e.getMessage(), e);
return "V. Анализ конкурентов\n\nОшибка при генерации раздела: " + e.getMessage();
}
}
/**
* Генерирует раздел VI: SWOT-анализ
*/
private String genSectionSWOT(Map<String, Object> contextJson) {
try {
String jsonString = objectMapper.writeValueAsString(contextJson);
StringBuilder promptBuilder = new StringBuilder();
promptBuilder.append("Ты — высокооплачиваемый бизнес-консультант и маркетинговый аналитик.\n\n");
promptBuilder.append("На основе следующего JSON напиши РАЗДЕЛ VI (SWOT-анализ) маркетингового отчета.\n\n");
promptBuilder.append("ТРЕБОВАНИЯ:\n");
promptBuilder.append("1. Объем: минимум 500-700 слов\n");
promptBuilder.append("2. Стиль: деловой, убедительный для владельца бизнеса\n");
promptBuilder.append("3. Глубина: аналитические инсайты с практическими выводами\n");
promptBuilder.append("4. Данные: используй ТОЛЬКО данные из JSON, не выдумывай цифры\n\n");
promptBuilder.append("СТРУКТУРА РАЗДЕЛА:\n");
promptBuilder.append("VI. SWOT-анализ\n\n");
promptBuilder.append("Детально проанализируй:\n");
promptBuilder.append("- Сильные стороны (Strengths) - как их использовать\n");
promptBuilder.append("- Слабые стороны (Weaknesses) - как их минимизировать\n");
promptBuilder.append("- Возможности (Opportunities) - как их реализовать\n");
promptBuilder.append("- Угрозы (Threats) - как им противостоять\n");
promptBuilder.append("- КРИТИЧНО: Проведи перекрестный анализ:\n");
promptBuilder.append(" * Как сильные стороны помогут использовать возможности\n");
promptBuilder.append(" * Как слабые стороны могут помешать противостоять угрозам\n");
promptBuilder.append(" * Стратегические комбинации (SO, ST, WO, WT)\n");
promptBuilder.append("- Практические рекомендации на основе SWOT-матрицы\n\n");
promptBuilder.append("КРИТИЧНО - ВСТАВКА ГРАФИКА:\n");
promptBuilder.append(
"1. В логичном месте раздела (после SWOT-анализа) вставь плейсхолдер [[CHART_SWOT]] на отдельной строке\n");
promptBuilder.append(
"2. ПЕРЕД графиком напиши вводный абзац (2-3 предложения), начинающийся с: \"Анализ данных на графике ниже показывает...\"\n");
promptBuilder.append(
"3. ПОСЛЕ графика напиши интерпретацию данных (2-3 предложения), начинающуюся с: \"Из этих показателей следует, что...\"\n\n");
promptBuilder.append("ВАЖНО:\n");
promptBuilder.append("- Начинай сразу с заголовка \"VI. SWOT-анализ\"\n");
promptBuilder.append("- Не добавляй вступления или заключения\n");
promptBuilder.append("- Используй данные из поля swot\n");
promptBuilder.append("- Обязательно проведи перекрестный анализ пересечений\n\n");
promptBuilder.append("JSON ДАННЫЕ:\n");
promptBuilder.append(jsonString);
String result = openAIAnalyticsService.generateWithInstructionWithModel(
jsonString, promptBuilder.toString(), "ru", textModelName);
if (result == null || result.trim().isEmpty()) {
logger.warn("genSectionSWOT: AI returned empty result");
return "VI. SWOT-анализ\n\nНе удалось сгенерировать раздел.";
}
logger.info("genSectionSWOT: Section generated successfully. Length: {} chars", result.length());
return result;
} catch (Exception e) {
logger.error("genSectionSWOT: Error generating section: {}", e.getMessage(), e);
return "VI. SWOT-анализ\n\nОшибка при генерации раздела: " + e.getMessage();
}
}
/**
* Генерирует раздел VII: Каналы продвижения и их потенциал
*/
private String genSectionChannels(Map<String, Object> contextJson) {
try {
String jsonString = objectMapper.writeValueAsString(contextJson);
StringBuilder promptBuilder = new StringBuilder();
promptBuilder.append("Ты — высокооплачиваемый бизнес-консультант и маркетинговый аналитик.\n\n");
promptBuilder.append(
"На основе следующего JSON напиши РАЗДЕЛ VII (Каналы продвижения и их потенциал) маркетингового отчета.\n\n");
promptBuilder.append("ТРЕБОВАНИЯ:\n");
promptBuilder.append("1. Объем: минимум 500-700 слов\n");
promptBuilder.append("2. Стиль: деловой, убедительный для владельца бизнеса\n");
promptBuilder.append("3. Глубина: аналитические инсайты с практическими выводами\n");
promptBuilder.append("4. Данные: используй ТОЛЬКО данные из JSON, не выдумывай цифры\n\n");
promptBuilder.append("СТРУКТУРА РАЗДЕЛА:\n");
promptBuilder.append("VII. Каналы продвижения и их потенциал\n\n");
promptBuilder.append("Детально проанализируй КАЖДЫЙ канал из channels:\n");
promptBuilder.append("- Потенциал канала для данной ниши (potentialIndex)\n");
promptBuilder.append("- Приоритетность канала (priorityLevel) и обоснование\n");
promptBuilder.append("- Роль канала в общей стратегии (roleInStrategy)\n");
promptBuilder.append("- Обоснование важности канала (justification)\n");
promptBuilder.append("- Рекомендации по использованию каждого канала\n");
promptBuilder.append("- Бюджетные рекомендации и ожидаемая эффективность\n");
promptBuilder.append("- Интеграция каналов в единую маркетинговую стратегию\n\n");
promptBuilder.append("КРИТИЧНО - ВСТАВКА ГРАФИКА:\n");
promptBuilder.append(
"1. В логичном месте раздела (после анализа каналов) вставь плейсхолдер [[CHART_CHANNELS]] на отдельной строке\n");
promptBuilder.append(
"2. ПЕРЕД графиком напиши вводный абзац (2-3 предложения), начинающийся с: \"Анализ данных на графике ниже показывает...\"\n");
promptBuilder.append(
"3. ПОСЛЕ графика напиши интерпретацию данных (2-3 предложения), начинающуюся с: \"Из этих показателей следует, что...\"\n\n");
promptBuilder.append("ВАЖНО:\n");
promptBuilder.append("- Начинай сразу с заголовка \"VII. Каналы продвижения и их потенциал\"\n");
promptBuilder.append("- Не добавляй вступления или заключения\n");
promptBuilder.append("- Используй данные из полей channels, channelsPotential\n");
promptBuilder.append("- Для каждого канала дай конкретные рекомендации\n\n");
promptBuilder.append("JSON ДАННЫЕ:\n");
promptBuilder.append(jsonString);
String result = openAIAnalyticsService.generateWithInstructionWithModel(
jsonString, promptBuilder.toString(), "ru", textModelName);
if (result == null || result.trim().isEmpty()) {
logger.warn("genSectionChannels: AI returned empty result");
return "VII. Каналы продвижения и их потенциал\n\nНе удалось сгенерировать раздел.";
}
logger.info("genSectionChannels: Section generated successfully. Length: {} chars", result.length());
return result;
} catch (Exception e) {
logger.error("genSectionChannels: Error generating section: {}", e.getMessage(), e);
return "VII. Каналы продвижения и их потенциал\n\nОшибка при генерации раздела: " + e.getMessage();
}
}
/**
* Генерирует раздел VIII: Воронка спроса
*/
private String genSectionFunnel(Map<String, Object> contextJson) {
try {
String jsonString = objectMapper.writeValueAsString(contextJson);
StringBuilder promptBuilder = new StringBuilder();
promptBuilder.append("Ты — высокооплачиваемый бизнес-консультант и маркетинговый аналитик.\n\n");
promptBuilder
.append("На основе следующего JSON напиши РАЗДЕЛ VIII (Воронка спроса) маркетингового отчета.\n\n");
promptBuilder.append("ТРЕБОВАНИЯ:\n");
promptBuilder.append("1. Объем: минимум 500-700 слов\n");
promptBuilder.append("2. Стиль: деловой, убедительный для владельца бизнеса\n");
promptBuilder.append("3. Глубина: аналитические инсайты с практическими выводами\n");
promptBuilder.append("4. Данные: используй ТОЛЬКО данные из JSON, не выдумывай цифры\n\n");
promptBuilder.append("СТРУКТУРА РАЗДЕЛА:\n");
promptBuilder.append("VIII. Воронка спроса\n\n");
promptBuilder.append("Детально проанализируй:\n");
promptBuilder.append("- Каждый этап воронки (stages из funnel): название, значение, конверсия\n");
promptBuilder.append("- Где находится \"узкое место\" воронки (самая низкая конверсия)\n");
promptBuilder.append("- Причины низкой конверсии на проблемных этапах\n");
promptBuilder.append("- Конкретные рекомендации по улучшению каждого этапа\n");
promptBuilder.append("- Как оптимизировать узкое место для увеличения общего конверсионного потока\n");
promptBuilder.append("- Ожидаемый эффект от оптимизации (количественные оценки)\n");
promptBuilder.append("- Интеграция воронки с каналами продвижения\n\n");
promptBuilder.append("КРИТИЧНО - ВСТАВКА ГРАФИКА:\n");
promptBuilder.append(
"1. В логичном месте раздела (после описания этапов) вставь плейсхолдер [[CHART_FUNNEL]] на отдельной строке\n");
promptBuilder.append(
"2. ПЕРЕД графиком напиши вводный абзац (2-3 предложения), начинающийся с: \"Анализ данных на графике ниже показывает...\"\n");
promptBuilder.append(
"3. ПОСЛЕ графика напиши интерпретацию данных (2-3 предложения), начинающуюся с: \"Из этих показателей следует, что...\"\n\n");
promptBuilder.append("ВАЖНО:\n");
promptBuilder.append("- Начинай сразу с заголовка \"VIII. Воронка спроса\"\n");
promptBuilder.append("- Не добавляй вступления или заключения\n");
promptBuilder.append("- Используй данные из полей funnel, conversionFunnel\n");
promptBuilder.append("- Обязательно укажи, где \"узкое место\" и как его исправить\n\n");
promptBuilder.append("JSON ДАННЫЕ:\n");
promptBuilder.append(jsonString);
String result = openAIAnalyticsService.generateWithInstructionWithModel(
jsonString, promptBuilder.toString(), "ru", textModelName);
if (result == null || result.trim().isEmpty()) {
logger.warn("genSectionFunnel: AI returned empty result");
return "VIII. Воронка спроса\n\nНе удалось сгенерировать раздел.";
}
logger.info("genSectionFunnel: Section generated successfully. Length: {} chars", result.length());
return result;
} catch (Exception e) {
logger.error("genSectionFunnel: Error generating section: {}", e.getMessage(), e);
return "VIII. Воронка спроса\n\nОшибка при генерации раздела: " + e.getMessage();
}
}
/**
* Генерирует раздел IX: Рекомендации по позиционированию и УТП
*/
private String genSectionPositioning(Map<String, Object> contextJson) {
try {
String jsonString = objectMapper.writeValueAsString(contextJson);
StringBuilder promptBuilder = new StringBuilder();
promptBuilder.append("Ты — высокооплачиваемый бизнес-консультант и маркетинговый аналитик.\n\n");
promptBuilder.append(
"На основе следующего JSON напиши РАЗДЕЛ IX (Рекомендации по позиционированию и УТП) маркетингового отчета.\n\n");
promptBuilder.append("ТРЕБОВАНИЯ:\n");
promptBuilder.append("1. Объем: минимум 500-700 слов\n");
promptBuilder.append("2. Стиль: деловой, убедительный для владельца бизнеса\n");
promptBuilder.append("3. Глубина: аналитические инсайты с практическими выводами\n");
promptBuilder.append("4. Данные: используй ТОЛЬКО данные из JSON, не выдумывай цифры\n\n");
promptBuilder.append("СТРУКТУРА РАЗДЕЛА:\n");
promptBuilder.append("IX. Рекомендации по позиционированию и УТП\n\n");
promptBuilder.append("Детально проанализируй:\n");
promptBuilder.append("- Позиционирование бренда (brandImage, keyMessage, toneOfVoice)\n");
promptBuilder.append("- Уникальное торговое предложение (УТП) - как его сформулировать и донести\n");
promptBuilder.append("- Факторы доверия (trustFactors) и как их использовать\n");
promptBuilder.append("- Как позиционирование дифференцирует от конкурентов\n");
promptBuilder.append("- Рекомендации по коммуникации позиционирования через разные каналы\n");
promptBuilder.append("- Как УТП решает проблемы целевой аудитории\n");
promptBuilder.append("- Практические шаги по внедрению позиционирования\n\n");
promptBuilder.append("ВАЖНО:\n");
promptBuilder.append("- Начинай сразу с заголовка \"IX. Рекомендации по позиционированию и УТП\"\n");
promptBuilder.append("- Не добавляй вступления или заключения\n");
promptBuilder.append("- Используй данные из полей positioning, valueProposition\n");
promptBuilder.append("- Давай конкретные, практические рекомендации\n\n");
promptBuilder.append("JSON ДАННЫЕ:\n");
promptBuilder.append(jsonString);
String result = openAIAnalyticsService.generateWithInstructionWithModel(
jsonString, promptBuilder.toString(), "ru", miniModelName);
if (result == null || result.trim().isEmpty()) {
logger.warn("genSectionPositioning: AI returned empty result");
return "IX. Рекомендации по позиционированию и УТП\n\nНе удалось сгенерировать раздел.";
}
logger.info("genSectionPositioning: Section generated successfully. Length: {} chars", result.length());
return result;
} catch (Exception e) {
logger.error("genSectionPositioning: Error generating section: {}", e.getMessage(), e);
return "IX. Рекомендации по позиционированию и УТП\n\nОшибка при генерации раздела: " + e.getMessage();
}
}
/**
* Генерирует раздел X: Рекомендации по контенту
*/
private String genSectionContent(Map<String, Object> contextJson) {
try {
String jsonString = objectMapper.writeValueAsString(contextJson);
StringBuilder promptBuilder = new StringBuilder();
promptBuilder.append("Ты — высокооплачиваемый бизнес-консультант и маркетинговый аналитик.\n\n");
promptBuilder.append(
"На основе следующего JSON напиши РАЗДЕЛ X (Рекомендации по контенту) маркетингового отчета.\n\n");
promptBuilder.append("ТРЕБОВАНИЯ:\n");
promptBuilder.append("1. Объем: минимум 500-700 слов\n");
promptBuilder.append("2. Стиль: деловой, убедительный для владельца бизнеса\n");
promptBuilder.append("3. Глубина: аналитические инсайты с практическими выводами\n");
promptBuilder.append("4. Данные: используй ТОЛЬКО данные из JSON, не выдумывай цифры\n\n");
promptBuilder.append("СТРУКТУРА РАЗДЕЛА:\n");
promptBuilder.append("X. Рекомендации по контенту\n\n");
promptBuilder.append("Детально проанализируй:\n");
promptBuilder.append("- Типы контента для разных целей (из contentRecommendations)\n");
promptBuilder.append("- Форматы контента для разных каналов продвижения\n");
promptBuilder.append("- Контент для разных этапов воронки (осведомленность, интерес, решение, действие)\n");
promptBuilder.append("- Контент для разных сегментов целевой аудитории\n");
promptBuilder.append("- Рекомендации по календарю контента (частота, темы, сезонность)\n");
promptBuilder.append("- Как контент поддерживает позиционирование и УТП\n");
promptBuilder.append("- Метрики эффективности контента и KPI\n\n");
promptBuilder.append("ВАЖНО:\n");
promptBuilder.append("- Начинай сразу с заголовка \"X. Рекомендации по контенту\"\n");
promptBuilder.append("- Не добавляй вступления или заключения\n");
promptBuilder.append("- Используй данные из поля contentRecommendations\n");
promptBuilder.append("- Давай конкретные, практические рекомендации по типам и форматам контента\n\n");
promptBuilder.append("JSON ДАННЫЕ:\n");
promptBuilder.append(jsonString);
String result = openAIAnalyticsService.generateWithInstructionWithModel(
jsonString, promptBuilder.toString(), "ru", miniModelName);
if (result == null || result.trim().isEmpty()) {
logger.warn("genSectionContent: AI returned empty result");
return "X. Рекомендации по контенту\n\nНе удалось сгенерировать раздел.";
}
logger.info("genSectionContent: Section generated successfully. Length: {} chars", result.length());
return result;
} catch (Exception e) {
logger.error("genSectionContent: Error generating section: {}", e.getMessage(), e);
return "X. Рекомендации по контенту\n\nОшибка при генерации раздела: " + e.getMessage();
}
}
/**
* Генерирует раздел XI: Итоговая стратегия
*/
private String genSectionStrategy(Map<String, Object> contextJson) {
try {
String jsonString = objectMapper.writeValueAsString(contextJson);
StringBuilder promptBuilder = new StringBuilder();
promptBuilder.append("Ты — высокооплачиваемый бизнес-консультант и маркетинговый аналитик.\n\n");
promptBuilder.append(
"На основе следующего JSON напиши РАЗДЕЛ XI (Итоговая стратегия: что делать в первую очередь) маркетингового отчета.\n\n");
promptBuilder.append("ТРЕБОВАНИЯ:\n");
promptBuilder.append("1. Объем: минимум 500-700 слов\n");
promptBuilder.append("2. Стиль: деловой, убедительный для владельца бизнеса\n");
promptBuilder.append("3. Глубина: аналитические инсайты с практическими выводами\n");
promptBuilder.append("4. Данные: используй ТОЛЬКО данные из JSON, не выдумывай цифры\n\n");
promptBuilder.append("СТРУКТУРА РАЗДЕЛА:\n");
promptBuilder.append("XI. Итоговая стратегия: что делать в первую очередь\n\n");
promptBuilder.append("Создай конкретный план действий на 6-12 месяцев:\n");
promptBuilder.append("- Приоритетные задачи (что делать в первую очередь, во вторую, в третью)\n");
promptBuilder.append("- Конкретные шаги с указанием сроков и ответственных\n");
promptBuilder.append("- Интеграция всех элементов: позиционирование, каналы, контент, воронка\n");
promptBuilder.append("- Как использовать сильные стороны и возможности (из SWOT)\n");
promptBuilder.append("- Как минимизировать слабые стороны и угрозы (из SWOT)\n");
promptBuilder.append("- Ожидаемые результаты и метрики успеха\n");
promptBuilder.append("- Бюджетные рекомендации и распределение ресурсов\n");
promptBuilder.append("- Критические точки контроля и корректировки стратегии\n\n");
promptBuilder.append("ВАЖНО:\n");
promptBuilder
.append("- Начинай сразу с заголовка \"XI. Итоговая стратегия: что делать в первую очередь\"\n");
promptBuilder.append("- Не добавляй вступления или заключения\n");
promptBuilder.append(
"- Используй данные из всех предыдущих разделов (swot, channels, funnel, positioning, valueProposition, contentRecommendations)\n");
promptBuilder.append("- Давай конкретный, практический план действий с приоритетами\n");
promptBuilder.append("- Учитывай цель бизнеса на 6-12 месяцев (goal)\n\n");
promptBuilder.append("JSON ДАННЫЕ:\n");
promptBuilder.append(jsonString);
String result = openAIAnalyticsService.generateWithInstructionWithModel(
jsonString, promptBuilder.toString(), "ru", miniModelName);
if (result == null || result.trim().isEmpty()) {
logger.warn("genSectionStrategy: AI returned empty result");
return "XI. Итоговая стратегия: что делать в первую очередь\n\nНе удалось сгенерировать раздел.";
}
logger.info("genSectionStrategy: Section generated successfully. Length: {} chars", result.length());
return result;
} catch (Exception e) {
logger.error("genSectionStrategy: Error generating section: {}", e.getMessage(), e);
return "XI. Итоговая стратегия: что делать в первую очередь\n\nОшибка при генерации раздела: "
+ e.getMessage();
}
}
/**
* Генерирует профессиональный текстовый маркетинговый отчет на основе
* JSON-анализа.