Commit 4f11d00cfd5d344c8b06c6f733a09b04c39b7016
1 parent
0139317a
【代码优化】AI:完善 TongYiChatModelTests 单测,方便大家快速体验
Showing
5 changed files
with
97 additions
and
126 deletions
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java
| @@ -14,8 +14,8 @@ public enum AiPlatformEnum { | @@ -14,8 +14,8 @@ public enum AiPlatformEnum { | ||
| 14 | 14 | ||
| 15 | // ========== 国内平台 ========== | 15 | // ========== 国内平台 ========== |
| 16 | 16 | ||
| 17 | + TONG_YI("TongYi", "通义千问"), // 阿里 | ||
| 17 | YI_YAN("YiYan", "文心一言"), // 百度 | 18 | YI_YAN("YiYan", "文心一言"), // 百度 |
| 18 | - QIAN_WEN("QianWen", "千问"), // 阿里 | ||
| 19 | DEEP_SEEK("DeepSeek", "DeepSeek"), // DeepSeek | 19 | DEEP_SEEK("DeepSeek", "DeepSeek"), // DeepSeek |
| 20 | XING_HUO("XingHuo", "星火"), // 讯飞 | 20 | XING_HUO("XingHuo", "星火"), // 讯飞 |
| 21 | 21 |
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiModelFactoryImpl.java
| @@ -55,12 +55,12 @@ public class AiModelFactoryImpl implements AiModelFactory { | @@ -55,12 +55,12 @@ public class AiModelFactoryImpl implements AiModelFactory { | ||
| 55 | return Singleton.get(cacheKey, (Func0<ChatModel>) () -> { | 55 | return Singleton.get(cacheKey, (Func0<ChatModel>) () -> { |
| 56 | //noinspection EnhancedSwitchMigration | 56 | //noinspection EnhancedSwitchMigration |
| 57 | switch (platform) { | 57 | switch (platform) { |
| 58 | + case TONG_YI: | ||
| 59 | + return buildTongYiChatModel(apiKey); | ||
| 58 | case YI_YAN: | 60 | case YI_YAN: |
| 59 | return buildYiYanChatClient(apiKey); | 61 | return buildYiYanChatClient(apiKey); |
| 60 | case XING_HUO: | 62 | case XING_HUO: |
| 61 | return buildXingHuoChatClient(apiKey); | 63 | return buildXingHuoChatClient(apiKey); |
| 62 | - case QIAN_WEN: | ||
| 63 | - return buildQianWenChatClient(apiKey); | ||
| 64 | case DEEP_SEEK: | 64 | case DEEP_SEEK: |
| 65 | return buildDeepSeekChatClient(apiKey); | 65 | return buildDeepSeekChatClient(apiKey); |
| 66 | case OPENAI: | 66 | case OPENAI: |
| @@ -77,16 +77,16 @@ public class AiModelFactoryImpl implements AiModelFactory { | @@ -77,16 +77,16 @@ public class AiModelFactoryImpl implements AiModelFactory { | ||
| 77 | public ChatModel getDefaultChatModel(AiPlatformEnum platform) { | 77 | public ChatModel getDefaultChatModel(AiPlatformEnum platform) { |
| 78 | //noinspection EnhancedSwitchMigration | 78 | //noinspection EnhancedSwitchMigration |
| 79 | switch (platform) { | 79 | switch (platform) { |
| 80 | - case OLLAMA: | ||
| 81 | - return SpringUtil.getBean(OllamaChatModel.class); | 80 | + case TONG_YI: |
| 81 | + return SpringUtil.getBean(TongYiChatModel.class); | ||
| 82 | case YI_YAN: | 82 | case YI_YAN: |
| 83 | return SpringUtil.getBean(QianFanChatModel.class); | 83 | return SpringUtil.getBean(QianFanChatModel.class); |
| 84 | case XING_HUO: | 84 | case XING_HUO: |
| 85 | return SpringUtil.getBean(XingHuoChatClient.class); | 85 | return SpringUtil.getBean(XingHuoChatClient.class); |
| 86 | - case QIAN_WEN: | ||
| 87 | - return SpringUtil.getBean(TongYiChatModel.class); | ||
| 88 | case OPENAI: | 86 | case OPENAI: |
| 89 | return SpringUtil.getBean(OpenAiChatModel.class); | 87 | return SpringUtil.getBean(OpenAiChatModel.class); |
| 88 | + case OLLAMA: | ||
| 89 | + return SpringUtil.getBean(OllamaChatModel.class); | ||
| 90 | default: | 90 | default: |
| 91 | throw new IllegalArgumentException(StrUtil.format("未知平台({})", platform)); | 91 | throw new IllegalArgumentException(StrUtil.format("未知平台({})", platform)); |
| 92 | } | 92 | } |
| @@ -143,6 +143,20 @@ public class AiModelFactoryImpl implements AiModelFactory { | @@ -143,6 +143,20 @@ public class AiModelFactoryImpl implements AiModelFactory { | ||
| 143 | // ========== 各种创建 spring-ai 客户端的方法 ========== | 143 | // ========== 各种创建 spring-ai 客户端的方法 ========== |
| 144 | 144 | ||
| 145 | /** | 145 | /** |
| 146 | + * 可参考 {@link TongYiAutoConfiguration#tongYiChatClient(Generation, TongYiChatProperties, TongYiConnectionProperties)} | ||
| 147 | + */ | ||
| 148 | + private static TongYiChatModel buildTongYiChatModel(String key) { | ||
| 149 | + com.alibaba.dashscope.aigc.generation.Generation generation = SpringUtil.getBean(Generation.class); | ||
| 150 | + TongYiChatProperties chatOptions = SpringUtil.getBean(TongYiChatProperties.class); | ||
| 151 | + // TODO @芋艿:貌似 apiKey 是全局唯一的???得测试下 | ||
| 152 | + // TODO @芋艿:貌似阿里云不是增量返回的 | ||
| 153 | + // 该 issue 进行跟进中 https://github.com/alibaba/spring-cloud-alibaba/issues/3790 | ||
| 154 | + TongYiConnectionProperties connectionProperties = new TongYiConnectionProperties(); | ||
| 155 | + connectionProperties.setApiKey(key); | ||
| 156 | + return new TongYiAutoConfiguration().tongYiChatClient(generation, chatOptions, connectionProperties); | ||
| 157 | + } | ||
| 158 | + | ||
| 159 | + /** | ||
| 146 | * 可参考 {@link OpenAiAutoConfiguration} | 160 | * 可参考 {@link OpenAiAutoConfiguration} |
| 147 | */ | 161 | */ |
| 148 | private static OpenAiChatModel buildOpenAiChatModel(String openAiToken, String url) { | 162 | private static OpenAiChatModel buildOpenAiChatModel(String openAiToken, String url) { |
| @@ -196,19 +210,6 @@ public class AiModelFactoryImpl implements AiModelFactory { | @@ -196,19 +210,6 @@ public class AiModelFactoryImpl implements AiModelFactory { | ||
| 196 | return new DeepSeekChatClient(apiKey); | 210 | return new DeepSeekChatClient(apiKey); |
| 197 | } | 211 | } |
| 198 | 212 | ||
| 199 | - /** | ||
| 200 | - * 可参考 {@link TongYiAutoConfiguration#tongYiChatClient(Generation, TongYiChatProperties, TongYiConnectionProperties)} | ||
| 201 | - */ | ||
| 202 | - private static TongYiChatModel buildQianWenChatClient(String key) { | ||
| 203 | - com.alibaba.dashscope.aigc.generation.Generation generation = SpringUtil.getBean(Generation.class); | ||
| 204 | - TongYiChatProperties chatOptions = SpringUtil.getBean(TongYiChatProperties.class); | ||
| 205 | - // TODO @xin:貌似 apiKey 是全局唯一的???得测试下 | ||
| 206 | - // TODO @xin:貌似阿里云不是增量返回的 | ||
| 207 | - TongYiConnectionProperties connectionProperties = new TongYiConnectionProperties(); | ||
| 208 | - connectionProperties.setApiKey(key); | ||
| 209 | - return new TongYiAutoConfiguration().tongYiChatClient(generation, chatOptions, connectionProperties); | ||
| 210 | - } | ||
| 211 | - | ||
| 212 | private StabilityAiImageModel buildStabilityAiImageClient(String apiKey, String url) { | 213 | private StabilityAiImageModel buildStabilityAiImageClient(String apiKey, String url) { |
| 213 | url = StrUtil.blankToDefault(url, StabilityAiApi.DEFAULT_BASE_URL); | 214 | url = StrUtil.blankToDefault(url, StabilityAiApi.DEFAULT_BASE_URL); |
| 214 | StabilityAiApi stabilityAiApi = new StabilityAiApi(apiKey, StabilityAiApi.DEFAULT_IMAGE_MODEL, url); | 215 | StabilityAiApi stabilityAiApi = new StabilityAiApi(apiKey, StabilityAiApi.DEFAULT_IMAGE_MODEL, url); |
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/util/AiUtils.java
| @@ -32,7 +32,7 @@ public class AiUtils { | @@ -32,7 +32,7 @@ public class AiUtils { | ||
| 32 | return QianFanChatOptions.builder().withTemperature(temperatureF).withMaxTokens(maxTokens).build(); | 32 | return QianFanChatOptions.builder().withTemperature(temperatureF).withMaxTokens(maxTokens).build(); |
| 33 | case XING_HUO: | 33 | case XING_HUO: |
| 34 | return XingHuoChatOptions.builder().model(model).temperature(temperatureF).maxTokens(maxTokens).build(); | 34 | return XingHuoChatOptions.builder().model(model).temperature(temperatureF).maxTokens(maxTokens).build(); |
| 35 | - case QIAN_WEN: | 35 | + case TONG_YI: |
| 36 | return TongYiChatOptions.builder().withModel(model).withTemperature(temperature).withMaxTokens(maxTokens).build(); | 36 | return TongYiChatOptions.builder().withModel(model).withTemperature(temperature).withMaxTokens(maxTokens).build(); |
| 37 | case DEEP_SEEK: | 37 | case DEEP_SEEK: |
| 38 | return DeepSeekChatOptions.builder().model(model).temperature(temperatureF).maxTokens(maxTokens).build(); | 38 | return DeepSeekChatOptions.builder().model(model).temperature(temperatureF).maxTokens(maxTokens).build(); |
yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/QianWenChatClientTests.java deleted
| 1 | -//package cn.iocoder.yudao.framework.ai.chat; | ||
| 2 | -// | ||
| 3 | -//import cn.iocoder.yudao.framework.ai.core.model.tongyi.QianWenChatClient; | ||
| 4 | -//import cn.iocoder.yudao.framework.ai.core.model.tongyi.QianWenChatModal; | ||
| 5 | -//import cn.iocoder.yudao.framework.ai.core.model.tongyi.QianWenOptions; | ||
| 6 | -//import cn.iocoder.yudao.framework.ai.core.model.tongyi.api.QianWenApi; | ||
| 7 | -//import com.alibaba.dashscope.aigc.generation.GenerationResult; | ||
| 8 | -//import com.alibaba.dashscope.aigc.generation.models.QwenParam; | ||
| 9 | -//import com.alibaba.dashscope.common.Message; | ||
| 10 | -//import com.alibaba.dashscope.common.MessageManager; | ||
| 11 | -//import com.alibaba.dashscope.common.Role; | ||
| 12 | -//import com.alibaba.dashscope.exception.InputRequiredException; | ||
| 13 | -//import com.alibaba.dashscope.exception.NoApiKeyException; | ||
| 14 | -//import org.junit.Before; | ||
| 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 | -//import reactor.core.publisher.Flux; | ||
| 21 | -// | ||
| 22 | -//import java.util.ArrayList; | ||
| 23 | -//import java.util.List; | ||
| 24 | -//import java.util.Scanner; | ||
| 25 | -//import java.util.function.Consumer; | ||
| 26 | -// | ||
| 27 | -//// TODO 芋艿:整理单测 | ||
| 28 | -///** | ||
| 29 | -// * author: fansili | ||
| 30 | -// * time: 2024/3/13 21:37 | ||
| 31 | -// */ | ||
| 32 | -//public class QianWenChatClientTests { | ||
| 33 | -// | ||
| 34 | -// private QianWenChatClient qianWenChatClient; | ||
| 35 | -// | ||
| 36 | -// @Before | ||
| 37 | -// public void setup() { | ||
| 38 | -// QianWenApi qianWenApi = new QianWenApi("sk-Zsd81gZYg7", QianWenChatModal.QWEN_72B_CHAT); | ||
| 39 | -// QianWenOptions qianWenOptions = new QianWenOptions(); | ||
| 40 | -// qianWenOptions.setTopP(0.8F); | ||
| 41 | -//// qianWenOptions.setTopK(3); TODO 芋艿:临时处理 | ||
| 42 | -//// qianWenOptions.setTemperature(0.6F); TODO 芋艿:临时处理 | ||
| 43 | -// qianWenChatClient = new QianWenChatClient( | ||
| 44 | -// qianWenApi, | ||
| 45 | -// qianWenOptions | ||
| 46 | -// ); | ||
| 47 | -// } | ||
| 48 | -// | ||
| 49 | -// @Test | ||
| 50 | -// public void callTest() { | ||
| 51 | -// List<org.springframework.ai.chat.messages.Message> messages = new ArrayList<>(); | ||
| 52 | -// messages.add(new SystemMessage("你是一个优质的小红书文艺作者,抒写着各城市的美好文化和风景。")); | ||
| 53 | -// messages.add(new UserMessage("长沙怎么样?")); | ||
| 54 | -// | ||
| 55 | -// ChatResponse call = qianWenChatClient.call(new Prompt(messages)); | ||
| 56 | -// System.err.println(call.getResult()); | ||
| 57 | -// } | ||
| 58 | -// | ||
| 59 | -// @Test | ||
| 60 | -// public void streamTest() { | ||
| 61 | -// List<org.springframework.ai.chat.messages.Message> messages = new ArrayList<>(); | ||
| 62 | -// messages.add(new SystemMessage("你是一个优质的文言文作者,用文言文描述着各城市的人文风景。")); | ||
| 63 | -// messages.add(new UserMessage("长沙怎么样?")); | ||
| 64 | -// | ||
| 65 | -// Flux<ChatResponse> flux = qianWenChatClient.stream(new Prompt(messages)); | ||
| 66 | -// flux.subscribe(new Consumer<ChatResponse>() { | ||
| 67 | -// @Override | ||
| 68 | -// public void accept(ChatResponse chatResponse) { | ||
| 69 | -// System.err.print(chatResponse.getResult().getOutput().getContent()); | ||
| 70 | -// } | ||
| 71 | -// }); | ||
| 72 | -// | ||
| 73 | -// // 阻止退出 | ||
| 74 | -// Scanner scanner = new Scanner(System.in); | ||
| 75 | -// scanner.nextLine(); | ||
| 76 | -// } | ||
| 77 | -// | ||
| 78 | -// @Test | ||
| 79 | -// public void qianwenDemoTest() throws NoApiKeyException, InputRequiredException { | ||
| 80 | -// com.alibaba.dashscope.aigc.generation.Generation gen = new com.alibaba.dashscope.aigc.generation.Generation(); | ||
| 81 | -// MessageManager msgManager = new MessageManager(10); | ||
| 82 | -// Message systemMsg = | ||
| 83 | -// Message.builder().role(Role.SYSTEM.getValue()).content("You are a helpful assistant.").build(); | ||
| 84 | -// Message userMsg = Message.builder().role(Role.USER.getValue()).content("就当前的海洋污染的情况,写一份限塑的倡议书提纲,需要有理有据地号召大家克制地使用塑料制品").build(); | ||
| 85 | -// msgManager.add(systemMsg); | ||
| 86 | -// msgManager.add(userMsg); | ||
| 87 | -// QwenParam param = | ||
| 88 | -// QwenParam.builder().model("qwen-72b-chat").messages(msgManager.get()) | ||
| 89 | -// .resultFormat(QwenParam.ResultFormat.MESSAGE) | ||
| 90 | -// .topP(0.8) | ||
| 91 | -// /* set the random seed, optional, default to 1234 if not set */ | ||
| 92 | -// .seed(100) | ||
| 93 | -// .apiKey("sk-Zsd81gZYg7") | ||
| 94 | -// .build(); | ||
| 95 | -// GenerationResult result = gen.call(param); | ||
| 96 | -// System.out.println(result); | ||
| 97 | -// System.out.println("-----------------"); | ||
| 98 | -// System.out.println("-----------------"); | ||
| 99 | -// msgManager.add(result); | ||
| 100 | -// param.setPrompt("能否缩短一些,只讲三点"); | ||
| 101 | -// param.setMessages(msgManager.get()); | ||
| 102 | -// result = gen.call(param); | ||
| 103 | -// System.out.println(result); | ||
| 104 | -// } | ||
| 105 | -//} |
yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/TongYiChatModelTests.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.ai.chat; | ||
| 2 | + | ||
| 3 | +import cn.hutool.core.util.ReflectUtil; | ||
| 4 | +import com.alibaba.cloud.ai.tongyi.chat.TongYiChatModel; | ||
| 5 | +import com.alibaba.cloud.ai.tongyi.chat.TongYiChatOptions; | ||
| 6 | +import com.alibaba.dashscope.aigc.generation.Generation; | ||
| 7 | +import com.alibaba.dashscope.common.MessageManager; | ||
| 8 | +import com.alibaba.dashscope.utils.Constants; | ||
| 9 | +import org.junit.jupiter.api.BeforeEach; | ||
| 10 | +import org.junit.jupiter.api.Disabled; | ||
| 11 | +import org.junit.jupiter.api.Test; | ||
| 12 | +import org.springframework.ai.chat.messages.Message; | ||
| 13 | +import org.springframework.ai.chat.messages.SystemMessage; | ||
| 14 | +import org.springframework.ai.chat.messages.UserMessage; | ||
| 15 | +import org.springframework.ai.chat.model.ChatResponse; | ||
| 16 | +import org.springframework.ai.chat.prompt.Prompt; | ||
| 17 | +import reactor.core.publisher.Flux; | ||
| 18 | + | ||
| 19 | +import java.util.ArrayList; | ||
| 20 | +import java.util.List; | ||
| 21 | + | ||
| 22 | +/** | ||
| 23 | + * {@link TongYiChatModel} 集成测试类 | ||
| 24 | + * | ||
| 25 | + * @author fansili | ||
| 26 | + */ | ||
| 27 | +public class TongYiChatModelTests { | ||
| 28 | + | ||
| 29 | + private final Generation generation = new Generation(); | ||
| 30 | + private final TongYiChatModel chatModel = new TongYiChatModel(generation, | ||
| 31 | + TongYiChatOptions.builder().withModel("qwen1.5-72b-chat").build()); | ||
| 32 | + | ||
| 33 | + static { | ||
| 34 | + Constants.apiKey = "sk-Zsd81gZYg7"; | ||
| 35 | + } | ||
| 36 | + | ||
| 37 | + @BeforeEach | ||
| 38 | + public void before() { | ||
| 39 | + // 防止 TongYiChatModel 调用空指针 | ||
| 40 | + ReflectUtil.setFieldValue(chatModel, "msgManager", new MessageManager()); | ||
| 41 | + } | ||
| 42 | + | ||
| 43 | + @Test | ||
| 44 | + @Disabled | ||
| 45 | + public void testCall() { | ||
| 46 | + // 准备参数 | ||
| 47 | + List<Message> messages = new ArrayList<>(); | ||
| 48 | + messages.add(new SystemMessage("你是一个优质的文言文作者,用文言文描述着各城市的人文风景。")); | ||
| 49 | + messages.add(new UserMessage("1 + 1 = ?")); | ||
| 50 | + | ||
| 51 | + // 调用 | ||
| 52 | + ChatResponse response = chatModel.call(new Prompt(messages)); | ||
| 53 | + // 打印结果 | ||
| 54 | + System.out.println(response); | ||
| 55 | + System.out.println(response.getResult().getOutput()); | ||
| 56 | + } | ||
| 57 | + | ||
| 58 | + @Test | ||
| 59 | + @Disabled | ||
| 60 | + public void testStream() { | ||
| 61 | + // 准备参数 | ||
| 62 | + List<Message> messages = new ArrayList<>(); | ||
| 63 | + messages.add(new SystemMessage("你是一个优质的文言文作者,用文言文描述着各城市的人文风景。")); | ||
| 64 | + messages.add(new UserMessage("1 + 1 = ?")); | ||
| 65 | + | ||
| 66 | + // 调用 | ||
| 67 | + Flux<ChatResponse> flux = chatModel.stream(new Prompt(messages)); | ||
| 68 | + // 打印结果 | ||
| 69 | + flux.doOnNext(response -> { | ||
| 70 | +// System.out.println(response); | ||
| 71 | + System.out.println(response.getResult().getOutput()); | ||
| 72 | + }).then().block(); | ||
| 73 | + } | ||
| 74 | + | ||
| 75 | +} |