Преглед изворни кода

【代码新增】AI:适配腾讯混元大模型、知识引擎(deepseek)

YunaiV пре 5 месеци
родитељ
комит
a1d5602c40
12 измењених фајлова са 265 додато и 29 уклоњено
  1. 51 18
      yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java
  2. 26 6
      yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java
  3. 1 0
      yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java
  4. 15 1
      yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiModelFactoryImpl.java
  5. 52 0
      yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/hunyuan/HunYuanChatModel.java
  6. 1 0
      yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/util/AiUtils.java
  7. 1 1
      yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/DeepSeekChatModelTests.java
  8. 1 1
      yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/DouBaoChatModelTests.java
  9. 111 0
      yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/HunYuanChatModelTests.java
  10. 1 1
      yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/OpenAIChatModelTests.java
  11. 1 1
      yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/XingHuoChatModelTests.java
  12. 4 0
      yudao-server/src/main/resources/application.yaml

+ 51 - 18
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;
 import cn.iocoder.yudao.framework.ai.core.factory.AiModelFactoryImpl;
 import cn.iocoder.yudao.framework.ai.core.model.deepseek.DeepSeekChatModel;
 import cn.iocoder.yudao.framework.ai.core.model.doubao.DouBaoChatModel;
+import cn.iocoder.yudao.framework.ai.core.model.hunyuan.HunYuanChatModel;
 import cn.iocoder.yudao.framework.ai.core.model.midjourney.api.MidjourneyApi;
 import cn.iocoder.yudao.framework.ai.core.model.suno.api.SunoApi;
 import cn.iocoder.yudao.framework.ai.core.model.xinghuo.XingHuoChatModel;
@@ -65,20 +66,20 @@ public class YudaoAiAutoConfiguration {
     }
 
     @Bean
