@@ -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 style, illustration style, real style中的一种
//如果style不等于painting style, illustration style, real 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. "
: " 图像生成失败,请稍后重试,如问题持续请联系管理员 " ;
}
}
}
}