Commit d865cc293b106501642985c193f81696a61f90cf
1 parent
db7315b8
【增加】chatglm 实现 spring ai 标准
Showing
5 changed files
with
261 additions
and
0 deletions
yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml
| @@ -60,6 +60,13 @@ | @@ -60,6 +60,13 @@ | ||
| 60 | <version>2.14.0</version> | 60 | <version>2.14.0</version> |
| 61 | </dependency> | 61 | </dependency> |
| 62 | 62 | ||
| 63 | + <!-- bigmodel --> | ||
| 64 | + <dependency> | ||
| 65 | + <groupId>cn.bigmodel.openapi</groupId> | ||
| 66 | + <artifactId>oapi-java-sdk</artifactId> | ||
| 67 | + <version>release-V4-2.0.2</version> | ||
| 68 | + </dependency> | ||
| 69 | + | ||
| 63 | <!-- Test 测试相关 --> | 70 | <!-- Test 测试相关 --> |
| 64 | <dependency> | 71 | <dependency> |
| 65 | <groupId>org.springframework.boot</groupId> | 72 | <groupId>org.springframework.boot</groupId> |
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/chatglm/ChatGlmImageModel.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.ai.core.model.chatglm; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.ai.core.model.chatglm.api.ChatGlmResponseMetadata; | ||
| 4 | +import com.zhipu.oapi.ClientV4; | ||
| 5 | +import com.zhipu.oapi.service.v4.image.CreateImageRequest; | ||
| 6 | +import com.zhipu.oapi.service.v4.image.ImageApiResponse; | ||
| 7 | +import org.springframework.ai.image.*; | ||
| 8 | + | ||
| 9 | +import java.io.ByteArrayOutputStream; | ||
| 10 | +import java.net.URL; | ||
| 11 | +import java.util.Base64; | ||
| 12 | +import java.util.stream.Collectors; | ||
| 13 | + | ||
| 14 | +public class ChatGlmImageModel implements ImageModel { | ||
| 15 | + | ||
| 16 | + private ClientV4 client; | ||
| 17 | + | ||
| 18 | + public ChatGlmImageModel(String apiSecretKey) { | ||
| 19 | + client = new ClientV4.Builder(apiSecretKey).build(); | ||
| 20 | + } | ||
| 21 | + | ||
| 22 | + @Override | ||
| 23 | + public ImageResponse call(ImagePrompt request) { | ||
| 24 | + CreateImageRequest imageRequest = CreateImageRequest.builder() | ||
| 25 | + .model(request.getOptions().getModel()) | ||
| 26 | + .prompt(request.getInstructions().get(0).getText()) | ||
| 27 | + .build(); | ||
| 28 | + return convert(client.createImage(imageRequest)); | ||
| 29 | + } | ||
| 30 | + | ||
| 31 | + private ImageResponse convert(ImageApiResponse result) { | ||
| 32 | + return new ImageResponse( | ||
| 33 | + result.getData().getData().stream().map(item -> { | ||
| 34 | + try { | ||
| 35 | + String url = item.getUrl(); | ||
| 36 | + String base64Image = convertImageToBase64(url); | ||
| 37 | + Image image = new Image(url, base64Image); | ||
| 38 | + return new ImageGeneration(image); | ||
| 39 | + } catch (Exception e) { | ||
| 40 | + throw new RuntimeException(e); | ||
| 41 | + } | ||
| 42 | + }).collect(Collectors.toList()), | ||
| 43 | + new ChatGlmResponseMetadata(result) | ||
| 44 | + ); | ||
| 45 | + } | ||
| 46 | + | ||
| 47 | + | ||
| 48 | + /** | ||
| 49 | + * Convert image to base64. | ||
| 50 | + * @param imageUrl the image url. | ||
| 51 | + * @return the base64 image. | ||
| 52 | + * @throws Exception the exception. | ||
| 53 | + */ | ||
| 54 | + public String convertImageToBase64(String imageUrl) throws Exception { | ||
| 55 | + | ||
| 56 | + var url = new URL(imageUrl); | ||
| 57 | + var inputStream = url.openStream(); | ||
| 58 | + var outputStream = new ByteArrayOutputStream(); | ||
| 59 | + var buffer = new byte[4096]; | ||
| 60 | + int bytesRead; | ||
| 61 | + | ||
| 62 | + while ((bytesRead = inputStream.read(buffer)) != -1) { | ||
| 63 | + outputStream.write(buffer, 0, bytesRead); | ||
| 64 | + } | ||
| 65 | + | ||
| 66 | + var imageBytes = outputStream.toByteArray(); | ||
| 67 | + | ||
| 68 | + String base64Image = Base64.getEncoder().encodeToString(imageBytes); | ||
| 69 | + | ||
| 70 | + inputStream.close(); | ||
| 71 | + outputStream.close(); | ||
| 72 | + | ||
| 73 | + return base64Image; | ||
| 74 | + } | ||
| 75 | +} |
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/chatglm/ChatGlmImageOptions.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.ai.core.model.chatglm; | ||
| 2 | + | ||
| 3 | +import com.fasterxml.jackson.annotation.JsonProperty; | ||
| 4 | +import lombok.Setter; | ||
| 5 | +import org.springframework.ai.image.ImageOptions; | ||
| 6 | + | ||
| 7 | +/** | ||
| 8 | + * chatglm | ||
| 9 | + * api地址:https://open.bigmodel.cn/dev/api#cogview | ||
| 10 | + */ | ||
| 11 | +@Setter | ||
| 12 | +public class ChatGlmImageOptions implements ImageOptions { | ||
| 13 | + | ||
| 14 | + @JsonProperty("n") | ||
| 15 | + private Integer n; | ||
| 16 | + | ||
| 17 | + @JsonProperty("model") | ||
| 18 | + private String model = "cogview-3"; | ||
| 19 | + | ||
| 20 | + @JsonProperty("size_width") | ||
| 21 | + private Integer width; | ||
| 22 | + | ||
| 23 | + @JsonProperty("size_height") | ||
| 24 | + private Integer height; | ||
| 25 | + | ||
| 26 | + @JsonProperty("size") | ||
| 27 | + private String size; | ||
| 28 | + | ||
| 29 | + @JsonProperty("style") | ||
| 30 | + private String style; | ||
| 31 | + | ||
| 32 | + @JsonProperty("user_id") | ||
| 33 | + private String user; | ||
| 34 | + | ||
| 35 | + @JsonProperty("responseFormat") | ||
| 36 | + private String responseFormat; | ||
| 37 | + | ||
| 38 | + // ==== build | ||
| 39 | + | ||
| 40 | + | ||
| 41 | + public static ChatGlmImageOptions.Builder builder() { | ||
| 42 | + return new ChatGlmImageOptions.Builder(); | ||
| 43 | + } | ||
| 44 | + | ||
| 45 | + public static class Builder { | ||
| 46 | + | ||
| 47 | + private final ChatGlmImageOptions options; | ||
| 48 | + | ||
| 49 | + private Builder() { | ||
| 50 | + this.options = new ChatGlmImageOptions(); | ||
| 51 | + } | ||
| 52 | + | ||
| 53 | + public ChatGlmImageOptions.Builder withN(Integer n) { | ||
| 54 | + options.setN(n); | ||
| 55 | + return this; | ||
| 56 | + } | ||
| 57 | + | ||
| 58 | + public ChatGlmImageOptions.Builder withModel(String model) { | ||
| 59 | + options.setModel(model); | ||
| 60 | + return this; | ||
| 61 | + } | ||
| 62 | + | ||
| 63 | + public ChatGlmImageOptions.Builder withWidth(Integer width) { | ||
| 64 | + options.setWidth(width); | ||
| 65 | + return this; | ||
| 66 | + } | ||
| 67 | + | ||
| 68 | + public ChatGlmImageOptions.Builder withHeight(Integer height) { | ||
| 69 | + options.setHeight(height); | ||
| 70 | + return this; | ||
| 71 | + } | ||
| 72 | + | ||
| 73 | + public ChatGlmImageOptions.Builder withStyle(String style) { | ||
| 74 | + options.setStyle(style); | ||
| 75 | + return this; | ||
| 76 | + } | ||
| 77 | + | ||
| 78 | + public ChatGlmImageOptions.Builder withUser(String user) { | ||
| 79 | + options.setUser(user); | ||
| 80 | + return this; | ||
| 81 | + } | ||
| 82 | + | ||
| 83 | + public ChatGlmImageOptions build() { | ||
| 84 | + return options; | ||
| 85 | + } | ||
| 86 | + | ||
| 87 | + } | ||
| 88 | + | ||
| 89 | + // ==== get | ||
| 90 | + | ||
| 91 | + @Override | ||
| 92 | + public Integer getN() { | ||
| 93 | + return n; | ||
| 94 | + } | ||
| 95 | + | ||
| 96 | + @Override | ||
| 97 | + public String getModel() { | ||
| 98 | + return model; | ||
| 99 | + } | ||
| 100 | + | ||
| 101 | + @Override | ||
| 102 | + public Integer getWidth() { | ||
| 103 | + return width; | ||
| 104 | + } | ||
| 105 | + | ||
| 106 | + @Override | ||
| 107 | + public Integer getHeight() { | ||
| 108 | + return height; | ||
| 109 | + } | ||
| 110 | + | ||
| 111 | + @Override | ||
| 112 | + public String getResponseFormat() { | ||
| 113 | + return responseFormat; | ||
| 114 | + } | ||
| 115 | +} |
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/chatglm/api/ChatGlmResponseMetadata.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.ai.core.model.chatglm.api; | ||
| 2 | + | ||
| 3 | +import com.zhipu.oapi.service.v4.image.ImageApiResponse; | ||
| 4 | +import org.springframework.ai.image.ImageResponseMetadata; | ||
| 5 | + | ||
| 6 | +import java.util.HashMap; | ||
| 7 | + | ||
| 8 | +public class ChatGlmResponseMetadata extends HashMap<String, Object> implements ImageResponseMetadata { | ||
| 9 | + | ||
| 10 | + private Long created; | ||
| 11 | + | ||
| 12 | + public ChatGlmResponseMetadata(ImageApiResponse result) { | ||
| 13 | + created = result.getData().getCreated(); | ||
| 14 | + } | ||
| 15 | + | ||
| 16 | + @Override | ||
| 17 | + public Long getCreated() { | ||
| 18 | + return created; | ||
| 19 | + } | ||
| 20 | + | ||
| 21 | + public void setCreated(Long created) { | ||
| 22 | + this.created = created; | ||
| 23 | + } | ||
| 24 | +} |
yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/image/ChatGlmImageModelTests.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.ai.image; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.ai.core.model.chatglm.ChatGlmImageModel; | ||
| 4 | +import cn.iocoder.yudao.framework.ai.core.model.chatglm.ChatGlmImageOptions; | ||
| 5 | +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; | ||
| 6 | +import com.alibaba.fastjson.JSON; | ||
| 7 | +import com.zhipu.oapi.ClientV4; | ||
| 8 | +import com.zhipu.oapi.core.httpclient.ApacheHttpClientTransport; | ||
| 9 | +import com.zhipu.oapi.service.v4.image.CreateImageRequest; | ||
| 10 | +import com.zhipu.oapi.service.v4.image.ImageApiResponse; | ||
| 11 | +import org.junit.jupiter.api.Test; | ||
| 12 | +import org.springframework.ai.image.ImageOptionsBuilder; | ||
| 13 | +import org.springframework.ai.image.ImagePrompt; | ||
| 14 | +import org.springframework.ai.image.ImageResponse; | ||
| 15 | +import org.springframework.ai.qianfan.QianFanImageModel; | ||
| 16 | +import org.springframework.ai.qianfan.QianFanImageOptions; | ||
| 17 | +import org.springframework.ai.qianfan.api.QianFanImageApi; | ||
| 18 | + | ||
| 19 | +/** | ||
| 20 | + * 百度千帆 image | ||
| 21 | + */ | ||
| 22 | +public class ChatGlmImageModelTests { | ||
| 23 | + | ||
| 24 | + @Test | ||
| 25 | + public void callTest() { | ||
| 26 | + ChatGlmImageModel model = new ChatGlmImageModel("78d3228c1d9e5e342a3e1ab349e2dd7b.VXLoq5vrwK2ofboy"); | ||
| 27 | + ImageResponse call = model.call(new ImagePrompt("万里长城", ChatGlmImageOptions.builder().build())); | ||
| 28 | + System.err.println(call.getResult().getOutput().getUrl()); | ||
| 29 | + } | ||
| 30 | + | ||
| 31 | + @Test | ||
| 32 | + public void createImageTest() { | ||
| 33 | + ClientV4 client = new ClientV4.Builder("78d3228c1d9e5e342a3e1ab349e2dd7b.VXLoq5vrwK2ofboy").build(); | ||
| 34 | + CreateImageRequest createImageRequest = new CreateImageRequest(); | ||
| 35 | + createImageRequest.setModel("cogview-3"); | ||
| 36 | + createImageRequest.setPrompt("长城!"); | ||
| 37 | + ImageApiResponse image = client.createImage(createImageRequest); | ||
| 38 | + System.err.println(JSON.toJSONString(image)); | ||
| 39 | + } | ||
| 40 | +} |