This commit is contained in:
Leo
2025-11-29 23:39:37 +08:00
parent 7fda3da9ed
commit 570fcb0b93
2 changed files with 342 additions and 43 deletions

View File

@@ -4,6 +4,7 @@ import cn.hutool.core.util.StrUtil;
import cn.van.business.util.ds.DeepSeekClientUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
@@ -27,6 +28,60 @@ public class SocialMediaService {
@Autowired
private MarketingImageService marketingImageService;
@Autowired(required = false)
private StringRedisTemplate redisTemplate;
// Redis Key 前缀
private static final String REDIS_KEY_PREFIX = "social_media:prompt:";
// 默认提示词模板
private static final String DEFAULT_KEYWORDS_PROMPT =
"请从以下商品标题中提取3-5个最核心的关键词这些关键词要能突出商品的核心卖点和特色。\n" +
"要求:\n" +
"1. 每个关键词2-4个字\n" +
"2. 关键词要能吸引小红书/抖音用户\n" +
"3. 用逗号分隔,只返回关键词,不要其他内容\n" +
"商品标题:%s";
private static final String DEFAULT_CONTENT_PROMPT_XHS =
"请为小红书平台生成一篇商品推广文案,要求:\n" +
"1. 风格:真实、种草、有温度\n" +
"2. 开头用emoji或感叹句吸引注意\n" +
"3. 内容:突出商品亮点、使用场景、性价比\n" +
"4. 结尾:引导行动(如:快冲、闭眼入等)\n" +
"5. 长度150-300字\n" +
"6. 适当使用emoji和换行\n" +
"\n商品信息\n" +
"商品名称:%s\n" +
"%s" + // 价格信息
"%s" + // 关键词
"\n请直接生成文案内容不要添加其他说明";
private static final String DEFAULT_CONTENT_PROMPT_DOUYIN =
"请为抖音平台生成一篇商品推广文案,要求:\n" +
"1. 风格:直接、有冲击力、吸引眼球\n" +
"2. 开头:用疑问句或对比句抓住注意力\n" +
"3. 内容:强调价格优势、限时优惠、稀缺性\n" +
"4. 结尾:制造紧迫感,引导立即行动\n" +
"5. 长度100-200字\n" +
"6. 使用短句,节奏感强\n" +
"\n商品信息\n" +
"商品名称:%s\n" +
"%s" + // 价格信息
"%s" + // 关键词
"\n请直接生成文案内容不要添加其他说明";
private static final String DEFAULT_CONTENT_PROMPT_BOTH =
"请生成一篇适合小红书和抖音平台的商品推广文案,要求:\n" +
"1. 风格:真实、有吸引力\n" +
"2. 突出商品亮点和价格优势\n" +
"3. 长度150-250字\n" +
"\n商品信息\n" +
"商品名称:%s\n" +
"%s" + // 价格信息
"%s" + // 关键词
"\n请直接生成文案内容不要添加其他说明";
/**
* 提取商品标题关键词
*
@@ -43,15 +98,9 @@ public class SocialMediaService {
}
try {
String prompt = String.format(
"请从以下商品标题中提取3-5个最核心的关键词这些关键词要能突出商品的核心卖点和特色。\n" +
"要求:\n" +
"1. 每个关键词2-4个字\n" +
"2. 关键词要能吸引小红书/抖音用户\n" +
"3. 用逗号分隔,只返回关键词,不要其他内容\n" +
"商品标题:%s",
productName
);
// 从 Redis 读取提示词模板,如果没有则使用默认模板
String promptTemplate = getPromptTemplate("keywords", DEFAULT_KEYWORDS_PROMPT);
String prompt = String.format(promptTemplate, productName);
String response = deepSeekClientUtil.getDeepSeekResponse(prompt);
@@ -115,45 +164,32 @@ public class SocialMediaService {
}
try {
// 构建提示词
StringBuilder prompt = new StringBuilder();
if ("xhs".equals(style)) {
prompt.append("请为小红书平台生成一篇商品推广文案,要求:\n");
prompt.append("1. 风格:真实、种草、有温度\n");
prompt.append("2. 开头用emoji或感叹句吸引注意\n");
prompt.append("3. 内容:突出商品亮点、使用场景、性价比\n");
prompt.append("4. 结尾:引导行动(如:快冲、闭眼入等)\n");
prompt.append("5. 长度150-300字\n");
prompt.append("6. 适当使用emoji和换行\n");
} else if ("douyin".equals(style)) {
prompt.append("请为抖音平台生成一篇商品推广文案,要求:\n");
prompt.append("1. 风格:直接、有冲击力、吸引眼球\n");
prompt.append("2. 开头:用疑问句或对比句抓住注意力\n");
prompt.append("3. 内容:强调价格优势、限时优惠、稀缺性\n");
prompt.append("4. 结尾:制造紧迫感,引导立即行动\n");
prompt.append("5. 长度100-200字\n");
prompt.append("6. 使用短句,节奏感强\n");
} else {
prompt.append("请生成一篇适合小红书和抖音平台的商品推广文案,要求:\n");
prompt.append("1. 风格:真实、有吸引力\n");
prompt.append("2. 突出商品亮点和价格优势\n");
prompt.append("3. 长度150-250字\n");
}
prompt.append("\n商品信息\n");
prompt.append("商品名称:").append(productName).append("\n");
// 构建价格信息
StringBuilder priceInfo = new StringBuilder();
if (originalPrice != null && originalPrice > 0) {
prompt.append("原价:¥").append(String.format("%.0f", originalPrice)).append("\n");
priceInfo.append("原价:¥").append(String.format("%.0f", originalPrice)).append("\n");
}
if (finalPrice != null && finalPrice > 0) {
prompt.append("到手价:¥").append(String.format("%.0f", finalPrice)).append("\n");
}
if (StrUtil.isNotBlank(keywords)) {
prompt.append("关键词:").append(keywords).append("\n");
priceInfo.append("到手价:¥").append(String.format("%.0f", finalPrice)).append("\n");
}
prompt.append("\n请直接生成文案内容不要添加其他说明");
// 构建关键词信息
String keywordsInfo = "";
if (StrUtil.isNotBlank(keywords)) {
keywordsInfo = "关键词:" + keywords + "\n";
}
// 从 Redis 读取提示词模板,如果没有则使用默认模板
String promptTemplate;
if ("xhs".equals(style)) {
promptTemplate = getPromptTemplate("content:xhs", DEFAULT_CONTENT_PROMPT_XHS);
} else if ("douyin".equals(style)) {
promptTemplate = getPromptTemplate("content:douyin", DEFAULT_CONTENT_PROMPT_DOUYIN);
} else {
promptTemplate = getPromptTemplate("content:both", DEFAULT_CONTENT_PROMPT_BOTH);
}
String prompt = String.format(promptTemplate, productName, priceInfo.toString(), keywordsInfo);
String content = deepSeekClientUtil.getDeepSeekResponse(prompt.toString());
@@ -257,6 +293,35 @@ public class SocialMediaService {
return keywords;
}
/**
* 从 Redis 获取提示词模板,如果没有则返回默认模板
*
* @param templateKey 模板键名keywords, content:xhs, content:douyin, content:both
* @param defaultTemplate 默认模板
* @return 提示词模板
*/
private String getPromptTemplate(String templateKey, String defaultTemplate) {
if (redisTemplate == null) {
log.debug("Redis未配置使用默认模板: {}", templateKey);
return defaultTemplate;
}
try {
String redisKey = REDIS_KEY_PREFIX + templateKey;
String template = redisTemplate.opsForValue().get(redisKey);
if (StrUtil.isNotBlank(template)) {
log.debug("从Redis读取模板: {}", templateKey);
return template;
} else {
log.debug("Redis中未找到模板使用默认模板: {}", templateKey);
return defaultTemplate;
}
} catch (Exception e) {
log.warn("读取Redis模板失败使用默认模板: {}", templateKey, e);
return defaultTemplate;
}
}
/**
* 生成简单文案(降级方案)
*/