-    @ConditionalOnProperty(value = "yudao.ai.xinghuo.enable", havingValue = "true")
-    public XingHuoChatModel xingHuoChatClient(YudaoAiProperties yudaoAiProperties) {
-        YudaoAiProperties.XingHuoProperties properties = yudaoAiProperties.getXinghuo();
-        return buildXingHuoChatClient(properties);
+    @ConditionalOnProperty(value = "yudao.ai.doubao.enable", havingValue = "true")
+    public DouBaoChatModel douBaoChatClient(YudaoAiProperties yudaoAiProperties) {
+        YudaoAiProperties.DouBaoProperties properties = yudaoAiProperties.getDoubao();
+        return buildDouBaoChatClient(properties);
     }
 
-    public XingHuoChatModel buildXingHuoChatClient(YudaoAiProperties.XingHuoProperties properties) {
+    public DouBaoChatModel buildDouBaoChatClient(YudaoAiProperties.DouBaoProperties properties) {
         if (StrUtil.isEmpty(properties.getModel())) {
-            properties.setModel(XingHuoChatModel.MODEL_DEFAULT);
+            properties.setModel(DouBaoChatModel.MODEL_DEFAULT);
         }
         OpenAiChatModel openAiChatModel = OpenAiChatModel.builder()
                 .openAiApi(OpenAiApi.builder()
-                        .baseUrl(XingHuoChatModel.BASE_URL)
-                        .apiKey(properties.getAppKey() + ":" + properties.getSecretKey())
+                        .baseUrl(DouBaoChatModel.BASE_URL)
+                        .apiKey(properties.getApiKey())
                         .build())
                 .defaultOptions(OpenAiChatOptions.builder()
                         .model(properties.getModel())
@@ -87,24 +88,56 @@ public class YudaoAiAutoConfiguration {
                         .topP(properties.getTopP())
                         .build())
                 .build();
-        return new XingHuoChatModel(openAiChatModel);
+        return new DouBaoChatModel(openAiChatModel);
     }
 
     @Bean
-    @ConditionalOnProperty(value = "yudao.ai.doubao.enable", havingValue = "true")
-    public DouBaoChatModel douBaoChatClient(YudaoAiProperties yudaoAiProperties) {
-        YudaoAiProperties.DouBaoProperties properties = yudaoAiProperties.getDoubao();
-        return buildDouBaoChatClient(properties);
+    @ConditionalOnProperty(value = "yudao.ai.hunyuan.enable", havingValue = "true")
+    public HunYuanChatModel hunYuanChatClient(YudaoAiProperties yudaoAiProperties) {
+        YudaoAiProperties.HunYuanProperties properties = yudaoAiProperties.getHunyuan();
+        return buildHunYuanChatClient(properties);
     }
 
-    public DouBaoChatModel buildDouBaoChatClient(YudaoAiProperties.DouBaoProperties properties) {
+    public HunYuanChatModel buildHunYuanChatClient(YudaoAiProperties.HunYuanProperties properties) {
         if (StrUtil.isEmpty(properties.getModel())) {
-            properties.setModel(DouBaoChatModel.MODEL_DEFAULT);
+            properties.setModel(HunYuanChatModel.MODEL_DEFAULT);
         }
+        // 特殊:由于混元大模型不提供 deepseek,而是通过知识引擎,所以需要区分下 URL
+        if (StrUtil.isEmpty(properties.getBaseUrl())) {
+            properties.setBaseUrl(StrUtil.startWithIgnoreCase(properties.getModel(), "deepseek") ?
+                    HunYuanChatModel.DEEP_SEEK_BASE_URL : HunYuanChatModel.BASE_URL);
+        }
+        // 创建 OpenAiChatModel、HunYuanChatModel 对象
         OpenAiChatModel openAiChatModel = OpenAiChatModel.builder()
                 .openAiApi(OpenAiApi.builder()
-                        .baseUrl(DouBaoChatModel.BASE_URL)
-                        .apiKey(properties.getApiKey())
+                      .baseUrl(properties.getBaseUrl())
+                      .apiKey(properties.getApiKey())
+                      .build())
+                .defaultOptions(OpenAiChatOptions.builder()
+                        .model(properties.getModel())
+                        .temperature(properties.getTemperature())
+                        .maxTokens(properties.getMaxTokens())
+                        .topP(properties.getTopP())
+                        .build())
+                .build();
+        return new HunYuanChatModel(openAiChatModel);
+    }
+
+    @Bean
+    @ConditionalOnProperty(value = "yudao.ai.xinghuo.enable", havingValue = "true")
+    public XingHuoChatModel xingHuoChatClient(YudaoAiProperties yudaoAiProperties) {
+        YudaoAiProperties.XingHuoProperties properties = yudaoAiProperties.getXinghuo();
+        return buildXingHuoChatClient(properties);
+    }
+
+    public XingHuoChatModel buildXingHuoChatClient(YudaoAiProperties.XingHuoProperties properties) {
+        if (StrUtil.isEmpty(properties.getModel())) {
+            properties.setModel(XingHuoChatModel.MODEL_DEFAULT);
+        }
+        OpenAiChatModel openAiChatModel = OpenAiChatModel.builder()
+                .openAiApi(OpenAiApi.builder()
+                        .baseUrl(XingHuoChatModel.BASE_URL)
+                        .apiKey(properties.getAppKey() + ":" + properties.getSecretKey())
                         .build())
                 .defaultOptions(OpenAiChatOptions.builder()
                         .model(properties.getModel())
@@ -113,7 +146,7 @@ public class YudaoAiAutoConfiguration {
                         .topP(properties.getTopP())
                         .build())
                 .build();
-        return new DouBaoChatModel(openAiChatModel);
+        return new XingHuoChatModel(openAiChatModel);
     }
 
     @Bean

+ 26 - 6
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java

@@ -25,6 +25,12 @@ public class YudaoAiProperties {
     @SuppressWarnings("SpellCheckingInspection")
     private DouBaoProperties doubao;
 
+    /**
+     * 腾讯混元
+     */
+    @SuppressWarnings("SpellCheckingInspection")
+    private HunYuanProperties hunyuan;
+
     /**
      * 讯飞星火
      */
@@ -43,12 +49,10 @@ public class YudaoAiProperties {
     private SunoProperties suno;
 
     @Data
-    public static class XingHuoProperties {
+    public static class DeepSeekProperties {
 
         private String enable;
-        private String appId;
-        private String appKey;
-        private String secretKey;
+        private String apiKey;
 
         private String model;
         private Double temperature;
@@ -58,7 +62,7 @@ public class YudaoAiProperties {
     }
 
     @Data
-    public static class DeepSeekProperties {
+    public static class DouBaoProperties {
 
         private String enable;
         private String apiKey;
@@ -71,9 +75,10 @@ public class YudaoAiProperties {
     }
 
     @Data
-    public static class DouBaoProperties {
+    public static class HunYuanProperties {
 
         private String enable;
+        private String baseUrl;
         private String apiKey;
 
         private String model;
@@ -83,6 +88,21 @@ public class YudaoAiProperties {
 
     }
 
+    @Data
+    public static class XingHuoProperties {
+
+        private String enable;
+        private String appId;
+        private String appKey;
+        private String secretKey;
+
+        private String model;
+        private Double temperature;
+        private Integer maxTokens;
+        private Double topP;
+
+    }
+
     @Data
     public static class MidjourneyProperties {
 

+ 1 - 0
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 {
     ZHI_PU("ZhiPu", "智谱"), // 智谱 AI
     XING_HUO("XingHuo", "星火"), // 讯飞
     DOU_BAO("DouBao", "豆包"), // 字节
+    HUN_YUAN("HunYuan", "混元"), // 腾讯
 
     // ========== 国外平台 ==========
 

+ 15 - 1
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;
 import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum;
 import cn.iocoder.yudao.framework.ai.core.model.deepseek.DeepSeekChatModel;
 import cn.iocoder.yudao.framework.ai.core.model.doubao.DouBaoChatModel;
+import cn.iocoder.yudao.framework.ai.core.model.hunyuan.HunYuanChatModel;
 import cn.iocoder.yudao.framework.ai.core.model.midjourney.api.MidjourneyApi;
 import cn.iocoder.yudao.framework.ai.core.model.suno.api.SunoApi;
 import cn.iocoder.yudao.framework.ai.core.model.xinghuo.XingHuoChatModel;
@@ -77,6 +78,8 @@ public class AiModelFactoryImpl implements AiModelFactory {
                     return buildDeepSeekChatModel(apiKey);
                 case DOU_BAO:
                     return buildDouBaoChatModel(apiKey);
+                case HUN_YUAN:
+                    return buildHunYuanChatModel(apiKey, url);
                 case ZHI_PU:
                     return buildZhiPuChatModel(apiKey, url);
                 case XING_HUO:
@@ -105,6 +108,8 @@ public class AiModelFactoryImpl implements AiModelFactory {
                 return SpringUtil.getBean(DeepSeekChatModel.class);
             case DOU_BAO:
                 return SpringUtil.getBean(DouBaoChatModel.class);
+            case HUN_YUAN:
+                return SpringUtil.getBean(HunYuanChatModel.class);
             case ZHI_PU:
                 return SpringUtil.getBean(ZhiPuAiChatModel.class);
             case XING_HUO:
@@ -272,10 +277,19 @@ public class AiModelFactoryImpl implements AiModelFactory {
      */
     private ChatModel buildDouBaoChatModel(String apiKey) {
         YudaoAiProperties.DouBaoProperties properties = new YudaoAiProperties.DouBaoProperties()
-               .setApiKey(apiKey);
+                .setApiKey(apiKey);
         return new YudaoAiAutoConfiguration().buildDouBaoChatClient(properties);
     }
 
+    /**
+     * 可参考 {@link YudaoAiAutoConfiguration#hunYuanChatClient(YudaoAiProperties)}
+     */
+    private ChatModel buildHunYuanChatModel(String apiKey, String url) {
+        YudaoAiProperties.HunYuanProperties properties = new YudaoAiProperties.HunYuanProperties()
+                .setBaseUrl(url).setApiKey(apiKey);
+        return new YudaoAiAutoConfiguration().buildHunYuanChatClient(properties);
+    }
+
     /**
      * 可参考 {@link ZhiPuAiAutoConfiguration} 的 zhiPuAiChatModel 方法
      */

+ 52 - 0
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/hunyuan/HunYuanChatModel.java

@@ -0,0 +1,52 @@
+package cn.iocoder.yudao.framework.ai.core.model.hunyuan;
+
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.ai.chat.model.ChatModel;
+import org.springframework.ai.chat.model.ChatResponse;
+import org.springframework.ai.chat.prompt.ChatOptions;
+import org.springframework.ai.chat.prompt.Prompt;
+import org.springframework.ai.openai.OpenAiChatModel;
+import reactor.core.publisher.Flux;
+
+/**
+ * 腾云混元 {@link ChatModel} 实现类
+ *
+ * 1. 混元大模型:基于 <a href="https://cloud.tencent.com/document/product/1729/111007">知识引擎原子能力</a> 实现
+ * 2. 知识引擎原子能力:基于 <a href="https://cloud.tencent.com/document/product/1772/115969">知识引擎原子能力</a> 实现
+ *
+ * @author fansili
+ */
+@Slf4j
+@RequiredArgsConstructor
+public class HunYuanChatModel implements ChatModel {
+
+    public static final String BASE_URL = "https://api.hunyuan.cloud.tencent.com";
+
+    public static final String MODEL_DEFAULT = "hunyuan-turbo";
+
+    public static final String DEEP_SEEK_BASE_URL = "https://api.lkeap.cloud.tencent.com";
+
+    public static final String DEEP_SEEK_MODEL_DEFAULT = "deepseek-v3";
+
+    /**
+     * 兼容 OpenAI 接口,进行复用
+     */
+    private final OpenAiChatModel openAiChatModel;
+
+    @Override
+    public ChatResponse call(Prompt prompt) {
+        return openAiChatModel.call(prompt);
+    }
+
+    @Override
+    public Flux<ChatResponse> stream(Prompt prompt) {
+        return openAiChatModel.stream(prompt);
+    }
+
+    @Override
+    public ChatOptions getDefaultOptions() {
+        return openAiChatModel.getDefaultOptions();
+    }
+
+}

+ 1 - 0
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 {
             case OPENAI:
             case DEEP_SEEK: // 复用 OpenAI 客户端
             case DOU_BAO: // 复用 OpenAI 客户端
+            case HUN_YUAN: // 复用 OpenAI 客户端
             case XING_HUO: // 复用 OpenAI 客户端
                 return OpenAiChatOptions.builder().model(model).temperature(temperature).maxTokens(maxTokens).build();
             case AZURE_OPENAI:

+ 1 - 1
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;
  */
 public class DeepSeekChatModelTests {
 
-    private static final OpenAiChatModel openAiChatModel = OpenAiChatModel.builder()
+    private final OpenAiChatModel openAiChatModel = OpenAiChatModel.builder()
             .openAiApi(OpenAiApi.builder()
                     .baseUrl(DeepSeekChatModel.BASE_URL)
                     .apiKey("sk-e52047409b144d97b791a6a46a2d") // apiKey

+ 1 - 1
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;
  */
 public class DouBaoChatModelTests {
 
-    private static final OpenAiChatModel openAiChatModel = OpenAiChatModel.builder()
+    private final OpenAiChatModel openAiChatModel = OpenAiChatModel.builder()
             .openAiApi(OpenAiApi.builder()
                     .baseUrl(DouBaoChatModel.BASE_URL)
                     .apiKey("5c1b5747-26d2-4ebd-a4e0-dd0e8d8b4272") // apiKey

+ 111 - 0
yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/HunYuanChatModelTests.java

@@ -0,0 +1,111 @@
+package cn.iocoder.yudao.framework.ai.chat;
+
+import cn.iocoder.yudao.framework.ai.core.model.deepseek.DeepSeekChatModel;
+import cn.iocoder.yudao.framework.ai.core.model.hunyuan.HunYuanChatModel;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.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 org.springframework.ai.openai.OpenAiChatModel;
+import org.springframework.ai.openai.OpenAiChatOptions;
+import org.springframework.ai.openai.api.OpenAiApi;
+import reactor.core.publisher.Flux;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * {@link DeepSeekChatModel} 集成测试
+ *
+ * @author 芋道源码
+ */
+public class HunYuanChatModelTests {
+
+    private final OpenAiChatModel openAiChatModel = OpenAiChatModel.builder()
+            .openAiApi(OpenAiApi.builder()
+                    .baseUrl(HunYuanChatModel.BASE_URL)
+                    .apiKey("sk-bcd") // apiKey
+                    .build())
+            .defaultOptions(OpenAiChatOptions.builder()
+                    .model(HunYuanChatModel.MODEL_DEFAULT) // 模型
+                    .temperature(0.7)
+                    .build())
+            .build();
+
+    private final HunYuanChatModel chatModel = new HunYuanChatModel(openAiChatModel);
+
+    @Test
+    @Disabled
+    public void testCall() {
+        // 准备参数
+        List<Message> messages = new ArrayList<>();
+        messages.add(new SystemMessage("你是一个优质的文言文作者,用文言文描述着各城市的人文风景。"));
+        messages.add(new UserMessage("1 + 1 = ?"));
+
+        // 调用
+        ChatResponse response = chatModel.call(new Prompt(messages));
+        // 打印结果
+        System.out.println(response);
+    }
+
+    @Test
+    @Disabled
+    public void testStream() {
+        // 准备参数
+        List<Message> messages = new ArrayList<>();
+        messages.add(new SystemMessage("你是一个优质的文言文作者,用文言文描述着各城市的人文风景。"));
+        messages.add(new UserMessage("1 + 1 = ?"));
+
+        // 调用
+        Flux<ChatResponse> flux = chatModel.stream(new Prompt(messages));
+        // 打印结果
+        flux.doOnNext(System.out::println).then().block();
+    }
+
+    private final OpenAiChatModel deepSeekOpenAiChatModel = OpenAiChatModel.builder()
+            .openAiApi(OpenAiApi.builder()
+                    .baseUrl(HunYuanChatModel.DEEP_SEEK_BASE_URL)
+                    .apiKey("sk-abc") // apiKey
+                    .build())
+            .defaultOptions(OpenAiChatOptions.builder()
+//                    .model(HunYuanChatModel.DEEP_SEEK_MODEL_DEFAULT) // 模型("deepseek-v3")
+                    .model("deepseek-r1") // 模型("deepseek-r1")
+                    .temperature(0.7)
+                    .build())
+            .build();
+
+    private final HunYuanChatModel deepSeekChatModel = new HunYuanChatModel(deepSeekOpenAiChatModel);
+
+    @Test
+    @Disabled
+    public void testCall_deepseek() {
+        // 准备参数
+        List<Message> messages = new ArrayList<>();
+        messages.add(new SystemMessage("你是一个优质的文言文作者,用文言文描述着各城市的人文风景。"));
+        messages.add(new UserMessage("1 + 1 = ?"));
+
+        // 调用
+        ChatResponse response = deepSeekChatModel.call(new Prompt(messages));
+        // 打印结果
+        System.out.println(response);
+    }
+
+    @Test
+    @Disabled
+    public void testStream_deekseek() {
+        // 准备参数
+        List<Message> messages = new ArrayList<>();
+        messages.add(new SystemMessage("你是一个优质的文言文作者,用文言文描述着各城市的人文风景。"));
+        messages.add(new UserMessage("1 + 1 = ?"));
+
+        // 调用
+        Flux<ChatResponse> flux = deepSeekChatModel.stream(new Prompt(messages));
+        // 打印结果
+        flux.doOnNext(System.out::println).then().block();
+    }
+
+
+}

+ 1 - 1
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;
  */
 public class OpenAIChatModelTests {
 
-    private static final OpenAiChatModel chatModel = OpenAiChatModel.builder()
+    private final OpenAiChatModel chatModel = OpenAiChatModel.builder()
             .openAiApi(OpenAiApi.builder()
                     .baseUrl("https://api.holdai.top")
                     .apiKey("sk-aN6nWn3fILjrgLFT0fC4Aa60B72e4253826c77B29dC94f17") // apiKey

+ 1 - 1
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;
  */
 public class XingHuoChatModelTests {
 
-    private static final OpenAiChatModel openAiChatModel = OpenAiChatModel.builder()
+    private final OpenAiChatModel openAiChatModel = OpenAiChatModel.builder()
         .openAiApi(OpenAiApi.builder()
                 .baseUrl(XingHuoChatModel.BASE_URL)
                 .apiKey("75b161ed2aef4719b275d6e7f2a4d4cd:YWYxYWI2MTA4ODI2NGZlYTQyNjAzZTcz") // appKey:secretKey

+ 4 - 0
yudao-server/src/main/resources/application.yaml

@@ -188,6 +188,10 @@ yudao:
       enable: true
       api-key: 5c1b5747-26d2-4ebd-a4e0-dd0e8d8b4272
       model: doubao-1-5-lite-32k-250115
+    hunyuan: # 腾讯混元
+      enable: true
+      api-key: sk-abc
+      model: hunyuan-turbo
     xinghuo: # 讯飞星火
       enable: true
       appKey: 75b161ed2aef4719b275d6e7f2a4d4cd