Commit 7dfa7a1573f116419d7aaad360a098b2706533fb

Authored by YunaiV
1 parent 6225e18f

【优化】AI:依赖从 io.springboot.ai 调整为 org.springframework.ai

Showing 16 changed files with 123 additions and 89 deletions
yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/model/AiModelEnum.java
... ... @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.ai.enums.model;
3 3 import lombok.AllArgsConstructor;
4 4 import lombok.Getter;
5 5  
  6 +// TODO @芋艿:可以考虑清理掉
6 7 /**
7 8 * ai 模型
8 9 *
... ...
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImpl.java
... ... @@ -26,9 +26,9 @@ import cn.iocoder.yudao.module.ai.service.model.AiChatModelService;
26 26 import cn.iocoder.yudao.module.ai.service.model.AiChatRoleService;
27 27 import jakarta.annotation.Resource;
28 28 import lombok.extern.slf4j.Slf4j;
29   -import org.springframework.ai.chat.ChatResponse;
30   -import org.springframework.ai.chat.StreamingChatClient;
31 29 import org.springframework.ai.chat.messages.*;
  30 +import org.springframework.ai.chat.model.ChatResponse;
  31 +import org.springframework.ai.chat.model.StreamingChatModel;
32 32 import org.springframework.ai.chat.prompt.ChatOptions;
33 33 import org.springframework.ai.chat.prompt.Prompt;
34 34 import org.springframework.ai.ollama.api.OllamaOptions;
... ... @@ -44,8 +44,8 @@ import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionU
44 44 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.error;
45 45 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
46 46 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
47   -import static cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants.CHAT_MESSAGE_NOT_EXIST;
48 47 import static cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants.CHAT_CONVERSATION_NOT_EXISTS;
  48 +import static cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants.CHAT_MESSAGE_NOT_EXIST;
49 49  
50 50 /**
51 51 * AI 聊天消息 Service 实现类
... ... @@ -117,7 +117,7 @@ public class AiChatMessageServiceImpl implements AiChatMessageService {
117 117 List<AiChatMessageDO> historyMessages = chatMessageMapper.selectListByConversationId(conversation.getId());
118 118 // 1.2 校验模型
119 119 AiChatModelDO model = chatModalService.validateChatModel(conversation.getModelId());
120   - StreamingChatClient chatClient = apiKeyService.getStreamingChatClient(model.getKeyId());
  120 + StreamingChatModel chatClient = apiKeyService.getStreamingChatClient(model.getKeyId());
121 121 // 1.3 获取用户头像、角色头像
122 122 AiChatRoleDO role = conversation.getRoleId() != null ? chatRoleService.getChatRole(conversation.getRoleId()) : null;
123 123  
... ... @@ -164,7 +164,14 @@ public class AiChatMessageServiceImpl implements AiChatMessageService {
164 164 }
165 165 // 1.2 history message 历史消息
166 166 List<AiChatMessageDO> contextMessages = filterContextMessages(messages, conversation, sendReqVO);
167   - contextMessages.forEach(message -> chatMessages.add(new ChatMessage(message.getType().toUpperCase(), message.getContent())));
  167 + contextMessages.forEach(message -> {
  168 + // TODO @芋艿:看看有没优化空间
  169 + if (MessageType.USER.getValue().equals(message.getType())) {
  170 + chatMessages.add(new UserMessage(message.getContent()));
  171 + } else {
  172 + chatMessages.add(new AssistantMessage(message.getContent()));
  173 + }
  174 + });
168 175 // 1.3 user message 新发送消息
169 176 chatMessages.add(new UserMessage(sendReqVO.getContent()));
170 177  
... ...
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java
... ... @@ -25,7 +25,7 @@ import cn.iocoder.yudao.module.ai.service.model.AiApiKeyService;
25 25 import cn.iocoder.yudao.module.infra.api.file.FileApi;
26 26 import jakarta.annotation.Resource;
27 27 import lombok.extern.slf4j.Slf4j;
28   -import org.springframework.ai.image.ImageClient;
  28 +import org.springframework.ai.image.ImageModel;
29 29 import org.springframework.ai.image.ImageOptions;
30 30 import org.springframework.ai.image.ImagePrompt;
31 31 import org.springframework.ai.image.ImageResponse;
... ... @@ -97,7 +97,7 @@ public class AiImageServiceImpl implements AiImageService {
97 97 // 1.1 构建请求
98 98 ImageOptions request = buildImageOptions(req);
99 99 // 1.2 执行请求
100   - ImageClient imageClient = apiKeyService.getImageClient(AiPlatformEnum.validatePlatform(req.getPlatform()));
  100 + ImageModel imageClient = apiKeyService.getImageClient(AiPlatformEnum.validatePlatform(req.getPlatform()));
101 101 ImageResponse response = imageClient.call(new ImagePrompt(req.getPrompt(), request));
102 102  
103 103 // 2. 上传到文件服务
... ...
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyService.java
... ... @@ -8,8 +8,8 @@ import cn.iocoder.yudao.module.ai.controller.admin.model.vo.apikey.AiApiKeyPageR
8 8 import cn.iocoder.yudao.module.ai.controller.admin.model.vo.apikey.AiApiKeySaveReqVO;
9 9 import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiApiKeyDO;
10 10 import jakarta.validation.Valid;
11   -import org.springframework.ai.chat.StreamingChatClient;
12   -import org.springframework.ai.image.ImageClient;
  11 +import org.springframework.ai.chat.model.StreamingChatModel;
  12 +import org.springframework.ai.image.ImageModel;
13 13  
14 14 import java.util.List;
15 15  
... ... @@ -81,7 +81,7 @@ public interface AiApiKeyService {
81 81 * @param id 编号
82 82 * @return StreamingChatClient 对象
83 83 */
84   - StreamingChatClient getStreamingChatClient(Long id);
  84 + StreamingChatModel getStreamingChatClient(Long id);
