This commit is contained in:
arys
2026-01-12 11:37:42 +05:00
parent 778f7124a9
commit 6b10806b16
2 changed files with 55 additions and 26 deletions
@@ -289,12 +289,29 @@ public class MarketingStrategyService {
if (optAnalysis.isPresent()) {
MarketingAnalysis analysis = optAnalysis.get();
StringBuilder businessContext = new StringBuilder();
if (analysis.getBusinessNiche() != null) {
businessContext.append("Ниша бизнеса: ").append(analysis.getBusinessNiche()).append(". ");
if (analysis.getProduct() != null && !analysis.getProduct().isEmpty()) {
businessContext.append("Главный объект изображения (продукт): ").append(analysis.getProduct()).append(". ");
}
if (analysis.getProduct() != null) {
businessContext.append("Продукт: ").append(analysis.getProduct()).append(".");
if (analysis.getBusinessNiche() != null && !analysis.getBusinessNiche().isEmpty()) {
businessContext.append("Ниша: ").append(analysis.getBusinessNiche()).append(". ");
}
if (analysis.getTargetAudience() != null) {
Map<String, Object> ta = analysis.getTargetAudience();
if (ta.containsKey("ageRanges") || ta.containsKey("types")) {
businessContext.append("Целевая аудитория (люди на фото): ");
if (ta.containsKey("types")) {
businessContext.append(ta.get("types")).append(" ");
}
if (ta.containsKey("ageRanges")) {
businessContext.append("возраст ").append(ta.get("ageRanges"));
}
businessContext.append(". ");
}
}
return businessContext.toString();
}
} catch (Exception e) {
@@ -504,14 +521,13 @@ public class MarketingStrategyService {
private void generateAndSaveImageForPost(MarketingStrategy.PostCalendarItem item, String businessContext) {
try {
// Create prompt for image generation
String imagePrompt = buildImagePrompt(item, businessContext);
// Generate image
logger.info("Generating image with prompt: {}", imagePrompt);
byte[] imageBytes = imageGenerationService.generateImage(imagePrompt);
if (imageBytes != null && imageBytes.length > 0) {
// Save image to MinIO
String filename = "post_image_" + System.currentTimeMillis() + "_" + item.hashCode() + ".png";
minIOService.uploadFile(filename, imageBytes, MediaType.IMAGE_PNG.toString());
@@ -531,26 +547,36 @@ public class MarketingStrategyService {
private String buildImagePrompt(MarketingStrategy.PostCalendarItem item, String businessContext) {
StringBuilder prompt = new StringBuilder();
prompt.append("Создай привлекательное маркетинговое изображение для поста в социальных сетях. ");
String style = "высококачественная фотография, реалистичное освещение, 8k, высокая детализация";
if (item.getPlatform() != null) {
String platform = item.getPlatform().toLowerCase();
if (platform.contains("linkedin")) {
style += ", корпоративный стиль, профессионально, минимализм, чисто";
} else if (platform.contains("instagram") || platform.contains("tiktok")) {
style += ", лайфстайл, эстетика, яркие цвета, привлекательно, инстаграм-стиль";
} else if (platform.contains("facebook")) {
style += ", уютно, дружелюбно, для сообщества";
}
}
prompt.append("Фотореалистичное изображение. ");
// Добавляем контекст продукта (это самое важное!)
if (businessContext != null && !businessContext.isEmpty()) {
prompt.append(businessContext).append(" ");
}
// 3. Контекст поста
if (item.getTheme() != null && !item.getTheme().isEmpty()) {
prompt.append("Тема поста: ").append(item.getTheme()).append(". ");
prompt.append("Сюжет изображения: ").append(item.getTheme()).append(". ");
}
if (item.getPostText() != null && !item.getPostText().isEmpty()) {
// Use first 100 characters of post text for context
String textPreview = item.getPostText().length() > 100
? item.getPostText().substring(0, 100) + "..."
: item.getPostText();
prompt.append("Текст поста: ").append(textPreview).append(". ");
}
prompt.append("Композиция: продукт или услуга в центре внимания. ");
prompt.append("Если на фото есть люди, они должны взаимодействовать с продуктом естественно. ");
prompt.append("Избегать: абстрактных концепций, людей с планшетами смотрящих в камеру, искусственных поз, текста на изображении, размытия, искажений. ");
prompt.append("Стиль: современный, профессиональный, привлекающий внимание, подходящий для социальных сетей. ");
prompt.append("Изображение должно быть ярким, но не перегруженным, с акцентом на главную идею поста.");
prompt.append("Визуальный стиль: ").append(style).append(".");
return prompt.toString();
}
@@ -87,8 +87,14 @@ public class NanoBananaImageGenerationService implements ImageGenerationService
}
String endpointUrl = String.format(VERTEX_API_TEMPLATE, location, projectId, location, model);
String enrichedPrompt = enrichPromptForGemini(prompt);
Map<String, Object> requestBody = buildImagenRequestBody(enrichedPrompt);
String finalPrompt = prompt;
if (prompt != null && prompt.length() < 50) {
finalPrompt = "High quality, photorealistic image of: " + prompt;
}
Map<String, Object> requestBody = buildImagenRequestBody(finalPrompt);
logger.info("Sending request to Vertex AI. Project: {}, Model: {}", projectId, model);
@@ -150,9 +156,11 @@ public class NanoBananaImageGenerationService implements ImageGenerationService
Map<String, Object> parameters = new HashMap<>();
parameters.put("sampleCount", 1);
parameters.put("aspectRatio", "1:1");
parameters.put("safetyFilterLevel", "block_some");
parameters.put("personGeneration", "allow_adult");
parameters.put("negativePrompt", "nsfw, nudity, sexual content, lgbt symbols, rainbow flags, provocative clothing, violence, gore, blood, deformed, ugly, watermark, text, signature");
parameters.put("negativePrompt", "nsfw, nudity, sexual content, lgbt symbols, rainbow flags, provocative clothing, violence, gore, blood, deformed, ugly, watermark, text, signature, low quality, blurry, distorted, unrealistic");
body.put("parameters", parameters);
return body;
@@ -186,9 +194,4 @@ public class NanoBananaImageGenerationService implements ImageGenerationService
.filter(t -> t instanceof WebClientResponseException &&
((WebClientResponseException) t).getStatusCode().value() == 429);
}
private String enrichPromptForGemini(String original) {
return "Professional, high quality, photorealistic image of: " + original +
". Style: neutral, business-appropriate, culturally respectful.";
}
}