Commit 750709d706fdad1fdde16e6fab7a75de238ea879
1 parent
3d0eb771
feat:【AI 大模型】deepseek、azure、baichuan、moonshot 适配 1.0.0
Showing
6 changed files
with
160 additions
and
113 deletions
yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/AiModelFactoryImpl.java
| ... | ... | @@ -8,11 +8,11 @@ import cn.hutool.core.util.ArrayUtil; |
| 8 | 8 | import cn.hutool.core.util.RuntimeUtil; |
| 9 | 9 | import cn.hutool.core.util.StrUtil; |
| 10 | 10 | import cn.hutool.extra.spring.SpringUtil; |
| 11 | +import cn.iocoder.yudao.framework.common.util.spring.SpringUtils; | |
| 12 | +import cn.iocoder.yudao.module.ai.enums.model.AiPlatformEnum; | |
| 11 | 13 | import cn.iocoder.yudao.module.ai.framework.ai.config.AiAutoConfiguration; |
| 12 | 14 | import cn.iocoder.yudao.module.ai.framework.ai.config.YudaoAiProperties; |
| 13 | -import cn.iocoder.yudao.module.ai.enums.model.AiPlatformEnum; | |
| 14 | 15 | import cn.iocoder.yudao.module.ai.framework.ai.core.model.baichuan.BaiChuanChatModel; |
| 15 | -import cn.iocoder.yudao.module.ai.framework.ai.core.model.deepseek.DeepSeekChatModel; | |
| 16 | 16 | import cn.iocoder.yudao.module.ai.framework.ai.core.model.doubao.DouBaoChatModel; |
| 17 | 17 | import cn.iocoder.yudao.module.ai.framework.ai.core.model.hunyuan.HunYuanChatModel; |
| 18 | 18 | import cn.iocoder.yudao.module.ai.framework.ai.core.model.midjourney.api.MidjourneyApi; |
| ... | ... | @@ -22,8 +22,9 @@ import cn.iocoder.yudao.module.ai.framework.ai.core.model.siliconflow.SiliconFlo |
| 22 | 22 | import cn.iocoder.yudao.module.ai.framework.ai.core.model.siliconflow.SiliconFlowImageModel; |
| 23 | 23 | import cn.iocoder.yudao.module.ai.framework.ai.core.model.suno.api.SunoApi; |
| 24 | 24 | import cn.iocoder.yudao.module.ai.framework.ai.core.model.xinghuo.XingHuoChatModel; |
| 25 | -import cn.iocoder.yudao.framework.common.util.spring.SpringUtils; | |
| 26 | -import com.alibaba.cloud.ai.autoconfigure.dashscope.DashScopeAutoConfiguration; | |
| 25 | +import com.alibaba.cloud.ai.autoconfigure.dashscope.DashScopeChatAutoConfiguration; | |
| 26 | +import com.alibaba.cloud.ai.autoconfigure.dashscope.DashScopeEmbeddingAutoConfiguration; | |
| 27 | +import com.alibaba.cloud.ai.autoconfigure.dashscope.DashScopeImageAutoConfiguration; | |
| 27 | 28 | import com.alibaba.cloud.ai.dashscope.api.DashScopeApi; |
| 28 | 29 | import com.alibaba.cloud.ai.dashscope.api.DashScopeImageApi; |
| 29 | 30 | import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatModel; |
| ... | ... | @@ -32,47 +33,55 @@ import com.alibaba.cloud.ai.dashscope.embedding.DashScopeEmbeddingModel; |
| 32 | 33 | import com.alibaba.cloud.ai.dashscope.embedding.DashScopeEmbeddingOptions; |
| 33 | 34 | import com.alibaba.cloud.ai.dashscope.image.DashScopeImageModel; |
| 34 | 35 | import com.azure.ai.openai.OpenAIClientBuilder; |
| 36 | +import com.azure.core.credential.KeyCredential; | |
| 35 | 37 | import io.micrometer.observation.ObservationRegistry; |
| 36 | 38 | import io.milvus.client.MilvusServiceClient; |
| 37 | 39 | import io.qdrant.client.QdrantClient; |
| 38 | 40 | import io.qdrant.client.QdrantGrpcClient; |
| 39 | 41 | import lombok.SneakyThrows; |
| 40 | -import org.springframework.ai.autoconfigure.azure.openai.AzureOpenAiAutoConfiguration; | |
| 41 | -import org.springframework.ai.autoconfigure.azure.openai.AzureOpenAiChatProperties; | |
| 42 | -import org.springframework.ai.autoconfigure.azure.openai.AzureOpenAiConnectionProperties; | |
| 43 | -import org.springframework.ai.autoconfigure.azure.openai.AzureOpenAiEmbeddingProperties; | |
| 44 | -import org.springframework.ai.autoconfigure.minimax.MiniMaxAutoConfiguration; | |
| 45 | -import org.springframework.ai.autoconfigure.moonshot.MoonshotAutoConfiguration; | |
| 46 | -import org.springframework.ai.autoconfigure.ollama.OllamaAutoConfiguration; | |
| 47 | -import org.springframework.ai.autoconfigure.openai.OpenAiAutoConfiguration; | |
| 48 | -import org.springframework.ai.autoconfigure.qianfan.QianFanAutoConfiguration; | |
| 49 | -import org.springframework.ai.autoconfigure.stabilityai.StabilityAiImageAutoConfiguration; | |
| 50 | -import org.springframework.ai.autoconfigure.vectorstore.milvus.MilvusServiceClientConnectionDetails; | |
| 51 | -import org.springframework.ai.autoconfigure.vectorstore.milvus.MilvusServiceClientProperties; | |
| 52 | -import org.springframework.ai.autoconfigure.vectorstore.milvus.MilvusVectorStoreAutoConfiguration; | |
| 53 | -import org.springframework.ai.autoconfigure.vectorstore.milvus.MilvusVectorStoreProperties; | |
| 54 | -import org.springframework.ai.autoconfigure.vectorstore.qdrant.QdrantVectorStoreAutoConfiguration; | |
| 55 | -import org.springframework.ai.autoconfigure.vectorstore.qdrant.QdrantVectorStoreProperties; | |
| 56 | -import org.springframework.ai.autoconfigure.vectorstore.redis.RedisVectorStoreAutoConfiguration; | |
| 57 | -import org.springframework.ai.autoconfigure.vectorstore.redis.RedisVectorStoreProperties; | |
| 58 | -import org.springframework.ai.autoconfigure.zhipuai.ZhiPuAiAutoConfiguration; | |
| 42 | +import org.springaicommunity.moonshot.MoonshotChatModel; | |
| 43 | +import org.springaicommunity.moonshot.MoonshotChatOptions; | |
| 44 | +import org.springaicommunity.moonshot.api.MoonshotApi; | |
| 45 | +import org.springaicommunity.moonshot.autoconfigure.MoonshotChatAutoConfiguration; | |
| 46 | +import org.springaicommunity.qianfan.QianFanChatModel; | |
| 47 | +import org.springaicommunity.qianfan.QianFanEmbeddingModel; | |
| 48 | +import org.springaicommunity.qianfan.QianFanEmbeddingOptions; | |
| 49 | +import org.springaicommunity.qianfan.QianFanImageModel; | |
| 50 | +import org.springaicommunity.qianfan.api.QianFanApi; | |
| 51 | +import org.springaicommunity.qianfan.api.QianFanImageApi; | |
| 52 | +import org.springaicommunity.qianfan.autoconfigure.QianFanChatAutoConfiguration; | |
| 53 | +import org.springaicommunity.qianfan.autoconfigure.QianFanEmbeddingAutoConfiguration; | |
| 59 | 54 | import org.springframework.ai.azure.openai.AzureOpenAiChatModel; |
| 60 | 55 | import org.springframework.ai.azure.openai.AzureOpenAiEmbeddingModel; |
| 61 | 56 | import org.springframework.ai.chat.model.ChatModel; |
| 57 | +import org.springframework.ai.deepseek.DeepSeekChatModel; | |
| 58 | +import org.springframework.ai.deepseek.DeepSeekChatOptions; | |
| 59 | +import org.springframework.ai.deepseek.api.DeepSeekApi; | |
| 62 | 60 | import org.springframework.ai.document.MetadataMode; |
| 63 | 61 | import org.springframework.ai.embedding.BatchingStrategy; |
| 64 | 62 | import org.springframework.ai.embedding.EmbeddingModel; |
| 63 | +import org.springframework.ai.embedding.observation.EmbeddingModelObservationConvention; | |
| 65 | 64 | import org.springframework.ai.image.ImageModel; |
| 66 | 65 | import org.springframework.ai.minimax.MiniMaxChatModel; |
| 67 | 66 | import org.springframework.ai.minimax.MiniMaxChatOptions; |
| 68 | 67 | import org.springframework.ai.minimax.MiniMaxEmbeddingModel; |
| 69 | 68 | import org.springframework.ai.minimax.MiniMaxEmbeddingOptions; |
| 70 | 69 | import org.springframework.ai.minimax.api.MiniMaxApi; |
| 71 | -import org.springframework.ai.model.function.FunctionCallbackResolver; | |
| 70 | +import org.springframework.ai.model.azure.openai.autoconfigure.AzureOpenAiChatAutoConfiguration; | |
| 71 | +import org.springframework.ai.model.azure.openai.autoconfigure.AzureOpenAiEmbeddingAutoConfiguration; | |
| 72 | +import org.springframework.ai.model.azure.openai.autoconfigure.AzureOpenAiEmbeddingProperties; | |
| 73 | +import org.springframework.ai.model.deepseek.autoconfigure.DeepSeekChatAutoConfiguration; | |
| 74 | +import org.springframework.ai.model.minimax.autoconfigure.MiniMaxChatAutoConfiguration; | |
| 75 | +import org.springframework.ai.model.minimax.autoconfigure.MiniMaxEmbeddingAutoConfiguration; | |
| 76 | +import org.springframework.ai.model.ollama.autoconfigure.OllamaChatAutoConfiguration; | |
| 77 | +import org.springframework.ai.model.openai.autoconfigure.OpenAiChatAutoConfiguration; | |
| 78 | +import org.springframework.ai.model.openai.autoconfigure.OpenAiEmbeddingAutoConfiguration; | |
| 79 | +import org.springframework.ai.model.openai.autoconfigure.OpenAiImageAutoConfiguration; | |
| 80 | +import org.springframework.ai.model.stabilityai.autoconfigure.StabilityAiImageAutoConfiguration; | |
| 72 | 81 | import org.springframework.ai.model.tool.ToolCallingManager; |
| 73 | -import org.springframework.ai.moonshot.MoonshotChatModel; | |
| 74 | -import org.springframework.ai.moonshot.MoonshotChatOptions; | |
| 75 | -import org.springframework.ai.moonshot.api.MoonshotApi; | |
| 82 | +import org.springframework.ai.model.zhipuai.autoconfigure.ZhiPuAiChatAutoConfiguration; | |
| 83 | +import org.springframework.ai.model.zhipuai.autoconfigure.ZhiPuAiEmbeddingAutoConfiguration; | |
| 84 | +import org.springframework.ai.model.zhipuai.autoconfigure.ZhiPuAiImageAutoConfiguration; | |
| 76 | 85 | import org.springframework.ai.ollama.OllamaChatModel; |
| 77 | 86 | import org.springframework.ai.ollama.OllamaEmbeddingModel; |
| 78 | 87 | import org.springframework.ai.ollama.api.OllamaApi; |
| ... | ... | @@ -84,21 +93,23 @@ import org.springframework.ai.openai.OpenAiImageModel; |
| 84 | 93 | import org.springframework.ai.openai.api.OpenAiApi; |
| 85 | 94 | import org.springframework.ai.openai.api.OpenAiImageApi; |
| 86 | 95 | import org.springframework.ai.openai.api.common.OpenAiApiConstants; |
| 87 | -import org.springframework.ai.qianfan.QianFanChatModel; | |
| 88 | -import org.springframework.ai.qianfan.QianFanEmbeddingModel; | |
| 89 | -import org.springframework.ai.qianfan.QianFanEmbeddingOptions; | |
| 90 | -import org.springframework.ai.qianfan.QianFanImageModel; | |
| 91 | -import org.springframework.ai.qianfan.api.QianFanApi; | |
| 92 | -import org.springframework.ai.qianfan.api.QianFanImageApi; | |
| 93 | 96 | import org.springframework.ai.stabilityai.StabilityAiImageModel; |
| 94 | 97 | import org.springframework.ai.stabilityai.api.StabilityAiApi; |
| 95 | 98 | import org.springframework.ai.vectorstore.SimpleVectorStore; |
| 96 | 99 | import org.springframework.ai.vectorstore.VectorStore; |
| 97 | 100 | import org.springframework.ai.vectorstore.milvus.MilvusVectorStore; |
| 101 | +import org.springframework.ai.vectorstore.milvus.autoconfigure.MilvusServiceClientConnectionDetails; | |
| 102 | +import org.springframework.ai.vectorstore.milvus.autoconfigure.MilvusServiceClientProperties; | |
| 103 | +import org.springframework.ai.vectorstore.milvus.autoconfigure.MilvusVectorStoreAutoConfiguration; | |
| 104 | +import org.springframework.ai.vectorstore.milvus.autoconfigure.MilvusVectorStoreProperties; | |
| 98 | 105 | import org.springframework.ai.vectorstore.observation.DefaultVectorStoreObservationConvention; |
| 99 | 106 | import org.springframework.ai.vectorstore.observation.VectorStoreObservationConvention; |
| 100 | 107 | import org.springframework.ai.vectorstore.qdrant.QdrantVectorStore; |
| 108 | +import org.springframework.ai.vectorstore.qdrant.autoconfigure.QdrantVectorStoreAutoConfiguration; | |
| 109 | +import org.springframework.ai.vectorstore.qdrant.autoconfigure.QdrantVectorStoreProperties; | |
| 101 | 110 | import org.springframework.ai.vectorstore.redis.RedisVectorStore; |
| 111 | +import org.springframework.ai.vectorstore.redis.autoconfigure.RedisVectorStoreAutoConfiguration; | |
| 112 | +import org.springframework.ai.vectorstore.redis.autoconfigure.RedisVectorStoreProperties; | |
| 102 | 113 | import org.springframework.ai.zhipuai.*; |
| 103 | 114 | import org.springframework.ai.zhipuai.api.ZhiPuAiApi; |
| 104 | 115 | import org.springframework.ai.zhipuai.api.ZhiPuAiImageApi; |
| ... | ... | @@ -190,7 +201,7 @@ public class AiModelFactoryImpl implements AiModelFactory { |
| 190 | 201 | case XING_HUO: |
| 191 | 202 | return SpringUtil.getBean(XingHuoChatModel.class); |
| 192 | 203 | case BAI_CHUAN: |
| 193 | - return SpringUtil.getBean(AzureOpenAiChatModel.class); | |
| 204 | + return SpringUtil.getBean(BaiChuanChatModel.class); | |
| 194 | 205 | case OPENAI: |
| 195 | 206 | return SpringUtil.getBean(OpenAiChatModel.class); |
| 196 | 207 | case AZURE_OPENAI: |
| ... | ... | @@ -319,27 +330,34 @@ public class AiModelFactoryImpl implements AiModelFactory { |
| 319 | 330 | // ========== 各种创建 spring-ai 客户端的方法 ========== |
| 320 | 331 | |
| 321 | 332 | /** |
| 322 | - * 可参考 {@link DashScopeAutoConfiguration} 的 dashscopeChatModel 方法 | |
| 333 | + * 可参考 {@link DashScopeChatAutoConfiguration} 的 dashscopeChatModel 方法 | |
| 323 | 334 | */ |
| 324 | 335 | private static DashScopeChatModel buildTongYiChatModel(String key) { |
| 325 | - DashScopeApi dashScopeApi = new DashScopeApi(key); | |
| 336 | + DashScopeApi dashScopeApi = DashScopeApi.builder().apiKey(key).build(); | |
| 326 | 337 | DashScopeChatOptions options = DashScopeChatOptions.builder().withModel(DashScopeApi.DEFAULT_CHAT_MODEL) |
| 327 | 338 | .withTemperature(0.7).build(); |
| 328 | - return new DashScopeChatModel(dashScopeApi, options, getFunctionCallbackResolver(), DEFAULT_RETRY_TEMPLATE); | |
| 339 | + return DashScopeChatModel.builder() | |
| 340 | + .dashScopeApi(dashScopeApi) | |
| 341 | + .defaultOptions(options) | |
| 342 | + .toolCallingManager(getToolCallingManager()) | |
| 343 | + .build(); | |
| 329 | 344 | } |
| 330 | 345 | |
| 331 | 346 | /** |
| 332 | - * 可参考 {@link DashScopeAutoConfiguration} 的 dashScopeImageModel 方法 | |
| 347 | + * 可参考 {@link DashScopeImageAutoConfiguration} 的 dashScopeImageModel 方法 | |
| 333 | 348 | */ |
| 334 | 349 | private static DashScopeImageModel buildTongYiImagesModel(String key) { |
| 335 | 350 | DashScopeImageApi dashScopeImageApi = new DashScopeImageApi(key); |
| 336 | - return new DashScopeImageModel(dashScopeImageApi); | |
| 351 | + return DashScopeImageModel.builder() | |
| 352 | + .dashScopeApi(dashScopeImageApi) | |
| 353 | + .build(); | |
| 337 | 354 | } |
| 338 | 355 | |
| 339 | 356 | /** |
| 340 | - * 可参考 {@link QianFanAutoConfiguration} 的 qianFanChatModel 方法 | |
| 357 | + * 可参考 {@link QianFanChatAutoConfiguration} 的 qianFanChatModel 方法 | |
| 341 | 358 | */ |
| 342 | 359 | private static QianFanChatModel buildYiYanChatModel(String key) { |
| 360 | + // TODO @芋艿:未测试 | |
| 343 | 361 | List<String> keys = StrUtil.split(key, '|'); |
| 344 | 362 | Assert.equals(keys.size(), 2, "YiYanChatClient 的密钥需要 (appKey|secretKey) 格式"); |
| 345 | 363 | String appKey = keys.get(0); |
| ... | ... | @@ -349,9 +367,10 @@ public class AiModelFactoryImpl implements AiModelFactory { |
| 349 | 367 | } |
| 350 | 368 | |
| 351 | 369 | /** |
| 352 | - * 可参考 {@link QianFanAutoConfiguration} 的 qianFanImageModel 方法 | |
| 370 | + * 可参考 {@link QianFanEmbeddingAutoConfiguration} 的 qianFanImageModel 方法 | |
| 353 | 371 | */ |
| 354 | 372 | private QianFanImageModel buildQianFanImageModel(String key) { |
| 373 | + // TODO @芋艿:未测试 | |
| 355 | 374 | List<String> keys = StrUtil.split(key, '|'); |
| 356 | 375 | Assert.equals(keys.size(), 2, "YiYanChatClient 的密钥需要 (appKey|secretKey) 格式"); |
| 357 | 376 | String appKey = keys.get(0); |
| ... | ... | @@ -361,12 +380,17 @@ public class AiModelFactoryImpl implements AiModelFactory { |
| 361 | 380 | } |
| 362 | 381 | |
| 363 | 382 | /** |
| 364 | - * 可参考 {@link AiAutoConfiguration#deepSeekChatModel(YudaoAiProperties)} | |
| 383 | + * 可参考 {@link DeepSeekChatAutoConfiguration} 的 deepSeekChatModel 方法 | |
| 365 | 384 | */ |
| 366 | 385 | private static DeepSeekChatModel buildDeepSeekChatModel(String apiKey) { |
| 367 | - YudaoAiProperties.DeepSeekProperties properties = new YudaoAiProperties.DeepSeekProperties() | |
| 368 | - .setApiKey(apiKey); | |
| 369 | - return new AiAutoConfiguration().buildDeepSeekChatModel(properties); | |
| 386 | + DeepSeekApi deepSeekApi = DeepSeekApi.builder().apiKey(apiKey).build(); | |
| 387 | + DeepSeekChatOptions options = DeepSeekChatOptions.builder().model(DeepSeekApi.DEFAULT_CHAT_MODEL) | |
| 388 | + .temperature(0.7).build(); | |
| 389 | + return DeepSeekChatModel.builder() | |
| 390 | + .deepSeekApi(deepSeekApi) | |
| 391 | + .defaultOptions(options) | |
| 392 | + .toolCallingManager(getToolCallingManager()) | |
| 393 | + .build(); | |
| 370 | 394 | } |
| 371 | 395 | |
| 372 | 396 | /** |
| ... | ... | @@ -397,17 +421,18 @@ public class AiModelFactoryImpl implements AiModelFactory { |
| 397 | 421 | } |
| 398 | 422 | |
| 399 | 423 | /** |
| 400 | - * 可参考 {@link ZhiPuAiAutoConfiguration} 的 zhiPuAiChatModel 方法 | |
| 424 | + * 可参考 {@link ZhiPuAiChatAutoConfiguration} 的 zhiPuAiChatModel 方法 | |
| 401 | 425 | */ |
| 402 | 426 | private ZhiPuAiChatModel buildZhiPuChatModel(String apiKey, String url) { |
| 403 | 427 | ZhiPuAiApi zhiPuAiApi = StrUtil.isEmpty(url) ? new ZhiPuAiApi(apiKey) |
| 404 | 428 | : new ZhiPuAiApi(url, apiKey); |
| 405 | 429 | ZhiPuAiChatOptions options = ZhiPuAiChatOptions.builder().model(ZhiPuAiApi.DEFAULT_CHAT_MODEL).temperature(0.7).build(); |
| 406 | - return new ZhiPuAiChatModel(zhiPuAiApi, options, getFunctionCallbackResolver(), DEFAULT_RETRY_TEMPLATE); | |
| 430 | + return new ZhiPuAiChatModel(zhiPuAiApi, options, getToolCallingManager(), DEFAULT_RETRY_TEMPLATE, | |
| 431 | + getObservationRegistry().getIfAvailable()); | |
| 407 | 432 | } |
| 408 | 433 | |
| 409 | 434 | /** |
| 410 | - * 可参考 {@link ZhiPuAiAutoConfiguration} 的 zhiPuAiImageModel 方法 | |
| 435 | + * 可参考 {@link ZhiPuAiImageAutoConfiguration} 的 zhiPuAiImageModel 方法 | |
| 411 | 436 | */ |
| 412 | 437 | private ZhiPuAiImageModel buildZhiPuAiImageModel(String apiKey, String url) { |
| 413 | 438 | ZhiPuAiImageApi zhiPuAiApi = StrUtil.isEmpty(url) ? new ZhiPuAiImageApi(apiKey) |
| ... | ... | @@ -416,23 +441,30 @@ public class AiModelFactoryImpl implements AiModelFactory { |
| 416 | 441 | } |
| 417 | 442 | |
| 418 | 443 | /** |
| 419 | - * 可参考 {@link MiniMaxAutoConfiguration} 的 miniMaxChatModel 方法 | |
| 444 | + * 可参考 {@link MiniMaxChatAutoConfiguration} 的 miniMaxChatModel 方法 | |
| 420 | 445 | */ |
| 421 | 446 | private MiniMaxChatModel buildMiniMaxChatModel(String apiKey, String url) { |
| 422 | 447 | MiniMaxApi miniMaxApi = StrUtil.isEmpty(url) ? new MiniMaxApi(apiKey) |
| 423 | 448 | : new MiniMaxApi(url, apiKey); |
| 424 | 449 | MiniMaxChatOptions options = MiniMaxChatOptions.builder().model(MiniMaxApi.DEFAULT_CHAT_MODEL).temperature(0.7).build(); |
| 425 | - return new MiniMaxChatModel(miniMaxApi, options, getFunctionCallbackResolver(), DEFAULT_RETRY_TEMPLATE); | |
| 450 | + return new MiniMaxChatModel(miniMaxApi, options, getToolCallingManager(), DEFAULT_RETRY_TEMPLATE); | |
| 426 | 451 | } |
| 427 | 452 | |
| 428 | 453 | /** |
| 429 | - * 可参考 {@link MoonshotAutoConfiguration} 的 moonshotChatModel 方法 | |
| 454 | + * 可参考 {@link MoonshotChatAutoConfiguration} 的 moonshotChatModel 方法 | |
| 430 | 455 | */ |
| 431 | 456 | private MoonshotChatModel buildMoonshotChatModel(String apiKey, String url) { |
| 432 | - MoonshotApi moonshotApi = StrUtil.isEmpty(url)? new MoonshotApi(apiKey) | |
| 433 | - : new MoonshotApi(url, apiKey); | |
| 457 | + MoonshotApi.Builder moonshotApiBuilder = MoonshotApi.builder() | |
| 458 | + .apiKey(apiKey); | |
| 459 | + if (StrUtil.isNotEmpty(url)) { | |
| 460 | + moonshotApiBuilder.baseUrl(url); | |
| 461 | + } | |
| 434 | 462 | MoonshotChatOptions options = MoonshotChatOptions.builder().model(MoonshotApi.DEFAULT_CHAT_MODEL).build(); |
| 435 | - return new MoonshotChatModel(moonshotApi, options, getFunctionCallbackResolver(), DEFAULT_RETRY_TEMPLATE); | |
| 463 | + return MoonshotChatModel.builder() | |
| 464 | + .moonshotApi(moonshotApiBuilder.build()) | |
| 465 | + .defaultOptions(options) | |
| 466 | + .toolCallingManager(getToolCallingManager()) | |
| 467 | + .build(); | |
| 436 | 468 | } |
| 437 | 469 | |
| 438 | 470 | /** |
| ... | ... | @@ -456,33 +488,32 @@ public class AiModelFactoryImpl implements AiModelFactory { |
| 456 | 488 | } |
| 457 | 489 | |
| 458 | 490 | /** |
| 459 | - * 可参考 {@link OpenAiAutoConfiguration} 的 openAiChatModel 方法 | |
| 491 | + * 可参考 {@link OpenAiChatAutoConfiguration} 的 openAiChatModel 方法 | |
| 460 | 492 | */ |
| 461 | 493 | private static OpenAiChatModel buildOpenAiChatModel(String openAiToken, String url) { |
| 462 | 494 | url = StrUtil.blankToDefault(url, OpenAiApiConstants.DEFAULT_BASE_URL); |
| 463 | 495 | OpenAiApi openAiApi = OpenAiApi.builder().baseUrl(url).apiKey(openAiToken).build(); |
| 464 | - return OpenAiChatModel.builder().openAiApi(openAiApi).toolCallingManager(getToolCallingManager()).build(); | |
| 496 | + return OpenAiChatModel.builder() | |
| 497 | + .openAiApi(openAiApi) | |
| 498 | + .toolCallingManager(getToolCallingManager()) | |
| 499 | + .build(); | |
| 465 | 500 | } |
| 466 | 501 | |
| 467 | - // TODO @芋艿:手头暂时没密钥,使用建议再测试下 | |
| 468 | 502 | /** |
| 469 | - * 可参考 {@link AzureOpenAiAutoConfiguration} | |
| 503 | + * 可参考 {@link AzureOpenAiChatAutoConfiguration} | |
| 470 | 504 | */ |
| 471 | 505 | private static AzureOpenAiChatModel buildAzureOpenAiChatModel(String apiKey, String url) { |
| 472 | - AzureOpenAiAutoConfiguration azureOpenAiAutoConfiguration = new AzureOpenAiAutoConfiguration(); | |
| 473 | - // 创建 OpenAIClient 对象 | |
| 474 | - AzureOpenAiConnectionProperties connectionProperties = new AzureOpenAiConnectionProperties(); | |
| 475 | - connectionProperties.setApiKey(apiKey); | |
| 476 | - connectionProperties.setEndpoint(url); | |
| 477 | - OpenAIClientBuilder openAIClient = azureOpenAiAutoConfiguration.openAIClientBuilder(connectionProperties, null); | |
| 478 | - // 获取 AzureOpenAiChatProperties 对象 | |
| 479 | - AzureOpenAiChatProperties chatProperties = SpringUtil.getBean(AzureOpenAiChatProperties.class); | |
| 480 | - return azureOpenAiAutoConfiguration.azureOpenAiChatModel(openAIClient, chatProperties, | |
| 481 | - getToolCallingManager(), null, null); | |
| 506 | + // TODO @芋艿:使用前,请测试,暂时没密钥!!! | |
| 507 | + OpenAIClientBuilder openAIClientBuilder = new OpenAIClientBuilder() | |
| 508 | + .endpoint(url).credential(new KeyCredential(apiKey)); | |
| 509 | + return AzureOpenAiChatModel.builder() | |
| 510 | + .openAIClientBuilder(openAIClientBuilder) | |
| 511 | + .toolCallingManager(getToolCallingManager()) | |
| 512 | + .build(); | |
| 482 | 513 | } |
| 483 | 514 | |
| 484 | 515 | /** |
| 485 | - * 可参考 {@link OpenAiAutoConfiguration} 的 openAiImageModel 方法 | |
| 516 | + * 可参考 {@link OpenAiImageAutoConfiguration} 的 openAiImageModel 方法 | |
| 486 | 517 | */ |
| 487 | 518 | private OpenAiImageModel buildOpenAiImageModel(String openAiToken, String url) { |
| 488 | 519 | url = StrUtil.blankToDefault(url, OpenAiApiConstants.DEFAULT_BASE_URL); |
| ... | ... | @@ -494,16 +525,18 @@ public class AiModelFactoryImpl implements AiModelFactory { |
| 494 | 525 | * 创建 SiliconFlowImageModel 对象 |
| 495 | 526 | */ |
| 496 | 527 | private SiliconFlowImageModel buildSiliconFlowImageModel(String apiToken, String url) { |
| 528 | + // TODO @芋艿:未测试 | |
| 497 | 529 | url = StrUtil.blankToDefault(url, SiliconFlowApiConstants.DEFAULT_BASE_URL); |
| 498 | 530 | SiliconFlowImageApi openAiApi = new SiliconFlowImageApi(url, apiToken); |
| 499 | 531 | return new SiliconFlowImageModel(openAiApi); |
| 500 | 532 | } |
| 501 | 533 | |
| 502 | 534 | /** |
| 503 | - * 可参考 {@link OllamaAutoConfiguration} 的 ollamaApi 方法 | |
| 535 | + * 可参考 {@link OllamaChatAutoConfiguration} 的 ollamaChatModel 方法 | |
| 504 | 536 | */ |
| 505 | 537 | private static OllamaChatModel buildOllamaChatModel(String url) { |
| 506 | - OllamaApi ollamaApi = new OllamaApi(url); | |
| 538 | + // TODO @芋艿:未测试 | |
| 539 | + OllamaApi ollamaApi = OllamaApi.builder().baseUrl(url).build(); | |
| 507 | 540 | return OllamaChatModel.builder().ollamaApi(ollamaApi).toolCallingManager(getToolCallingManager()).build(); |
| 508 | 541 | } |
| 509 | 542 | |
| ... | ... | @@ -519,16 +552,16 @@ public class AiModelFactoryImpl implements AiModelFactory { |
| 519 | 552 | // ========== 各种创建 EmbeddingModel 的方法 ========== |
| 520 | 553 | |
| 521 | 554 | /** |
| 522 | - * 可参考 {@link DashScopeAutoConfiguration} 的 dashscopeEmbeddingModel 方法 | |
| 555 | + * 可参考 {@link DashScopeEmbeddingAutoConfiguration} 的 dashscopeEmbeddingModel 方法 | |
| 523 | 556 | */ |
| 524 | 557 | private DashScopeEmbeddingModel buildTongYiEmbeddingModel(String apiKey, String model) { |
| 525 | - DashScopeApi dashScopeApi = new DashScopeApi(apiKey); | |
| 558 | + DashScopeApi dashScopeApi = DashScopeApi.builder().apiKey(apiKey).build(); | |
| 526 | 559 | DashScopeEmbeddingOptions dashScopeEmbeddingOptions = DashScopeEmbeddingOptions.builder().withModel(model).build(); |
| 527 | 560 | return new DashScopeEmbeddingModel(dashScopeApi, MetadataMode.EMBED, dashScopeEmbeddingOptions); |
| 528 | 561 | } |
| 529 | 562 | |
| 530 | 563 | /** |
| 531 | - * 可参考 {@link ZhiPuAiAutoConfiguration} 的 zhiPuAiEmbeddingModel 方法 | |
| 564 | + * 可参考 {@link ZhiPuAiEmbeddingAutoConfiguration} 的 zhiPuAiEmbeddingModel 方法 | |
| 532 | 565 | */ |
| 533 | 566 | private ZhiPuAiEmbeddingModel buildZhiPuEmbeddingModel(String apiKey, String url, String model) { |
| 534 | 567 | ZhiPuAiApi zhiPuAiApi = StrUtil.isEmpty(url) ? new ZhiPuAiApi(apiKey) |
| ... | ... | @@ -538,7 +571,7 @@ public class AiModelFactoryImpl implements AiModelFactory { |
| 538 | 571 | } |
| 539 | 572 | |
| 540 | 573 | /** |
| 541 | - * 可参考 {@link MiniMaxAutoConfiguration} 的 miniMaxEmbeddingModel 方法 | |
| 574 | + * 可参考 {@link MiniMaxEmbeddingAutoConfiguration} 的 miniMaxEmbeddingModel 方法 | |
| 542 | 575 | */ |
| 543 | 576 | private EmbeddingModel buildMiniMaxEmbeddingModel(String apiKey, String url, String model) { |
| 544 | 577 | MiniMaxApi miniMaxApi = StrUtil.isEmpty(url)? new MiniMaxApi(apiKey) |
| ... | ... | @@ -548,7 +581,7 @@ public class AiModelFactoryImpl implements AiModelFactory { |
| 548 | 581 | } |
| 549 | 582 | |
| 550 | 583 | /** |
| 551 | - * 可参考 {@link QianFanAutoConfiguration} 的 qianFanEmbeddingModel 方法 | |
| 584 | + * 可参考 {@link QianFanEmbeddingAutoConfiguration} 的 qianFanEmbeddingModel 方法 | |
| 552 | 585 | */ |
| 553 | 586 | private QianFanEmbeddingModel buildYiYanEmbeddingModel(String key, String model) { |
| 554 | 587 | List<String> keys = StrUtil.split(key, '|'); |
| ... | ... | @@ -561,13 +594,13 @@ public class AiModelFactoryImpl implements AiModelFactory { |
| 561 | 594 | } |
| 562 | 595 | |
| 563 | 596 | private OllamaEmbeddingModel buildOllamaEmbeddingModel(String url, String model) { |
| 564 | - OllamaApi ollamaApi = new OllamaApi(url); | |
| 597 | + OllamaApi ollamaApi = OllamaApi.builder().baseUrl(url).build(); | |
| 565 | 598 | OllamaOptions ollamaOptions = OllamaOptions.builder().model(model).build(); |
| 566 | 599 | return OllamaEmbeddingModel.builder().ollamaApi(ollamaApi).defaultOptions(ollamaOptions).build(); |
| 567 | 600 | } |
| 568 | 601 | |
| 569 | 602 | /** |
| 570 | - * 可参考 {@link OpenAiAutoConfiguration} 的 openAiEmbeddingModel 方法 | |
| 603 | + * 可参考 {@link OpenAiEmbeddingAutoConfiguration} 的 openAiEmbeddingModel 方法 | |
| 571 | 604 | */ |
| 572 | 605 | private OpenAiEmbeddingModel buildOpenAiEmbeddingModel(String openAiToken, String url, String model) { |
| 573 | 606 | url = StrUtil.blankToDefault(url, OpenAiApiConstants.DEFAULT_BASE_URL); |
| ... | ... | @@ -576,21 +609,19 @@ public class AiModelFactoryImpl implements AiModelFactory { |
| 576 | 609 | return new OpenAiEmbeddingModel(openAiApi, MetadataMode.EMBED, openAiEmbeddingProperties); |
| 577 | 610 | } |
| 578 | 611 | |
| 579 | - // TODO @芋艿:手头暂时没密钥,使用建议再测试下 | |
| 580 | 612 | /** |
| 581 | - * 可参考 {@link AzureOpenAiAutoConfiguration} 的 azureOpenAiEmbeddingModel 方法 | |
| 613 | + * 可参考 {@link AzureOpenAiEmbeddingAutoConfiguration} 的 azureOpenAiEmbeddingModel 方法 | |
| 582 | 614 | */ |
| 583 | 615 | private AzureOpenAiEmbeddingModel buildAzureOpenAiEmbeddingModel(String apiKey, String url, String model) { |
| 584 | - AzureOpenAiAutoConfiguration azureOpenAiAutoConfiguration = new AzureOpenAiAutoConfiguration(); | |
| 585 | - // 创建 OpenAIClient 对象 | |
| 586 | - AzureOpenAiConnectionProperties connectionProperties = new AzureOpenAiConnectionProperties(); | |
| 587 | - connectionProperties.setApiKey(apiKey); | |
| 588 | - connectionProperties.setEndpoint(url); | |
| 589 | - OpenAIClientBuilder openAIClient = azureOpenAiAutoConfiguration.openAIClientBuilder(connectionProperties, null); | |
| 616 | + // TODO @芋艿:手头暂时没密钥,使用建议再测试下 | |
| 617 | + AzureOpenAiEmbeddingAutoConfiguration azureOpenAiAutoConfiguration = new AzureOpenAiEmbeddingAutoConfiguration(); | |
| 618 | + // 创建 OpenAIClientBuilder 对象 | |
| 619 | + OpenAIClientBuilder openAIClientBuilder = new OpenAIClientBuilder() | |
| 620 | + .endpoint(url).credential(new KeyCredential(apiKey)); | |
| 590 | 621 | // 获取 AzureOpenAiChatProperties 对象 |
| 591 | 622 | AzureOpenAiEmbeddingProperties embeddingProperties = SpringUtil.getBean(AzureOpenAiEmbeddingProperties.class); |
| 592 | - return azureOpenAiAutoConfiguration.azureOpenAiEmbeddingModel(openAIClient, embeddingProperties, | |
| 593 | - null, null); | |
| 623 | + return azureOpenAiAutoConfiguration.azureOpenAiEmbeddingModel(openAIClientBuilder, embeddingProperties, | |
| 624 | + getObservationRegistry(), getEmbeddingModelObservationConvention()); | |
| 594 | 625 | } |
| 595 | 626 | |
| 596 | 627 | // ========== 各种创建 VectorStore 的方法 ========== |
| ... | ... | @@ -657,10 +688,11 @@ public class AiModelFactoryImpl implements AiModelFactory { |
| 657 | 688 | RedisProperties redisProperties = SpringUtils.getBean(RedisProperties.class); |
| 658 | 689 | JedisPooled jedisPooled = new JedisPooled(redisProperties.getHost(), redisProperties.getPort()); |
| 659 | 690 | // 创建 RedisVectorStoreProperties 对象 |
| 691 | + // TODO @芋艿:index-name 可能影响索引名; | |
| 660 | 692 | RedisVectorStoreAutoConfiguration configuration = new RedisVectorStoreAutoConfiguration(); |
| 661 | 693 | RedisVectorStoreProperties properties = SpringUtil.getBean(RedisVectorStoreProperties.class); |
| 662 | 694 | RedisVectorStore redisVectorStore = RedisVectorStore.builder(jedisPooled, embeddingModel) |
| 663 | - .indexName(properties.getIndex()).prefix(properties.getPrefix()) | |
| 695 | + .indexName(properties.getIndexName()).prefix(properties.getPrefix()) | |
| 664 | 696 | .initializeSchema(properties.isInitializeSchema()) |
| 665 | 697 | .metadataFields(convertList(metadataFields.entrySet(), entry -> { |
| 666 | 698 | String fieldName = entry.getKey(); |
| ... | ... | @@ -730,10 +762,12 @@ public class AiModelFactoryImpl implements AiModelFactory { |
| 730 | 762 | |
| 731 | 763 | private static ObjectProvider<VectorStoreObservationConvention> getCustomObservationConvention() { |
| 732 | 764 | return new ObjectProvider<>() { |
| 765 | + | |
| 733 | 766 | @Override |
| 734 | 767 | public VectorStoreObservationConvention getObject() throws BeansException { |
| 735 | 768 | return new DefaultVectorStoreObservationConvention(); |
| 736 | 769 | } |
| 770 | + | |
| 737 | 771 | }; |
| 738 | 772 | } |
| 739 | 773 | |
| ... | ... | @@ -745,8 +779,15 @@ public class AiModelFactoryImpl implements AiModelFactory { |
| 745 | 779 | return SpringUtil.getBean(ToolCallingManager.class); |
| 746 | 780 | } |
| 747 | 781 | |
| 748 | - private static FunctionCallbackResolver getFunctionCallbackResolver() { | |
| 749 | - return SpringUtil.getBean(FunctionCallbackResolver.class); | |
| 782 | + private static ObjectProvider<EmbeddingModelObservationConvention> getEmbeddingModelObservationConvention() { | |
| 783 | + return new ObjectProvider<>() { | |
| 784 | + | |
| 785 | + @Override | |
| 786 | + public EmbeddingModelObservationConvention getObject() throws BeansException { | |
| 787 | + return SpringUtil.getBean(EmbeddingModelObservationConvention.class); | |
| 788 | + } | |
| 789 | + | |
| 790 | + }; | |
| 750 | 791 | } |
| 751 | 792 | |
| 752 | 793 | } | ... | ... |
yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/chat/AzureOpenAIChatModelTests.java
| ... | ... | @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.ai.framework.ai.core.model.chat; |
| 2 | 2 | |
| 3 | 3 | import com.azure.ai.openai.OpenAIClientBuilder; |
| 4 | 4 | import com.azure.core.credential.AzureKeyCredential; |
| 5 | -import com.azure.core.util.ClientOptions; | |
| 6 | 5 | import org.junit.jupiter.api.Disabled; |
| 7 | 6 | import org.junit.jupiter.api.Test; |
| 8 | 7 | import org.springframework.ai.azure.openai.AzureOpenAiChatModel; |
| ... | ... | @@ -17,7 +16,7 @@ import reactor.core.publisher.Flux; |
| 17 | 16 | import java.util.ArrayList; |
| 18 | 17 | import java.util.List; |
| 19 | 18 | |
| 20 | -import static org.springframework.ai.autoconfigure.azure.openai.AzureOpenAiChatProperties.DEFAULT_DEPLOYMENT_NAME; | |
| 19 | +import static org.springframework.ai.model.azure.openai.autoconfigure.AzureOpenAiChatProperties.DEFAULT_DEPLOYMENT_NAME; | |
| 21 | 20 | |
| 22 | 21 | /** |
| 23 | 22 | * {@link AzureOpenAiChatModel} 集成测试 |
| ... | ... | @@ -29,10 +28,13 @@ public class AzureOpenAIChatModelTests { |
| 29 | 28 | // TODO @芋艿:晚点在调整 |
| 30 | 29 | private final OpenAIClientBuilder openAiApi = new OpenAIClientBuilder() |
| 31 | 30 | .endpoint("https://eastusprejade.openai.azure.com") |
| 32 | - .credential(new AzureKeyCredential("xxx")) | |
| 33 | - .clientOptions((new ClientOptions()).setApplicationId("spring-ai")); | |
| 34 | - private final AzureOpenAiChatModel chatModel = new AzureOpenAiChatModel(openAiApi, | |
| 35 | - AzureOpenAiChatOptions.builder().deploymentName(DEFAULT_DEPLOYMENT_NAME).build()); | |
| 31 | + .credential(new AzureKeyCredential("xxx")); | |
| 32 | + private final AzureOpenAiChatModel chatModel = AzureOpenAiChatModel.builder() | |
| 33 | + .openAIClientBuilder(openAiApi) | |
| 34 | + .defaultOptions(AzureOpenAiChatOptions.builder() | |
| 35 | + .deploymentName(DEFAULT_DEPLOYMENT_NAME) | |
| 36 | + .build()) | |
| 37 | + .build(); | |
| 36 | 38 | |
| 37 | 39 | @Test |
| 38 | 40 | @Disabled | ... | ... |
yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/chat/BaiChuanChatModelTests.java
| 1 | 1 | package cn.iocoder.yudao.module.ai.framework.ai.core.model.chat; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.module.ai.framework.ai.core.model.baichuan.BaiChuanChatModel; |
| 4 | -import cn.iocoder.yudao.module.ai.framework.ai.core.model.deepseek.DeepSeekChatModel; | |
| 5 | 4 | import org.junit.jupiter.api.Disabled; |
| 6 | 5 | import org.junit.jupiter.api.Test; |
| 7 | 6 | import org.springframework.ai.chat.messages.Message; |
| ... | ... | @@ -35,7 +34,7 @@ public class BaiChuanChatModelTests { |
| 35 | 34 | .build()) |
| 36 | 35 | .build(); |
| 37 | 36 | |
| 38 | - private final DeepSeekChatModel chatModel = new DeepSeekChatModel(openAiChatModel); | |
| 37 | + private final BaiChuanChatModel chatModel = new BaiChuanChatModel(openAiChatModel); | |
| 39 | 38 | |
| 40 | 39 | @Test |
| 41 | 40 | @Disabled | ... | ... |
yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/chat/MoonshotChatModelTests.java
| ... | ... | @@ -2,14 +2,14 @@ package cn.iocoder.yudao.module.ai.framework.ai.core.model.chat; |
| 2 | 2 | |
| 3 | 3 | import org.junit.jupiter.api.Disabled; |
| 4 | 4 | import org.junit.jupiter.api.Test; |
| 5 | +import org.springaicommunity.moonshot.MoonshotChatModel; | |
| 6 | +import org.springaicommunity.moonshot.MoonshotChatOptions; | |
| 7 | +import org.springaicommunity.moonshot.api.MoonshotApi; | |
| 5 | 8 | import org.springframework.ai.chat.messages.Message; |
| 6 | 9 | import org.springframework.ai.chat.messages.SystemMessage; |
| 7 | 10 | import org.springframework.ai.chat.messages.UserMessage; |
| 8 | 11 | import org.springframework.ai.chat.model.ChatResponse; |
| 9 | 12 | import org.springframework.ai.chat.prompt.Prompt; |
| 10 | -import org.springframework.ai.moonshot.MoonshotChatModel; | |
| 11 | -import org.springframework.ai.moonshot.MoonshotChatOptions; | |
| 12 | -import org.springframework.ai.moonshot.api.MoonshotApi; | |
| 13 | 13 | import reactor.core.publisher.Flux; |
| 14 | 14 | |
| 15 | 15 | import java.util.ArrayList; |
| ... | ... | @@ -22,11 +22,15 @@ import java.util.List; |
| 22 | 22 | */ |
| 23 | 23 | public class MoonshotChatModelTests { |
| 24 | 24 | |
| 25 | - private final MoonshotChatModel chatModel = new MoonshotChatModel( | |
| 26 | - new MoonshotApi("sk-aHYYV1SARscItye5QQRRNbXij4fy65Ee7pNZlC9gsSQnUKXA"), // 密钥 | |
| 27 | - MoonshotChatOptions.builder() | |
| 28 | - .model("moonshot-v1-8k") // 模型 | |
| 29 | - .build()); | |
| 25 | + private final MoonshotChatModel chatModel = MoonshotChatModel.builder() | |
| 26 | + .moonshotApi(MoonshotApi.builder() | |
| 27 | + .apiKey("sk-aHYYV1SARscItye5QQRRNbXij4fy65Ee7pNZlC9gsSQnUKXA") // 密钥 | |
| 28 | + .build()) | |
| 29 | + .defaultOptions(MoonshotChatOptions.builder() | |
| 30 | + .model("kimi-k2-0711-preview") // 模型 | |
| 31 | + .build()) | |
| 32 | + .build(); | |
| 33 | + | |
| 30 | 34 | @Test |
| 31 | 35 | @Disabled |
| 32 | 36 | public void testCall() { | ... | ... |
yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/image/StabilityAiImageModelTests.java
| ... | ... | @@ -31,8 +31,8 @@ public class StabilityAiImageModelTests { |
| 31 | 31 | public void testCall() { |
| 32 | 32 | // 准备参数 |
| 33 | 33 | ImageOptions options = OpenAiImageOptions.builder() |
| 34 | - .withModel("stable-diffusion-v1-6") | |
| 35 | - .withHeight(320).withWidth(320) | |
| 34 | + .model("stable-diffusion-v1-6") | |
| 35 | + .height(320).width(320) | |
| 36 | 36 | .build(); |
| 37 | 37 | ImagePrompt prompt = new ImagePrompt("great wall", options); |
| 38 | 38 | ... | ... |
yudao-server/src/main/resources/application.yaml
| ... | ... | @@ -188,13 +188,14 @@ spring: |
| 188 | 188 | api-key: xxxx |
| 189 | 189 | moonshot: # 月之暗灭(KIMI) |
| 190 | 190 | api-key: sk-abc |
| 191 | + deepseek: # DeepSeek | |
| 192 | + api-key: sk-e94db327cc7d457d99a8de8810fc6b12 | |
| 193 | + chat: | |
| 194 | + options: | |
| 195 | + model: deepseek-chat | |
| 191 | 196 | |
| 192 | 197 | yudao: |
| 193 | 198 | ai: |
| 194 | - deep-seek: # DeepSeek | |
| 195 | - enable: true | |
| 196 | - api-key: sk-e94db327cc7d457d99a8de8810fc6b12 | |
| 197 | - model: deepseek-chat | |
| 198 | 199 | doubao: # 字节豆包 |
| 199 | 200 | enable: true |
| 200 | 201 | api-key: 5c1b5747-26d2-4ebd-a4e0-dd0e8d8b4272 | ... | ... |