85 85  
86 86 /**
87 87 * 获得 ImageClient 对象
... ... @@ -91,7 +91,7 @@ public interface AiApiKeyService {
91 91 * @param platform 平台
92 92 * @return ImageClient 对象
93 93 */
94   - ImageClient getImageClient(AiPlatformEnum platform);
  94 + ImageModel getImageClient(AiPlatformEnum platform);
95 95  
96 96 /**
97 97 * 获得 MidjourneyApi 对象
... ...
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyServiceImpl.java
... ... @@ -12,8 +12,8 @@ import cn.iocoder.yudao.module.ai.controller.admin.model.vo.apikey.AiApiKeySaveR
12 12 import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiApiKeyDO;
13 13 import cn.iocoder.yudao.module.ai.dal.mysql.model.AiApiKeyMapper;
14 14 import jakarta.annotation.Resource;
15   -import org.springframework.ai.chat.StreamingChatClient;
16   -import org.springframework.ai.image.ImageClient;
  15 +import org.springframework.ai.chat.model.StreamingChatModel;
  16 +import org.springframework.ai.image.ImageModel;
17 17 import org.springframework.stereotype.Service;
18 18 import org.springframework.validation.annotation.Validated;
19 19  
... ... @@ -98,14 +98,14 @@ public class AiApiKeyServiceImpl implements AiApiKeyService {
98 98 // ========== 与 spring-ai 集成 ==========
99 99  
100 100 @Override
101   - public StreamingChatClient getStreamingChatClient(Long id) {
  101 + public StreamingChatModel getStreamingChatClient(Long id) {
102 102 AiApiKeyDO apiKey = validateApiKey(id);
103 103 AiPlatformEnum platform = AiPlatformEnum.validatePlatform(apiKey.getPlatform());
104 104 return clientFactory.getOrCreateStreamingChatClient(platform, apiKey.getApiKey(), apiKey.getUrl());
105 105 }
106 106  
107 107 @Override
108   - public ImageClient getImageClient(AiPlatformEnum platform) {
  108 + public ImageModel getImageClient(AiPlatformEnum platform) {
109 109 AiApiKeyDO apiKey = apiKeyMapper.selectFirstByPlatformAndStatus(platform.getName(), CommonStatusEnum.ENABLE.getStatus());
110 110 if (apiKey == null) {
111 111 return null;
... ...
yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml
... ... @@ -2,33 +2,38 @@
2 2 <project xmlns="http://maven.apache.org/POM/4.0.0"
3 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5   - <modelVersion>4.0.0</modelVersion>
6 5 <parent>
7 6 <groupId>cn.iocoder.boot</groupId>
8 7 <artifactId>yudao-module-ai</artifactId>
9 8 <version>${revision}</version>
10 9 </parent>
  10 + <modelVersion>4.0.0</modelVersion>
11 11  
12 12 <artifactId>yudao-spring-boot-starter-ai</artifactId>
  13 + <name>${project.artifactId}</name>
  14 + <description>AI 大模型拓展,接入国内外大模型</description>
  15 + <properties>
  16 + <spring-ai.version>1.0.0-M1</spring-ai.version>
  17 + </properties>
13 18  
14 19 <dependencies>
15 20 <dependency>
16   - <groupId>io.springboot.ai</groupId>
  21 + <groupId>org.springframework.ai</groupId>
17 22 <artifactId>spring-ai-ollama-spring-boot-starter</artifactId>
18   - <version>1.0.3</version>
  23 + <version>${spring-ai.version}</version>
19 24 </dependency>
20 25 <dependency>
21   - <groupId>io.springboot.ai</groupId>
  26 + <groupId>org.springframework.ai</groupId>
22 27 <artifactId>spring-ai-openai-spring-boot-starter</artifactId>
23   - <version>1.0.3</version>
  28 + <version>${spring-ai.version}</version>
24 29 </dependency>
25 30 <dependency>
26   - <groupId>io.springboot.ai</groupId>
27   - <artifactId>spring-ai-stability-ai</artifactId>
28   - <version>1.0.3</version>
  31 + <groupId>org.springframework.ai</groupId>
  32 + <artifactId>spring-ai-stability-ai-spring-boot-starter</artifactId>
  33 + <version>${spring-ai.version}</version>
29 34 </dependency>
30 35 <!-- <dependency>-->
31   -<!-- <groupId>io.springboot.ai</groupId>-->
  36 +<!-- <groupId>org.springframework.ai</groupId>-->
32 37 <!-- <artifactId>spring-ai-vertex-ai-gemini</artifactId>-->
33 38 <!-- <version>1.0.3</version>-->
34 39 <!-- </dependency>-->
... ...
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactory.java
... ... @@ -3,8 +3,8 @@ package cn.iocoder.yudao.framework.ai.core.factory;
3 3 import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum;
4 4 import cn.iocoder.yudao.framework.ai.core.model.midjourney.api.MidjourneyApi;
5 5 import cn.iocoder.yudao.framework.ai.core.model.suno.api.SunoApi;
6   -import org.springframework.ai.chat.StreamingChatClient;
7   -import org.springframework.ai.image.ImageClient;
  6 +import org.springframework.ai.chat.model.StreamingChatModel;
  7 +import org.springframework.ai.image.ImageModel;
8 8  
9 9 /**
10 10 * AI 客户端工厂的接口类
... ... @@ -23,7 +23,7 @@ public interface AiClientFactory {
23 23 * @param url API URL
24 24 * @return StreamingChatClient 对象
25 25 */
26   - StreamingChatClient getOrCreateStreamingChatClient(AiPlatformEnum platform, String apiKey, String url);
  26 + StreamingChatModel getOrCreateStreamingChatClient(AiPlatformEnum platform, String apiKey, String url);
