diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java
index a7e68656b..3a8ff8346 100644
--- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java
+++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java
@@ -9,7 +9,6 @@ import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.http.HttpUtil;
import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum;
-import cn.iocoder.yudao.framework.ai.core.model.chatglm.ChatGlmImageOptions;
import cn.iocoder.yudao.framework.ai.core.model.midjourney.api.MidjourneyApi;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
@@ -34,6 +33,7 @@ import org.springframework.ai.image.ImageResponse;
import org.springframework.ai.openai.OpenAiImageOptions;
import org.springframework.ai.qianfan.QianFanImageOptions;
import org.springframework.ai.stabilityai.api.StabilityAiImageOptions;
+import org.springframework.ai.zhipuai.ZhiPuAiImageOptions;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -105,7 +105,9 @@ public class AiImageServiceImpl implements AiImageService {
ImageResponse response = imageModel.call(new ImagePrompt(req.getPrompt(), request));
// 2. 上传到文件服务
- byte[] fileContent = Base64.decode(response.getResult().getOutput().getB64Json());
+ String b64Json = response.getResult().getOutput().getB64Json();
+ byte[] fileContent = StrUtil.isNotEmpty(b64Json) ? Base64.decode(b64Json)
+ : HttpUtil.downloadBytes(response.getResult().getOutput().getUrl());
String filePath = fileApi.createFile(fileContent);
// 3. 更新数据库
@@ -149,8 +151,8 @@ public class AiImageServiceImpl implements AiImageService {
.withModel(draw.getModel()).withN(1)
.withHeight(draw.getHeight()).withWidth(draw.getWidth())
.build();
- } else if (ObjUtil.equal(draw.getPlatform(), AiPlatformEnum.CHATGLM.getPlatform())) {
- return ChatGlmImageOptions.builder()
+ } else if (ObjUtil.equal(draw.getPlatform(), AiPlatformEnum.ZHI_PU.getPlatform())) {
+ return ZhiPuAiImageOptions.builder()
.withModel(draw.getModel())
.build();
}
diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml b/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml
index f0e9d19a7..4aa6273cf 100644
--- a/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml
+++ b/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml
@@ -60,13 +60,6 @@
2.14.0
-
-
- cn.bigmodel.openapi
- oapi-java-sdk
- release-V4-2.0.2
-
-
org.springframework.boot
diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java
index 2e302501c..596118168 100644
--- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java
+++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java
@@ -28,7 +28,6 @@ public enum AiPlatformEnum {
STABLE_DIFFUSION("StableDiffusion", "StableDiffusion"), // Stability AI
MIDJOURNEY("Midjourney", "Midjourney"), // Midjourney
SUNO("Suno", "Suno"), // Suno AI
- CHATGLM("ChatGlm", "ChatGlm"), // Suno AI
;
diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiModelFactoryImpl.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiModelFactoryImpl.java
index 2dae410cb..a5df28246 100644
--- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiModelFactoryImpl.java
+++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiModelFactoryImpl.java
@@ -9,7 +9,6 @@ import cn.hutool.extra.spring.SpringUtil;
import cn.iocoder.yudao.framework.ai.config.YudaoAiAutoConfiguration;
import cn.iocoder.yudao.framework.ai.config.YudaoAiProperties;
import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum;
-import cn.iocoder.yudao.framework.ai.core.model.chatglm.ChatGlmImageModel;
import cn.iocoder.yudao.framework.ai.core.model.deepseek.DeepSeekChatModel;
import cn.iocoder.yudao.framework.ai.core.model.midjourney.api.MidjourneyApi;
import cn.iocoder.yudao.framework.ai.core.model.suno.api.SunoApi;
@@ -31,6 +30,7 @@ import org.springframework.ai.autoconfigure.qianfan.QianFanImageProperties;
import org.springframework.ai.autoconfigure.zhipuai.ZhiPuAiAutoConfiguration;
import org.springframework.ai.autoconfigure.zhipuai.ZhiPuAiChatProperties;
import org.springframework.ai.autoconfigure.zhipuai.ZhiPuAiConnectionProperties;
+import org.springframework.ai.autoconfigure.zhipuai.ZhiPuAiImageProperties;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.image.ImageModel;
import org.springframework.ai.model.function.FunctionCallbackContext;
@@ -48,7 +48,9 @@ import org.springframework.ai.qianfan.api.QianFanImageApi;
import org.springframework.ai.stabilityai.StabilityAiImageModel;
import org.springframework.ai.stabilityai.api.StabilityAiApi;
import org.springframework.ai.zhipuai.ZhiPuAiChatModel;
+import org.springframework.ai.zhipuai.ZhiPuAiImageModel;
import org.springframework.ai.zhipuai.api.ZhiPuAiApi;
+import org.springframework.ai.zhipuai.api.ZhiPuAiImageApi;
import org.springframework.retry.support.RetryTemplate;
import org.springframework.web.client.ResponseErrorHandler;
import org.springframework.web.client.RestClient;
@@ -119,6 +121,8 @@ public class AiModelFactoryImpl implements AiModelFactory {
return SpringUtil.getBean(TongYiImagesModel.class);
case YI_YAN:
return SpringUtil.getBean(QianFanImageModel.class);
+ case ZHI_PU:
+ return SpringUtil.getBean(ZhiPuAiImageModel.class);
case OPENAI:
return SpringUtil.getBean(OpenAiImageModel.class);
case STABLE_DIFFUSION:
@@ -136,12 +140,12 @@ public class AiModelFactoryImpl implements AiModelFactory {
return buildTongYiImagesModel(apiKey);
case YI_YAN:
return buildQianFanImageModel(apiKey);
+ case ZHI_PU:
+ return buildZhiPuAiImageModel(apiKey, url);
case OPENAI:
return buildOpenAiImageModel(apiKey, url);
case STABLE_DIFFUSION:
return buildStabilityAiImageModel(apiKey, url);
- case CHATGLM:
- return buildChatGlmModel(apiKey);
default:
throw new IllegalArgumentException(StrUtil.format("未知平台({})", platform));
}
@@ -225,7 +229,8 @@ public class AiModelFactoryImpl implements AiModelFactory {
}
/**
- * 可参考 {@link ZhiPuAiAutoConfiguration#zhiPuAiChatModel(ZhiPuAiConnectionProperties, ZhiPuAiChatProperties, RestClient.Builder, List, FunctionCallbackContext, RetryTemplate, ResponseErrorHandler)}
+ * 可参考 {@link ZhiPuAiAutoConfiguration#zhiPuAiChatModel(
+ * ZhiPuAiConnectionProperties, ZhiPuAiChatProperties, RestClient.Builder, List, FunctionCallbackContext, RetryTemplate, ResponseErrorHandler)}
*/
private ZhiPuAiChatModel buildZhiPuChatModel(String apiKey, String url) {
url = StrUtil.blankToDefault(url, ZhiPuAiConnectionProperties.DEFAULT_BASE_URL);
@@ -233,6 +238,16 @@ public class AiModelFactoryImpl implements AiModelFactory {
return new ZhiPuAiChatModel(zhiPuAiApi);
}
+ /**
+ * 可参考 {@link ZhiPuAiAutoConfiguration#zhiPuAiImageModel(
+ * ZhiPuAiConnectionProperties, ZhiPuAiImageProperties, RestClient.Builder, RetryTemplate, ResponseErrorHandler)}
+ */
+ private ZhiPuAiImageModel buildZhiPuAiImageModel(String apiKey, String url) {
+ url = StrUtil.blankToDefault(url, ZhiPuAiConnectionProperties.DEFAULT_BASE_URL);
+ ZhiPuAiImageApi zhiPuAiApi = new ZhiPuAiImageApi(url, apiKey, RestClient.builder());
+ return new ZhiPuAiImageModel(zhiPuAiApi);
+ }
+
/**
* 可参考 {@link YudaoAiAutoConfiguration#xingHuoChatClient(YudaoAiProperties)}
*/
@@ -276,7 +291,4 @@ public class AiModelFactoryImpl implements AiModelFactory {
return new StabilityAiImageModel(stabilityAiApi);
}
- private ChatGlmImageModel buildChatGlmModel(String apiKey) {
- return new ChatGlmImageModel(apiKey);
- }
}
diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/chatglm/ChatGlmImageModel.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/chatglm/ChatGlmImageModel.java
deleted file mode 100644
index b6275f4e8..000000000
--- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/chatglm/ChatGlmImageModel.java
+++ /dev/null
@@ -1,75 +0,0 @@
-package cn.iocoder.yudao.framework.ai.core.model.chatglm;
-
-import cn.iocoder.yudao.framework.ai.core.model.chatglm.api.ChatGlmResponseMetadata;
-import com.zhipu.oapi.ClientV4;
-import com.zhipu.oapi.service.v4.image.CreateImageRequest;
-import com.zhipu.oapi.service.v4.image.ImageApiResponse;
-import org.springframework.ai.image.*;
-
-import java.io.ByteArrayOutputStream;
-import java.net.URL;
-import java.util.Base64;
-import java.util.stream.Collectors;
-
-public class ChatGlmImageModel implements ImageModel {
-
- private ClientV4 client;
-
- public ChatGlmImageModel(String apiSecretKey) {
- client = new ClientV4.Builder(apiSecretKey).build();
- }
-
- @Override
- public ImageResponse call(ImagePrompt request) {
- CreateImageRequest imageRequest = CreateImageRequest.builder()
- .model(request.getOptions().getModel())
- .prompt(request.getInstructions().get(0).getText())
- .build();
- return convert(client.createImage(imageRequest));
- }
-
- private ImageResponse convert(ImageApiResponse result) {
- return new ImageResponse(
- result.getData().getData().stream().map(item -> {
- try {
- String url = item.getUrl();
- String base64Image = convertImageToBase64(url);
- Image image = new Image(url, base64Image);
- return new ImageGeneration(image);
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }).collect(Collectors.toList()),
- new ChatGlmResponseMetadata(result)
- );
- }
-
-
- /**
- * Convert image to base64.
- * @param imageUrl the image url.
- * @return the base64 image.
- * @throws Exception the exception.
- */
- public String convertImageToBase64(String imageUrl) throws Exception {
-
- var url = new URL(imageUrl);
- var inputStream = url.openStream();
- var outputStream = new ByteArrayOutputStream();
- var buffer = new byte[4096];
- int bytesRead;
-
- while ((bytesRead = inputStream.read(buffer)) != -1) {
- outputStream.write(buffer, 0, bytesRead);
- }
-
- var imageBytes = outputStream.toByteArray();
-
- String base64Image = Base64.getEncoder().encodeToString(imageBytes);
-
- inputStream.close();
- outputStream.close();
-
- return base64Image;
- }
-}
diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/chatglm/ChatGlmImageOptions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/chatglm/ChatGlmImageOptions.java
deleted file mode 100644
index 4396d9cd4..000000000
--- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/chatglm/ChatGlmImageOptions.java
+++ /dev/null
@@ -1,115 +0,0 @@
-package cn.iocoder.yudao.framework.ai.core.model.chatglm;
-
-import com.fasterxml.jackson.annotation.JsonProperty;
-import lombok.Setter;
-import org.springframework.ai.image.ImageOptions;
-
-/**
- * chatglm
- * api地址:https://open.bigmodel.cn/dev/api#cogview
- */
-@Setter
-public class ChatGlmImageOptions implements ImageOptions {
-
- @JsonProperty("n")
- private Integer n;
-
- @JsonProperty("model")
- private String model = "cogview-3";
-
- @JsonProperty("size_width")
- private Integer width;
-
- @JsonProperty("size_height")
- private Integer height;
-
- @JsonProperty("size")
- private String size;
-
- @JsonProperty("style")
- private String style;
-
- @JsonProperty("user_id")
- private String user;
-
- @JsonProperty("responseFormat")
- private String responseFormat;
-
- // ==== build
-
-
- public static ChatGlmImageOptions.Builder builder() {
- return new ChatGlmImageOptions.Builder();
- }
-
- public static class Builder {
-
- private final ChatGlmImageOptions options;
-
- private Builder() {
- this.options = new ChatGlmImageOptions();
- }
-
- public ChatGlmImageOptions.Builder withN(Integer n) {
- options.setN(n);
- return this;
- }
-
- public ChatGlmImageOptions.Builder withModel(String model) {
- options.setModel(model);
- return this;
- }
-
- public ChatGlmImageOptions.Builder withWidth(Integer width) {
- options.setWidth(width);
- return this;
- }
-
- public ChatGlmImageOptions.Builder withHeight(Integer height) {
- options.setHeight(height);
- return this;
- }
-
- public ChatGlmImageOptions.Builder withStyle(String style) {
- options.setStyle(style);
- return this;
- }
-
- public ChatGlmImageOptions.Builder withUser(String user) {
- options.setUser(user);
- return this;
- }
-
- public ChatGlmImageOptions build() {
- return options;
- }
-
- }
-
- // ==== get
-
- @Override
- public Integer getN() {
- return n;
- }
-
- @Override
- public String getModel() {
- return model;
- }
-
- @Override
- public Integer getWidth() {
- return width;
- }
-
- @Override
- public Integer getHeight() {
- return height;
- }
-
- @Override
- public String getResponseFormat() {
- return responseFormat;
- }
-}
diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/chatglm/api/ChatGlmResponseMetadata.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/chatglm/api/ChatGlmResponseMetadata.java
deleted file mode 100644
index e83f53eb1..000000000
--- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/chatglm/api/ChatGlmResponseMetadata.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package cn.iocoder.yudao.framework.ai.core.model.chatglm.api;
-
-import com.zhipu.oapi.service.v4.image.ImageApiResponse;
-import org.springframework.ai.image.ImageResponseMetadata;
-
-import java.util.HashMap;
-
-public class ChatGlmResponseMetadata extends HashMap implements ImageResponseMetadata {
-
- private Long created;
-
- public ChatGlmResponseMetadata(ImageApiResponse result) {
- created = result.getData().getCreated();
- }
-
- @Override
- public Long getCreated() {
- return created;
- }
-
- public void setCreated(Long created) {
- this.created = created;
- }
-}
diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/image/ChatGlmImageModelTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/image/ChatGlmImageModelTests.java
deleted file mode 100644
index c54056b75..000000000
--- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/image/ChatGlmImageModelTests.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package cn.iocoder.yudao.framework.ai.image;
-
-import cn.iocoder.yudao.framework.ai.core.model.chatglm.ChatGlmImageModel;
-import cn.iocoder.yudao.framework.ai.core.model.chatglm.ChatGlmImageOptions;
-import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
-import com.alibaba.fastjson.JSON;
-import com.zhipu.oapi.ClientV4;
-import com.zhipu.oapi.core.httpclient.ApacheHttpClientTransport;
-import com.zhipu.oapi.service.v4.image.CreateImageRequest;
-import com.zhipu.oapi.service.v4.image.ImageApiResponse;
-import org.junit.jupiter.api.Test;
-import org.springframework.ai.image.ImageOptionsBuilder;
-import org.springframework.ai.image.ImagePrompt;
-import org.springframework.ai.image.ImageResponse;
-import org.springframework.ai.qianfan.QianFanImageModel;
-import org.springframework.ai.qianfan.QianFanImageOptions;
-import org.springframework.ai.qianfan.api.QianFanImageApi;
-
-/**
- * 百度千帆 image
- */
-public class ChatGlmImageModelTests {
-
- @Test
- public void callTest() {
- ChatGlmImageModel model = new ChatGlmImageModel("78d3228c1d9e5e342a3e1ab349e2dd7b.VXLoq5vrwK2ofboy");
- ImageResponse call = model.call(new ImagePrompt("万里长城", ChatGlmImageOptions.builder().build()));
- System.err.println(call.getResult().getOutput().getUrl());
- }
-
- @Test
- public void createImageTest() {
- ClientV4 client = new ClientV4.Builder("78d3228c1d9e5e342a3e1ab349e2dd7b.VXLoq5vrwK2ofboy").build();
- CreateImageRequest createImageRequest = new CreateImageRequest();
- createImageRequest.setModel("cogview-3");
- createImageRequest.setPrompt("长城!");
- ImageApiResponse image = client.createImage(createImageRequest);
- System.err.println(JSON.toJSONString(image));
- }
-}
diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/image/ZhiPuAiImageModelTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/image/ZhiPuAiImageModelTests.java
new file mode 100644
index 000000000..f9338995f
--- /dev/null
+++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/image/ZhiPuAiImageModelTests.java
@@ -0,0 +1,35 @@
+package cn.iocoder.yudao.framework.ai.image;
+
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+import org.springframework.ai.image.ImagePrompt;
+import org.springframework.ai.image.ImageResponse;
+import org.springframework.ai.zhipuai.ZhiPuAiImageModel;
+import org.springframework.ai.zhipuai.ZhiPuAiImageOptions;
+import org.springframework.ai.zhipuai.api.ZhiPuAiImageApi;
+
+/**
+ * {@link ZhiPuAiImageModel} 集成测试
+ */
+public class ZhiPuAiImageModelTests {
+
+ private final ZhiPuAiImageApi imageApi = new ZhiPuAiImageApi(
+ "78d3228c1d9e5e342a3e1ab349e2dd7b.VXLoq5vrwK2ofboy");
+ private final ZhiPuAiImageModel imageModel = new ZhiPuAiImageModel(imageApi);
+
+ @Test
+ @Disabled
+ public void testCall() {
+ // 准备参数
+ ZhiPuAiImageOptions imageOptions = ZhiPuAiImageOptions.builder()
+ .withModel(ZhiPuAiImageApi.ImageModel.CogView_3.getValue())
+ .build();
+ ImagePrompt prompt = new ImagePrompt("万里长城", imageOptions);
+
+ // 方法调用
+ ImageResponse response = imageModel.call(prompt);
+ // 打印结果
+ System.out.println(response);
+ }
+
+}