Commit 3aad33c3cd40c3ff8ca4131cb72bdb63e8791167

Authored by 芋道源码
Committed by Gitee
2 parents a18682e8 73502d56

!1013 新增文心一言、智谱 AI 的绘图能力

Merge pull request !1013 from 芋道源码/master-jdk21-ai
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java
@@ -33,6 +33,7 @@ import org.springframework.ai.image.ImageResponse; @@ -33,6 +33,7 @@ import org.springframework.ai.image.ImageResponse;
33 import org.springframework.ai.openai.OpenAiImageOptions; 33 import org.springframework.ai.openai.OpenAiImageOptions;
34 import org.springframework.ai.qianfan.QianFanImageOptions; 34 import org.springframework.ai.qianfan.QianFanImageOptions;
35 import org.springframework.ai.stabilityai.api.StabilityAiImageOptions; 35 import org.springframework.ai.stabilityai.api.StabilityAiImageOptions;
  36 +import org.springframework.ai.zhipuai.ZhiPuAiImageOptions;
36 import org.springframework.scheduling.annotation.Async; 37 import org.springframework.scheduling.annotation.Async;
37 import org.springframework.stereotype.Service; 38 import org.springframework.stereotype.Service;
38 import org.springframework.transaction.annotation.Transactional; 39 import org.springframework.transaction.annotation.Transactional;
@@ -104,7 +105,9 @@ public class AiImageServiceImpl implements AiImageService { @@ -104,7 +105,9 @@ public class AiImageServiceImpl implements AiImageService {
104 ImageResponse response = imageModel.call(new ImagePrompt(req.getPrompt(), request)); 105 ImageResponse response = imageModel.call(new ImagePrompt(req.getPrompt(), request));
105 106
106 // 2. 上传到文件服务 107 // 2. 上传到文件服务
107 - byte[] fileContent = Base64.decode(response.getResult().getOutput().getB64Json()); 108 + String b64Json = response.getResult().getOutput().getB64Json();
  109 + byte[] fileContent = StrUtil.isNotEmpty(b64Json) ? Base64.decode(b64Json)
  110 + : HttpUtil.downloadBytes(response.getResult().getOutput().getUrl());
108 String filePath = fileApi.createFile(fileContent); 111 String filePath = fileApi.createFile(fileContent);
109 112
110 // 3. 更新数据库 113 // 3. 更新数据库
@@ -148,6 +151,10 @@ public class AiImageServiceImpl implements AiImageService { @@ -148,6 +151,10 @@ public class AiImageServiceImpl implements AiImageService {
148 .withModel(draw.getModel()).withN(1) 151 .withModel(draw.getModel()).withN(1)
149 .withHeight(draw.getHeight()).withWidth(draw.getWidth()) 152 .withHeight(draw.getHeight()).withWidth(draw.getWidth())
150 .build(); 153 .build();
  154 + } else if (ObjUtil.equal(draw.getPlatform(), AiPlatformEnum.ZHI_PU.getPlatform())) {
  155 + return ZhiPuAiImageOptions.builder()
  156 + .withModel(draw.getModel())
  157 + .build();
151 } 158 }
152 throw new IllegalArgumentException("不支持的 AI 平台:" + draw.getPlatform()); 159 throw new IllegalArgumentException("不支持的 AI 平台:" + draw.getPlatform());
153 } 160 }
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiModelFactoryImpl.java
@@ -30,6 +30,7 @@ import org.springframework.ai.autoconfigure.qianfan.QianFanImageProperties; @@ -30,6 +30,7 @@ import org.springframework.ai.autoconfigure.qianfan.QianFanImageProperties;
30 import org.springframework.ai.autoconfigure.zhipuai.ZhiPuAiAutoConfiguration; 30 import org.springframework.ai.autoconfigure.zhipuai.ZhiPuAiAutoConfiguration;
31 import org.springframework.ai.autoconfigure.zhipuai.ZhiPuAiChatProperties; 31 import org.springframework.ai.autoconfigure.zhipuai.ZhiPuAiChatProperties;
32 import org.springframework.ai.autoconfigure.zhipuai.ZhiPuAiConnectionProperties; 32 import org.springframework.ai.autoconfigure.zhipuai.ZhiPuAiConnectionProperties;
  33 +import org.springframework.ai.autoconfigure.zhipuai.ZhiPuAiImageProperties;