27 27  
28 28 /**
29 29 * 基于默认配置,获得 StreamingChatClient 对象
... ... @@ -33,7 +33,7 @@ public interface AiClientFactory {
33 33 * @param platform 平台
34 34 * @return StreamingChatClient 对象
35 35 */
36   - StreamingChatClient getDefaultStreamingChatClient(AiPlatformEnum platform);
  36 + StreamingChatModel getDefaultStreamingChatClient(AiPlatformEnum platform);
37 37  
38 38 /**
39 39 * 基于默认配置,获得 ImageClient 对象
... ... @@ -43,7 +43,7 @@ public interface AiClientFactory {
43 43 * @param platform 平台
44 44 * @return ImageClient 对象
45 45 */
46   - ImageClient getDefaultImageClient(AiPlatformEnum platform);
  46 + ImageModel getDefaultImageClient(AiPlatformEnum platform);
47 47  
48 48 /**
49 49 * 基于指定配置,获得 ImageClient 对象
... ... @@ -55,7 +55,7 @@ public interface AiClientFactory {
55 55 * @param url API URL
56 56 * @return ImageClient 对象
57 57 */
58   - ImageClient getOrCreateImageClient(AiPlatformEnum platform, String apiKey, String url);
  58 + ImageModel getOrCreateImageClient(AiPlatformEnum platform, String apiKey, String url);
