.
This commit is contained in:
@@ -27,11 +27,15 @@ import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Semaphore;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
@Service
|
||||
public class MarketingAnalysisService {
|
||||
private final Semaphore openAiSemaphore = new Semaphore(3); // Разрешить только 3 активных запроса к OpenAI на всё
|
||||
// приложение
|
||||
|
||||
private static final String AI_MANDATORY_JSON_USAGE_WARNING = "ВНИМАНИЕ: Если в предоставленном JSON есть данные, ты ОБЯЗАН использовать их и вставить соответствующий тег [[CHART_...]]. "
|
||||
+ "Никогда не пиши, что данных нет, если JSON не пустой.\n\n";
|
||||
private static final String AI_ULTIMATE_JSON_PRESENCE_INSTRUCTION = ""
|
||||
@@ -1556,42 +1560,52 @@ public class MarketingAnalysisService {
|
||||
String fallbackModel,
|
||||
int attempts,
|
||||
String sectionId) {
|
||||
int maxAttempts = Math.max(1, attempts);
|
||||
String last = null;
|
||||
DetailLevel detailLevel = resolveDetailLevelFromContext(contextJson);
|
||||
String systemPrompt = buildSystemPromptForSection(detailLevel, sectionId);
|
||||
Integer maxTokensOverride = detailLevel == DetailLevel.ПОДРОБНО ? REPORT_BASE_MAX_TOKENS * 2 : null;
|
||||
try {
|
||||
|
||||
for (int i = 1; i <= maxAttempts; i++) {
|
||||
String modelToUse = primaryModel;
|
||||
// На последней попытке можно переключиться на запасную модель (если задана)
|
||||
if (i == maxAttempts && fallbackModel != null && !fallbackModel.isBlank()) {
|
||||
modelToUse = fallbackModel;
|
||||
}
|
||||
try {
|
||||
last = openAIAnalyticsService.generateWithInstructionWithModel(
|
||||
jsonContext, prompt, lang, modelToUse, systemPrompt, maxTokensOverride);
|
||||
} catch (Exception e) {
|
||||
logger.warn("generateWithRetry: attempt {} failed with exception: {}", i, e.getMessage());
|
||||
last = null;
|
||||
}
|
||||
openAiSemaphore.acquire();
|
||||
int maxAttempts = Math.max(1, attempts);
|
||||
String last = null;
|
||||
DetailLevel detailLevel = resolveDetailLevelFromContext(contextJson);
|
||||
String systemPrompt = buildSystemPromptForSection(detailLevel, sectionId);
|
||||
Integer maxTokensOverride = detailLevel == DetailLevel.ПОДРОБНО ? REPORT_BASE_MAX_TOKENS * 2 : null;
|
||||
|
||||
if (isValidAiResponse(last)) {
|
||||
return last;
|
||||
}
|
||||
|
||||
// Небольшая пауза между попытками, чтобы сгладить кратковременные сбои
|
||||
if (i < maxAttempts) {
|
||||
for (int i = 1; i <= maxAttempts; i++) {
|
||||
String modelToUse = primaryModel;
|
||||
// На последней попытке можно переключиться на запасную модель (если задана)
|
||||
if (i == maxAttempts && fallbackModel != null && !fallbackModel.isBlank()) {
|
||||
modelToUse = fallbackModel;
|
||||
}
|
||||
try {
|
||||
Thread.sleep(250L);
|
||||
} catch (InterruptedException ie) {
|
||||
Thread.currentThread().interrupt();
|
||||
break;
|
||||
last = openAIAnalyticsService.generateWithInstructionWithModel(
|
||||
jsonContext, prompt, lang, modelToUse, systemPrompt, maxTokensOverride);
|
||||
} catch (Exception e) {
|
||||
logger.warn("generateWithRetry: attempt {} failed with exception: {}", i, e.getMessage());
|
||||
last = null;
|
||||
}
|
||||
|
||||
if (isValidAiResponse(last)) {
|
||||
return last;
|
||||
}
|
||||
|
||||
// Небольшая пауза между попытками, чтобы сгладить кратковременные сбои
|
||||
if (i < maxAttempts) {
|
||||
try {
|
||||
Thread.sleep(250L);
|
||||
} catch (InterruptedException ie) {
|
||||
Thread.currentThread().interrupt();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return last;
|
||||
return last;
|
||||
} catch (Exception e) {
|
||||
logger.error("generateWithRetryForSection: Error generating section: {}", e.getMessage(), e);
|
||||
logger.error("generateWithRetryForSection: Stack trace: ", e);
|
||||
return null;
|
||||
} finally {
|
||||
openAiSemaphore.release();
|
||||
}
|
||||
}
|
||||
|
||||
// Backward-compatible helper (legacy signature). Kept because file historically
|
||||
|
||||
Reference in New Issue
Block a user