From d865cc293b106501642985c193f81696a61f90cf Mon Sep 17 00:00:00 2001
From: cherishsince <cherishsince@aliyun.com>
Date: Fri, 12 Jul 2024 15:03:34 +0800
Subject: [PATCH 1/3] =?UTF-8?q?=E3=80=90=E5=A2=9E=E5=8A=A0=E3=80=91chatglm?=
 =?UTF-8?q?=20=E5=AE=9E=E7=8E=B0=20spring=20ai=20=E6=A0=87=E5=87=86?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../yudao-spring-boot-starter-ai/pom.xml      |   7 ++
 .../core/model/chatglm/ChatGlmImageModel.java |  75 ++++++++++++
 .../model/chatglm/ChatGlmImageOptions.java    | 115 ++++++++++++++++++
 .../chatglm/api/ChatGlmResponseMetadata.java  |  24 ++++
 .../ai/image/ChatGlmImageModelTests.java      |  40 ++++++
 5 files changed, 261 insertions(+)
 create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/chatglm/ChatGlmImageModel.java
 create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/chatglm/ChatGlmImageOptions.java
 create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/chatglm/api/ChatGlmResponseMetadata.java
 create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/image/ChatGlmImageModelTests.java

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 4aa6273cf..f0e9d19a7 100644
--- a/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml
+++ b/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml
@@ -60,6 +60,13 @@
             <version>2.14.0</version>
         </dependency>
 
+        <!-- bigmodel -->
+        <dependency>
+            <groupId>cn.bigmodel.openapi</groupId>
+            <artifactId>oapi-java-sdk</artifactId>
+            <version>release-V4-2.0.2</version>
+        </dependency>
+
         <!-- Test 测试相关 -->
         <dependency>
             <groupId>org.springframework.boot</groupId>
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
new file mode 100644
index 000000000..b6275f4e8
--- /dev/null
+++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/chatglm/ChatGlmImageModel.java
@@ -0,0 +1,75 @@
+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
new file mode 100644
index 000000000..4396d9cd4
--- /dev/null
+++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/chatglm/ChatGlmImageOptions.java
@@ -0,0 +1,115 @@
+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
new file mode 100644
index 000000000..e83f53eb1
--- /dev/null
+++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/chatglm/api/ChatGlmResponseMetadata.java
@@ -0,0 +1,24 @@
+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<String, Object> 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
new file mode 100644
index 000000000..c54056b75
--- /dev/null
+++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/image/ChatGlmImageModelTests.java
@@ -0,0 +1,40 @@
+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));
+    }
+}

From 4311fe4517fb45d720e15ed3eb45d7bee12edec4 Mon Sep 17 00:00:00 2001
From: cherishsince <cherishsince@aliyun.com>
Date: Fri, 12 Jul 2024 15:44:59 +0800
Subject: [PATCH 2/3] =?UTF-8?q?=E3=80=90=E5=A2=9E=E5=8A=A0=E3=80=91image?=
 =?UTF-8?q?=20=E5=AF=B9=E6=8E=A5=20Chatglm=20=E6=A8=A1=E5=9E=8B?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../yudao/module/ai/service/image/AiImageServiceImpl.java   | 5 +++++
 .../yudao/framework/ai/core/enums/AiPlatformEnum.java       | 1 +
 .../yudao/framework/ai/core/factory/AiModelFactoryImpl.java | 6 ++++++
 3 files changed, 12 insertions(+)

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 02c1ab334..a7e68656b 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,6 +9,7 @@ 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;
@@ -148,6 +149,10 @@ 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()
+                    .withModel(draw.getModel())
+                    .build();
         }
         throw new IllegalArgumentException("不支持的 AI 平台:" + draw.getPlatform());
     }
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 596118168..2e302501c 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,6 +28,7 @@ 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 66a32167c..2dae410cb 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,6 +9,7 @@ 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;
@@ -139,6 +140,8 @@ public class AiModelFactoryImpl implements AiModelFactory {
                 return buildOpenAiImageModel(apiKey, url);
             case STABLE_DIFFUSION:
                 return buildStabilityAiImageModel(apiKey, url);
+            case CHATGLM:
+                return buildChatGlmModel(apiKey);
             default:
                 throw new IllegalArgumentException(StrUtil.format("未知平台({})", platform));
         }
@@ -273,4 +276,7 @@ public class AiModelFactoryImpl implements AiModelFactory {
         return new StabilityAiImageModel(stabilityAiApi);
     }
 
+    private ChatGlmImageModel buildChatGlmModel(String apiKey) {
+        return new ChatGlmImageModel(apiKey);
+    }
 }

From 73502d565fad087689a851b9eb1edb35eb3d50cc Mon Sep 17 00:00:00 2001
From: YunaiV <zhijiantianya@gmail.com>
Date: Sat, 13 Jul 2024 00:06:48 +0800
Subject: [PATCH 3/3] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E4=BC=98?=
 =?UTF-8?q?=E5=8C=96=E3=80=91AI=EF=BC=9AChatGlm=20=E6=9B=BF=E6=8D=A2?=
 =?UTF-8?q?=E6=88=90=20ZhiPuAiImage=20=E5=AE=9E=E7=8E=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../ai/service/image/AiImageServiceImpl.java  |  10 +-
 .../yudao-spring-boot-starter-ai/pom.xml      |   7 --
 .../ai/core/enums/AiPlatformEnum.java         |   1 -
 .../ai/core/factory/AiModelFactoryImpl.java   |  26 ++--
 .../core/model/chatglm/ChatGlmImageModel.java |  75 ------------
 .../model/chatglm/ChatGlmImageOptions.java    | 115 ------------------
 .../chatglm/api/ChatGlmResponseMetadata.java  |  24 ----
 .../ai/image/ChatGlmImageModelTests.java      |  40 ------
 .../ai/image/ZhiPuAiImageModelTests.java      |  35 ++++++
 9 files changed, 60 insertions(+), 273 deletions(-)
 delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/chatglm/ChatGlmImageModel.java
 delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/chatglm/ChatGlmImageOptions.java
 delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/chatglm/api/ChatGlmResponseMetadata.java
 delete mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/image/ChatGlmImageModelTests.java
 create mode 100644 yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/image/ZhiPuAiImageModelTests.java

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 @@
             <version>2.14.0</version>
         </dependency>
 
-        <!-- bigmodel -->
-        <dependency>
-            <groupId>cn.bigmodel.openapi</groupId>
-            <artifactId>oapi-java-sdk</artifactId>
-            <version>release-V4-2.0.2</version>
-        </dependency>
-
         <!-- Test 测试相关 -->
         <dependency>
             <groupId>org.springframework.boot</groupId>
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<String, Object> 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);
+    }
+
+}