.
This commit is contained in:
@@ -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-анализа.
|
||||
|
||||
Reference in New Issue
Block a user