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 | 14 | |
| 15 | 15 | // ========== 国内平台 ========== |
| 16 | 16 | |
| 17 | + TONG_YI("TongYi", "通义千问"), // 阿里 | |
| 17 | 18 | YI_YAN("YiYan", "文心一言"), // 百度 |
| 18 | - QIAN_WEN("QianWen", "千问"), // 阿里 | |
| 19 | 19 | DEEP_SEEK("DeepSeek", "DeepSeek"), // DeepSeek |
| 20 | 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 | 55 | return Singleton.get(cacheKey, (Func0<ChatModel>) () -> { |
| 56 | 56 | //noinspection EnhancedSwitchMigration |
| 57 | 57 | switch (platform) { |
| 58 | + case TONG_YI: | |
| 59 | + return buildTongYiChatModel(apiKey); | |
| 58 | 60 | case YI_YAN: |
| 59 | 61 | return buildYiYanChatClient(apiKey); |
| 60 | 62 | case XING_HUO: |
| 61 | 63 | return buildXingHuoChatClient(apiKey); |
| 62 | - case QIAN_WEN: | |
| 63 | - return buildQianWenChatClient(apiKey); | |
| 64 | 64 | case DEEP_SEEK: |
| 65 | 65 | return buildDeepSeekChatClient(apiKey); |
| 66 | 66 | case OPENAI: |
| ... | ... | @@ -77,16 +77,16 @@ public class AiModelFactoryImpl implements AiModelFactory { |
| 77 | 77 | public ChatModel getDefaultChatModel(AiPlatformEnum platform) { |
| 78 | 78 | //noinspection EnhancedSwitchMigration |
| 79 | 79 | switch (platform) { |
| 80 | - case OLLAMA: | |
| 81 | - return SpringUtil.getBean(OllamaChatModel.class); | |
| 80 | + case TONG_YI: | |
| 81 | + return SpringUtil.getBean(TongYiChatModel.class); | |
| 82 | 82 | case YI_YAN: |
| 83 | 83 | return SpringUtil.getBean(QianFanChatModel.class); |
| 84 | 84 | case XING_HUO: |
| 85 | 85 | return SpringUtil.getBean(XingHuoChatClient.class); |
| 86 | - case QIAN_WEN: | |
| 87 | - return SpringUtil.getBean(TongYiChatModel.class); | |
| 88 | 86 | case OPENAI: |
| 89 | 87 | return SpringUtil.getBean(OpenAiChatModel.class); |
| 88 | + case OLLAMA: | |
| 89 | + return SpringUtil.getBean(OllamaChatModel.class); | |
| 90 | 90 | default: |
| 91 | 91 | throw new IllegalArgumentException(StrUtil.format("未知平台({})", platform)); |
| 92 | 92 | } |
| ... | ... | @@ -143,6 +143,20 @@ public class AiModelFactoryImpl implements AiModelFactory { |
| 143 | 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 | 160 | * 可参考 {@link OpenAiAutoConfiguration} |
| 147 | 161 | */ |
| 148 | 162 | private static OpenAiChatModel buildOpenAiChatModel(String openAiToken, String url) { |
| ... | ... | @@ -196,19 +210,6 @@ public class AiModelFactoryImpl implements AiModelFactory { |
| 196 | 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 | 213 | private StabilityAiImageModel buildStabilityAiImageClient(String apiKey, String url) { |
| 213 | 214 | url = StrUtil.blankToDefault(url, StabilityAiApi.DEFAULT_BASE_URL); |
| 214 | 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 | 32 | return QianFanChatOptions.builder().withTemperature(temperatureF).withMaxTokens(maxTokens).build(); |
| 33 | 33 | case XING_HUO: |
| 34 | 34 | return XingHuoChatOptions.builder().model(model).temperature(temperatureF).maxTokens(maxTokens).build(); |
| 35 | - case QIAN_WEN: | |
| 35 | + case TONG_YI: | |
| 36 | 36 | return TongYiChatOptions.builder().withModel(model).withTemperature(temperature).withMaxTokens(maxTokens).build(); |
| 37 | 37 | case DEEP_SEEK: |
| 38 | 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 | +} | ... | ... |