|
|
@@ -17,6 +17,7 @@ import com.cyksj.common.util.Jsons;
|
|
|
import com.cyksj.common.util.QueryWrapperUtils;
|
|
|
import com.cyksj.common.util.StringUtil;
|
|
|
import com.yhlxj.dao.mapper.GroupsRelationMapper;
|
|
|
+import com.yhlxj.dao.mapper.midjourney.MidjourneyApiChannelMapper;
|
|
|
import com.yhlxj.dao.mapper.midjourney.MidjourneyUserConversationMapper;
|
|
|
import com.yhlxj.dao.mapper.midjourney.MidjourneyUserMapper;
|
|
|
import com.yhlxj.dao.model.dto.BlendDimensions;
|
|
|
@@ -79,6 +80,11 @@ public class MidjourneyServiceImpl implements MidjourneyService {
|
|
|
|
|
|
private static final List<String> status = List.of("MODAL","CANCEL","FAILURE");
|
|
|
|
|
|
+ /**
|
|
|
+ * 需要切换账号或服务商进行重试的操作
|
|
|
+ */
|
|
|
+ private static final List<String> RETRY_ACTION = List.of("imagine","blend","describe","shorten");
|
|
|
+
|
|
|
private static final String PROMPT = "--v 6 ";
|
|
|
private static final String SETTINGS = "{\"version\":\"--v 6\",\"remix\":false,\"raw\":false,\"variation\":\"HIGH\",\"mode\":\"relax\",\"stylize\":\"MED\"}";
|
|
|
|
|
|
@@ -99,6 +105,8 @@ public class MidjourneyServiceImpl implements MidjourneyService {
|
|
|
|
|
|
private final GroupsRelationMapper groupsRelationMapper;
|
|
|
|
|
|
+ private final MidjourneyApiChannelMapper midjourneyApiChannelMapper;
|
|
|
+
|
|
|
@Override
|
|
|
public MidjourneyUser getUser(String userToken) {
|
|
|
MidjourneyUser midjourneyUser = midjourneyUserMapper.selectOne(Wrappers.lambdaQuery(MidjourneyUser.class)
|
|
|
@@ -139,17 +147,17 @@ public class MidjourneyServiceImpl implements MidjourneyService {
|
|
|
if (CollectionUtil.isNotEmpty(base64Array)) {
|
|
|
imagineParam.put("base64Array", base64Array);
|
|
|
}
|
|
|
- SubmitResult result = submit(user,mode,"imagine", null,imagineParam);
|
|
|
+ SubmitResult result = submit(user,mode,"imagine", null,imagineParam, null);
|
|
|
if (mode == 2) {
|
|
|
redisService.hincr(RedisService.key.MIDJOURNEY_ACCOUNT.getName(), result.getInstanceId().toString(), 1.0);
|
|
|
}
|
|
|
- saveConversation(user.getId(), mode,result,"IMAGINE", StringUtils.EMPTY, botType);
|
|
|
+ saveConversation(user.getId(), mode,result,"IMAGINE", StringUtils.EMPTY, botType,result.getApiChannelId());
|
|
|
Map<String, Object> properties = result.getProperties();
|
|
|
properties.put("finalPrompt",prompt);
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
- public MidjourneyUserConversation saveConversation(Long userId,Integer mode,SubmitResult result, String action,String prompt, String botType) throws Exception {
|
|
|
+ public MidjourneyUserConversation saveConversation(Long userId,Integer mode,SubmitResult result, String action,String prompt, String botType, Long apiChannelId) throws Exception {
|
|
|
Long taskId = Long.parseLong(result.getResult());
|
|
|
Map<String, Object> properties = result.getProperties();
|
|
|
MidjourneyUserConversation conversation = null;
|
|
|
@@ -176,6 +184,9 @@ public class MidjourneyServiceImpl implements MidjourneyService {
|
|
|
if (conversation.getInstanceId() == null) {
|
|
|
conversation.setInstanceId(result.getInstanceId());
|
|
|
}
|
|
|
+ if(apiChannelId != null){
|
|
|
+ conversation.setApiChannelId(apiChannelId);
|
|
|
+ }
|
|
|
if (conversation.getId() == null) {
|
|
|
conversationMapper.insert(conversation);
|
|
|
}else {
|
|
|
@@ -191,11 +202,11 @@ public class MidjourneyServiceImpl implements MidjourneyService {
|
|
|
.put("state", user.getId().toString())
|
|
|
.put("base64", base64)
|
|
|
.build();
|
|
|
- SubmitResult result = submit(user,mode,"describe", null, param);
|
|
|
+ SubmitResult result = submit(user,mode,"describe", null, param, null);
|
|
|
if (mode == 2) {
|
|
|
redisService.hincr(RedisService.key.MIDJOURNEY_ACCOUNT.getName(), result.getInstanceId().toString(), 1.0);
|
|
|
}
|
|
|
- saveConversation(user.getId(), mode,result,"DESCRIBE", StringUtils.EMPTY, botType);
|
|
|
+ saveConversation(user.getId(), mode,result,"DESCRIBE", StringUtils.EMPTY, botType, result.getApiChannelId());
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
@@ -208,11 +219,11 @@ public class MidjourneyServiceImpl implements MidjourneyService {
|
|
|
if (dimensions != null) {
|
|
|
param.put("dimensions", dimensions);
|
|
|
}
|
|
|
- SubmitResult result = submit(user,mode,"blend", null, param);
|
|
|
+ SubmitResult result = submit(user,mode,"blend", null, param, null);
|
|
|
if (mode == 2) {
|
|
|
redisService.hincr(RedisService.key.MIDJOURNEY_ACCOUNT.getName(), result.getInstanceId().toString(), 1.0);
|
|
|
}
|
|
|
- saveConversation(user.getId(), mode,result,"BLEND", StringUtils.EMPTY, botType);
|
|
|
+ saveConversation(user.getId(), mode,result,"BLEND", StringUtils.EMPTY, botType, result.getApiChannelId());
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
@@ -232,11 +243,11 @@ public class MidjourneyServiceImpl implements MidjourneyService {
|
|
|
if (StringUtils.isNotBlank(maskBase64)) {
|
|
|
param.put("maskBase64", maskBase64);
|
|
|
}
|
|
|
- SubmitResult result = submit(user,mode,"modal", null, param);
|
|
|
+ SubmitResult result = submit(user,mode,"modal", null, param,midjourneyUserConversation.getApiChannelId());
|
|
|
if (mode == 2) {
|
|
|
redisService.hincr(RedisService.key.MIDJOURNEY_ACCOUNT.getName(), result.getInstanceId().toString(), 1.0);
|
|
|
}
|
|
|
- saveConversation(user.getId(), mode,result,"MODAL", StringUtils.EMPTY, StringUtils.EMPTY);
|
|
|
+ saveConversation(user.getId(), mode,result,"MODAL", StringUtils.EMPTY, StringUtils.EMPTY,midjourneyUserConversation.getApiChannelId());
|
|
|
Map<String, Object> properties = result.getProperties();
|
|
|
properties.put("finalPrompt",prompt);
|
|
|
properties.put("messageContent","**"+midjourneyUserConversation.getPrompt()+"** - <@mj>" + (mode == 1 ? "(fast)" : "(relaxed)"));
|
|
|
@@ -249,11 +260,11 @@ public class MidjourneyServiceImpl implements MidjourneyService {
|
|
|
.put("prompt", prompt)
|
|
|
.put("state", user.getId().toString())
|
|
|
.build();
|
|
|
- SubmitResult result = submit(user,mode,"shorten", null, param);
|
|
|
+ SubmitResult result = submit(user,mode,"shorten", null, param, null);
|
|
|
if (mode == 2) {
|
|
|
redisService.hincr(RedisService.key.MIDJOURNEY_ACCOUNT.getName(), result.getInstanceId().toString(), 1.0);
|
|
|
}
|
|
|
- saveConversation(user.getId(), mode, result,"SHORTEN", StringUtils.EMPTY, botType);
|
|
|
+ saveConversation(user.getId(), mode, result,"SHORTEN", StringUtils.EMPTY, botType, result.getApiChannelId());
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
@@ -338,7 +349,7 @@ public class MidjourneyServiceImpl implements MidjourneyService {
|
|
|
// }
|
|
|
|
|
|
@Override
|
|
|
- public SubmitResult submitAction(MidjourneyUser user,MidjourneyUserConversation conversation,Integer mode, Long taskId, String customId, Long num, String botType) throws Exception {
|
|
|
+ public SubmitResult submitAction(MidjourneyUser user,MidjourneyUserConversation conversation,Integer mode, Long taskId, String customId, Long num, String botType, Long apiChannelId) throws Exception {
|
|
|
AtomicBoolean modalFlag = new AtomicBoolean(false);
|
|
|
if (StringUtils.isNotBlank(conversation.getButtons())){
|
|
|
List<MessageButton> messageButtons = Jsons.parseList(conversation.getButtons(), MessageButton.class);
|
|
|
@@ -373,7 +384,7 @@ public class MidjourneyServiceImpl implements MidjourneyService {
|
|
|
.put("state", user.getId().toString())
|
|
|
.put("customId", customId)
|
|
|
.build();
|
|
|
- SubmitResult result = submit(user,mode,"action", conversation.getInstanceId(),param);
|
|
|
+ SubmitResult result = submit(user,mode,"action", conversation.getInstanceId(),param, apiChannelId);
|
|
|
if (result.getCode() == 21) {
|
|
|
if (mode == 2 && modalFlag.get()){
|
|
|
SubmitResult modal = submitModal(user, mode,Long.valueOf(result.getResult()), conversation.getPrompt(), null);
|
|
|
@@ -395,20 +406,37 @@ public class MidjourneyServiceImpl implements MidjourneyService {
|
|
|
Map<String, Object> properties = result.getProperties();
|
|
|
properties.put("finalPrompt",conversation.getPrompt());
|
|
|
properties.put("messageContent","**"+conversation.getPrompt()+"** - <@mj>" + (mode == 1 ? " (fast)" : " (relaxed)"));
|
|
|
- MidjourneyUserConversation midjourneyUserConversation = saveConversation(user.getId(), mode, result, "ACTION", StringUtils.EMPTY, botType);
|
|
|
+ MidjourneyUserConversation midjourneyUserConversation = saveConversation(user.getId(), mode, result, "ACTION", StringUtils.EMPTY, botType, apiChannelId);
|
|
|
properties.put("id",midjourneyUserConversation.getId());
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
|
|
|
- public SubmitResult submit(MidjourneyUser user,Integer mode,String action,Long instanceId, Map<String, Object> param) throws Exception {
|
|
|
- String url = "";
|
|
|
+ public SubmitResult submit(MidjourneyUser user, Integer mode, String action, Long instanceId, Map<String, Object> param, Long apiChannelId) throws Exception {
|
|
|
+
|
|
|
String accountWithMinUsage = "";
|
|
|
+ String url = "";
|
|
|
+ String token = "";
|
|
|
if (mode == 1) {
|
|
|
param.put("mode", "FAST");
|
|
|
- url = FAST_HOST;
|
|
|
+
|
|
|
+ MidjourneyApiChannel midjourneyApiChannel = midjourneyApiChannelMapper.selectOne(QueryWrapperUtils.buildWrapper((wrapper)->{
|
|
|
+ if(apiChannelId != null && apiChannelId != 0){
|
|
|
+ wrapper.eq(MidjourneyApiChannel::getId,apiChannelId);
|
|
|
+ }else {
|
|
|
+ wrapper.eq(MidjourneyApiChannel::getIsDefault, true);
|
|
|
+ }
|
|
|
+ }));
|
|
|
+ if (midjourneyApiChannel == null) {
|
|
|
+ throw BusinessRuntimeException.getInstance("FAST模式账号异常");
|
|
|
+ }
|
|
|
+
|
|
|
+ url = midjourneyApiChannel.getUrl();
|
|
|
+ token = midjourneyApiChannel.getToken();
|
|
|
+
|
|
|
} else if (mode == 2) {
|
|
|
url = RELAX_HOST;
|
|
|
+ token = RELAX_TOKEN;
|
|
|
//慢速查询在使用次数最少的账号
|
|
|
accountWithMinUsage = getAccountWithMinUsage(instanceId);
|
|
|
if (accountWithMinUsage == null) {
|
|
|
@@ -418,25 +446,45 @@ public class MidjourneyServiceImpl implements MidjourneyService {
|
|
|
.put("instanceId",accountWithMinUsage).build());
|
|
|
userSubmitLimit(user,action,param.get("customId"));
|
|
|
}
|
|
|
- url = url + getActionUrl(action);
|
|
|
- param.put("notifyHook",midjourneyHost +(EnvCommonService.active.equals(envCommonService.getEnv()) ? "/8083":"/8082") + "/api/applets/midjourney/notifyHook");
|
|
|
- HttpRequest request = HttpRequest.post(url).body(Jsons.toJson(param));
|
|
|
- request = mode == 1 ? request.header("Authorization", FAST_TOKEN) : request.header("mj-api-secret", RELAX_TOKEN);
|
|
|
- String body = request.execute().body();
|
|
|
- log.info("action body:{}", body);
|
|
|
- SubmitResult submitResult = Jsons.parseObject(body, SubmitResult.class);
|
|
|
+ SubmitResult submitResult = submit2MjProxy(url, token, mode, action, param);
|
|
|
int code = submitResult.getCode();
|
|
|
if (code != 1 && code != 21 && code != 22) {
|
|
|
if (code == 3) {
|
|
|
- if(mode == 2 && StringUtils.isNotBlank(accountWithMinUsage)){
|
|
|
+ if(mode == 2){
|
|
|
redisService.hdel(RedisService.key.MIDJOURNEY_ACCOUNT.getName(),accountWithMinUsage);
|
|
|
String finalAccountWithMinUsage = accountWithMinUsage;
|
|
|
TASK_EXECUTOR.execute(() -> {
|
|
|
MidjourneyAccount account = midjourneyAccountService.getOne(Wrappers.lambdaQuery(MidjourneyAccount.class).eq(MidjourneyAccount::getInstanceId, finalAccountWithMinUsage).last("limit 1"));
|
|
|
midjourneyAccountService.updateStatus(account.getId());
|
|
|
});
|
|
|
- submit(user,mode, action, instanceId, param);
|
|
|
+ if(RETRY_ACTION.contains(action)){
|
|
|
+ submit(user,mode, action, instanceId, param, null);
|
|
|
+ }
|
|
|
+ } else if(mode == 1) {
|
|
|
+ // 重试逻辑,切换供应商域名
|
|
|
+ if(RETRY_ACTION.contains(action)){
|
|
|
+ List<MidjourneyApiChannel> midjourneyApiChannels = midjourneyApiChannelMapper.selectList(QueryWrapperUtils.buildWrapper((wrapper) -> {
|
|
|
+ wrapper.eq(MidjourneyApiChannel::getIsDefault, false);
|
|
|
+ }));
|
|
|
+ for (MidjourneyApiChannel midjourneyApiChannel : midjourneyApiChannels) {
|
|
|
+ submitResult = submit2MjProxy(midjourneyApiChannel.getUrl(), midjourneyApiChannel.getToken(), mode, action, param);
|
|
|
+ if (submitResult.getCode() == 1 || submitResult.getCode() == 22){
|
|
|
+ submitResult.setApiChannelId(midjourneyApiChannel.getId());
|
|
|
+ }else if (submitResult.getCode() == 24) {
|
|
|
+ JSONObject jsonObject = JSONUtil.parseObj(submitResult.getResult());
|
|
|
+ throw BusinessRuntimeException.getInstance("prompt包含敏感词:"+jsonObject.getStr("bannedWord"));
|
|
|
+ }else {
|
|
|
+ if(submitResult.getCode() == 3){
|
|
|
+ log.info("服务商 :{}, 账号短缺", midjourneyApiChannel.getName());
|
|
|
+ }else {
|
|
|
+ log.error("服务商:{}, action:{}, error message:{}", midjourneyApiChannel.getName(), action, submitResult.getDescription());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
}
|
|
|
+
|
|
|
throw BusinessRuntimeException.getInstance("该任务所属的源Mj账号已被官网封禁或暂时风控。请稍后再试,或重新生成图片");
|
|
|
}
|
|
|
if (code == 4) {
|
|
|
@@ -447,7 +495,7 @@ public class MidjourneyServiceImpl implements MidjourneyService {
|
|
|
throw BusinessRuntimeException.getInstance("prompt包含敏感词:"+jsonObject.getStr("bannedWord"));
|
|
|
}
|
|
|
log.error("action:" + action + " error message:" + submitResult.getDescription());
|
|
|
- throw BusinessRuntimeException.getInstance("队列已满,请稍后尝试");
|
|
|
+ throw BusinessRuntimeException.getInstance("该任务源Mj账号队列已满,请稍后尝试");
|
|
|
}
|
|
|
if (StringUtils.isNotBlank(accountWithMinUsage) && mode == 2) {
|
|
|
submitResult.setInstanceId(Long.valueOf(accountWithMinUsage));
|
|
|
@@ -455,6 +503,24 @@ public class MidjourneyServiceImpl implements MidjourneyService {
|
|
|
return submitResult;
|
|
|
}
|
|
|
|
|
|
+ private SubmitResult submit2MjProxy(String url, String token, Integer mode, String action, Map<String, Object> param) throws Exception {
|
|
|
+
|
|
|
+ url = url + getActionUrl(action);
|
|
|
+ param.put("notifyHook",midjourneyHost +(EnvCommonService.active.equals(envCommonService.getEnv()) ? "/8083":"/8082") + "/api/applets/midjourney/notifyHook");
|
|
|
+ HttpRequest request = HttpRequest.post(url).body(Jsons.toJson(param));
|
|
|
+ request = mode == 1 ? request.header("Authorization", token) : request.header("mj-api-secret", token);
|
|
|
+ String body = request.execute().body();
|
|
|
+ log.info("action body:{}", body);
|
|
|
+ SubmitResult submitResult = Jsons.parseObject(body, SubmitResult.class);
|
|
|
+ return submitResult;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void switchSupplierDomain() {
|
|
|
+ // 实现切换供应商域名的逻辑
|
|
|
+ // 例如,重新设置FAST_HOST或RELAX_HOST
|
|
|
+ log.info("Switching supplier domain...");
|
|
|
+ }
|
|
|
+
|
|
|
|
|
|
/**
|
|
|
* 用户生图次数限制
|