diff --git a/src/main/java/kz/konturai/parser/service/MarketingAnalysisService.java b/src/main/java/kz/konturai/parser/service/MarketingAnalysisService.java index 9e1b201..dfa4cb2 100644 --- a/src/main/java/kz/konturai/parser/service/MarketingAnalysisService.java +++ b/src/main/java/kz/konturai/parser/service/MarketingAnalysisService.java @@ -1410,6 +1410,44 @@ public class MarketingAnalysisService { } } + /** + * Проверяет, является ли ответ от AI валидным (не является отказом или ошибкой) + * + * @param result Ответ от AI + * @return true если ответ валиден, false если это отказ или ошибка + */ + private boolean isValidAiResponse(String result) { + if (result == null || result.trim().isEmpty()) { + return false; + } + + String lowerResult = result.toLowerCase().trim(); + + // Проверяем на типичные ответы отказа от OpenAI + if (lowerResult.contains("i'm sorry") || + lowerResult.contains("i cannot") || + lowerResult.contains("i can't assist") || + lowerResult.contains("i cannot assist") || + lowerResult.contains("i'm unable to") || + lowerResult.contains("i cannot help") || + lowerResult.contains("i can't help") || + lowerResult.startsWith("sorry") || + (lowerResult.contains("cannot") && lowerResult.contains("assist")) || + (lowerResult.contains("can't") && lowerResult.contains("assist"))) { + logger.warn("isValidAiResponse: AI returned refusal message: {}", + result.substring(0, Math.min(100, result.length()))); + return false; + } + + // Проверяем, что ответ содержит хотя бы минимальное содержание + if (result.trim().length() < 50) { + logger.warn("isValidAiResponse: Response too short: {} chars", result.length()); + return false; + } + + return true; + } + /** * Подготавливает контекстный JSON для конкретного раздела отчета. * Извлекает только релевантные данные для экономии токенов. @@ -1576,8 +1614,8 @@ public class MarketingAnalysisService { String result = openAIAnalyticsService.generateWithInstructionWithModel( jsonString, promptBuilder.toString(), "ru", miniModelName); - if (result == null || result.trim().isEmpty()) { - logger.warn("genSectionSummary: AI returned empty result"); + if (!isValidAiResponse(result)) { + logger.warn("genSectionSummary: AI returned invalid or refusal response"); return "I. Краткое резюме\n\nНе удалось сгенерировать раздел."; } @@ -1624,8 +1662,8 @@ public class MarketingAnalysisService { String result = openAIAnalyticsService.generateWithInstructionWithModel( jsonString, promptBuilder.toString(), "ru", miniModelName); - if (result == null || result.trim().isEmpty()) { - logger.warn("genSectionProduct: AI returned empty result"); + if (!isValidAiResponse(result)) { + logger.warn("genSectionProduct: AI returned invalid or refusal response"); return "II. Анализ продукта\n\nНе удалось сгенерировать раздел."; } @@ -1679,8 +1717,8 @@ public class MarketingAnalysisService { String result = openAIAnalyticsService.generateWithInstructionWithModel( jsonString, promptBuilder.toString(), "ru", textModelName); - if (result == null || result.trim().isEmpty()) { - logger.warn("genSectionMarket: AI returned empty result"); + if (!isValidAiResponse(result)) { + logger.warn("genSectionMarket: AI returned invalid or refusal response"); return "III. Анализ рынка и сезонности\n\nНе удалось сгенерировать раздел."; } @@ -1735,8 +1773,8 @@ public class MarketingAnalysisService { String result = openAIAnalyticsService.generateWithInstructionWithModel( jsonString, promptBuilder.toString(), "ru", textModelName); - if (result == null || result.trim().isEmpty()) { - logger.warn("genSectionAudience: AI returned empty result"); + if (!isValidAiResponse(result)) { + logger.warn("genSectionAudience: AI returned invalid or refusal response"); return "IV. Анализ целевой аудитории\n\nНе удалось сгенерировать раздел."; } @@ -1792,8 +1830,8 @@ public class MarketingAnalysisService { String result = openAIAnalyticsService.generateWithInstructionWithModel( jsonString, promptBuilder.toString(), "ru", textModelName); - if (result == null || result.trim().isEmpty()) { - logger.warn("genSectionCompetitors: AI returned empty result"); + if (!isValidAiResponse(result)) { + logger.warn("genSectionCompetitors: AI returned invalid or refusal response"); return "V. Анализ конкурентов\n\nНе удалось сгенерировать раздел."; } @@ -1849,8 +1887,8 @@ public class MarketingAnalysisService { String result = openAIAnalyticsService.generateWithInstructionWithModel( jsonString, promptBuilder.toString(), "ru", textModelName); - if (result == null || result.trim().isEmpty()) { - logger.warn("genSectionSWOT: AI returned empty result"); + if (!isValidAiResponse(result)) { + logger.warn("genSectionSWOT: AI returned invalid or refusal response"); return "VI. SWOT-анализ\n\nНе удалось сгенерировать раздел."; } @@ -1905,8 +1943,8 @@ public class MarketingAnalysisService { String result = openAIAnalyticsService.generateWithInstructionWithModel( jsonString, promptBuilder.toString(), "ru", textModelName); - if (result == null || result.trim().isEmpty()) { - logger.warn("genSectionChannels: AI returned empty result"); + if (!isValidAiResponse(result)) { + logger.warn("genSectionChannels: AI returned invalid or refusal response"); return "VII. Каналы продвижения и их потенциал\n\nНе удалось сгенерировать раздел."; } @@ -1961,8 +1999,8 @@ public class MarketingAnalysisService { String result = openAIAnalyticsService.generateWithInstructionWithModel( jsonString, promptBuilder.toString(), "ru", textModelName); - if (result == null || result.trim().isEmpty()) { - logger.warn("genSectionFunnel: AI returned empty result"); + if (!isValidAiResponse(result)) { + logger.warn("genSectionFunnel: AI returned invalid or refusal response"); return "VIII. Воронка спроса\n\nНе удалось сгенерировать раздел."; } @@ -2010,8 +2048,8 @@ public class MarketingAnalysisService { String result = openAIAnalyticsService.generateWithInstructionWithModel( jsonString, promptBuilder.toString(), "ru", miniModelName); - if (result == null || result.trim().isEmpty()) { - logger.warn("genSectionPositioning: AI returned empty result"); + if (!isValidAiResponse(result)) { + logger.warn("genSectionPositioning: AI returned invalid or refusal response"); return "IX. Рекомендации по позиционированию и УТП\n\nНе удалось сгенерировать раздел."; } @@ -2059,8 +2097,8 @@ public class MarketingAnalysisService { String result = openAIAnalyticsService.generateWithInstructionWithModel( jsonString, promptBuilder.toString(), "ru", miniModelName); - if (result == null || result.trim().isEmpty()) { - logger.warn("genSectionContent: AI returned empty result"); + if (!isValidAiResponse(result)) { + logger.warn("genSectionContent: AI returned invalid or refusal response"); return "X. Рекомендации по контенту\n\nНе удалось сгенерировать раздел."; } @@ -2112,8 +2150,8 @@ public class MarketingAnalysisService { String result = openAIAnalyticsService.generateWithInstructionWithModel( jsonString, promptBuilder.toString(), "ru", miniModelName); - if (result == null || result.trim().isEmpty()) { - logger.warn("genSectionStrategy: AI returned empty result"); + if (!isValidAiResponse(result)) { + logger.warn("genSectionStrategy: AI returned invalid or refusal response"); return "XI. Итоговая стратегия: что делать в первую очередь\n\nНе удалось сгенерировать раздел."; }