diff --git a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/model/AiModelEnum.java b/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/model/AiModelEnum.java index a546051ab..9e584e18f 100644 --- a/yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/model/AiModelEnum.java +++ b/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; import lombok.AllArgsConstructor; import lombok.Getter; +// TODO @芋艿:可以考虑清理掉 /** * ai 模型 * diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImpl.java index 172c6658d..cb4ca4c77 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImpl.java +++ b/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; import cn.iocoder.yudao.module.ai.service.model.AiChatRoleService; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; -import org.springframework.ai.chat.ChatResponse; -import org.springframework.ai.chat.StreamingChatClient; import org.springframework.ai.chat.messages.*; +import org.springframework.ai.chat.model.ChatResponse; +import org.springframework.ai.chat.model.StreamingChatModel; import org.springframework.ai.chat.prompt.ChatOptions; import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.ollama.api.OllamaOptions; @@ -44,8 +44,8 @@ import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionU import static cn.iocoder.yudao.framework.common.pojo.CommonResult.error; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; -import static cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants.CHAT_MESSAGE_NOT_EXIST; import static cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants.CHAT_CONVERSATION_NOT_EXISTS; +import static cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants.CHAT_MESSAGE_NOT_EXIST; /** * AI 聊天消息 Service 实现类 @@ -117,7 +117,7 @@ public class AiChatMessageServiceImpl implements AiChatMessageService { List historyMessages = chatMessageMapper.selectListByConversationId(conversation.getId()); // 1.2 校验模型 AiChatModelDO model = chatModalService.validateChatModel(conversation.getModelId()); - StreamingChatClient chatClient = apiKeyService.getStreamingChatClient(model.getKeyId()); + StreamingChatModel chatClient = apiKeyService.getStreamingChatClient(model.getKeyId()); // 1.3 获取用户头像、角色头像 AiChatRoleDO role = conversation.getRoleId() != null ? chatRoleService.getChatRole(conversation.getRoleId()) : null; @@ -164,7 +164,14 @@ public class AiChatMessageServiceImpl implements AiChatMessageService { } // 1.2 history message 历史消息 List contextMessages = filterContextMessages(messages, conversation, sendReqVO); - contextMessages.forEach(message -> chatMessages.add(new ChatMessage(message.getType().toUpperCase(), message.getContent()))); + contextMessages.forEach(message -> { + // TODO @芋艿:看看有没优化空间 + if (MessageType.USER.getValue().equals(message.getType())) { + chatMessages.add(new UserMessage(message.getContent())); + } else { + chatMessages.add(new AssistantMessage(message.getContent())); + } + }); // 1.3 user message 新发送消息 chatMessages.add(new UserMessage(sendReqVO.getContent())); 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 dcde32bdb..cef3bcff2 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 @@ -25,7 +25,7 @@ import cn.iocoder.yudao.module.ai.service.model.AiApiKeyService; import cn.iocoder.yudao.module.infra.api.file.FileApi; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; -import org.springframework.ai.image.ImageClient; +import org.springframework.ai.image.ImageModel; import org.springframework.ai.image.ImageOptions; import org.springframework.ai.image.ImagePrompt; import org.springframework.ai.image.ImageResponse; @@ -97,7 +97,7 @@ public class AiImageServiceImpl implements AiImageService { // 1.1 构建请求 ImageOptions request = buildImageOptions(req); // 1.2 执行请求 - ImageClient imageClient = apiKeyService.getImageClient(AiPlatformEnum.validatePlatform(req.getPlatform())); + ImageModel imageClient = apiKeyService.getImageClient(AiPlatformEnum.validatePlatform(req.getPlatform())); ImageResponse response = imageClient.call(new ImagePrompt(req.getPrompt(), request)); // 2. 上传到文件服务 diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyService.java index 4ba0be41d..bf4305b67 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyService.java +++ b/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 import cn.iocoder.yudao.module.ai.controller.admin.model.vo.apikey.AiApiKeySaveReqVO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiApiKeyDO; import jakarta.validation.Valid; -import org.springframework.ai.chat.StreamingChatClient; -import org.springframework.ai.image.ImageClient; +import org.springframework.ai.chat.model.StreamingChatModel; +import org.springframework.ai.image.ImageModel; import java.util.List; @@ -81,7 +81,7 @@ public interface AiApiKeyService { * @param id 编号 * @return StreamingChatClient 对象 */ - StreamingChatClient getStreamingChatClient(Long id); + StreamingChatModel getStreamingChatClient(Long id); /** * 获得 ImageClient 对象 @@ -91,7 +91,7 @@ public interface AiApiKeyService { * @param platform 平台 * @return ImageClient 对象 */ - ImageClient getImageClient(AiPlatformEnum platform); + ImageModel getImageClient(AiPlatformEnum platform); /** * 获得 MidjourneyApi 对象 diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyServiceImpl.java index 6ef2bf5f5..efdb967ce 100644 --- a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyServiceImpl.java +++ b/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 import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiApiKeyDO; import cn.iocoder.yudao.module.ai.dal.mysql.model.AiApiKeyMapper; import jakarta.annotation.Resource; -import org.springframework.ai.chat.StreamingChatClient; -import org.springframework.ai.image.ImageClient; +import org.springframework.ai.chat.model.StreamingChatModel; +import org.springframework.ai.image.ImageModel; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; @@ -98,14 +98,14 @@ public class AiApiKeyServiceImpl implements AiApiKeyService { // ========== 与 spring-ai 集成 ========== @Override - public StreamingChatClient getStreamingChatClient(Long id) { + public StreamingChatModel getStreamingChatClient(Long id) { AiApiKeyDO apiKey = validateApiKey(id); AiPlatformEnum platform = AiPlatformEnum.validatePlatform(apiKey.getPlatform()); return clientFactory.getOrCreateStreamingChatClient(platform, apiKey.getApiKey(), apiKey.getUrl()); } @Override - public ImageClient getImageClient(AiPlatformEnum platform) { + public ImageModel getImageClient(AiPlatformEnum platform) { AiApiKeyDO apiKey = apiKeyMapper.selectFirstByPlatformAndStatus(platform.getName(), CommonStatusEnum.ENABLE.getStatus()); if (apiKey == null) { return null; 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 686be5d4b..2cea7a4ad 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml @@ -2,33 +2,38 @@ - 4.0.0 cn.iocoder.boot yudao-module-ai ${revision} + 4.0.0 yudao-spring-boot-starter-ai + ${project.artifactId} + AI 大模型拓展,接入国内外大模型 + + 1.0.0-M1 + - io.springboot.ai + org.springframework.ai spring-ai-ollama-spring-boot-starter - 1.0.3 + ${spring-ai.version} - io.springboot.ai + org.springframework.ai spring-ai-openai-spring-boot-starter - 1.0.3 + ${spring-ai.version} - io.springboot.ai - spring-ai-stability-ai - 1.0.3 + org.springframework.ai + spring-ai-stability-ai-spring-boot-starter + ${spring-ai.version} - + diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactory.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactory.java index d2f3d32c8..44ad08294 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactory.java +++ b/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; import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; import cn.iocoder.yudao.framework.ai.core.model.midjourney.api.MidjourneyApi; import cn.iocoder.yudao.framework.ai.core.model.suno.api.SunoApi; -import org.springframework.ai.chat.StreamingChatClient; -import org.springframework.ai.image.ImageClient; +import org.springframework.ai.chat.model.StreamingChatModel; +import org.springframework.ai.image.ImageModel; /** * AI 客户端工厂的接口类 @@ -23,7 +23,7 @@ public interface AiClientFactory { * @param url API URL * @return StreamingChatClient 对象 */ - StreamingChatClient getOrCreateStreamingChatClient(AiPlatformEnum platform, String apiKey, String url); + StreamingChatModel getOrCreateStreamingChatClient(AiPlatformEnum platform, String apiKey, String url); /** * 基于默认配置,获得 StreamingChatClient 对象 @@ -33,7 +33,7 @@ public interface AiClientFactory { * @param platform 平台 * @return StreamingChatClient 对象 */ - StreamingChatClient getDefaultStreamingChatClient(AiPlatformEnum platform); + StreamingChatModel getDefaultStreamingChatClient(AiPlatformEnum platform); /** * 基于默认配置,获得 ImageClient 对象 @@ -43,7 +43,7 @@ public interface AiClientFactory { * @param platform 平台 * @return ImageClient 对象 */ - ImageClient getDefaultImageClient(AiPlatformEnum platform); + ImageModel getDefaultImageClient(AiPlatformEnum platform); /** * 基于指定配置,获得 ImageClient 对象 @@ -55,7 +55,7 @@ public interface AiClientFactory { * @param url API URL * @return ImageClient 对象 */ - ImageClient getOrCreateImageClient(AiPlatformEnum platform, String apiKey, String url); + ImageModel getOrCreateImageClient(AiPlatformEnum platform, String apiKey, String url); /** * 基于指定配置,获得 MidjourneyApi 对象 diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactoryImpl.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactoryImpl.java index a904551f7..e72bc866a 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactoryImpl.java +++ b/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; import cn.iocoder.yudao.framework.ai.core.model.yiyan.api.YiYanApi; import org.springframework.ai.autoconfigure.ollama.OllamaAutoConfiguration; import org.springframework.ai.autoconfigure.openai.OpenAiAutoConfiguration; -import org.springframework.ai.chat.StreamingChatClient; -import org.springframework.ai.image.ImageClient; -import org.springframework.ai.ollama.OllamaChatClient; +import org.springframework.ai.chat.model.StreamingChatModel; +import org.springframework.ai.image.ImageModel; +import org.springframework.ai.ollama.OllamaChatModel; import org.springframework.ai.ollama.api.OllamaApi; -import org.springframework.ai.openai.OpenAiChatClient; -import org.springframework.ai.openai.OpenAiImageClient; +import org.springframework.ai.openai.OpenAiChatModel; +import org.springframework.ai.openai.OpenAiImageModel; import org.springframework.ai.openai.api.ApiUtils; import org.springframework.ai.openai.api.OpenAiApi; import org.springframework.ai.openai.api.OpenAiImageApi; -import org.springframework.ai.stabilityai.StabilityAiImageClient; +import org.springframework.ai.stabilityai.StabilityAiImageModel; import org.springframework.ai.stabilityai.api.StabilityAiApi; import org.springframework.web.client.RestClient; @@ -43,9 +43,9 @@ import java.util.List; public class AiClientFactoryImpl implements AiClientFactory { @Override - public StreamingChatClient getOrCreateStreamingChatClient(AiPlatformEnum platform, String apiKey, String url) { - String cacheKey = buildClientCacheKey(StreamingChatClient.class, platform, apiKey, url); - return Singleton.get(cacheKey, (Func0) () -> { + public StreamingChatModel getOrCreateStreamingChatClient(AiPlatformEnum platform, String apiKey, String url) { + String cacheKey = buildClientCacheKey(StreamingChatModel.class, platform, apiKey, url); + return Singleton.get(cacheKey, (Func0) () -> { //noinspection EnhancedSwitchMigration switch (platform) { case OPENAI: @@ -67,13 +67,13 @@ public class AiClientFactoryImpl implements AiClientFactory { } @Override - public StreamingChatClient getDefaultStreamingChatClient(AiPlatformEnum platform) { + public StreamingChatModel getDefaultStreamingChatClient(AiPlatformEnum platform) { //noinspection EnhancedSwitchMigration switch (platform) { case OPENAI: - return SpringUtil.getBean(OpenAiChatClient.class); + return SpringUtil.getBean(OpenAiChatModel.class); case OLLAMA: - return SpringUtil.getBean(OllamaChatClient.class); + return SpringUtil.getBean(OllamaChatModel.class); case YI_YAN: return SpringUtil.getBean(YiYanChatClient.class); case XING_HUO: @@ -86,20 +86,20 @@ public class AiClientFactoryImpl implements AiClientFactory { } @Override - public ImageClient getDefaultImageClient(AiPlatformEnum platform) { + public ImageModel getDefaultImageClient(AiPlatformEnum platform) { //noinspection EnhancedSwitchMigration switch (platform) { case OPENAI: - return SpringUtil.getBean(OpenAiImageClient.class); + return SpringUtil.getBean(OpenAiImageModel.class); case STABLE_DIFFUSION: - return SpringUtil.getBean(StabilityAiImageClient.class); + return SpringUtil.getBean(StabilityAiImageModel.class); default: throw new IllegalArgumentException(StrUtil.format("未知平台({})", platform)); } } @Override - public ImageClient getOrCreateImageClient(AiPlatformEnum platform, String apiKey, String url) { + public ImageModel getOrCreateImageClient(AiPlatformEnum platform, String apiKey, String url) { //noinspection EnhancedSwitchMigration switch (platform) { case OPENAI: @@ -138,18 +138,18 @@ public class AiClientFactoryImpl implements AiClientFactory { /** * 可参考 {@link OpenAiAutoConfiguration} */ - private static OpenAiChatClient buildOpenAiChatClient(String openAiToken, String url) { + private static OpenAiChatModel buildOpenAiChatClient(String openAiToken, String url) { url = StrUtil.blankToDefault(url, ApiUtils.DEFAULT_BASE_URL); OpenAiApi openAiApi = new OpenAiApi(url, openAiToken); - return new OpenAiChatClient(openAiApi); + return new OpenAiChatModel(openAiApi); } /** * 可参考 {@link OllamaAutoConfiguration} */ - private static OllamaChatClient buildOllamaChatClient(String url) { + private static OllamaChatModel buildOllamaChatClient(String url) { OllamaApi ollamaApi = new OllamaApi(url); - return new OllamaChatClient(ollamaApi); + return new OllamaChatModel(ollamaApi); } /** @@ -192,16 +192,16 @@ public class AiClientFactoryImpl implements AiClientFactory { // return new VertexAiGeminiChatClient(vertexApi); // } - private ImageClient buildOpenAiImageClient(String openAiToken, String url) { + private OpenAiImageModel buildOpenAiImageClient(String openAiToken, String url) { url = StrUtil.blankToDefault(url, ApiUtils.DEFAULT_BASE_URL); OpenAiImageApi openAiApi = new OpenAiImageApi(url, openAiToken, RestClient.builder()); - return new OpenAiImageClient(openAiApi); + return new OpenAiImageModel(openAiApi); } - private ImageClient buildStabilityAiImageClient(String apiKey, String url) { + private StabilityAiImageModel buildStabilityAiImageClient(String apiKey, String url) { url = StrUtil.blankToDefault(url, StabilityAiApi.DEFAULT_BASE_URL); StabilityAiApi stabilityAiApi = new StabilityAiApi(apiKey, StabilityAiApi.DEFAULT_IMAGE_MODEL, url); - return new StabilityAiImageClient(stabilityAiApi); + return new StabilityAiImageModel(stabilityAiApi); } } diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/QianWenChatClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/QianWenChatClient.java index 02a25cef4..c3f4b4a5b 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/QianWenChatClient.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/tongyi/QianWenChatClient.java @@ -1,11 +1,7 @@ package cn.iocoder.yudao.framework.ai.core.model.tongyi; -import cn.hutool.core.util.NumberUtil; import cn.iocoder.yudao.framework.ai.core.exception.ChatException; import cn.iocoder.yudao.framework.ai.core.model.tongyi.api.QianWenApi; -import org.springframework.ai.chat.*; -import org.springframework.ai.chat.prompt.ChatOptions; -import org.springframework.ai.chat.prompt.Prompt; import cn.iocoder.yudao.framework.ai.core.model.yiyan.exception.YiYanApiException; import com.alibaba.dashscope.aigc.generation.GenerationResult; import com.alibaba.dashscope.aigc.generation.models.QwenParam; @@ -14,6 +10,12 @@ import com.google.common.collect.Lists; import io.reactivex.Flowable; import lombok.extern.slf4j.Slf4j; import org.jetbrains.annotations.NotNull; +import org.springframework.ai.chat.model.ChatModel; +import org.springframework.ai.chat.model.ChatResponse; +import org.springframework.ai.chat.model.Generation; +import org.springframework.ai.chat.model.StreamingChatModel; +import org.springframework.ai.chat.prompt.ChatOptions; +import org.springframework.ai.chat.prompt.Prompt; import org.springframework.http.ResponseEntity; import org.springframework.retry.RetryCallback; import org.springframework.retry.RetryContext; @@ -35,7 +37,7 @@ import java.util.stream.Collectors; * time: 2024/3/13 21:06 */ @Slf4j -public class QianWenChatClient implements ChatClient, StreamingChatClient { +public class QianWenChatClient implements ChatModel, StreamingChatModel { private QianWenApi qianWenApi; @@ -90,6 +92,12 @@ public class QianWenChatClient implements ChatClient, StreamingChatClient { }); } + @Override + public ChatOptions getDefaultOptions() { + // TODO 芋艿:需要跟进下 + throw new UnsupportedOperationException(); + } + private QwenParam createRequest(Prompt prompt, boolean stream) { // 获取 ChatOptions QianWenOptions chatOptions = getChatOptions(prompt); diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/xinghuo/XingHuoChatClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/xinghuo/XingHuoChatClient.java index 5537fc1eb..9c4e52c3a 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/xinghuo/XingHuoChatClient.java +++ b/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; import cn.iocoder.yudao.framework.ai.core.model.xinghuo.api.XingHuoApi; import cn.iocoder.yudao.framework.ai.core.model.xinghuo.api.XingHuoChatCompletion; import cn.iocoder.yudao.framework.ai.core.model.xinghuo.api.XingHuoChatCompletionRequest; -import org.springframework.ai.chat.*; +import lombok.extern.slf4j.Slf4j; +import org.springframework.ai.chat.model.ChatModel; +import org.springframework.ai.chat.model.ChatResponse; +import org.springframework.ai.chat.model.Generation; +import org.springframework.ai.chat.model.StreamingChatModel; import org.springframework.ai.chat.prompt.ChatOptions; import org.springframework.ai.chat.prompt.Prompt; -import lombok.extern.slf4j.Slf4j; import org.springframework.http.ResponseEntity; import org.springframework.retry.RetryCallback; import org.springframework.retry.RetryContext; @@ -29,7 +32,7 @@ import java.util.stream.Collectors; * time: 2024/3/11 10:19 */ @Slf4j -public class XingHuoChatClient implements ChatClient, StreamingChatClient { +public class XingHuoChatClient implements ChatModel, StreamingChatModel { private XingHuoApi xingHuoApi; @@ -64,7 +67,6 @@ public class XingHuoChatClient implements ChatClient, StreamingChatClient { @Override public ChatResponse call(Prompt prompt) { - return this.retryTemplate.execute(ctx -> { // ctx 会有重试的信息 // 获取 chatOptions 属性 @@ -78,6 +80,12 @@ public class XingHuoChatClient implements ChatClient, StreamingChatClient { }); } + @Override + public ChatOptions getDefaultOptions() { + // TODO 芋艿:需要跟进下 + throw new UnsupportedOperationException(); + } + @Override public Flux stream(Prompt prompt) { // 获取 chatOptions 属性 diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/yiyan/YiYanChatClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/yiyan/YiYanChatClient.java index ab24f9584..a4fa1d3f5 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/yiyan/YiYanChatClient.java +++ b/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 import cn.iocoder.yudao.framework.ai.core.model.yiyan.api.YiYanChatCompletionResponse; import cn.iocoder.yudao.framework.ai.core.model.yiyan.exception.YiYanApiException; import lombok.extern.slf4j.Slf4j; -import org.springframework.ai.chat.ChatClient; -import org.springframework.ai.chat.ChatResponse; -import org.springframework.ai.chat.Generation; -import org.springframework.ai.chat.StreamingChatClient; +import org.springframework.ai.chat.client.ChatClient; import org.springframework.ai.chat.messages.Message; import org.springframework.ai.chat.messages.MessageType; +import org.springframework.ai.chat.model.ChatModel; +import org.springframework.ai.chat.model.ChatResponse; +import org.springframework.ai.chat.model.Generation; +import org.springframework.ai.chat.model.StreamingChatModel; import org.springframework.ai.chat.prompt.ChatOptions; import org.springframework.ai.chat.prompt.Prompt; import org.springframework.http.ResponseEntity; @@ -33,7 +34,7 @@ import java.util.stream.Collectors; * @author fansili */ @Slf4j -public class YiYanChatClient implements ChatClient, StreamingChatClient { +public class YiYanChatClient implements ChatModel, StreamingChatModel { private final YiYanApi yiYanApi; @@ -86,6 +87,12 @@ public class YiYanChatClient implements ChatClient, StreamingChatClient { }); } + @Override + public ChatOptions getDefaultOptions() { + // TODO 芋艿:需要跟进下 + throw new UnsupportedOperationException(); + } + @Override public Flux stream(Prompt prompt) { YiYanChatCompletionRequest request = this.createRequest(prompt, true); @@ -99,8 +106,6 @@ public class YiYanChatClient implements ChatClient, StreamingChatClient { }); } - - private YiYanChatCompletionRequest createRequest(Prompt prompt, boolean stream) { // 参考 https://cloud.baidu.com/doc/WENXINWORKSHOP/s/clntwmv7t 文档,system 是独立字段 // 1.1 获取 user 和 assistant diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index 6eedc9cc8..b52df354b 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/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 +cn.iocoder.yudao.framework.ai.config.YudaoAiAutoConfiguration \ No newline at end of file diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/QianWenChatClientTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/QianWenChatClientTests.java index 42bb0a437..b343d16b9 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/QianWenChatClientTests.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/QianWenChatClientTests.java @@ -1,9 +1,5 @@ package cn.iocoder.yudao.framework.ai.chat; -import org.springframework.ai.chat.ChatResponse; -import org.springframework.ai.chat.messages.SystemMessage; -import org.springframework.ai.chat.messages.UserMessage; -import org.springframework.ai.chat.prompt.Prompt; import cn.iocoder.yudao.framework.ai.core.model.tongyi.QianWenChatClient; import cn.iocoder.yudao.framework.ai.core.model.tongyi.QianWenChatModal; import cn.iocoder.yudao.framework.ai.core.model.tongyi.QianWenOptions; @@ -17,6 +13,10 @@ import com.alibaba.dashscope.exception.InputRequiredException; import com.alibaba.dashscope.exception.NoApiKeyException; import org.junit.Before; import org.junit.Test; +import org.springframework.ai.chat.messages.SystemMessage; +import org.springframework.ai.chat.messages.UserMessage; +import org.springframework.ai.chat.model.ChatResponse; +import org.springframework.ai.chat.prompt.Prompt; import reactor.core.publisher.Flux; import java.util.ArrayList; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/XingHuoChatClientTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/XingHuoChatClientTests.java index 671af5e6d..00f4c1d37 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/XingHuoChatClientTests.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/XingHuoChatClientTests.java @@ -1,16 +1,16 @@ package cn.iocoder.yudao.framework.ai.chat; -import org.springframework.ai.chat.ChatResponse; -import org.springframework.ai.chat.messages.Message; -import org.springframework.ai.chat.messages.SystemMessage; -import org.springframework.ai.chat.messages.UserMessage; -import org.springframework.ai.chat.prompt.Prompt; import cn.iocoder.yudao.framework.ai.core.model.xinghuo.XingHuoChatClient; import cn.iocoder.yudao.framework.ai.core.model.xinghuo.XingHuoChatModel; import cn.iocoder.yudao.framework.ai.core.model.xinghuo.XingHuoOptions; import cn.iocoder.yudao.framework.ai.core.model.xinghuo.api.XingHuoApi; import org.junit.Before; import org.junit.Test; +import org.springframework.ai.chat.messages.Message; +import org.springframework.ai.chat.messages.SystemMessage; +import org.springframework.ai.chat.messages.UserMessage; +import org.springframework.ai.chat.model.ChatResponse; +import org.springframework.ai.chat.prompt.Prompt; import reactor.core.publisher.Flux; import java.util.ArrayList; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/YiYanChatTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/YiYanChatTests.java index dc376c167..9b1d37d45 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/YiYanChatTests.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/YiYanChatTests.java @@ -1,16 +1,16 @@ package cn.iocoder.yudao.framework.ai.chat; -import org.springframework.ai.chat.ChatResponse; +import cn.iocoder.yudao.framework.ai.core.model.yiyan.YiYanChatClient; +import cn.iocoder.yudao.framework.ai.core.model.yiyan.YiYanChatOptions; +import cn.iocoder.yudao.framework.ai.core.model.yiyan.api.YiYanApi; +import cn.iocoder.yudao.framework.ai.core.model.yiyan.api.YiYanChatModel; +import org.junit.Before; +import org.junit.Test; import org.springframework.ai.chat.messages.Message; import org.springframework.ai.chat.messages.SystemMessage; import org.springframework.ai.chat.messages.UserMessage; +import org.springframework.ai.chat.model.ChatResponse; import org.springframework.ai.chat.prompt.Prompt; -import cn.iocoder.yudao.framework.ai.core.model.yiyan.YiYanChatClient; -import cn.iocoder.yudao.framework.ai.core.model.yiyan.api.YiYanChatModel; -import cn.iocoder.yudao.framework.ai.core.model.yiyan.YiYanChatOptions; -import cn.iocoder.yudao.framework.ai.core.model.yiyan.api.YiYanApi; -import org.junit.Before; -import org.junit.Test; import reactor.core.publisher.Flux; import java.util.ArrayList; diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/image/OpenAiImageClientTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/image/OpenAiImageClientTests.java index 7d519c258..7c73b2de2 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/image/OpenAiImageClientTests.java +++ b/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; import org.springframework.ai.image.ImageResponse; import org.junit.Before; import org.junit.Test; -import org.springframework.ai.openai.OpenAiImageClient; +import org.springframework.ai.openai.OpenAiImageModel; import org.springframework.ai.openai.api.OpenAiImageApi; import javax.imageio.ImageIO; @@ -23,12 +23,12 @@ import java.util.Scanner; public class OpenAiImageClientTests { - private OpenAiImageClient openAiImageClient; + private OpenAiImageModel openAiImageClient; @Before public void setup() { // 初始化 openAiImageClient - this.openAiImageClient = new OpenAiImageClient( + this.openAiImageClient = new OpenAiImageModel( new OpenAiImageApi("") // new OpenAiImageOptions().setResponseFormat(OpenAiImageOptions.ResponseFormatEnum.URL.getValue()) TODO 芋艿:临时处理 );