33 import org.springframework.ai.chat.model.ChatModel; 34 import org.springframework.ai.chat.model.ChatModel;
34 import org.springframework.ai.image.ImageModel; 35 import org.springframework.ai.image.ImageModel;
35 import org.springframework.ai.model.function.FunctionCallbackContext; 36 import org.springframework.ai.model.function.FunctionCallbackContext;
@@ -47,7 +48,9 @@ import org.springframework.ai.qianfan.api.QianFanImageApi; @@ -47,7 +48,9 @@ import org.springframework.ai.qianfan.api.QianFanImageApi;
47 import org.springframework.ai.stabilityai.StabilityAiImageModel; 48 import org.springframework.ai.stabilityai.StabilityAiImageModel;
48 import org.springframework.ai.stabilityai.api.StabilityAiApi; 49 import org.springframework.ai.stabilityai.api.StabilityAiApi;
49 import org.springframework.ai.zhipuai.ZhiPuAiChatModel; 50 import org.springframework.ai.zhipuai.ZhiPuAiChatModel;
  51 +import org.springframework.ai.zhipuai.ZhiPuAiImageModel;
50 import org.springframework.ai.zhipuai.api.ZhiPuAiApi; 52 import org.springframework.ai.zhipuai.api.ZhiPuAiApi;
  53 +import org.springframework.ai.zhipuai.api.ZhiPuAiImageApi;
