Commit a1d5602c404ca6483045a85541e663c2269aa316
1 parent
46726fe6
【代码新增】AI:适配腾讯混元大模型、知识引擎(deepseek)
Showing
12 changed files
with
265 additions
and
29 deletions
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java
| @@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.ai.core.factory.AiModelFactory; | @@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.ai.core.factory.AiModelFactory; | ||
| 5 | import cn.iocoder.yudao.framework.ai.core.factory.AiModelFactoryImpl; | 5 | import cn.iocoder.yudao.framework.ai.core.factory.AiModelFactoryImpl; |
| 6 | import cn.iocoder.yudao.framework.ai.core.model.deepseek.DeepSeekChatModel; | 6 | import cn.iocoder.yudao.framework.ai.core.model.deepseek.DeepSeekChatModel; |
| 7 | import cn.iocoder.yudao.framework.ai.core.model.doubao.DouBaoChatModel; | 7 | import cn.iocoder.yudao.framework.ai.core.model.doubao.DouBaoChatModel; |
| 8 | +import cn.iocoder.yudao.framework.ai.core.model.hunyuan.HunYuanChatModel; | ||
| 8 | import cn.iocoder.yudao.framework.ai.core.model.midjourney.api.MidjourneyApi; | 9 | import cn.iocoder.yudao.framework.ai.core.model.midjourney.api.MidjourneyApi; |
| 9 | import cn.iocoder.yudao.framework.ai.core.model.suno.api.SunoApi; | 10 | import cn.iocoder.yudao.framework.ai.core.model.suno.api.SunoApi; |
| 10 | import cn.iocoder.yudao.framework.ai.core.model.xinghuo.XingHuoChatModel; | 11 | import cn.iocoder.yudao.framework.ai.core.model.xinghuo.XingHuoChatModel; |
| @@ -65,20 +66,20 @@ public class YudaoAiAutoConfiguration { | @@ -65,20 +66,20 @@ public class YudaoAiAutoConfiguration { | ||
| 65 | } | 66 | } |
| 66 | 67 | ||
| 67 | @Bean | 68 | @Bean |
| 68 | - @ConditionalOnProperty(value = "yudao.ai.xinghuo.enable", havingValue = "true") | ||
| 69 | - public XingHuoChatModel xingHuoChatClient(YudaoAiProperties yudaoAiProperties) { | ||
| 70 | - YudaoAiProperties.XingHuoProperties properties = yudaoAiProperties.getXinghuo(); | ||
| 71 | - return buildXingHuoChatClient(properties); | 69 | + @ConditionalOnProperty(value = "yudao.ai.doubao.enable", havingValue = "true") |
| 70 | + public DouBaoChatModel douBaoChatClient(YudaoAiProperties yudaoAiProperties) { | ||
| 71 | + YudaoAiProperties.DouBaoProperties properties = yudaoAiProperties.getDoubao(); | ||
| 72 | + return buildDouBaoChatClient(properties); | ||
| 72 | } | 73 | } |
| 73 | 74 | ||
| 74 | - public XingHuoChatModel buildXingHuoChatClient(YudaoAiProperties.XingHuoProperties properties) { | 75 | + public DouBaoChatModel buildDouBaoChatClient(YudaoAiProperties.DouBaoProperties properties) { |
| 75 | if (StrUtil.isEmpty(properties.getModel())) { | 76 | if (StrUtil.isEmpty(properties.getModel())) { |
| 76 | - properties.setModel(XingHuoChatModel.MODEL_DEFAULT); | 77 | + properties.setModel(DouBaoChatModel.MODEL_DEFAULT); |
| 77 | } | 78 | } |
| 78 | OpenAiChatModel openAiChatModel = OpenAiChatModel.builder() | 79 | OpenAiChatModel openAiChatModel = OpenAiChatModel.builder() |
| 79 | .openAiApi(OpenAiApi.builder() | 80 | .openAiApi(OpenAiApi.builder() |
| 80 | - .baseUrl(XingHuoChatModel.BASE_URL) | ||
| 81 | - .apiKey(properties.getAppKey() + ":" + properties.getSecretKey()) | 81 | + .baseUrl(DouBaoChatModel.BASE_URL) |
| 82 | + .apiKey(properties.getApiKey()) | ||
| 82 | .build()) | 83 | .build()) |
| 83 | .defaultOptions(OpenAiChatOptions.builder() | 84 | .defaultOptions(OpenAiChatOptions.builder() |
| 84 | .model(properties.getModel()) | 85 | .model(properties.getModel()) |
| @@ -87,24 +88,56 @@ public class YudaoAiAutoConfiguration { | @@ -87,24 +88,56 @@ public class YudaoAiAutoConfiguration { | ||
| 87 | .topP(properties.getTopP()) | 88 | .topP(properties.getTopP()) |
| 88 | .build()) | 89 | .build()) |
| 89 | .build(); | 90 | .build(); |
| 90 | - return new XingHuoChatModel(openAiChatModel); | 91 | + return new DouBaoChatModel(openAiChatModel); |
| 91 | } | 92 | } |
| 92 | 93 | ||
| 93 | @Bean | 94 | @Bean |
| 94 | - @ConditionalOnProperty(value = "yudao.ai.doubao.enable", havingValue = "true") | ||
| 95 | - public DouBaoChatModel douBaoChatClient(YudaoAiProperties yudaoAiProperties) { | ||
| 96 | - YudaoAiProperties.DouBaoProperties properties = yudaoAiProperties.getDoubao(); | ||
| 97 | - return buildDouBaoChatClient(properties); | 95 | + @ConditionalOnProperty(value = "yudao.ai.hunyuan.enable", havingValue = "true") |
| 96 | + public HunYuanChatModel hunYuanChatClient(YudaoAiProperties yudaoAiProperties) { | ||
| 97 | + YudaoAiProperties.HunYuanProperties properties = yudaoAiProperties.getHunyuan(); | ||
| 98 | + return buildHunYuanChatClient(properties); | ||
| 98 | } | 99 | } |
| 99 | 100 | ||
| 100 | - public DouBaoChatModel buildDouBaoChatClient(YudaoAiProperties.DouBaoProperties properties) { | 101 | + public HunYuanChatModel buildHunYuanChatClient(YudaoAiProperties.HunYuanProperties properties) { |
| 101 | if (StrUtil.isEmpty(properties.getModel())) { | 102 | if (StrUtil.isEmpty(properties.getModel())) { |
| 102 | - properties.setModel(DouBaoChatModel.MODEL_DEFAULT); | 103 | + properties.setModel(HunYuanChatModel.MODEL_DEFAULT); |
| 103 | } | 104 | } |
| 105 | + // 特殊:由于混元大模型不提供 deepseek,而是通过知识引擎,所以需要区分下 URL | ||
| 106 | + if (StrUtil.isEmpty(properties.getBaseUrl())) { | ||
| 107 | + properties.setBaseUrl(StrUtil.startWithIgnoreCase(properties.getModel(), "deepseek") ? | ||
| 108 | + HunYuanChatModel.DEEP_SEEK_BASE_URL : HunYuanChatModel.BASE_URL); | ||
| 109 | + } | ||
| 110 | + // 创建 OpenAiChatModel、HunYuanChatModel 对象 | ||
| 104 | OpenAiChatModel openAiChatModel = OpenAiChatModel.builder() | 111 | OpenAiChatModel openAiChatModel = OpenAiChatModel.builder() |
| 105 | .openAiApi(OpenAiApi.builder() | 112 | .openAiApi(OpenAiApi.builder() |
| 106 | - .baseUrl(DouBaoChatModel.BASE_URL) | ||
| 107 | - .apiKey(properties.getApiKey()) | 113 | + .baseUrl(properties.getBaseUrl()) |
| 114 | + .apiKey(properties.getApiKey()) | ||
| 115 | + .build()) | ||
| 116 | + .defaultOptions(OpenAiChatOptions.builder() | ||
| 117 | + .model(properties.getModel()) | ||
| 118 | + .temperature(properties.getTemperature()) | ||
| 119 | + .maxTokens(properties.getMaxTokens()) | ||
| 120 | + .topP(properties.getTopP()) | ||
| 121 | + .build()) | ||
| 122 | + .build(); | ||
| 123 | + return new HunYuanChatModel(openAiChatModel); | ||
| 124 | + } | ||
| 125 | + | ||
| 126 | + @Bean | ||
| 127 | + @ConditionalOnProperty(value = "yudao.ai.xinghuo.enable", havingValue = "true") | ||
| 128 | + public XingHuoChatModel xingHuoChatClient(YudaoAiProperties yudaoAiProperties) { | ||
| 129 | + YudaoAiProperties.XingHuoProperties properties = yudaoAiProperties.getXinghuo(); | ||
| 130 | + return buildXingHuoChatClient(properties); | ||
| 131 | + } | ||
| 132 | + | ||
| 133 | + public XingHuoChatModel buildXingHuoChatClient(YudaoAiProperties.XingHuoProperties properties) { | ||
| 134 | + if (StrUtil.isEmpty(properties.getModel())) { | ||
| 135 | + properties.setModel(XingHuoChatModel.MODEL_DEFAULT); | ||
| 136 | + } | ||
| 137 | + OpenAiChatModel openAiChatModel = OpenAiChatModel.builder() | ||
| 138 | + .openAiApi(OpenAiApi.builder() | ||
| 139 | + .baseUrl(XingHuoChatModel.BASE_URL) | ||
| 140 | + .apiKey(properties.getAppKey() + ":" + properties.getSecretKey()) | ||
| 108 | .build()) | 141 | .build()) |
| 109 | .defaultOptions(OpenAiChatOptions.builder() | 142 | .defaultOptions(OpenAiChatOptions.builder() |
| 110 | .model(properties.getModel()) | 143 | .model(properties.getModel()) |
| @@ -113,7 +146,7 @@ public class YudaoAiAutoConfiguration { | @@ -113,7 +146,7 @@ public class YudaoAiAutoConfiguration { | ||
| 113 | .topP(properties.getTopP()) | 146 | .topP(properties.getTopP()) |
| 114 | .build()) | 147 | .build()) |
| 115 | .build(); | 148 | .build(); |
| 116 | - return new DouBaoChatModel(openAiChatModel); | 149 | + return new XingHuoChatModel(openAiChatModel); |
| 117 | } | 150 | } |
| 118 | 151 | ||
| 119 | @Bean | 152 | @Bean |
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java
| @@ -26,6 +26,12 @@ public class YudaoAiProperties { | @@ -26,6 +26,12 @@ public class YudaoAiProperties { | ||
| 26 | private DouBaoProperties doubao; | 26 | private DouBaoProperties doubao; |
| 27 | 27 | ||
| 28 | /** | 28 | /** |
| 29 | + * 腾讯混元 | ||
| 30 | + */ | ||
| 31 | + @SuppressWarnings("SpellCheckingInspection") | ||
| 32 | + private HunYuanProperties hunyuan; | ||
| 33 | + | ||
| 34 | + /** | ||
| 29 | * 讯飞星火 | 35 | * 讯飞星火 |
| 30 | */ | 36 | */ |
| 31 | @SuppressWarnings("SpellCheckingInspection") | 37 | @SuppressWarnings("SpellCheckingInspection") |
| @@ -43,12 +49,10 @@ public class YudaoAiProperties { | @@ -43,12 +49,10 @@ public class YudaoAiProperties { | ||
| 43 | private SunoProperties suno; | 49 | private SunoProperties suno; |
| 44 | 50 | ||
| 45 | @Data | 51 | @Data |
| 46 | - public static class XingHuoProperties { | 52 | + public static class DeepSeekProperties { |
| 47 | 53 | ||
| 48 | private String enable; | 54 | private String enable; |
| 49 | - private String appId; | ||
| 50 | - private String appKey; | ||
| 51 | - private String secretKey; | 55 | + private String apiKey; |
| 52 | 56 | ||
| 53 | private String model; | 57 | private String model; |
| 54 | private Double temperature; | 58 | private Double temperature; |
| @@ -58,7 +62,7 @@ public class YudaoAiProperties { | @@ -58,7 +62,7 @@ public class YudaoAiProperties { | ||
| 58 | } | 62 | } |
| 59 | 63 | ||
| 60 | @Data | 64 | @Data |
| 61 | - public static class DeepSeekProperties { | 65 | + public static class DouBaoProperties { |
| 62 | 66 | ||
| 63 | private String enable; | 67 | private String enable; |
| 64 | private String apiKey; | 68 | private String apiKey; |
| @@ -71,9 +75,10 @@ public class YudaoAiProperties { | @@ -71,9 +75,10 @@ public class YudaoAiProperties { | ||
| 71 | } | 75 | } |
| 72 | 76 | ||
| 73 | @Data | 77 | @Data |
| 74 | - public static class DouBaoProperties { | 78 | + public static class HunYuanProperties { |
| 75 | 79 | ||
| 76 | private String enable; | 80 | private String enable; |
| 81 | + private String baseUrl; | ||
| 77 | private String apiKey; | 82 | private String apiKey; |
| 78 | 83 | ||
| 79 | private String model; | 84 | private String model; |
| @@ -84,6 +89,21 @@ public class YudaoAiProperties { | @@ -84,6 +89,21 @@ public class YudaoAiProperties { | ||
| 84 | } | 89 | } |
| 85 | 90 | ||
| 86 | @Data | 91 | @Data |
| 92 | + public static class XingHuoProperties { | ||
| 93 | + | ||
| 94 | + private String enable; | ||
| 95 | + private String appId; | ||
| 96 | + private String appKey; | ||
| 97 | + private String secretKey; | ||
| 98 | + | ||
| 99 | + private String model; | ||
| 100 | + private Double temperature; | ||
| 101 | + private Integer maxTokens; | ||
| 102 | + private Double topP; | ||
| 103 | + | ||
| 104 | + } | ||
| 105 | + | ||
| 106 | + @Data | ||
| 87 | public static class MidjourneyProperties { | 107 | public static class MidjourneyProperties { |
| 88 | 108 | ||
| 89 | private String enable; | 109 | private String enable; |
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java
| @@ -20,6 +20,7 @@ public enum AiPlatformEnum { | @@ -20,6 +20,7 @@ public enum AiPlatformEnum { | ||
| 20 | ZHI_PU("ZhiPu", "智谱"), // 智谱 AI | 20 | ZHI_PU("ZhiPu", "智谱"), // 智谱 AI |
| 21 | XING_HUO("XingHuo", "星火"), // 讯飞 | 21 | XING_HUO("XingHuo", "星火"), // 讯飞 |
| 22 | DOU_BAO("DouBao", "豆包"), // 字节 | 22 | DOU_BAO("DouBao", "豆包"), // 字节 |
| 23 | + HUN_YUAN("HunYuan", "混元"), // 腾讯 | ||
| 23 | 24 | ||
| 24 | // ========== 国外平台 ========== | 25 | // ========== 国外平台 ========== |
| 25 | 26 |
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiModelFactoryImpl.java
| @@ -11,6 +11,7 @@ import cn.iocoder.yudao.framework.ai.config.YudaoAiProperties; | @@ -11,6 +11,7 @@ import cn.iocoder.yudao.framework.ai.config.YudaoAiProperties; | ||
| 11 | import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; | 11 | import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; |
| 12 | import cn.iocoder.yudao.framework.ai.core.model.deepseek.DeepSeekChatModel; | 12 | import cn.iocoder.yudao.framework.ai.core.model.deepseek.DeepSeekChatModel; |
| 13 | import cn.iocoder.yudao.framework.ai.core.model.doubao.DouBaoChatModel; | 13 | import cn.iocoder.yudao.framework.ai.core.model.doubao.DouBaoChatModel; |
| 14 | +import cn.iocoder.yudao.framework.ai.core.model.hunyuan.HunYuanChatModel; | ||
| 14 | import cn.iocoder.yudao.framework.ai.core.model.midjourney.api.MidjourneyApi; | 15 | import cn.iocoder.yudao.framework.ai.core.model.midjourney.api.MidjourneyApi; |
| 15 | import cn.iocoder.yudao.framework.ai.core.model.suno.api.SunoApi; | 16 | import cn.iocoder.yudao.framework.ai.core.model.suno.api.SunoApi; |
| 16 | import cn.iocoder.yudao.framework.ai.core.model.xinghuo.XingHuoChatModel; | 17 | import cn.iocoder.yudao.framework.ai.core.model.xinghuo.XingHuoChatModel; |
| @@ -77,6 +78,8 @@ public class AiModelFactoryImpl implements AiModelFactory { | @@ -77,6 +78,8 @@ public class AiModelFactoryImpl implements AiModelFactory { | ||
| 77 | return buildDeepSeekChatModel(apiKey); | 78 | return buildDeepSeekChatModel(apiKey); |
| 78 | case DOU_BAO: | 79 | case DOU_BAO: |
| 79 | return buildDouBaoChatModel(apiKey); | 80 | return buildDouBaoChatModel(apiKey); |
| 81 | + case HUN_YUAN: | ||
| 82 | + return buildHunYuanChatModel(apiKey, url); | ||
| 80 | case ZHI_PU: | 83 | case ZHI_PU: |
| 81 | return buildZhiPuChatModel(apiKey, url); | 84 | return buildZhiPuChatModel(apiKey, url); |
| 82 | case XING_HUO: | 85 | case XING_HUO: |
| @@ -105,6 +108,8 @@ public class AiModelFactoryImpl implements AiModelFactory { | @@ -105,6 +108,8 @@ public class AiModelFactoryImpl implements AiModelFactory { | ||
| 105 | return SpringUtil.getBean(DeepSeekChatModel.class); | 108 | return SpringUtil.getBean(DeepSeekChatModel.class); |
| 106 | case DOU_BAO: | 109 | case DOU_BAO: |
| 107 | return SpringUtil.getBean(DouBaoChatModel.class); | 110 | return SpringUtil.getBean(DouBaoChatModel.class); |
| 111 | + case HUN_YUAN: | ||
| 112 | + return SpringUtil.getBean(HunYuanChatModel.class); | ||
| 108 | case ZHI_PU: | 113 | case ZHI_PU: |
| 109 | return SpringUtil.getBean(ZhiPuAiChatModel.class); | 114 | return SpringUtil.getBean(ZhiPuAiChatModel.class); |
| 110 | case XING_HUO: | 115 | case XING_HUO: |
| @@ -272,11 +277,20 @@ public class AiModelFactoryImpl implements AiModelFactory { | @@ -272,11 +277,20 @@ public class AiModelFactoryImpl implements AiModelFactory { | ||
| 272 | */ | 277 | */ |
| 273 | private ChatModel buildDouBaoChatModel(String apiKey) { | 278 | private ChatModel buildDouBaoChatModel(String apiKey) { |
| 274 | YudaoAiProperties.DouBaoProperties properties = new YudaoAiProperties.DouBaoProperties() | 279 | YudaoAiProperties.DouBaoProperties properties = new YudaoAiProperties.DouBaoProperties() |
| 275 | - .setApiKey(apiKey); | 280 | + .setApiKey(apiKey); |
| 276 | return new YudaoAiAutoConfiguration().buildDouBaoChatClient(properties); | 281 | return new YudaoAiAutoConfiguration().buildDouBaoChatClient(properties); |
| 277 | } | 282 | } |
| 278 | 283 | ||
| 279 | /** | 284 | /** |
| 285 | + * 可参考 {@link YudaoAiAutoConfiguration#hunYuanChatClient(YudaoAiProperties)} | ||
| 286 | + */ | ||
| 287 | + private ChatModel buildHunYuanChatModel(String apiKey, String url) { | ||
| 288 | + YudaoAiProperties.HunYuanProperties properties = new YudaoAiProperties.HunYuanProperties() | ||
| 289 | + .setBaseUrl(url).setApiKey(apiKey); | ||
| 290 | + return new YudaoAiAutoConfiguration().buildHunYuanChatClient(properties); | ||
| 291 | + } | ||
| 292 | + | ||
| 293 | + /** | ||
| 280 | * 可参考 {@link ZhiPuAiAutoConfiguration} 的 zhiPuAiChatModel 方法 | 294 | * 可参考 {@link ZhiPuAiAutoConfiguration} 的 zhiPuAiChatModel 方法 |
| 281 | */ | 295 | */ |
| 282 | private ZhiPuAiChatModel buildZhiPuChatModel(String apiKey, String url) { | 296 | private ZhiPuAiChatModel buildZhiPuChatModel(String apiKey, String url) { |
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/hunyuan/HunYuanChatModel.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.ai.core.model.hunyuan; | ||
| 2 | + | ||
| 3 | +import lombok.RequiredArgsConstructor; | ||
| 4 | +import lombok.extern.slf4j.Slf4j; | ||
| 5 | +import org.springframework.ai.chat.model.ChatModel; | ||
| 6 | +import org.springframework.ai.chat.model.ChatResponse; | ||
| 7 | +import org.springframework.ai.chat.prompt.ChatOptions; | ||
| 8 | +import org.springframework.ai.chat.prompt.Prompt; | ||
| 9 | +import org.springframework.ai.openai.OpenAiChatModel; | ||
| 10 | +import reactor.core.publisher.Flux; | ||
| 11 | + | ||
| 12 | +/** | ||
| 13 | + * 腾云混元 {@link ChatModel} 实现类 | ||
| 14 | + * | ||
| 15 | + * 1. 混元大模型:基于 <a href="https://cloud.tencent.com/document/product/1729/111007">知识引擎原子能力</a> 实现 | ||
| 16 | + * 2. 知识引擎原子能力:基于 <a href="https://cloud.tencent.com/document/product/1772/115969">知识引擎原子能力</a> 实现 | ||
| 17 | + * | ||
| 18 | + * @author fansili | ||
| 19 | + */ | ||
| 20 | +@Slf4j | ||
| 21 | +@RequiredArgsConstructor | ||
| 22 | +public class HunYuanChatModel implements ChatModel { | ||
| 23 | + | ||
| 24 | + public static final String BASE_URL = "https://api.hunyuan.cloud.tencent.com"; | ||
| 25 | + | ||
| 26 | + public static final String MODEL_DEFAULT = "hunyuan-turbo"; | ||
| 27 | + | ||
| 28 | + public static final String DEEP_SEEK_BASE_URL = "https://api.lkeap.cloud.tencent.com"; | ||
| 29 | + | ||
| 30 | + public static final String DEEP_SEEK_MODEL_DEFAULT = "deepseek-v3"; | ||
| 31 | + | ||
| 32 | + /** | ||
| 33 | + * 兼容 OpenAI 接口,进行复用 | ||
| 34 | + */ | ||
| 35 | + private final OpenAiChatModel openAiChatModel; | ||
| 36 | + | ||
| 37 | + @Override | ||
| 38 | + public ChatResponse call(Prompt prompt) { | ||
| 39 | + return openAiChatModel.call(prompt); | ||
| 40 | + } | ||
| 41 | + | ||
| 42 | + @Override | ||
| 43 | + public Flux<ChatResponse> stream(Prompt prompt) { | ||
| 44 | + return openAiChatModel.stream(prompt); | ||
| 45 | + } | ||
| 46 | + | ||
| 47 | + @Override | ||
| 48 | + public ChatOptions getDefaultOptions() { | ||
| 49 | + return openAiChatModel.getDefaultOptions(); | ||
| 50 | + } | ||
| 51 | + | ||
| 52 | +} |
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/util/AiUtils.java
| @@ -31,6 +31,7 @@ public class AiUtils { | @@ -31,6 +31,7 @@ public class AiUtils { | ||
| 31 | case OPENAI: | 31 | case OPENAI: |
| 32 | case DEEP_SEEK: // 复用 OpenAI 客户端 | 32 | case DEEP_SEEK: // 复用 OpenAI 客户端 |
| 33 | case DOU_BAO: // 复用 OpenAI 客户端 | 33 | case DOU_BAO: // 复用 OpenAI 客户端 |
| 34 | + case HUN_YUAN: // 复用 OpenAI 客户端 | ||
| 34 | case XING_HUO: // 复用 OpenAI 客户端 | 35 | case XING_HUO: // 复用 OpenAI 客户端 |
| 35 | return OpenAiChatOptions.builder().model(model).temperature(temperature).maxTokens(maxTokens).build(); | 36 | return OpenAiChatOptions.builder().model(model).temperature(temperature).maxTokens(maxTokens).build(); |
| 36 | case AZURE_OPENAI: | 37 | case AZURE_OPENAI: |
yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/DeepSeekChatModelTests.java
| @@ -23,7 +23,7 @@ import java.util.List; | @@ -23,7 +23,7 @@ import java.util.List; | ||
| 23 | */ | 23 | */ |
| 24 | public class DeepSeekChatModelTests { | 24 | public class DeepSeekChatModelTests { |
| 25 | 25 | ||
| 26 | - private static final OpenAiChatModel openAiChatModel = OpenAiChatModel.builder() | 26 | + private final OpenAiChatModel openAiChatModel = OpenAiChatModel.builder() |
| 27 | .openAiApi(OpenAiApi.builder() | 27 | .openAiApi(OpenAiApi.builder() |
| 28 | .baseUrl(DeepSeekChatModel.BASE_URL) | 28 | .baseUrl(DeepSeekChatModel.BASE_URL) |
| 29 | .apiKey("sk-e52047409b144d97b791a6a46a2d") // apiKey | 29 | .apiKey("sk-e52047409b144d97b791a6a46a2d") // apiKey |
yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/DouBaoChatModelTests.java
| @@ -24,7 +24,7 @@ import java.util.List; | @@ -24,7 +24,7 @@ import java.util.List; | ||
| 24 | */ | 24 | */ |
| 25 | public class DouBaoChatModelTests { | 25 | public class DouBaoChatModelTests { |
| 26 | 26 | ||
| 27 | - private static final OpenAiChatModel openAiChatModel = OpenAiChatModel.builder() | 27 | + private final OpenAiChatModel openAiChatModel = OpenAiChatModel.builder() |
| 28 | .openAiApi(OpenAiApi.builder() | 28 | .openAiApi(OpenAiApi.builder() |
| 29 | .baseUrl(DouBaoChatModel.BASE_URL) | 29 | .baseUrl(DouBaoChatModel.BASE_URL) |
| 30 | .apiKey("5c1b5747-26d2-4ebd-a4e0-dd0e8d8b4272") // apiKey | 30 | .apiKey("5c1b5747-26d2-4ebd-a4e0-dd0e8d8b4272") // apiKey |
yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/HunYuanChatModelTests.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.ai.chat; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.ai.core.model.deepseek.DeepSeekChatModel; | ||
| 4 | +import cn.iocoder.yudao.framework.ai.core.model.hunyuan.HunYuanChatModel; | ||
| 5 | +import org.junit.jupiter.api.Disabled; | ||
| 6 | +import org.junit.jupiter.api.Test; | ||
| 7 | +import org.springframework.ai.chat.messages.Message; | ||
| 8 | +import org.springframework.ai.chat.messages.SystemMessage; | ||
| 9 | +import org.springframework.ai.chat.messages.UserMessage; | ||
| 10 | +import org.springframework.ai.chat.model.ChatResponse; | ||
| 11 | +import org.springframework.ai.chat.prompt.Prompt; | ||
| 12 | +import org.springframework.ai.openai.OpenAiChatModel; | ||
| 13 | +import org.springframework.ai.openai.OpenAiChatOptions; | ||
| 14 | +import org.springframework.ai.openai.api.OpenAiApi; | ||
| 15 | +import reactor.core.publisher.Flux; | ||
| 16 | + | ||
| 17 | +import java.util.ArrayList; | ||
| 18 | +import java.util.List; | ||
| 19 | + | ||
| 20 | +/** | ||
| 21 | + * {@link DeepSeekChatModel} 集成测试 | ||
| 22 | + * | ||
| 23 | + * @author 芋道源码 | ||
| 24 | + */ | ||
| 25 | +public class HunYuanChatModelTests { | ||
| 26 | + | ||
| 27 | + private final OpenAiChatModel openAiChatModel = OpenAiChatModel.builder() | ||
| 28 | + .openAiApi(OpenAiApi.builder() | ||
| 29 | + .baseUrl(HunYuanChatModel.BASE_URL) | ||
| 30 | + .apiKey("sk-bcd") // apiKey | ||
| 31 | + .build()) | ||
| 32 | + .defaultOptions(OpenAiChatOptions.builder() | ||
| 33 | + .model(HunYuanChatModel.MODEL_DEFAULT) // 模型 | ||
| 34 | + .temperature(0.7) | ||
| 35 | + .build()) | ||
| 36 | + .build(); | ||
| 37 | + | ||
| 38 | + private final HunYuanChatModel chatModel = new HunYuanChatModel(openAiChatModel); | ||
| 39 | + | ||
| 40 | + @Test | ||
| 41 | + @Disabled | ||
| 42 | + public void testCall() { | ||
| 43 | + // 准备参数 | ||
| 44 | + List<Message> messages = new ArrayList<>(); | ||
| 45 | + messages.add(new SystemMessage("你是一个优质的文言文作者,用文言文描述着各城市的人文风景。")); | ||
| 46 | + messages.add(new UserMessage("1 + 1 = ?")); | ||
| 47 | + | ||
| 48 | + // 调用 | ||
| 49 | + ChatResponse response = chatModel.call(new Prompt(messages)); | ||
| 50 | + // 打印结果 | ||
| 51 | + System.out.println(response); | ||
| 52 | + } | ||
| 53 | + | ||
| 54 | + @Test | ||
| 55 | + @Disabled | ||
| 56 | + public void testStream() { | ||
| 57 | + // 准备参数 | ||
| 58 | + List<Message> messages = new ArrayList<>(); | ||
| 59 | + messages.add(new SystemMessage("你是一个优质的文言文作者,用文言文描述着各城市的人文风景。")); | ||
| 60 | + messages.add(new UserMessage("1 + 1 = ?")); | ||
| 61 | + | ||
| 62 | + // 调用 | ||
| 63 | + Flux<ChatResponse> flux = chatModel.stream(new Prompt(messages)); | ||
| 64 | + // 打印结果 | ||
| 65 | + flux.doOnNext(System.out::println).then().block(); | ||
| 66 | + } | ||
| 67 | + | ||
| 68 | + private final OpenAiChatModel deepSeekOpenAiChatModel = OpenAiChatModel.builder() | ||
| 69 | + .openAiApi(OpenAiApi.builder() | ||
| 70 | + .baseUrl(HunYuanChatModel.DEEP_SEEK_BASE_URL) | ||
| 71 | + .apiKey("sk-abc") // apiKey | ||
| 72 | + .build()) | ||
| 73 | + .defaultOptions(OpenAiChatOptions.builder() | ||
| 74 | +// .model(HunYuanChatModel.DEEP_SEEK_MODEL_DEFAULT) // 模型("deepseek-v3") | ||
| 75 | + .model("deepseek-r1") // 模型("deepseek-r1") | ||
| 76 | + .temperature(0.7) | ||
| 77 | + .build()) | ||
| 78 | + .build(); | ||
| 79 | + | ||
| 80 | + private final HunYuanChatModel deepSeekChatModel = new HunYuanChatModel(deepSeekOpenAiChatModel); | ||
| 81 | + | ||
| 82 | + @Test | ||
| 83 | + @Disabled | ||
| 84 | + public void testCall_deepseek() { | ||
| 85 | + // 准备参数 | ||
| 86 | + List<Message> messages = new ArrayList<>(); | ||
| 87 | + messages.add(new SystemMessage("你是一个优质的文言文作者,用文言文描述着各城市的人文风景。")); | ||
| 88 | + messages.add(new UserMessage("1 + 1 = ?")); | ||
| 89 | + | ||
| 90 | + // 调用 | ||
| 91 | + ChatResponse response = deepSeekChatModel.call(new Prompt(messages)); | ||
| 92 | + // 打印结果 | ||
| 93 | + System.out.println(response); | ||
| 94 | + } | ||
| 95 | + | ||
| 96 | + @Test | ||
| 97 | + @Disabled | ||
| 98 | + public void testStream_deekseek() { | ||
| 99 | + // 准备参数 | ||
| 100 | + List<Message> messages = new ArrayList<>(); | ||
| 101 | + messages.add(new SystemMessage("你是一个优质的文言文作者,用文言文描述着各城市的人文风景。")); | ||
| 102 | + messages.add(new UserMessage("1 + 1 = ?")); | ||
| 103 | + | ||
| 104 | + // 调用 | ||
| 105 | + Flux<ChatResponse> flux = deepSeekChatModel.stream(new Prompt(messages)); | ||
| 106 | + // 打印结果 | ||
| 107 | + flux.doOnNext(System.out::println).then().block(); | ||
| 108 | + } | ||
| 109 | + | ||
| 110 | + | ||
| 111 | +} |
yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/OpenAIChatModelTests.java
| @@ -22,7 +22,7 @@ import java.util.List; | @@ -22,7 +22,7 @@ import java.util.List; | ||
| 22 | */ | 22 | */ |
| 23 | public class OpenAIChatModelTests { | 23 | public class OpenAIChatModelTests { |
| 24 | 24 | ||
| 25 | - private static final OpenAiChatModel chatModel = OpenAiChatModel.builder() | 25 | + private final OpenAiChatModel chatModel = OpenAiChatModel.builder() |
| 26 | .openAiApi(OpenAiApi.builder() | 26 | .openAiApi(OpenAiApi.builder() |
| 27 | .baseUrl("https://api.holdai.top") | 27 | .baseUrl("https://api.holdai.top") |
| 28 | .apiKey("sk-aN6nWn3fILjrgLFT0fC4Aa60B72e4253826c77B29dC94f17") // apiKey | 28 | .apiKey("sk-aN6nWn3fILjrgLFT0fC4Aa60B72e4253826c77B29dC94f17") // apiKey |
yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/XingHuoChatModelTests.java
| @@ -23,7 +23,7 @@ import java.util.List; | @@ -23,7 +23,7 @@ import java.util.List; | ||
| 23 | */ | 23 | */ |
| 24 | public class XingHuoChatModelTests { | 24 | public class XingHuoChatModelTests { |
| 25 | 25 | ||
| 26 | - private static final OpenAiChatModel openAiChatModel = OpenAiChatModel.builder() | 26 | + private final OpenAiChatModel openAiChatModel = OpenAiChatModel.builder() |
| 27 | .openAiApi(OpenAiApi.builder() | 27 | .openAiApi(OpenAiApi.builder() |
| 28 | .baseUrl(XingHuoChatModel.BASE_URL) | 28 | .baseUrl(XingHuoChatModel.BASE_URL) |
| 29 | .apiKey("75b161ed2aef4719b275d6e7f2a4d4cd:YWYxYWI2MTA4ODI2NGZlYTQyNjAzZTcz") // appKey:secretKey | 29 | .apiKey("75b161ed2aef4719b275d6e7f2a4d4cd:YWYxYWI2MTA4ODI2NGZlYTQyNjAzZTcz") // appKey:secretKey |
yudao-server/src/main/resources/application.yaml
| @@ -188,6 +188,10 @@ yudao: | @@ -188,6 +188,10 @@ yudao: | ||
| 188 | enable: true | 188 | enable: true |
| 189 | api-key: 5c1b5747-26d2-4ebd-a4e0-dd0e8d8b4272 | 189 | api-key: 5c1b5747-26d2-4ebd-a4e0-dd0e8d8b4272 |
| 190 | model: doubao-1-5-lite-32k-250115 | 190 | model: doubao-1-5-lite-32k-250115 |
| 191 | + hunyuan: # 腾讯混元 | ||
| 192 | + enable: true | ||
| 193 | + api-key: sk-abc | ||
| 194 | + model: hunyuan-turbo | ||
| 191 | xinghuo: # 讯飞星火 | 195 | xinghuo: # 讯飞星火 |
| 192 | enable: true | 196 | enable: true |
| 193 | appKey: 75b161ed2aef4719b275d6e7f2a4d4cd | 197 | appKey: 75b161ed2aef4719b275d6e7f2a4d4cd |