修改配置增加模特功能修改

fix:模特有时会没有设置成功性别
豆包qwen模型增加违规提示词提醒
This commit is contained in:
litianxiang
2025-10-13 13:42:38 +08:00
parent 67f0ce7c6c
commit 02f7031a67
5 changed files with 308 additions and 76 deletions

View File

@@ -53,7 +53,7 @@ public class CollectionElement implements Serializable {
private String level2Type; private String level2Type;
/** /**
* 三级类型 目前为线稿标注性别 * 三级类型 目前为线稿和模特标注性别
*/ */
@TableField("level3_type") @TableField("level3_type")
private String level3Type; private String level3Type;

View File

@@ -579,24 +579,28 @@ public class CollectionElementServiceImpl extends ServiceImpl<CollectionElementM
//去掉与性别不符合的线稿元素 - 使用 Iterator 安全移除元素 //去掉与性别不符合的线稿元素 - 使用 Iterator 安全移除元素
Iterator<CollectionSketchDTO> sketchIterator = designDTO.getSketchBoards().iterator(); Iterator<CollectionSketchDTO> sketchIterator = designDTO.getSketchBoards().iterator();
while (sketchIterator.hasNext()) { while (sketchIterator.hasNext()) {
CollectionSketchDTO sketchBoard = sketchIterator.next(); try {
String level2Type = sketchBoard.getLevel2Type(); CollectionSketchDTO sketchBoard = sketchIterator.next();
String level3Type = null; String level2Type = sketchBoard.getLevel2Type();
if ("Collection".equals(sketchBoard.getDesignType())) { String level3Type = null;
level3Type = collectionElementMapper.selectOne(new LambdaQueryWrapper<CollectionElement>().eq(CollectionElement::getId, sketchBoard.getSketchBoardId()).select(CollectionElement::getLevel3Type)).getLevel3Type(); if ("Collection".equals(sketchBoard.getDesignType())) {
} else if ("Library".equals(sketchBoard.getDesignType())){ level3Type = collectionElementMapper.selectOne(new LambdaQueryWrapper<CollectionElement>().eq(CollectionElement::getId, sketchBoard.getSketchBoardId()).select(CollectionElement::getLevel3Type)).getLevel3Type();
level3Type = libraryService.getById(sketchBoard.getSketchBoardId()).getLevel3Type(); } else if ("Library".equals(sketchBoard.getDesignType())){
} else if ("Generate".equals(sketchBoard.getDesignType())){ level3Type = libraryService.getById(sketchBoard.getSketchBoardId()).getLevel3Type();
GenerateDetail generateDetail = generateDetailMapper.selectById(sketchBoard.getSketchBoardId()); } else if ("Generate".equals(sketchBoard.getDesignType())){
assert generateDetail != null; GenerateDetail generateDetail = generateDetailMapper.selectById(sketchBoard.getSketchBoardId());
Generate generate = generateMapper.selectById(generateDetail.getGenerateId()); assert generateDetail != null;
assert generate != null; Generate generate = generateMapper.selectById(generateDetail.getGenerateId());
level3Type = GenerateServiceImpl.extractGender(generate.getGenerateType()); assert generate != null;
} level3Type = GenerateServiceImpl.extractGender(generate.getGenerateType());
//判断性别和当前project性别是否一致不一致则移除 }
assert level3Type != null; //判断性别和当前project性别是否一致不一致则移除
if (!level3Type.equalsIgnoreCase(designDTO.getModelSex())) { assert level3Type != null;
sketchIterator.remove(); if (!level3Type.equalsIgnoreCase(designDTO.getModelSex())) {
sketchIterator.remove();
}
} catch (Exception e) {
continue;
} }
} }

View File

@@ -31,6 +31,7 @@ import com.alibaba.dashscope.utils.JsonUtils;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.serializer.SerializerFeature; import com.alibaba.fastjson.serializer.SerializerFeature;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException; import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
@@ -463,7 +464,7 @@ public class GenerateServiceImpl extends ServiceImpl<GenerateMapper, Generate> i
case "Sketchboard": case "Sketchboard":
// text = "clear lines, simple outlines monochrome white vector image of " + translated + ", no background, sketch flat, front view display, best quality, ultra-high resolution 8k"; // text = "clear lines, simple outlines monochrome white vector image of " + translated + ", no background, sketch flat, front view display, best quality, ultra-high resolution 8k";
text = "a single item of sketch of " + translated + ", 4k, white background"; text = "a single item of sketch of " + translated + ", 4k, white background";
if (Objects.nonNull(generate) && generate.getModelName().equals("high")){ if (Objects.nonNull(generate) && generate.getModelName().equals("high")) {
text = text + ", only technical pattern of a single garment"; text = text + ", only technical pattern of a single garment";
} }
if (!StringUtil.isNullOrEmpty(ageGroup) && ageGroup.equals("Child")) { if (!StringUtil.isNullOrEmpty(ageGroup) && ageGroup.equals("Child")) {
@@ -619,7 +620,7 @@ public class GenerateServiceImpl extends ServiceImpl<GenerateMapper, Generate> i
} }
String modelName = generateDTO.getModelName(); String modelName = generateDTO.getModelName();
if (StringUtil.isNullOrEmpty(modelName)){ if (StringUtil.isNullOrEmpty(modelName)) {
return handleStandardGeneration(generateDTO); return handleStandardGeneration(generateDTO);
} }
@@ -674,12 +675,14 @@ public class GenerateServiceImpl extends ServiceImpl<GenerateMapper, Generate> i
// processCreditDeduction(generateDTO.getUserId(), taskId, CreditsEventsEnum.WX_TEXT2IMG); // processCreditDeduction(generateDTO.getUserId(), taskId, CreditsEventsEnum.WX_TEXT2IMG);
return new PrepareForGenerateVO(Collections.singletonList(taskId), 200); return new PrepareForGenerateVO(Collections.singletonList(taskId), 200);
} }
public String toProductAsyncTask(String imagePath, String useModel, String prompt) { public String toProductAsyncTask(String imagePath, String useModel, String prompt) {
long startTime = System.currentTimeMillis(); long startTime = System.currentTimeMillis();
log.info("开始执行toProductAsyncTask - model: {}, imagePath: {}, prompt: {}", log.info("开始执行toProductAsyncTask - model: {}, imagePath: {}, prompt: {}",
useModel, imagePath, prompt); useModel, imagePath, prompt);
if (StringUtil.isNullOrEmpty(imagePath)||StringUtil.isNullOrEmpty(useModel)||StringUtil.isNullOrEmpty(prompt)){ if (StringUtil.isNullOrEmpty(imagePath) || StringUtil.isNullOrEmpty(useModel) || StringUtil.isNullOrEmpty(prompt)) {
log.error("参数验证失败 - imagePath: {}, useModel: {}, prompt: {}", imagePath, useModel, prompt); log.error("参数验证失败 - imagePath: {}, useModel: {}, prompt: {}", imagePath, useModel, prompt);
throw new BusinessException("Parameter Exception"); throw new BusinessException("Parameter Exception");
} }
@@ -694,10 +697,10 @@ public class GenerateServiceImpl extends ServiceImpl<GenerateMapper, Generate> i
finalImagePath = addWhiteBackground(imagePath); finalImagePath = addWhiteBackground(imagePath);
//去掉"data:image/png;base64," //去掉"data:image/png;base64,"
finalImagePath = finalImagePath.replace("data:image/png;base64,", ""); finalImagePath = finalImagePath.replace("data:image/png;base64,", "");
// 如果白色背景处理失败或不需要直接获取原图的base64编码 // 如果白色背景处理失败或不需要直接获取原图的base64编码
if (StringUtil.isNullOrEmpty(finalImagePath)) { if (StringUtil.isNullOrEmpty(finalImagePath)) {
finalImagePath = minioUtil.getImageAsBase64(imagePath); finalImagePath = minioUtil.getImageAsBase64(imagePath);
} }
} catch (IOException e) { } catch (IOException e) {
log.error("Error getting image as base64 taskId: {} ", taskId, e); log.error("Error getting image as base64 taskId: {} ", taskId, e);
throw new BusinessException("Parameter Exception"); throw new BusinessException("Parameter Exception");
@@ -791,15 +794,15 @@ public class GenerateServiceImpl extends ServiceImpl<GenerateMapper, Generate> i
int maxRetries = 3; int maxRetries = 3;
int retryDelay = 2000; // 2秒 int retryDelay = 2000; // 2秒
boolean success = false; boolean success = false;
for (int attempt = 1; attempt <= maxRetries && !success; attempt++) { for (int attempt = 1; attempt <= maxRetries && !success; attempt++) {
try { try {
log.info("发起HTTP请求 - 尝试次数: {}/{}, URL: {}, taskId: {}", attempt, maxRetries, request.url(), taskId); log.info("发起HTTP请求 - 尝试次数: {}/{}, URL: {}, taskId: {}", attempt, maxRetries, request.url(), taskId);
long requestStartTime = System.currentTimeMillis(); long requestStartTime = System.currentTimeMillis();
try (Response response = client.newCall(request).execute()) { try (Response response = client.newCall(request).execute()) {
long requestEndTime = System.currentTimeMillis(); long requestEndTime = System.currentTimeMillis();
log.info("HTTP请求完成 - 响应状态: {}, 耗时: {}ms, taskId: {}", log.info("HTTP请求完成 - 响应状态: {}, 耗时: {}ms, taskId: {}",
response.code(), (requestEndTime - requestStartTime), taskId); response.code(), (requestEndTime - requestStartTime), taskId);
if (!response.isSuccessful()) { if (!response.isSuccessful()) {
log.warn("Google API响应失败状态码: {} for taskId: {}", response.code(), taskId); log.warn("Google API响应失败状态码: {} for taskId: {}", response.code(), taskId);
@@ -810,7 +813,7 @@ public class GenerateServiceImpl extends ServiceImpl<GenerateMapper, Generate> i
throw new IOException("HTTP error code: " + response.code()); throw new IOException("HTTP error code: " + response.code());
} }
} }
String result = response.body().string(); String result = response.body().string();
// log.info("Google 响应结果:{}", result); // log.info("Google 响应结果:{}", result);
com.alibaba.fastjson.JSONObject jsonResponse = JSON.parseObject(result); com.alibaba.fastjson.JSONObject jsonResponse = JSON.parseObject(result);
@@ -830,7 +833,7 @@ public class GenerateServiceImpl extends ServiceImpl<GenerateMapper, Generate> i
for (int i = 0; i < parts.size(); i++) { for (int i = 0; i < parts.size(); i++) {
com.alibaba.fastjson.JSONObject part = parts.getJSONObject(i); com.alibaba.fastjson.JSONObject part = parts.getJSONObject(i);
if (part.containsKey("inlineData")) { if (part.containsKey("inlineData")) {
com.alibaba.fastjson.JSONObject inlineDataResult= part.getJSONObject("inlineData"); com.alibaba.fastjson.JSONObject inlineDataResult = part.getJSONObject("inlineData");
base64Data = inlineDataResult.getString("data"); base64Data = inlineDataResult.getString("data");
break; break;
} }
@@ -855,11 +858,11 @@ public class GenerateServiceImpl extends ServiceImpl<GenerateMapper, Generate> i
} }
} }
} catch (IOException e) { } catch (IOException e) {
log.warn("网络连接问题 - 异常类型: {}, 尝试: {}/{}, taskId: {}, 错误详情: {}", log.warn("网络连接问题 - 异常类型: {}, 尝试: {}/{}, taskId: {}, 错误详情: {}",
e.getClass().getSimpleName(), attempt, maxRetries, taskId, e.getMessage()); e.getClass().getSimpleName(), attempt, maxRetries, taskId, e.getMessage());
if (attempt < maxRetries) { if (attempt < maxRetries) {
int delayMs = retryDelay * attempt; int delayMs = retryDelay * attempt;
log.info("准备重试 - 延迟: {}ms, 下次尝试: {}/{}, taskId: {}", log.info("准备重试 - 延迟: {}ms, 下次尝试: {}/{}, taskId: {}",
delayMs, (attempt + 1), maxRetries, taskId); delayMs, (attempt + 1), maxRetries, taskId);
try { try {
Thread.sleep(delayMs); // 递增延迟重试 Thread.sleep(delayMs); // 递增延迟重试
@@ -881,15 +884,14 @@ public class GenerateServiceImpl extends ServiceImpl<GenerateMapper, Generate> i
redisUtil.addToString(key, new Gson().toJson(failResultVO), CommonConstant.GENERATE_RESULT_EXPIRE_TIME); redisUtil.addToString(key, new Gson().toJson(failResultVO), CommonConstant.GENERATE_RESULT_EXPIRE_TIME);
} }
}, asyncTaskExecutor); }, asyncTaskExecutor);
long endTime = System.currentTimeMillis(); long endTime = System.currentTimeMillis();
log.info("toProductAsyncTask执行完成 - taskId: {}, 总耗时: {}ms", taskId, (endTime - startTime)); log.info("toProductAsyncTask执行完成 - taskId: {}, 总耗时: {}ms", taskId, (endTime - startTime));
return taskId; return taskId;
} }
public String createGoogleAsyncTask(GenerateThroughImageTextDTO generateDTO, String useModel, String prompt) {
public String createGoogleAsyncTask(GenerateThroughImageTextDTO generateDTO, String useModel, String prompt) {
// 从 resources 加载 JSON 文件 // 从 resources 加载 JSON 文件
String level1Type = generateDTO.getLevel1Type(); String level1Type = generateDTO.getLevel1Type();
String level2Type = generateDTO.getLevel2Type(); String level2Type = generateDTO.getLevel2Type();
@@ -987,6 +989,7 @@ public class GenerateServiceImpl extends ServiceImpl<GenerateMapper, Generate> i
// imagen 模型的参数 // imagen 模型的参数
parametersObj.set("addWatermark", false); parametersObj.set("addWatermark", false);
parametersObj.set("sampleCount", 1); parametersObj.set("sampleCount", 1);
parametersObj.set("aspectRatio", "9:16");
// 构建完整的请求体 // 构建完整的请求体
requestBody.set("instances", Arrays.asList(instanceObj)); requestBody.set("instances", Arrays.asList(instanceObj));
@@ -1009,14 +1012,14 @@ public class GenerateServiceImpl extends ServiceImpl<GenerateMapper, Generate> i
CompletableFuture.runAsync(() -> { CompletableFuture.runAsync(() -> {
long startTime = System.currentTimeMillis(); long startTime = System.currentTimeMillis();
log.info("开始执行 createGoogleAsyncTask 方法taskId: {}, model: {}, prompt: {}", taskId, useModel, prompt); log.info("开始执行 createGoogleAsyncTask 方法taskId: {}, model: {}, prompt: {}", taskId, useModel, prompt);
final int maxRetries = 3; final int maxRetries = 3;
final int retryDelayMs = 2000; final int retryDelayMs = 2000;
for (int attempt = 1; attempt <= maxRetries; attempt++) { for (int attempt = 1; attempt <= maxRetries; attempt++) {
try { try {
log.info("Google API 调用尝试 {}/{} - taskId: {}", attempt, maxRetries, taskId); log.info("Google API 调用尝试 {}/{} - taskId: {}", attempt, maxRetries, taskId);
// 异步获取token // 异步获取token
String tokenValue = null; String tokenValue = null;
try (InputStream inputStream = GenerateServiceImpl.class.getClassLoader() try (InputStream inputStream = GenerateServiceImpl.class.getClassLoader()
@@ -1042,7 +1045,7 @@ public class GenerateServiceImpl extends ServiceImpl<GenerateMapper, Generate> i
.callTimeout(180, TimeUnit.SECONDS) .callTimeout(180, TimeUnit.SECONDS)
.retryOnConnectionFailure(true) .retryOnConnectionFailure(true)
.build(); .build();
Request request = new Request.Builder() Request request = new Request.Builder()
.url(endpoint) .url(endpoint)
.addHeader("Authorization", "Bearer " + tokenValue) .addHeader("Authorization", "Bearer " + tokenValue)
@@ -1055,9 +1058,9 @@ public class GenerateServiceImpl extends ServiceImpl<GenerateMapper, Generate> i
long requestStartTime = System.currentTimeMillis(); long requestStartTime = System.currentTimeMillis();
try (Response response = client.newCall(request).execute()) { try (Response response = client.newCall(request).execute()) {
long requestDuration = System.currentTimeMillis() - requestStartTime; long requestDuration = System.currentTimeMillis() - requestStartTime;
log.info("Google API 请求完成 - taskId: {}, 尝试: {}, URL: {}, 状态码: {}, 耗时: {}ms", log.info("Google API 请求完成 - taskId: {}, 尝试: {}, URL: {}, 状态码: {}, 耗时: {}ms",
taskId, attempt, endpoint, response.code(), requestDuration); taskId, attempt, endpoint, response.code(), requestDuration);
String result = response.body().string(); String result = response.body().string();
// log.info("Google 响应结果:{}", result); // log.info("Google 响应结果:{}", result);
@@ -1098,7 +1101,7 @@ public class GenerateServiceImpl extends ServiceImpl<GenerateMapper, Generate> i
// 生成成功更新Redis状态和URL // 生成成功更新Redis状态和URL
GenerateResultVO successResultVO = new GenerateResultVO(taskId, null, minioPath, "Success"); GenerateResultVO successResultVO = new GenerateResultVO(taskId, null, minioPath, "Success");
redisUtil.addToString(key, new Gson().toJson(successResultVO), CommonConstant.GENERATE_RESULT_EXPIRE_TIME); redisUtil.addToString(key, new Gson().toJson(successResultVO), CommonConstant.GENERATE_RESULT_EXPIRE_TIME);
long totalDuration = System.currentTimeMillis() - startTime; long totalDuration = System.currentTimeMillis() - startTime;
log.info("Google 图片生成成功 - taskId: {}, 总耗时: {}ms", taskId, totalDuration); log.info("Google 图片生成成功 - taskId: {}, 总耗时: {}ms", taskId, totalDuration);
return; // 成功后立即返回 return; // 成功后立即返回
@@ -1112,9 +1115,9 @@ public class GenerateServiceImpl extends ServiceImpl<GenerateMapper, Generate> i
} }
} catch (IOException e) { } catch (IOException e) {
// 只对 IOException 进行重试 // 只对 IOException 进行重试
log.warn("Google API 调用发生 IOException - taskId: {}, 尝试: {}/{}, 异常: {}", log.warn("Google API 调用发生 IOException - taskId: {}, 尝试: {}/{}, 异常: {}",
taskId, attempt, maxRetries, e.getMessage()); taskId, attempt, maxRetries, e.getMessage());
if (attempt < maxRetries) { if (attempt < maxRetries) {
try { try {
long delay = retryDelayMs * attempt; // 递增延迟 long delay = retryDelayMs * attempt; // 递增延迟
@@ -1133,14 +1136,14 @@ public class GenerateServiceImpl extends ServiceImpl<GenerateMapper, Generate> i
} }
} catch (Exception e) { } catch (Exception e) {
// 对于其他异常非IOException记录错误并直接返回不重试 // 对于其他异常非IOException记录错误并直接返回不重试
log.error("Google API 调用发生意外异常 - taskId: {}, 异常类型: {}, 异常信息: {}", log.error("Google API 调用发生意外异常 - taskId: {}, 异常类型: {}, 异常信息: {}",
taskId, e.getClass().getSimpleName(), e.getMessage(), e); taskId, e.getClass().getSimpleName(), e.getMessage(), e);
GenerateResultVO failResultVO = new GenerateResultVO(taskId, null, null, "Fail"); GenerateResultVO failResultVO = new GenerateResultVO(taskId, null, null, "Fail");
redisUtil.addToString(key, new Gson().toJson(failResultVO), CommonConstant.GENERATE_RESULT_EXPIRE_TIME); redisUtil.addToString(key, new Gson().toJson(failResultVO), CommonConstant.GENERATE_RESULT_EXPIRE_TIME);
return; // 非网络异常,直接返回不重试 return; // 非网络异常,直接返回不重试
} }
} }
// 如果所有重试都失败了,记录最终失败日志 // 如果所有重试都失败了,记录最终失败日志
long totalDuration = System.currentTimeMillis() - startTime; long totalDuration = System.currentTimeMillis() - startTime;
log.error("Google API 调用最终失败,所有重试都已用尽 - taskId: {}, 总耗时: {}ms", taskId, totalDuration); log.error("Google API 调用最终失败,所有重试都已用尽 - taskId: {}, 总耗时: {}ms", taskId, totalDuration);
@@ -1154,15 +1157,14 @@ public class GenerateServiceImpl extends ServiceImpl<GenerateMapper, Generate> i
taskId, taskId,
level1Type, level1Type,
level2Type, level2Type,
prompt, generateDTO.getText(),
"text(" + gender + ")", "text(" + gender + ")",
useModel, // 记录使用的具体模型名称 useModel, // 记录使用的具体模型名称
new Date() new Date()
); );
save(generate); save(generate);
return taskId; return taskId;
} }
@@ -1256,7 +1258,7 @@ public class GenerateServiceImpl extends ServiceImpl<GenerateMapper, Generate> i
&& StringUtil.isNullOrEmpty(generateDTO.getLevel2Type())) { && StringUtil.isNullOrEmpty(generateDTO.getLevel2Type())) {
throw new BusinessException("level2Type.cannot.be.empty"); throw new BusinessException("level2Type.cannot.be.empty");
} }
if (generateDTO.getLevel1Type().equals(PRINT_BOARD.getRealName())&&generateDTO.getLevel2Type().equals(CreditsEventsEnum.PATTERN.getName())) { if (generateDTO.getLevel1Type().equals(PRINT_BOARD.getRealName()) && generateDTO.getLevel2Type().equals(CreditsEventsEnum.PATTERN.getName())) {
int firstCommaIndex = generateDTO.getText().indexOf(","); int firstCommaIndex = generateDTO.getText().indexOf(",");
String style = generateDTO.getText().substring(0, firstCommaIndex).trim(); String style = generateDTO.getText().substring(0, firstCommaIndex).trim();
//如果style不等于painting styleillustration stylereal style中的一种 //如果style不等于painting styleillustration stylereal style中的一种
@@ -1335,16 +1337,37 @@ public class GenerateServiceImpl extends ServiceImpl<GenerateMapper, Generate> i
try { try {
result = imageSynthesis.asyncCall(param); result = imageSynthesis.asyncCall(param);
} catch (Exception e) { } catch (Exception e) {
String exceptionMessage = e.getMessage();
if (exceptionMessage != null && exceptionMessage.contains("\"message\"")) {
try {
// 解析JSON格式的异常信息
JSONObject jsonObj = JSONUtil.parseObj(exceptionMessage);
exceptionMessage = jsonObj.getStr("message");
if ("Input data may contain inappropriate content.".equals(exceptionMessage)){
LambdaQueryWrapper<Account> select = new LambdaQueryWrapper<Account>().eq(Account::getId, userId).select(Account::getLanguage);
Account account = accountService.getOne(select);
if ("CHINESE_SIMPLIFIED".equals(account.getLanguage())){
exceptionMessage = "输入数据可能包含不当内容。";
}
}
throw new RuntimeException(exceptionMessage);
} catch (Exception parseException) {
// 如果解析失败,返回原始消息
throw new RuntimeException(exceptionMessage);
}
}
throw new RuntimeException(e.getMessage()); throw new RuntimeException(e.getMessage());
} }
String taskId = result.getOutput().getTaskId(); String taskId = result.getOutput().getTaskId();
log.info("qwen text2image 请求生成:{}, taskId{}", JsonUtils.toJson(result), taskId); log.info("qwen text2image 请求生成:{}, taskId{}", JsonUtils.toJson(result), taskId);
Generate generate = new Generate(userId, taskId, level1Type, level2Type, prompt, "text(" + gender + ")", "qwen-image", new Date()); Generate generate = new Generate(userId, taskId, level1Type, level2Type, generateDTO.getText(), "text(" + gender + ")", "qwen-image", new Date());
save(generate); save(generate);
return taskId; return taskId;
} }
public String createDouBaoAsyncTask(GenerateThroughImageTextDTO generateDTO, String useModel, String prompt) { public String createDouBaoAsyncTask(GenerateThroughImageTextDTO generateDTO, String useModel, String prompt) {
// 从DTO中获取基础参数 // 从DTO中获取基础参数
String level1Type = generateDTO.getLevel1Type(); String level1Type = generateDTO.getLevel1Type();
@@ -1393,6 +1416,19 @@ public class GenerateServiceImpl extends ServiceImpl<GenerateMapper, Generate> i
requestBuilder.image(finalImagePath1); requestBuilder.image(finalImagePath1);
} }
// 保存生成记录到数据库
Generate generate = new Generate(
userId,
taskId,
level1Type,
level2Type,
generateDTO.getText(),
"text(" + gender + ")",
useModel, // 记录使用的具体模型名称
new Date()
);
save(generate);
GenerateImagesRequest generateRequest = requestBuilder.build(); GenerateImagesRequest generateRequest = requestBuilder.build();
ImagesResponse imagesResponse = service.generateImages(generateRequest); ImagesResponse imagesResponse = service.generateImages(generateRequest);
@@ -1404,27 +1440,88 @@ public class GenerateServiceImpl extends ServiceImpl<GenerateMapper, Generate> i
GenerateResultVO successResultVO = new GenerateResultVO(taskId, null, imageUrl, "Success"); GenerateResultVO successResultVO = new GenerateResultVO(taskId, null, imageUrl, "Success");
redisUtil.addToString(key, new Gson().toJson(successResultVO), CommonConstant.GENERATE_RESULT_EXPIRE_TIME); redisUtil.addToString(key, new Gson().toJson(successResultVO), CommonConstant.GENERATE_RESULT_EXPIRE_TIME);
// 保存生成记录到数据库
Generate generate = new Generate(
userId,
taskId,
level1Type,
level2Type,
prompt,
"text(" + gender + ")",
useModel, // 记录使用的具体模型名称
new Date()
);
save(generate);
// TODO: 处理积分扣除逻辑 // TODO: 处理积分扣除逻辑
} catch (Exception e) { } catch (Exception e) {
log.error("Doubao image generation failed for taskId: {}", taskId, e); log.error("Doubao image generation failed for taskId: {}", taskId, e);
// 生成失败更新Redis状态 LambdaQueryWrapper<Account> select = new LambdaQueryWrapper<Account>().eq(Account::getId, userId).select(Account::getLanguage);
GenerateResultVO failResultVO = new GenerateResultVO(taskId, null, null, "Fail"); Account account = accountService.getOne(select);
// 根据用户语言设置默认错误信息
String errorMessage = "图像生成失败,请稍后重试"; // 默认中文
String userLanguage = "CHINESE_SIMPLIFIED"; // 默认语言
if (account != null && account.getLanguage() != null) {
userLanguage = account.getLanguage();
if (account.getLanguage().equals("ENGLISH")) {
errorMessage = "Image generation failed, please try again later";
} else if (account.getLanguage().equals("CHINESE_SIMPLIFIED")) {
errorMessage = "图像生成失败,请稍后重试";
}
}
String errorCode = null;
// 检查是否为ArkHttpException提取code和detailMessage
try {
// 通过反射获取code字段
java.lang.reflect.Field codeField = e.getClass().getDeclaredField("code");
codeField.setAccessible(true);
Object codeValue = codeField.get(e);
if (codeValue != null) {
errorCode = codeValue.toString();
}
// 通过反射获取detailMessage字段
e.printStackTrace();
String detailMessageValue = e.getMessage();
if (detailMessageValue != null) {
String detailMessage = detailMessageValue.toString();
// 根据错误码返回相应的用户友好错误信息
errorMessage = getDoubaoErrorMessage(errorCode, detailMessage, userLanguage);
}
} catch (Exception reflectionException) {
reflectionException.printStackTrace();
log.warn("Failed to extract error details from ArkHttpException: {}", reflectionException.getMessage());
// 如果反射失败,尝试从异常消息中提取信息
String exceptionMessage = e.getMessage();
if (exceptionMessage != null) {
boolean isEnglish = "ENGLISH".equals(userLanguage);
if (exceptionMessage.contains("OutputImageSensitiveContentDetected")) {
errorMessage = isEnglish ? "Generated image may contain sensitive content, please try with different input" : "生成的图像可能包含敏感信息,请更换输入内容后重试";
} else if (exceptionMessage.contains("InputTextSensitiveContentDetected")) {
errorMessage = isEnglish ? "Input text may contain sensitive content, please try again" : "输入文本可能包含敏感信息,请更换后重试";
} else if (exceptionMessage.contains("InputImageSensitiveContentDetected")) {
errorMessage = isEnglish ? "Input image may contain sensitive content, please try again" : "输入图像可能包含敏感信息,请更换后重试";
} else if (exceptionMessage.contains("SensitiveContentDetected")) {
errorMessage = isEnglish ? "Input content may contain sensitive information, please try again" : "输入内容可能包含敏感信息,请更换后重试";
} else if (exceptionMessage.contains("MissingParameter")) {
errorMessage = isEnglish ? "Request parameters are incomplete, please check input" : "请求参数不完整,请检查输入内容";
} else if (exceptionMessage.contains("InvalidParameter")) {
errorMessage = isEnglish ? "Request parameters are invalid, please check input format" : "请求参数无效,请检查输入格式";
} else if (exceptionMessage.contains("InvalidImageURL")) {
errorMessage = isEnglish ? "Image format is incorrect or data is corrupted, please re-upload" : "图片格式不正确或数据损坏,请重新上传";
} else if (exceptionMessage.contains("OutofContextError")) {
errorMessage = isEnglish ? "Input content is too long, please shorten text or image size" : "输入内容过长,请缩短文本或图片尺寸";
} else if (exceptionMessage.contains("AuthenticationError")) {
errorMessage = isEnglish ? "Service authentication failed, please contact administrator" : "服务认证失败,请联系管理员";
} else if (exceptionMessage.contains("TooManyRequests") || exceptionMessage.contains("429")) {
errorMessage = isEnglish ? "Too many requests, please try again later" : "请求过于频繁,请稍后重试";
} else if (exceptionMessage.contains("InternalServerError") || exceptionMessage.contains("500")) {
errorMessage = isEnglish ? "Image generation service is temporarily unavailable, please try again later" : "图像生成服务暂时不可用,请稍后重试";
}
}
}
// 更新Redis状态为失败
GenerateResultVO failResultVO = new GenerateResultVO(taskId, null, errorMessage, "Fail");
redisUtil.addToString(key, new Gson().toJson(failResultVO), CommonConstant.GENERATE_RESULT_EXPIRE_TIME); redisUtil.addToString(key, new Gson().toJson(failResultVO), CommonConstant.GENERATE_RESULT_EXPIRE_TIME);
// 记录详细错误信息用于调试
log.error("Doubao API error - taskId: {}, errorCode: {}, errorMessage: {}",
taskId, errorCode, errorMessage);
} }
}); });
@@ -3238,6 +3335,12 @@ public class GenerateServiceImpl extends ServiceImpl<GenerateMapper, Generate> i
} else { } else {
throw new BusinessException("Unknown generate task"); throw new BusinessException("Unknown generate task");
} }
} else if ("Fail".equals(cachedResult.getStatus())) {
// 获取失败原因
String errorMessage = cachedResult.getUrl();
if (errorMessage != null) {
throw new BusinessException(errorMessage, ResultEnum.PROMPT.getCode());
}
} }
// 4. 其他状态(如 Unknown返回默认失败 // 4. 其他状态(如 Unknown返回默认失败
@@ -3764,16 +3867,16 @@ public class GenerateServiceImpl extends ServiceImpl<GenerateMapper, Generate> i
/** /**
* 接入flux模型用于imageToSketch(sketch extract) || relighting || to product image * 接入flux模型用于imageToSketch(sketch extract) || relighting || to product image
* *
* @param func 功能枚举名指定使用flux模型的具体功能类型 * @param func 功能枚举名指定使用flux模型的具体功能类型
* @param prompt 用户输入的提示词,如果为空则使用默认提示词 * @param prompt 用户输入的提示词,如果为空则使用默认提示词
* @param imagePath 图片minio路径作为输入图像的base64编码源 * @param imagePath 图片minio路径作为输入图像的base64编码源
* @param childStyle 是否为儿童风格,影响提示词的构建 * @param childStyle 是否为儿童风格,影响提示词的构建
* @return 返回taskId用于异步获取结果 * @return 返回taskId用于异步获取结果
*/ */
public String flux(CreditsEventsEnum func, String prompt, String imagePath, boolean childStyle) { public String flux(CreditsEventsEnum func, String prompt, String imagePath, boolean childStyle) {
// Flux API的请求地址 // Flux API的请求地址
String fluxRequestUrl = "https://api.bfl.ai/v1/flux-kontext-pro"; String fluxRequestUrl = "https://api.bfl.ai/v1/flux-kontext-pro";
// 如果用户没有提供提示词,根据功能类型设置默认提示词 // 如果用户没有提供提示词,根据功能类型设置默认提示词
if (StringUtil.isNullOrEmpty(prompt)) { if (StringUtil.isNullOrEmpty(prompt)) {
switch (func) { switch (func) {
@@ -3807,7 +3910,7 @@ public class GenerateServiceImpl extends ServiceImpl<GenerateMapper, Generate> i
break; break;
} }
} }
// 构建Flux API请求体 // 构建Flux API请求体
JSONObject requestBody = new JSONObject(); JSONObject requestBody = new JSONObject();
@@ -3829,7 +3932,7 @@ public class GenerateServiceImpl extends ServiceImpl<GenerateMapper, Generate> i
log.info("flux 请求入参:{}", requestBody); log.info("flux 请求入参:{}", requestBody);
// 提示词不能为空的校验 // 提示词不能为空的校验
if (prompt.isEmpty()) throw new BusinessException("test"); if (prompt.isEmpty()) throw new BusinessException("test");
// 如果提供了输入图片路径需要将图片转换为base64格式 // 如果提供了输入图片路径需要将图片转换为base64格式
if (!StringUtil.isNullOrEmpty(imagePath)) { if (!StringUtil.isNullOrEmpty(imagePath)) {
try { try {
@@ -3854,7 +3957,7 @@ public class GenerateServiceImpl extends ServiceImpl<GenerateMapper, Generate> i
String resp = sendRequestUtil.sendFluxPost(fluxRequestUrl, requestBody.toString()); String resp = sendRequestUtil.sendFluxPost(fluxRequestUrl, requestBody.toString());
JSONObject respObj = JSONUtil.parseObj(resp); JSONObject respObj = JSONUtil.parseObj(resp);
log.info("flux 发起生成请求返回结果: {}", respObj); log.info("flux 发起生成请求返回结果: {}", respObj);
// 从响应中提取任务ID // 从响应中提取任务ID
String taskId = respObj.getStr("id"); String taskId = respObj.getStr("id");
if (StringUtil.isNullOrEmpty(taskId)) { if (StringUtil.isNullOrEmpty(taskId)) {
@@ -3869,7 +3972,7 @@ public class GenerateServiceImpl extends ServiceImpl<GenerateMapper, Generate> i
String key = RedisUtil.FLUX_POLLING_URL + taskId; String key = RedisUtil.FLUX_POLLING_URL + taskId;
// 将轮询URL存储到Redis中设置过期时间 // 将轮询URL存储到Redis中设置过期时间
redisUtil.addToString(key, pollingUrl, CommonConstant.GENERATE_RESULT_EXPIRE_TIME); redisUtil.addToString(key, pollingUrl, CommonConstant.GENERATE_RESULT_EXPIRE_TIME);
// 添加到api_generate表中以便之后对结果查询做补偿机制 // 添加到api_generate表中以便之后对结果查询做补偿机制
apiGenerateService.addAPIGenerateRecordAsync(UserContext.getUserHolder().getId(), taskId, func.getName(), "flux", "Pending"); apiGenerateService.addAPIGenerateRecordAsync(UserContext.getUserHolder().getId(), taskId, func.getName(), "flux", "Pending");
@@ -4019,4 +4122,123 @@ public class GenerateServiceImpl extends ServiceImpl<GenerateMapper, Generate> i
return null; return null;
} }
} }
/**
* 根据豆包错误码和详细信息返回用户友好的错误信息
*
* @param errorCode 错误码
* @param detailMessage 详细错误信息
* @return 用户友好的错误信息
*/
private String getDoubaoErrorMessage(String errorCode, String detailMessage, String userLanguage) {
boolean isEnglish = "ENGLISH".equals(userLanguage);
if (errorCode == null) {
return isEnglish ? "Image generation failed, please try again later" : "图像生成失败,请稍后重试";
}
switch (errorCode) {
// === 用户输入问题(用户可以自行解决) ===
// 敏感内容检测 - 用户需要修改提示词
case "SensitiveContentDetected":
case "SensitiveContentDetected.SevereViolation":
case "SensitiveContentDetected.Violence":
case "InputTextSensitiveContentDetected":
return isEnglish ? "Your prompt contains sensitive content. Please modify your description and try again."
: "您的提示词包含敏感内容,请修改描述后重试";
case "InputImageSensitiveContentDetected":
return isEnglish ? "Your uploaded image contains sensitive content. Please use a different image and try again."
: "您上传的图片包含敏感内容,请更换图片后重试";
case "InputVideoSensitiveContentDetected":
return isEnglish ? "Your uploaded video contains sensitive content. Please use a different video and try again."
: "您上传的视频包含敏感内容,请更换视频后重试";
case "OutputTextSensitiveContentDetected":
case "OutputImageSensitiveContentDetected":
case "OutputVideoSensitiveContentDetected":
return isEnglish ? "The generated content may contain sensitive information. Please modify your prompt and try again."
: "生成的内容可能包含敏感信息,请修改提示词后重试";
// 图片格式问题 - 用户需要检查图片
case "InvalidImageURL.EmptyURL":
return isEnglish ? "No image was uploaded. Please upload an image and try again."
: "未上传图片,请上传图片后重试";
case "InvalidImageURL.InvalidFormat":
return isEnglish ? "The image format is not supported or the image is corrupted. Please upload a valid image (JPG, PNG, etc.) and try again."
: "图片格式不支持或图片已损坏请上传有效的图片格式JPG、PNG等后重试";
// 内容长度问题 - 用户需要缩短内容
case "OutofContextError":
return isEnglish ? "Your prompt and image content is too long. Please shorten your description or use a smaller image and try again."
: "您的提示词和图片内容过长,请缩短描述或使用更小的图片后重试";
// 请求频率问题 - 用户需要等待
case "TooManyRequests":
return isEnglish ? "You are sending requests too frequently. Please wait a moment and try again."
: "您的请求过于频繁,请稍等片刻后重试";
// === 系统问题(需要联系管理员) ===
// 参数格式错误 - 系统问题
case "MissingParameter":
case "InvalidParameter":
case "Duplicate.Tags.Key":
case "InvalidArgumentError":
case "InvalidArgumentError.UnknownRole":
case "InvalidArgumentError.InvalidImageDetail":
case "InvalidArgumentError.InvalidPixelLimit":
return isEnglish ? "System error: Invalid request parameters. Please contact the administrator."
: "系统错误:请求参数格式有误,请联系管理员";
// 认证问题 - 系统问题
case "AuthenticationError":
return isEnglish ? "System error: Authentication failed. Please contact the administrator."
: "系统错误:身份验证失败,请联系管理员";
// 服务配置问题 - 系统问题
case "InvalidEndpoint.ClosedEndpoint":
case "OperationDenied.InvalidState":
case "OperationDenied.ConflictedValidationSet":
case "NotFound.Model":
case "NotFound.Endpoint":
case "NotFound.Context":
case "InvalidOperation.Conflict":
case "ModelNotOpen":
return isEnglish ? "System error: Service configuration issue. Please contact the administrator."
: "系统错误:服务配置问题,请联系管理员";
// 配额/费用问题 - 系统问题
case "QuotaExceeded.DailyQuota":
case "QuotaExceeded.MonthlyQuota":
case "QuotaExceeded.TotalQuota":
case "QuotaExceeded.RPM":
case "QuotaExceeded.TPM":
case "QuotaExceeded.RPD":
case "QuotaExceeded.TPD":
return isEnglish ? "System error: Service quota exceeded. Please contact the administrator."
: "系统错误:服务配额已用完,请联系管理员";
// 服务器错误 - 系统问题
case "InternalError":
case "ServiceUnavailable":
return isEnglish ? "System error: Service is temporarily unavailable. Please contact the administrator or try again later."
: "系统错误:服务暂时不可用,请联系管理员或稍后重试";
default:
// 根据详细信息判断是用户问题还是系统问题
if (detailMessage != null) {
if (detailMessage.contains("sensitive") || detailMessage.contains("敏感")) {
return isEnglish ? "Your content contains sensitive information. Please modify and try again."
: "您的内容包含敏感信息,请修改后重试";
} else if (detailMessage.contains("quota") || detailMessage.contains("配额") ||
detailMessage.contains("parameter") || detailMessage.contains("参数") ||
detailMessage.contains("auth") || detailMessage.contains("认证")) {
return isEnglish ? "System error occurred. Please contact the administrator."
: "系统错误,请联系管理员";
}
}
return isEnglish ? "Image generation failed. Please try again later or contact the administrator if the problem persists."
: "图像生成失败,请稍后重试,如问题持续请联系管理员";
}
}
} }

View File

@@ -604,6 +604,8 @@ public class LLMServiceImpl implements LLMService {
collectionElement.setAccountId(userHolder.getId()); collectionElement.setAccountId(userHolder.getId());
collectionElement.setProjectId(project.getId()); collectionElement.setProjectId(project.getId());
collectionElement.setLevel1Type(CollectionLevel1TypeEnum.MODEL.getRealName()); collectionElement.setLevel1Type(CollectionLevel1TypeEnum.MODEL.getRealName());
collectionElement.setLevel3Type(workspaceService.getProjectSexById(project.getId()));
// collectionElement.setLevel2Type(board.getLevel2Type()); // collectionElement.setLevel2Type(board.getLevel2Type());
collectionElement.setName(sysFile.getName()); collectionElement.setName(sysFile.getName());
collectionElement.setUrl(sysFile.getUrl()); collectionElement.setUrl(sysFile.getUrl());

View File

@@ -728,7 +728,10 @@ public class WorkspaceServiceImpl extends ServiceImpl<WorkspaceMapper, Workspace
if (!workspaceNew.getSex().equals(workspace.getSex())) { if (!workspaceNew.getSex().equals(workspace.getSex())) {
// deleteSketchByProjectId(projectId); // deleteSketchByProjectId(projectId);
SysFile sysFile = sysFileService.getOneBySex(projectDTO.getStyleId(), projectDTO.getWorkspace().getSex(), projectDTO.getWorkspace().getAgeGroup()); SysFile sysFile = sysFileService.getOneBySex(projectDTO.getStyleId(), projectDTO.getWorkspace().getSex(), projectDTO.getWorkspace().getAgeGroup());
if (!checkIfModelExistsInProject(sysFile.getMd5(), projectId)) { LambdaQueryWrapper<CollectionElement> queryWrapper = new LambdaQueryWrapper<CollectionElement>().eq(CollectionElement::getProjectId, projectId)
.eq(CollectionElement::getLevel1Type, CollectionLevel1TypeEnum.MODEL.getRealName())
.eq(CollectionElement::getLevel3Type, workspaceNew.getSex());
if (collectionElementMapper.selectCount(queryWrapper) == 0){
CollectionElement collectionElement = new CollectionElement(); CollectionElement collectionElement = new CollectionElement();
collectionElement.setAccountId(userInfo.getId()); collectionElement.setAccountId(userInfo.getId());
collectionElement.setProjectId(projectId); collectionElement.setProjectId(projectId);
@@ -812,6 +815,7 @@ public class WorkspaceServiceImpl extends ServiceImpl<WorkspaceMapper, Workspace
collectionElement.setAccountId(userInfo.getId()); collectionElement.setAccountId(userInfo.getId());
collectionElement.setProjectId(project.getId()); collectionElement.setProjectId(project.getId());
collectionElement.setLevel1Type(CollectionLevel1TypeEnum.MODEL.getRealName()); collectionElement.setLevel1Type(CollectionLevel1TypeEnum.MODEL.getRealName());
collectionElement.setLevel3Type(projectDTO.getWorkspace().getSex());
collectionElement.setName(sysFile.getName()); collectionElement.setName(sysFile.getName());
collectionElement.setUrl(sysFile.getUrl()); collectionElement.setUrl(sysFile.getUrl());
collectionElement.setMd5(sysFile.getMd5()); collectionElement.setMd5(sysFile.getMd5());