59 59  
60 60 /**
61 61 * 基于指定配置,获得 MidjourneyApi 对象
... ...
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactoryImpl.java
... ... @@ -20,16 +20,16 @@ import cn.iocoder.yudao.framework.ai.core.model.yiyan.YiYanChatClient;
20 20 import cn.iocoder.yudao.framework.ai.core.model.yiyan.api.YiYanApi;
21 21 import org.springframework.ai.autoconfigure.ollama.OllamaAutoConfiguration;
22 22 import org.springframework.ai.autoconfigure.openai.OpenAiAutoConfiguration;
23   -import org.springframework.ai.chat.StreamingChatClient;
24   -import org.springframework.ai.image.ImageClient;
25   -import org.springframework.ai.ollama.OllamaChatClient;
  23 +import org.springframework.ai.chat.model.StreamingChatModel;
  24 +import org.springframework.ai.image.ImageModel;
  25 +import org.springframework.ai.ollama.OllamaChatModel;
26 26 import org.springframework.ai.ollama.api.OllamaApi;
27   -import org.springframework.ai.openai.OpenAiChatClient;
28   -import org.springframework.ai.openai.OpenAiImageClient;
  27 +import org.springframework.ai.openai.OpenAiChatModel;
  28 +import org.springframework.ai.openai.OpenAiImageModel;
29 29 import org.springframework.ai.openai.api.ApiUtils;
30 30 import org.springframework.ai.openai.api.OpenAiApi;
31 31 import org.springframework.ai.openai.api.OpenAiImageApi;
32   -import org.springframework.ai.stabilityai.StabilityAiImageClient;
  32 +import org.springframework.ai.stabilityai.StabilityAiImageModel;
33 33 import org.springframework.ai.stabilityai.api.StabilityAiApi;
34 34 import org.springframework.web.client.RestClient;
35 35  
... ... @@ -43,9 +43,9 @@ import java.util.List;
43 43 public class AiClientFactoryImpl implements AiClientFactory {
44 44  
45 45 @Override
46   - public StreamingChatClient getOrCreateStreamingChatClient(AiPlatformEnum platform, String apiKey, String url) {
47   - String cacheKey = buildClientCacheKey(StreamingChatClient.class, platform, apiKey, url);
48   - return Singleton.get(cacheKey, (Func0<StreamingChatClient>) () -> {
  46 + public StreamingChatModel getOrCreateStreamingChatClient(AiPlatformEnum platform, String apiKey, String url) {
  47 + String cacheKey = buildClientCacheKey(StreamingChatModel.class, platform, apiKey, url);
  48 + return Singleton.get(cacheKey, (Func0<StreamingChatModel>) () -> {
49 49 //noinspection EnhancedSwitchMigration
50 50 switch (platform) {
51 51 case OPENAI:
... ... @@ -67,13 +67,13 @@ public class AiClientFactoryImpl implements AiClientFactory {
67 67 }
68 68  
69 69 @Override
70   - public StreamingChatClient getDefaultStreamingChatClient(AiPlatformEnum platform) {
  70 + public StreamingChatModel getDefaultStreamingChatClient(AiPlatformEnum platform) {
71 71 //noinspection EnhancedSwitchMigration
72 72 switch (platform) {
73 73 case OPENAI:
74   - return SpringUtil.getBean(OpenAiChatClient.class);
  74 + return SpringUtil.getBean(OpenAiChatModel.class);
75 75 case OLLAMA:
76   - return SpringUtil.getBean(OllamaChatClient.class);
  76 + return SpringUtil.getBean(OllamaChatModel.class);
77 77 case YI_YAN:
78 78 return SpringUtil.getBean(YiYanChatClient.class);
79 79 case XING_HUO:
... ... @@ -86,20 +86,20 @@ public class AiClientFactoryImpl implements AiClientFactory {
86 86 }
87 87  
88 88 @Override
89   - public ImageClient getDefaultImageClient(AiPlatformEnum platform) {
  89 + public ImageModel getDefaultImageClient(AiPlatformEnum platform) {
90 90 //noinspection EnhancedSwitchMigration
91 91 switch (platform) {
92 92 case OPENAI:
93   - return SpringUtil.getBean(OpenAiImageClient.class);
  93 + return SpringUtil.getBean(OpenAiImageModel.class);
94 94 case STABLE_DIFFUSION:
95   - return SpringUtil.getBean(StabilityAiImageClient.class);
  95 + return SpringUtil.getBean(StabilityAiImageModel.class);
96 96 default:
97 97 throw new IllegalArgumentException(StrUtil.format("未知平台({})", platform));
98 98 }
99 99 }
100 100  
101 101 @Override
102   - public ImageClient getOrCreateImageClient(AiPlatformEnum platform, String apiKey, String url) {
  102 + public ImageModel getOrCreateImageClient(AiPlatformEnum platform, String apiKey, String url) {
103 103 //noinspection EnhancedSwitchMigration
104 104 switch (platform) {
105 105 case OPENAI:
... ... @@ -138,18 +138,18 @@ public class AiClientFactoryImpl implements AiClientFactory {
138 138 /**
139 139 * 可参考 {@link OpenAiAutoConfiguration}
140 140 */
141   - private static OpenAiChatClient buildOpenAiChatClient(String openAiToken, String url) {
  141 + private static OpenAiChatModel buildOpenAiChatClient(String openAiToken, String url) {
142 142 url = StrUtil.blankToDefault(url, ApiUtils.DEFAULT_BASE_URL);
143 143 OpenAiApi openAiApi = new OpenAiApi(url, openAiToken);
144   - return new OpenAiChatClient(openAiApi);
  144 + return new OpenAiChatModel(openAiApi);
145 145 }
146 146  
147 147 /**
148 148 * 可参考 {@link OllamaAutoConfiguration}
149 149 */
150   - private static OllamaChatClient buildOllamaChatClient(String url) {
  150 + private static OllamaChatModel buildOllamaChatClient(String url) {
151 151 OllamaApi ollamaApi = new OllamaApi(url);
152   - return new OllamaChatClient(ollamaApi);
  152 + return new OllamaChatModel(ollamaApi);
153 153 }
154 154  
155 155 /**
... ... @@ -192,16 +192,16 @@ public class AiClientFactoryImpl implements AiClientFactory {
192 192 // return new VertexAiGeminiChatClient(vertexApi);
193 193 // }
194 194  
195   - private ImageClient buildOpenAiImageClient(String openAiToken, String url) {
  195 + private OpenAiImageModel buildOpenAiImageClient(String openAiToken, String url) {
196 196 url = StrUtil.blankToDefault(url, ApiUtils.DEFAULT_BASE_URL);
197 197 OpenAiImageApi openAiApi = new OpenAiImageApi(url, openAiToken, RestClient.builder());
198   - return new OpenAiImageClient(openAiApi);
  198 + return new OpenAiImageModel(openAiApi);
199 199 }
200 200  
201   - private ImageClient buildStabilityAiImageClient(String apiKey, String url) {
  201 + private StabilityAiImageModel buildStabilityAiImageClient(String apiKey, String url) {
202 202 url = StrUtil.blankToDefault(url, StabilityAiApi.DEFAULT_BASE_URL);
203 203 StabilityAiApi stabilityAiApi = new StabilityAiApi(apiKey, StabilityAiApi.DEFAULT_IMAGE_MODEL, url);
204   - return new StabilityAiImageClient(stabilityAiApi);
  204 + return new StabilityAiImageModel(stabilityAiApi);
205 205 }
206 206  
207 207 }
... ...
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/QianWenChatClient.java
1 1 package cn.iocoder.yudao.framework.ai.core.model.tongyi;
2 2  
3   -import cn.hutool.core.util.NumberUtil;
4 3 import cn.iocoder.yudao.framework.ai.core.exception.ChatException;
5 4 import cn.iocoder.yudao.framework.ai.core.model.tongyi.api.QianWenApi;
6   -import org.springframework.ai.chat.*;
7   -import org.springframework.ai.chat.prompt.ChatOptions;
8   -import org.springframework.ai.chat.prompt.Prompt;
9 5 import cn.iocoder.yudao.framework.ai.core.model.yiyan.exception.YiYanApiException;
10 6 import com.alibaba.dashscope.aigc.generation.GenerationResult;
11 7 import com.alibaba.dashscope.aigc.generation.models.QwenParam;
... ... @@ -14,6 +10,12 @@ import com.google.common.collect.Lists;
14 10 import io.reactivex.Flowable;
15 11 import lombok.extern.slf4j.Slf4j;
16 12 import org.jetbrains.annotations.NotNull;
  13 +import org.springframework.ai.chat.model.ChatModel;
  14 +import org.springframework.ai.chat.model.ChatResponse;
  15 +import org.springframework.ai.chat.model.Generation;
  16 +import org.springframework.ai.chat.model.StreamingChatModel;
  17 +import org.springframework.ai.chat.prompt.ChatOptions;
  18 +import org.springframework.ai.chat.prompt.Prompt;
17 19 import org.springframework.http.ResponseEntity;
18 20 import org.springframework.retry.RetryCallback;
19 21 import org.springframework.retry.RetryContext;
... ... @@ -35,7 +37,7 @@ import java.util.stream.Collectors;
35 37 * time: 2024/3/13 21:06
36 38 */
37 39 @Slf4j
38   -public class QianWenChatClient implements ChatClient, StreamingChatClient {
  40 +public class QianWenChatClient implements ChatModel, StreamingChatModel {
39 41  
40 42 private QianWenApi qianWenApi;
41 43  
... ... @@ -90,6 +92,12 @@ public class QianWenChatClient implements ChatClient, StreamingChatClient {
90 92 });
91 93 }
92 94  
  95 + @Override
  96 + public ChatOptions getDefaultOptions() {
  97 + // TODO 芋艿:需要跟进下
  98 + throw new UnsupportedOperationException();
  99 + }
  100 +
93 101 private QwenParam createRequest(Prompt prompt, boolean stream) {
94 102 // 获取 ChatOptions
95 103 QianWenOptions chatOptions = getChatOptions(prompt);
... ...
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/xinghuo/XingHuoChatClient.java
... ... @@ -6,10 +6,13 @@ import cn.iocoder.yudao.framework.ai.core.exception.ChatException;
6 6 import cn.iocoder.yudao.framework.ai.core.model.xinghuo.api.XingHuoApi;
7 7 import cn.iocoder.yudao.framework.ai.core.model.xinghuo.api.XingHuoChatCompletion;
8 8 import cn.iocoder.yudao.framework.ai.core.model.xinghuo.api.XingHuoChatCompletionRequest;
9   -import org.springframework.ai.chat.*;
  9 +import lombok.extern.slf4j.Slf4j;
  10 +import org.springframework.ai.chat.model.ChatModel;
  11 +import org.springframework.ai.chat.model.ChatResponse;
  12 +import org.springframework.ai.chat.model.Generation;
  13 +import org.springframework.ai.chat.model.StreamingChatModel;
10 14 import org.springframework.ai.chat.prompt.ChatOptions;
11 15 import org.springframework.ai.chat.prompt.Prompt;
12   -import lombok.extern.slf4j.Slf4j;
13 16 import org.springframework.http.ResponseEntity;
14 17 import org.springframework.retry.RetryCallback;
15 18 import org.springframework.retry.RetryContext;
... ... @@ -29,7 +32,7 @@ import java.util.stream.Collectors;
29 32 * time: 2024/3/11 10:19
30 33 */
31 34 @Slf4j
32   -public class XingHuoChatClient implements ChatClient, StreamingChatClient {
  35 +public class XingHuoChatClient implements ChatModel, StreamingChatModel {
33 36  
34 37 private XingHuoApi xingHuoApi;
35 38  
... ... @@ -64,7 +67,6 @@ public class XingHuoChatClient implements ChatClient, StreamingChatClient {
64 67  
65 68 @Override
66 69 public ChatResponse call(Prompt prompt) {
67   -
68 70 return this.retryTemplate.execute(ctx -> {
69 71 // ctx 会有重试的信息
70 72 // 获取 chatOptions 属性
... ... @@ -79,6 +81,12 @@ public class XingHuoChatClient implements ChatClient, StreamingChatClient {
79 81 }
80 82  
81 83 @Override
  84 + public ChatOptions getDefaultOptions() {
  85 + // TODO 芋艿:需要跟进下
  86 + throw new UnsupportedOperationException();
  87 + }
  88 +
  89 + @Override
82 90 public Flux<ChatResponse> stream(Prompt prompt) {
83 91 // 获取 chatOptions 属性
84 92 XingHuoOptions chatOptions = this.getChatOptions(prompt);
... ...
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/yiyan/YiYanChatClient.java
... ... @@ -7,12 +7,13 @@ import cn.iocoder.yudao.framework.ai.core.model.yiyan.api.YiYanChatCompletionReq
7 7 import cn.iocoder.yudao.framework.ai.core.model.yiyan.api.YiYanChatCompletionResponse;
8 8 import cn.iocoder.yudao.framework.ai.core.model.yiyan.exception.YiYanApiException;
9 9 import lombok.extern.slf4j.Slf4j;
10   -import org.springframework.ai.chat.ChatClient;
11   -import org.springframework.ai.chat.ChatResponse;
12   -import org.springframework.ai.chat.Generation;
13   -import org.springframework.ai.chat.StreamingChatClient;
  10 +import org.springframework.ai.chat.client.ChatClient;
14 11 import org.springframework.ai.chat.messages.Message;
15 12 import org.springframework.ai.chat.messages.MessageType;
  13 +import org.springframework.ai.chat.model.ChatModel;
  14 +import org.springframework.ai.chat.model.ChatResponse;
  15 +import org.springframework.ai.chat.model.Generation;
  16 +import org.springframework.ai.chat.model.StreamingChatModel;
16 17 import org.springframework.ai.chat.prompt.ChatOptions;
17 18 import org.springframework.ai.chat.prompt.Prompt;
18 19 import org.springframework.http.ResponseEntity;
... ... @@ -33,7 +34,7 @@ import java.util.stream.Collectors;
33 34 * @author fansili
34 35 */
35 36 @Slf4j
36   -public class YiYanChatClient implements ChatClient, StreamingChatClient {
  37 +public class YiYanChatClient implements ChatModel, StreamingChatModel {
37 38  
38 39 private final YiYanApi yiYanApi;
39 40  
... ... @@ -87,6 +88,12 @@ public class YiYanChatClient implements ChatClient, StreamingChatClient {
87 88 }
88 89  
89 90 @Override
  91 + public ChatOptions getDefaultOptions() {
  92 + // TODO 芋艿:需要跟进下
  93 + throw new UnsupportedOperationException();
  94 + }
  95 +
  96 + @Override
90 97 public Flux<ChatResponse> stream(Prompt prompt) {
91 98 YiYanChatCompletionRequest request = this.createRequest(prompt, true);
92 99 return this.retryTemplate.execute(ctx -> {
... ... @@ -99,8 +106,6 @@ public class YiYanChatClient implements ChatClient, StreamingChatClient {
99 106 });
100 107 }
101 108  
102   -
103   -
104 109 private YiYanChatCompletionRequest createRequest(Prompt prompt, boolean stream) {
105 110 // 参考 https://cloud.baidu.com/doc/WENXINWORKSHOP/s/clntwmv7t 文档,system 是独立字段
106 111 // 1.1 获取 user 和 assistant
... ...
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
1 1 -cn.iocoder.yudao.framework.ai.config.YudaoAiAutoConfiguration
  2 +cn.iocoder.yudao.framework.ai.config.YudaoAiAutoConfiguration
2 3 \ No newline at end of file
... ...
yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/QianWenChatClientTests.java
1 1 package cn.iocoder.yudao.framework.ai.chat;
2 2  
3   -import org.springframework.ai.chat.ChatResponse;
4   -import org.springframework.ai.chat.messages.SystemMessage;
5   -import org.springframework.ai.chat.messages.UserMessage;
6   -import org.springframework.ai.chat.prompt.Prompt;
7 3 import cn.iocoder.yudao.framework.ai.core.model.tongyi.QianWenChatClient;
8 4 import cn.iocoder.yudao.framework.ai.core.model.tongyi.QianWenChatModal;
9 5 import cn.iocoder.yudao.framework.ai.core.model.tongyi.QianWenOptions;
... ... @@ -17,6 +13,10 @@ import com.alibaba.dashscope.exception.InputRequiredException;
17 13 import com.alibaba.dashscope.exception.NoApiKeyException;
18 14 import org.junit.Before;
19 15 import org.junit.Test;
  16 +import org.springframework.ai.chat.messages.SystemMessage;
  17 +import org.springframework.ai.chat.messages.UserMessage;
  18 +import org.springframework.ai.chat.model.ChatResponse;
  19 +import org.springframework.ai.chat.prompt.Prompt;
20 20 import reactor.core.publisher.Flux;
21 21  
22 22 import java.util.ArrayList;
... ...
yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/XingHuoChatClientTests.java
1 1 package cn.iocoder.yudao.framework.ai.chat;
2 2  
3   -import org.springframework.ai.chat.ChatResponse;
4   -import org.springframework.ai.chat.messages.Message;
5   -import org.springframework.ai.chat.messages.SystemMessage;
6   -import org.springframework.ai.chat.messages.UserMessage;
7   -import org.springframework.ai.chat.prompt.Prompt;
8 3 import cn.iocoder.yudao.framework.ai.core.model.xinghuo.XingHuoChatClient;
9 4 import cn.iocoder.yudao.framework.ai.core.model.xinghuo.XingHuoChatModel;
10 5 import cn.iocoder.yudao.framework.ai.core.model.xinghuo.XingHuoOptions;
11 6 import cn.iocoder.yudao.framework.ai.core.model.xinghuo.api.XingHuoApi;
12 7 import org.junit.Before;
13 8 import org.junit.Test;
  9 +import org.springframework.ai.chat.messages.Message;
  10 +import org.springframework.ai.chat.messages.SystemMessage;
  11 +import org.springframework.ai.chat.messages.UserMessage;
  12 +import org.springframework.ai.chat.model.ChatResponse;
  13 +import org.springframework.ai.chat.prompt.Prompt;
14 14 import reactor.core.publisher.Flux;
15 15  
16 16 import java.util.ArrayList;
... ...
yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/YiYanChatTests.java
1 1 package cn.iocoder.yudao.framework.ai.chat;
2 2  
3   -import org.springframework.ai.chat.ChatResponse;
4   -import org.springframework.ai.chat.messages.Message;
5   -import org.springframework.ai.chat.messages.SystemMessage;
6   -import org.springframework.ai.chat.messages.UserMessage;
7   -import org.springframework.ai.chat.prompt.Prompt;
8 3 import cn.iocoder.yudao.framework.ai.core.model.yiyan.YiYanChatClient;
9   -import cn.iocoder.yudao.framework.ai.core.model.yiyan.api.YiYanChatModel;
10 4 import cn.iocoder.yudao.framework.ai.core.model.yiyan.YiYanChatOptions;
11 5 import cn.iocoder.yudao.framework.ai.core.model.yiyan.api.YiYanApi;
  6 +import cn.iocoder.yudao.framework.ai.core.model.yiyan.api.YiYanChatModel;
12 7 import org.junit.Before;
13 8 import org.junit.Test;
  9 +import org.springframework.ai.chat.messages.Message;
  10 +import org.springframework.ai.chat.messages.SystemMessage;
  11 +import org.springframework.ai.chat.messages.UserMessage;
  12 +import org.springframework.ai.chat.model.ChatResponse;
  13 +import org.springframework.ai.chat.prompt.Prompt;
14 14 import reactor.core.publisher.Flux;
15 15  
16 16 import java.util.ArrayList;
... ...
yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/image/OpenAiImageClientTests.java
... ... @@ -4,7 +4,7 @@ import org.springframework.ai.image.ImagePrompt;
4 4 import org.springframework.ai.image.ImageResponse;
5 5 import org.junit.Before;
6 6 import org.junit.Test;
7   -import org.springframework.ai.openai.OpenAiImageClient;
  7 +import org.springframework.ai.openai.OpenAiImageModel;
8 8 import org.springframework.ai.openai.api.OpenAiImageApi;
9 9  
10 10 import javax.imageio.ImageIO;
... ... @@ -23,12 +23,12 @@ import java.util.Scanner;
23 23 public class OpenAiImageClientTests {
24 24  
25 25  
26   - private OpenAiImageClient openAiImageClient;
  26 + private OpenAiImageModel openAiImageClient;
27 27  
28 28 @Before
29 29 public void setup() {
30 30 // 初始化 openAiImageClient
31   - this.openAiImageClient = new OpenAiImageClient(
  31 + this.openAiImageClient = new OpenAiImageModel(
32 32 new OpenAiImageApi("")
33 33 // new OpenAiImageOptions().setResponseFormat(OpenAiImageOptions.ResponseFormatEnum.URL.getValue()) TODO 芋艿:临时处理
34 34 );
... ...