51 import org.springframework.retry.support.RetryTemplate; 54 import org.springframework.retry.support.RetryTemplate;
52 import org.springframework.web.client.ResponseErrorHandler; 55 import org.springframework.web.client.ResponseErrorHandler;
53 import org.springframework.web.client.RestClient; 56 import org.springframework.web.client.RestClient;
@@ -118,6 +121,8 @@ public class AiModelFactoryImpl implements AiModelFactory { @@ -118,6 +121,8 @@ public class AiModelFactoryImpl implements AiModelFactory {
118 return SpringUtil.getBean(TongYiImagesModel.class); 121 return SpringUtil.getBean(TongYiImagesModel.class);
119 case YI_YAN: 122 case YI_YAN:
120 return SpringUtil.getBean(QianFanImageModel.class); 123 return SpringUtil.getBean(QianFanImageModel.class);
  124 + case ZHI_PU:
  125 + return SpringUtil.getBean(ZhiPuAiImageModel.class);
121 case OPENAI: 126 case OPENAI:
122 return SpringUtil.getBean(OpenAiImageModel.class); 127 return SpringUtil.getBean(OpenAiImageModel.class);
123 case STABLE_DIFFUSION: 128 case STABLE_DIFFUSION:
@@ -135,6 +140,8 @@ public class AiModelFactoryImpl implements AiModelFactory { @@ -135,6 +140,8 @@ public class AiModelFactoryImpl implements AiModelFactory {
135 return buildTongYiImagesModel(apiKey); 140 return buildTongYiImagesModel(apiKey);
136 case YI_YAN: 141 case YI_YAN:
137 return buildQianFanImageModel(apiKey); 142 return buildQianFanImageModel(apiKey);
  143 + case ZHI_PU:
  144 + return buildZhiPuAiImageModel(apiKey, url);
138 case OPENAI: 145 case OPENAI:
139 return buildOpenAiImageModel(apiKey, url); 146 return buildOpenAiImageModel(apiKey, url);
140 case STABLE_DIFFUSION: 147 case STABLE_DIFFUSION:
@@ -222,7 +229,8 @@ public class AiModelFactoryImpl implements AiModelFactory { @@ -222,7 +229,8 @@ public class AiModelFactoryImpl implements AiModelFactory {
222 } 229 }
223 230
224 /** 231 /**
225 - * 可参考 {@link ZhiPuAiAutoConfiguration#zhiPuAiChatModel(ZhiPuAiConnectionProperties, ZhiPuAiChatProperties, RestClient.Builder, List, FunctionCallbackContext, RetryTemplate, ResponseErrorHandler)} 232 + * 可参考 {@link ZhiPuAiAutoConfiguration#zhiPuAiChatModel(
  233 + * ZhiPuAiConnectionProperties, ZhiPuAiChatProperties, RestClient.Builder, List, FunctionCallbackContext, RetryTemplate, ResponseErrorHandler)}
226 */ 234 */
227 private ZhiPuAiChatModel buildZhiPuChatModel(String apiKey, String url) { 235 private ZhiPuAiChatModel buildZhiPuChatModel(String apiKey, String url) {
228 url = StrUtil.blankToDefault(url, ZhiPuAiConnectionProperties.DEFAULT_BASE_URL); 236 url = StrUtil.blankToDefault(url, ZhiPuAiConnectionProperties.DEFAULT_BASE_URL);
@@ -231,6 +239,16 @@ public class AiModelFactoryImpl implements AiModelFactory { @@ -231,6 +239,16 @@ public class AiModelFactoryImpl implements AiModelFactory {
231 } 239 }
232 240
233 /** 241 /**
  242 + * 可参考 {@link ZhiPuAiAutoConfiguration#zhiPuAiImageModel(
  243 + * ZhiPuAiConnectionProperties, ZhiPuAiImageProperties, RestClient.Builder, RetryTemplate, ResponseErrorHandler)}
  244 + */
  245 + private ZhiPuAiImageModel buildZhiPuAiImageModel(String apiKey, String url) {
  246 + url = StrUtil.blankToDefault(url, ZhiPuAiConnectionProperties.DEFAULT_BASE_URL);
  247 + ZhiPuAiImageApi zhiPuAiApi = new ZhiPuAiImageApi(url, apiKey, RestClient.builder());
  248 + return new ZhiPuAiImageModel(zhiPuAiApi);
  249 + }
  250 +
  251 + /**
234 * 可参考 {@link YudaoAiAutoConfiguration#xingHuoChatClient(YudaoAiProperties)} 252 * 可参考 {@link YudaoAiAutoConfiguration#xingHuoChatClient(YudaoAiProperties)}
235 */ 253 */
236 private static XingHuoChatModel buildXingHuoChatModel(String key) { 254 private static XingHuoChatModel buildXingHuoChatModel(String key) {
yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/image/ZhiPuAiImageModelTests.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.ai.image;
  2 +
  3 +import org.junit.jupiter.api.Disabled;
  4 +import org.junit.jupiter.api.Test;
  5 +import org.springframework.ai.image.ImagePrompt;
  6 +import org.springframework.ai.image.ImageResponse;
  7 +import org.springframework.ai.zhipuai.ZhiPuAiImageModel;
  8 +import org.springframework.ai.zhipuai.ZhiPuAiImageOptions;
  9 +import org.springframework.ai.zhipuai.api.ZhiPuAiImageApi;
  10 +
  11 +/**
  12 + * {@link ZhiPuAiImageModel} 集成测试
  13 + */
  14 +public class ZhiPuAiImageModelTests {
  15 +
  16 + private final ZhiPuAiImageApi imageApi = new ZhiPuAiImageApi(
  17 + "78d3228c1d9e5e342a3e1ab349e2dd7b.VXLoq5vrwK2ofboy");
  18 + private final ZhiPuAiImageModel imageModel = new ZhiPuAiImageModel(imageApi);
  19 +
  20 + @Test
  21 + @Disabled
  22 + public void testCall() {
  23 + // 准备参数
  24 + ZhiPuAiImageOptions imageOptions = ZhiPuAiImageOptions.builder()
  25 + .withModel(ZhiPuAiImageApi.ImageModel.CogView_3.getValue())
  26 + .build();
  27 + ImagePrompt prompt = new ImagePrompt("万里长城", imageOptions);
  28 +
  29 + // 方法调用
  30 + ImageResponse response = imageModel.call(prompt);
  31 + // 打印结果
  32 + System.out.println(response);
  33 + }
  34 +
  35 +}