feat:【AI 大模型】依赖 spring ai 升级到 1.0.0
parent
7a8e089a42
commit
ef874191a6
|
@ -14,11 +14,12 @@
|
|||
<description>
|
||||
ai 模块下,接入 LLM 大模型,支持聊天、绘图、音乐、写作、思维导图等功能。
|
||||
目前已接入各种模型,不限于:
|
||||
国内:通义千问、文心一言、讯飞星火、智谱 GLM、DeepSeek
|
||||
国外:OpenAI、Ollama、Midjourney、StableDiffusion、Suno
|
||||
国内:通义千问、文心一言、讯飞星火、智谱 GLM、DeepSeek
|
||||
国外:OpenAI、Ollama、Midjourney、StableDiffusion、Suno
|
||||
</description>
|
||||
<properties>
|
||||
<spring-ai.version>1.0.0-M6</spring-ai.version>
|
||||
<spring-ai.version>1.0.0</spring-ai.version>
|
||||
<alibaba-ai.version>1.0.0.2</alibaba-ai.version>
|
||||
<tinyflow.version>1.0.2</tinyflow.version>
|
||||
</properties>
|
||||
|
||||
|
@ -110,65 +111,73 @@
|
|||
<!-- Spring AI Model 模型接入 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.ai</groupId>
|
||||
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
|
||||
<artifactId>spring-ai-starter-model-openai</artifactId>
|
||||
<version>${spring-ai.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.ai</groupId>
|
||||
<artifactId>spring-ai-azure-openai-spring-boot-starter</artifactId>
|
||||
<artifactId>spring-ai-starter-model-azure-openai</artifactId>
|
||||
<version>${spring-ai.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.ai</groupId>
|
||||
<artifactId>spring-ai-ollama-spring-boot-starter</artifactId>
|
||||
<artifactId>spring-ai-starter-model-deepseek</artifactId>
|
||||
<version>${spring-ai.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.ai</groupId>
|
||||
<artifactId>spring-ai-stability-ai-spring-boot-starter</artifactId>
|
||||
<artifactId>spring-ai-starter-model-ollama</artifactId>
|
||||
<version>${spring-ai.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<!-- 通义千问 -->
|
||||
<groupId>com.alibaba.cloud.ai</groupId>
|
||||
<artifactId>spring-ai-alibaba-starter</artifactId>
|
||||
<version>${spring-ai.version}.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<!-- 文心一言 -->
|
||||
<groupId>org.springframework.ai</groupId>
|
||||
<artifactId>spring-ai-qianfan-spring-boot-starter</artifactId>
|
||||
<artifactId>spring-ai-starter-model-stability-ai</artifactId>
|
||||
<version>${spring-ai.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<!-- 智谱 GLM -->
|
||||
<groupId>org.springframework.ai</groupId>
|
||||
<artifactId>spring-ai-zhipuai-spring-boot-starter</artifactId>
|
||||
<artifactId>spring-ai-starter-model-zhipuai</artifactId>
|
||||
<version>${spring-ai.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.ai</groupId>
|
||||
<artifactId>spring-ai-minimax-spring-boot-starter</artifactId>
|
||||
<artifactId>spring-ai-starter-model-minimax</artifactId>
|
||||
<version>${spring-ai.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.ai</groupId>
|
||||
<artifactId>spring-ai-moonshot-spring-boot-starter</artifactId>
|
||||
<version>${spring-ai.version}</version>
|
||||
<!-- 通义千问 -->
|
||||
<groupId>com.alibaba.cloud.ai</groupId>
|
||||
<artifactId>spring-ai-alibaba-starter-dashscope</artifactId>
|
||||
<version>${alibaba-ai.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<!-- 文心一言 -->
|
||||
<groupId>org.springaicommunity</groupId>
|
||||
<artifactId>qianfan-spring-boot-starter</artifactId>
|
||||
<version>1.0.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<!-- 月之暗灭 -->
|
||||
<groupId>org.springaicommunity</groupId>
|
||||
<artifactId>moonshot-spring-boot-starter</artifactId>
|
||||
<version>1.0.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 向量存储:https://db-engines.com/en/ranking/vector+dbms -->
|
||||
<dependency>
|
||||
<!-- Qdrant:https://qdrant.tech/ -->
|
||||
<groupId>org.springframework.ai</groupId>
|
||||
<artifactId>spring-ai-qdrant-store</artifactId>
|
||||
<artifactId>spring-ai-starter-vector-store-qdrant</artifactId>
|
||||
<version>${spring-ai.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<!-- Redis:https://redis.io/docs/latest/develop/get-started/vector-database/ -->
|
||||
<groupId>org.springframework.ai</groupId>
|
||||
<artifactId>spring-ai-redis-store</artifactId>
|
||||
<artifactId>spring-ai-starter-vector-store-redis</artifactId>
|
||||
<version>${spring-ai.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
@ -179,7 +188,7 @@
|
|||
<dependency>
|
||||
<!-- Milvus:https://milvus.io/ -->
|
||||
<groupId>org.springframework.ai</groupId>
|
||||
<artifactId>spring-ai-milvus-store</artifactId>
|
||||
<artifactId>spring-ai-starter-vector-store-milvus</artifactId>
|
||||
<version>${spring-ai.version}</version>
|
||||
<exclusions>
|
||||
<!-- 解决和 logback 的日志冲突 -->
|
||||
|
|
|
@ -13,8 +13,8 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
|
|||
* @author 芋道源码
|
||||
*/
|
||||
@SpringBootApplication(exclude = {
|
||||
org.springframework.ai.autoconfigure.vectorstore.qdrant.QdrantVectorStoreAutoConfiguration.class,
|
||||
org.springframework.ai.autoconfigure.vectorstore.milvus.MilvusVectorStoreAutoConfiguration.class,
|
||||
org.springframework.ai.vectorstore.qdrant.autoconfigure.QdrantVectorStoreAutoConfiguration.class,
|
||||
org.springframework.ai.vectorstore.milvus.autoconfigure.MilvusVectorStoreAutoConfiguration.class,
|
||||
}) // 解决 application-${profile}.yaml 配置文件下,通过 spring.autoconfigure.exclude 无法排除的问题
|
||||
public class AiServerApplication {
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@ import cn.hutool.extra.spring.SpringUtil;
|
|||
import cn.iocoder.yudao.module.ai.framework.ai.core.AiModelFactory;
|
||||
import cn.iocoder.yudao.module.ai.framework.ai.core.AiModelFactoryImpl;
|
||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.baichuan.BaiChuanChatModel;
|
||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.deepseek.DeepSeekChatModel;
|
||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.doubao.DouBaoChatModel;
|
||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.hunyuan.HunYuanChatModel;
|
||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.midjourney.api.MidjourneyApi;
|
||||
|
@ -14,10 +13,6 @@ import cn.iocoder.yudao.module.ai.framework.ai.core.model.siliconflow.SiliconFlo
|
|||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.suno.api.SunoApi;
|
||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.xinghuo.XingHuoChatModel;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.ai.autoconfigure.vectorstore.milvus.MilvusServiceClientProperties;
|
||||
import org.springframework.ai.autoconfigure.vectorstore.milvus.MilvusVectorStoreProperties;
|
||||
import org.springframework.ai.autoconfigure.vectorstore.qdrant.QdrantVectorStoreProperties;
|
||||
import org.springframework.ai.autoconfigure.vectorstore.redis.RedisVectorStoreProperties;
|
||||
import org.springframework.ai.embedding.BatchingStrategy;
|
||||
import org.springframework.ai.embedding.TokenCountBatchingStrategy;
|
||||
import org.springframework.ai.model.tool.ToolCallingManager;
|
||||
|
@ -26,6 +21,10 @@ import org.springframework.ai.openai.OpenAiChatOptions;
|
|||
import org.springframework.ai.openai.api.OpenAiApi;
|
||||
import org.springframework.ai.tokenizer.JTokkitTokenCountEstimator;
|
||||
import org.springframework.ai.tokenizer.TokenCountEstimator;
|
||||
import org.springframework.ai.vectorstore.milvus.autoconfigure.MilvusServiceClientProperties;
|
||||
import org.springframework.ai.vectorstore.milvus.autoconfigure.MilvusVectorStoreProperties;
|
||||
import org.springframework.ai.vectorstore.qdrant.autoconfigure.QdrantVectorStoreProperties;
|
||||
import org.springframework.ai.vectorstore.redis.autoconfigure.RedisVectorStoreProperties;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
@ -52,33 +51,6 @@ public class AiAutoConfiguration {
|
|||
|
||||
// ========== 各种 AI Client 创建 ==========
|
||||
|
||||
@Bean
|
||||
@ConditionalOnProperty(value = "yudao.ai.deepseek.enable", havingValue = "true")
|
||||
public DeepSeekChatModel deepSeekChatModel(YudaoAiProperties yudaoAiProperties) {
|
||||
YudaoAiProperties.DeepSeekProperties properties = yudaoAiProperties.getDeepseek();
|
||||
return buildDeepSeekChatModel(properties);
|
||||
}
|
||||
|
||||
public DeepSeekChatModel buildDeepSeekChatModel(YudaoAiProperties.DeepSeekProperties properties) {
|
||||
if (StrUtil.isEmpty(properties.getModel())) {
|
||||
properties.setModel(DeepSeekChatModel.MODEL_DEFAULT);
|
||||
}
|
||||
OpenAiChatModel openAiChatModel = OpenAiChatModel.builder()
|
||||
.openAiApi(OpenAiApi.builder()
|
||||
.baseUrl(DeepSeekChatModel.BASE_URL)
|
||||
.apiKey(properties.getApiKey())
|
||||
.build())
|
||||
.defaultOptions(OpenAiChatOptions.builder()
|
||||
.model(properties.getModel())
|
||||
.temperature(properties.getTemperature())
|
||||
.maxTokens(properties.getMaxTokens())
|
||||
.topP(properties.getTopP())
|
||||
.build())
|
||||
.toolCallingManager(getToolCallingManager())
|
||||
.build();
|
||||
return new DeepSeekChatModel(openAiChatModel);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnProperty(value = "yudao.ai.doubao.enable", havingValue = "true")
|
||||
public DouBaoChatModel douBaoChatClient(YudaoAiProperties yudaoAiProperties) {
|
||||
|
|
|
@ -13,12 +13,6 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
|
|||
@Data
|
||||
public class YudaoAiProperties {
|
||||
|
||||
/**
|
||||
* DeepSeek
|
||||
*/
|
||||
@SuppressWarnings("SpellCheckingInspection")
|
||||
private DeepSeekProperties deepseek;
|
||||
|
||||
/**
|
||||
* 字节豆包
|
||||
*/
|
||||
|
@ -60,19 +54,6 @@ public class YudaoAiProperties {
|
|||
@SuppressWarnings("SpellCheckingInspection")
|
||||
private SunoProperties suno;
|
||||
|
||||
@Data
|
||||
public static class DeepSeekProperties {
|
||||
|
||||
private String enable;
|
||||
private String apiKey;
|
||||
|
||||
private String model;
|
||||
private Double temperature;
|
||||
private Integer maxTokens;
|
||||
private Double topP;
|
||||
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class DouBaoProperties {
|
||||
|
||||
|
|
|
@ -8,11 +8,11 @@ import cn.hutool.core.util.ArrayUtil;
|
|||
import cn.hutool.core.util.RuntimeUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.extra.spring.SpringUtil;
|
||||
import cn.iocoder.yudao.framework.common.util.spring.SpringUtils;
|
||||
import cn.iocoder.yudao.module.ai.enums.model.AiPlatformEnum;
|
||||
import cn.iocoder.yudao.module.ai.framework.ai.config.AiAutoConfiguration;
|
||||
import cn.iocoder.yudao.module.ai.framework.ai.config.YudaoAiProperties;
|
||||
import cn.iocoder.yudao.module.ai.enums.model.AiPlatformEnum;
|
||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.baichuan.BaiChuanChatModel;
|
||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.deepseek.DeepSeekChatModel;
|
||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.doubao.DouBaoChatModel;
|
||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.hunyuan.HunYuanChatModel;
|
||||
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
|
|||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.siliconflow.SiliconFlowImageModel;
|
||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.suno.api.SunoApi;
|
||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.xinghuo.XingHuoChatModel;
|
||||
import cn.iocoder.yudao.framework.common.util.spring.SpringUtils;
|
||||
import com.alibaba.cloud.ai.autoconfigure.dashscope.DashScopeAutoConfiguration;
|
||||
import com.alibaba.cloud.ai.autoconfigure.dashscope.DashScopeChatAutoConfiguration;
|
||||
import com.alibaba.cloud.ai.autoconfigure.dashscope.DashScopeEmbeddingAutoConfiguration;
|
||||
import com.alibaba.cloud.ai.autoconfigure.dashscope.DashScopeImageAutoConfiguration;
|
||||
import com.alibaba.cloud.ai.dashscope.api.DashScopeApi;
|
||||
import com.alibaba.cloud.ai.dashscope.api.DashScopeImageApi;
|
||||
import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatModel;
|
||||
|
@ -32,47 +33,55 @@ import com.alibaba.cloud.ai.dashscope.embedding.DashScopeEmbeddingModel;
|
|||
import com.alibaba.cloud.ai.dashscope.embedding.DashScopeEmbeddingOptions;
|
||||
import com.alibaba.cloud.ai.dashscope.image.DashScopeImageModel;
|
||||
import com.azure.ai.openai.OpenAIClientBuilder;
|
||||
import com.azure.core.credential.KeyCredential;
|
||||
import io.micrometer.observation.ObservationRegistry;
|
||||
import io.milvus.client.MilvusServiceClient;
|
||||
import io.qdrant.client.QdrantClient;
|
||||
import io.qdrant.client.QdrantGrpcClient;
|
||||
import lombok.SneakyThrows;
|
||||
import org.springframework.ai.autoconfigure.azure.openai.AzureOpenAiAutoConfiguration;
|
||||
import org.springframework.ai.autoconfigure.azure.openai.AzureOpenAiChatProperties;
|
||||
import org.springframework.ai.autoconfigure.azure.openai.AzureOpenAiConnectionProperties;
|
||||
import org.springframework.ai.autoconfigure.azure.openai.AzureOpenAiEmbeddingProperties;
|
||||
import org.springframework.ai.autoconfigure.minimax.MiniMaxAutoConfiguration;
|
||||
import org.springframework.ai.autoconfigure.moonshot.MoonshotAutoConfiguration;
|
||||
import org.springframework.ai.autoconfigure.ollama.OllamaAutoConfiguration;
|
||||
import org.springframework.ai.autoconfigure.openai.OpenAiAutoConfiguration;
|
||||
import org.springframework.ai.autoconfigure.qianfan.QianFanAutoConfiguration;
|
||||
import org.springframework.ai.autoconfigure.stabilityai.StabilityAiImageAutoConfiguration;
|
||||
import org.springframework.ai.autoconfigure.vectorstore.milvus.MilvusServiceClientConnectionDetails;
|
||||
import org.springframework.ai.autoconfigure.vectorstore.milvus.MilvusServiceClientProperties;
|
||||
import org.springframework.ai.autoconfigure.vectorstore.milvus.MilvusVectorStoreAutoConfiguration;
|
||||
import org.springframework.ai.autoconfigure.vectorstore.milvus.MilvusVectorStoreProperties;
|
||||
import org.springframework.ai.autoconfigure.vectorstore.qdrant.QdrantVectorStoreAutoConfiguration;
|
||||
import org.springframework.ai.autoconfigure.vectorstore.qdrant.QdrantVectorStoreProperties;
|
||||
import org.springframework.ai.autoconfigure.vectorstore.redis.RedisVectorStoreAutoConfiguration;
|
||||
import org.springframework.ai.autoconfigure.vectorstore.redis.RedisVectorStoreProperties;
|
||||
import org.springframework.ai.autoconfigure.zhipuai.ZhiPuAiAutoConfiguration;
|
||||
import org.springaicommunity.moonshot.MoonshotChatModel;
|
||||
import org.springaicommunity.moonshot.MoonshotChatOptions;
|
||||
import org.springaicommunity.moonshot.api.MoonshotApi;
|
||||
import org.springaicommunity.moonshot.autoconfigure.MoonshotChatAutoConfiguration;
|
||||
import org.springaicommunity.qianfan.QianFanChatModel;
|
||||
import org.springaicommunity.qianfan.QianFanEmbeddingModel;
|
||||
import org.springaicommunity.qianfan.QianFanEmbeddingOptions;
|
||||
import org.springaicommunity.qianfan.QianFanImageModel;
|
||||
import org.springaicommunity.qianfan.api.QianFanApi;
|
||||
import org.springaicommunity.qianfan.api.QianFanImageApi;
|
||||
import org.springaicommunity.qianfan.autoconfigure.QianFanChatAutoConfiguration;
|
||||
import org.springaicommunity.qianfan.autoconfigure.QianFanEmbeddingAutoConfiguration;
|
||||
import org.springframework.ai.azure.openai.AzureOpenAiChatModel;
|
||||
import org.springframework.ai.azure.openai.AzureOpenAiEmbeddingModel;
|
||||
import org.springframework.ai.chat.model.ChatModel;
|
||||
import org.springframework.ai.deepseek.DeepSeekChatModel;
|
||||
import org.springframework.ai.deepseek.DeepSeekChatOptions;
|
||||
import org.springframework.ai.deepseek.api.DeepSeekApi;
|
||||
import org.springframework.ai.document.MetadataMode;
|
||||
import org.springframework.ai.embedding.BatchingStrategy;
|
||||
import org.springframework.ai.embedding.EmbeddingModel;
|
||||
import org.springframework.ai.embedding.observation.EmbeddingModelObservationConvention;
|
||||
import org.springframework.ai.image.ImageModel;
|
||||
import org.springframework.ai.minimax.MiniMaxChatModel;
|
||||
import org.springframework.ai.minimax.MiniMaxChatOptions;
|
||||
import org.springframework.ai.minimax.MiniMaxEmbeddingModel;
|
||||
import org.springframework.ai.minimax.MiniMaxEmbeddingOptions;
|
||||
import org.springframework.ai.minimax.api.MiniMaxApi;
|
||||
import org.springframework.ai.model.function.FunctionCallbackResolver;
|
||||
import org.springframework.ai.model.azure.openai.autoconfigure.AzureOpenAiChatAutoConfiguration;
|
||||
import org.springframework.ai.model.azure.openai.autoconfigure.AzureOpenAiEmbeddingAutoConfiguration;
|
||||
import org.springframework.ai.model.azure.openai.autoconfigure.AzureOpenAiEmbeddingProperties;
|
||||
import org.springframework.ai.model.deepseek.autoconfigure.DeepSeekChatAutoConfiguration;
|
||||
import org.springframework.ai.model.minimax.autoconfigure.MiniMaxChatAutoConfiguration;
|
||||
import org.springframework.ai.model.minimax.autoconfigure.MiniMaxEmbeddingAutoConfiguration;
|
||||
import org.springframework.ai.model.ollama.autoconfigure.OllamaChatAutoConfiguration;
|
||||
import org.springframework.ai.model.openai.autoconfigure.OpenAiChatAutoConfiguration;
|
||||
import org.springframework.ai.model.openai.autoconfigure.OpenAiEmbeddingAutoConfiguration;
|
||||
import org.springframework.ai.model.openai.autoconfigure.OpenAiImageAutoConfiguration;
|
||||
import org.springframework.ai.model.stabilityai.autoconfigure.StabilityAiImageAutoConfiguration;
|
||||
import org.springframework.ai.model.tool.ToolCallingManager;
|
||||
import org.springframework.ai.moonshot.MoonshotChatModel;
|
||||
import org.springframework.ai.moonshot.MoonshotChatOptions;
|
||||
import org.springframework.ai.moonshot.api.MoonshotApi;
|
||||
import org.springframework.ai.model.zhipuai.autoconfigure.ZhiPuAiChatAutoConfiguration;
|
||||
import org.springframework.ai.model.zhipuai.autoconfigure.ZhiPuAiEmbeddingAutoConfiguration;
|
||||
import org.springframework.ai.model.zhipuai.autoconfigure.ZhiPuAiImageAutoConfiguration;
|
||||
import org.springframework.ai.ollama.OllamaChatModel;
|
||||
import org.springframework.ai.ollama.OllamaEmbeddingModel;
|
||||
import org.springframework.ai.ollama.api.OllamaApi;
|
||||
|
@ -84,21 +93,23 @@ import org.springframework.ai.openai.OpenAiImageModel;
|
|||
import org.springframework.ai.openai.api.OpenAiApi;
|
||||
import org.springframework.ai.openai.api.OpenAiImageApi;
|
||||
import org.springframework.ai.openai.api.common.OpenAiApiConstants;
|
||||
import org.springframework.ai.qianfan.QianFanChatModel;
|
||||
import org.springframework.ai.qianfan.QianFanEmbeddingModel;
|
||||
import org.springframework.ai.qianfan.QianFanEmbeddingOptions;
|
||||
import org.springframework.ai.qianfan.QianFanImageModel;
|
||||
import org.springframework.ai.qianfan.api.QianFanApi;
|
||||
import org.springframework.ai.qianfan.api.QianFanImageApi;
|
||||
import org.springframework.ai.stabilityai.StabilityAiImageModel;
|
||||
import org.springframework.ai.stabilityai.api.StabilityAiApi;
|
||||
import org.springframework.ai.vectorstore.SimpleVectorStore;
|
||||
import org.springframework.ai.vectorstore.VectorStore;
|
||||
import org.springframework.ai.vectorstore.milvus.MilvusVectorStore;
|
||||
import org.springframework.ai.vectorstore.milvus.autoconfigure.MilvusServiceClientConnectionDetails;
|
||||
import org.springframework.ai.vectorstore.milvus.autoconfigure.MilvusServiceClientProperties;
|
||||
import org.springframework.ai.vectorstore.milvus.autoconfigure.MilvusVectorStoreAutoConfiguration;
|
||||
import org.springframework.ai.vectorstore.milvus.autoconfigure.MilvusVectorStoreProperties;
|
||||
import org.springframework.ai.vectorstore.observation.DefaultVectorStoreObservationConvention;
|
||||
import org.springframework.ai.vectorstore.observation.VectorStoreObservationConvention;
|
||||
import org.springframework.ai.vectorstore.qdrant.QdrantVectorStore;
|
||||
import org.springframework.ai.vectorstore.qdrant.autoconfigure.QdrantVectorStoreAutoConfiguration;
|
||||
import org.springframework.ai.vectorstore.qdrant.autoconfigure.QdrantVectorStoreProperties;
|
||||
import org.springframework.ai.vectorstore.redis.RedisVectorStore;
|
||||
import org.springframework.ai.vectorstore.redis.autoconfigure.RedisVectorStoreAutoConfiguration;
|
||||
import org.springframework.ai.vectorstore.redis.autoconfigure.RedisVectorStoreProperties;
|
||||
import org.springframework.ai.zhipuai.*;
|
||||
import org.springframework.ai.zhipuai.api.ZhiPuAiApi;
|
||||
import org.springframework.ai.zhipuai.api.ZhiPuAiImageApi;
|
||||
|
@ -190,7 +201,7 @@ public class AiModelFactoryImpl implements AiModelFactory {
|
|||
case XING_HUO:
|
||||
return SpringUtil.getBean(XingHuoChatModel.class);
|
||||
case BAI_CHUAN:
|
||||
return SpringUtil.getBean(AzureOpenAiChatModel.class);
|
||||
return SpringUtil.getBean(BaiChuanChatModel.class);
|
||||
case OPENAI:
|
||||
return SpringUtil.getBean(OpenAiChatModel.class);
|
||||
case AZURE_OPENAI:
|
||||
|
@ -319,27 +330,34 @@ public class AiModelFactoryImpl implements AiModelFactory {
|
|||
// ========== 各种创建 spring-ai 客户端的方法 ==========
|
||||
|
||||
/**
|
||||
* 可参考 {@link DashScopeAutoConfiguration} 的 dashscopeChatModel 方法
|
||||
* 可参考 {@link DashScopeChatAutoConfiguration} 的 dashscopeChatModel 方法
|
||||
*/
|
||||
private static DashScopeChatModel buildTongYiChatModel(String key) {
|
||||
DashScopeApi dashScopeApi = new DashScopeApi(key);
|
||||
DashScopeApi dashScopeApi = DashScopeApi.builder().apiKey(key).build();
|
||||
DashScopeChatOptions options = DashScopeChatOptions.builder().withModel(DashScopeApi.DEFAULT_CHAT_MODEL)
|
||||
.withTemperature(0.7).build();
|
||||
return new DashScopeChatModel(dashScopeApi, options, getFunctionCallbackResolver(), DEFAULT_RETRY_TEMPLATE);
|
||||
return DashScopeChatModel.builder()
|
||||
.dashScopeApi(dashScopeApi)
|
||||
.defaultOptions(options)
|
||||
.toolCallingManager(getToolCallingManager())
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 可参考 {@link DashScopeAutoConfiguration} 的 dashScopeImageModel 方法
|
||||
* 可参考 {@link DashScopeImageAutoConfiguration} 的 dashScopeImageModel 方法
|
||||
*/
|
||||
private static DashScopeImageModel buildTongYiImagesModel(String key) {
|
||||
DashScopeImageApi dashScopeImageApi = new DashScopeImageApi(key);
|
||||
return new DashScopeImageModel(dashScopeImageApi);
|
||||
return DashScopeImageModel.builder()
|
||||
.dashScopeApi(dashScopeImageApi)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 可参考 {@link QianFanAutoConfiguration} 的 qianFanChatModel 方法
|
||||
* 可参考 {@link QianFanChatAutoConfiguration} 的 qianFanChatModel 方法
|
||||
*/
|
||||
private static QianFanChatModel buildYiYanChatModel(String key) {
|
||||
// TODO spring ai qianfan 有 bug,无法使用 https://github.com/spring-ai-community/qianfan/issues/6
|
||||
List<String> keys = StrUtil.split(key, '|');
|
||||
Assert.equals(keys.size(), 2, "YiYanChatClient 的密钥需要 (appKey|secretKey) 格式");
|
||||
String appKey = keys.get(0);
|
||||
|
@ -349,9 +367,10 @@ public class AiModelFactoryImpl implements AiModelFactory {
|
|||
}
|
||||
|
||||
/**
|
||||
* 可参考 {@link QianFanAutoConfiguration} 的 qianFanImageModel 方法
|
||||
* 可参考 {@link QianFanEmbeddingAutoConfiguration} 的 qianFanImageModel 方法
|
||||
*/
|
||||
private QianFanImageModel buildQianFanImageModel(String key) {
|
||||
// TODO spring ai qianfan 有 bug,无法使用 https://github.com/spring-ai-community/qianfan/issues/6
|
||||
List<String> keys = StrUtil.split(key, '|');
|
||||
Assert.equals(keys.size(), 2, "YiYanChatClient 的密钥需要 (appKey|secretKey) 格式");
|
||||
String appKey = keys.get(0);
|
||||
|
@ -361,12 +380,17 @@ public class AiModelFactoryImpl implements AiModelFactory {
|
|||
}
|
||||
|
||||
/**
|
||||
* 可参考 {@link AiAutoConfiguration#deepSeekChatModel(YudaoAiProperties)}
|
||||
* 可参考 {@link DeepSeekChatAutoConfiguration} 的 deepSeekChatModel 方法
|
||||
*/
|
||||
private static DeepSeekChatModel buildDeepSeekChatModel(String apiKey) {
|
||||
YudaoAiProperties.DeepSeekProperties properties = new YudaoAiProperties.DeepSeekProperties()
|
||||
.setApiKey(apiKey);
|
||||
return new AiAutoConfiguration().buildDeepSeekChatModel(properties);
|
||||
DeepSeekApi deepSeekApi = DeepSeekApi.builder().apiKey(apiKey).build();
|
||||
DeepSeekChatOptions options = DeepSeekChatOptions.builder().model(DeepSeekApi.DEFAULT_CHAT_MODEL)
|
||||
.temperature(0.7).build();
|
||||
return DeepSeekChatModel.builder()
|
||||
.deepSeekApi(deepSeekApi)
|
||||
.defaultOptions(options)
|
||||
.toolCallingManager(getToolCallingManager())
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -397,17 +421,18 @@ public class AiModelFactoryImpl implements AiModelFactory {
|
|||
}
|
||||
|
||||
/**
|
||||
* 可参考 {@link ZhiPuAiAutoConfiguration} 的 zhiPuAiChatModel 方法
|
||||
* 可参考 {@link ZhiPuAiChatAutoConfiguration} 的 zhiPuAiChatModel 方法
|
||||
*/
|
||||
private ZhiPuAiChatModel buildZhiPuChatModel(String apiKey, String url) {
|
||||
ZhiPuAiApi zhiPuAiApi = StrUtil.isEmpty(url) ? new ZhiPuAiApi(apiKey)
|
||||
: new ZhiPuAiApi(url, apiKey);
|
||||
ZhiPuAiChatOptions options = ZhiPuAiChatOptions.builder().model(ZhiPuAiApi.DEFAULT_CHAT_MODEL).temperature(0.7).build();
|
||||
return new ZhiPuAiChatModel(zhiPuAiApi, options, getFunctionCallbackResolver(), DEFAULT_RETRY_TEMPLATE);
|
||||
return new ZhiPuAiChatModel(zhiPuAiApi, options, getToolCallingManager(), DEFAULT_RETRY_TEMPLATE,
|
||||
getObservationRegistry().getIfAvailable());
|
||||
}
|
||||
|
||||
/**
|
||||
* 可参考 {@link ZhiPuAiAutoConfiguration} 的 zhiPuAiImageModel 方法
|
||||
* 可参考 {@link ZhiPuAiImageAutoConfiguration} 的 zhiPuAiImageModel 方法
|
||||
*/
|
||||
private ZhiPuAiImageModel buildZhiPuAiImageModel(String apiKey, String url) {
|
||||
ZhiPuAiImageApi zhiPuAiApi = StrUtil.isEmpty(url) ? new ZhiPuAiImageApi(apiKey)
|
||||
|
@ -416,23 +441,30 @@ public class AiModelFactoryImpl implements AiModelFactory {
|
|||
}
|
||||
|
||||
/**
|
||||
* 可参考 {@link MiniMaxAutoConfiguration} 的 miniMaxChatModel 方法
|
||||
* 可参考 {@link MiniMaxChatAutoConfiguration} 的 miniMaxChatModel 方法
|
||||
*/
|
||||
private MiniMaxChatModel buildMiniMaxChatModel(String apiKey, String url) {
|
||||
MiniMaxApi miniMaxApi = StrUtil.isEmpty(url) ? new MiniMaxApi(apiKey)
|
||||
: new MiniMaxApi(url, apiKey);
|
||||
MiniMaxChatOptions options = MiniMaxChatOptions.builder().model(MiniMaxApi.DEFAULT_CHAT_MODEL).temperature(0.7).build();
|
||||
return new MiniMaxChatModel(miniMaxApi, options, getFunctionCallbackResolver(), DEFAULT_RETRY_TEMPLATE);
|
||||
return new MiniMaxChatModel(miniMaxApi, options, getToolCallingManager(), DEFAULT_RETRY_TEMPLATE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 可参考 {@link MoonshotAutoConfiguration} 的 moonshotChatModel 方法
|
||||
* 可参考 {@link MoonshotChatAutoConfiguration} 的 moonshotChatModel 方法
|
||||
*/
|
||||
private MoonshotChatModel buildMoonshotChatModel(String apiKey, String url) {
|
||||
MoonshotApi moonshotApi = StrUtil.isEmpty(url)? new MoonshotApi(apiKey)
|
||||
: new MoonshotApi(url, apiKey);
|
||||
MoonshotApi.Builder moonshotApiBuilder = MoonshotApi.builder()
|
||||
.apiKey(apiKey);
|
||||
if (StrUtil.isNotEmpty(url)) {
|
||||
moonshotApiBuilder.baseUrl(url);
|
||||
}
|
||||
MoonshotChatOptions options = MoonshotChatOptions.builder().model(MoonshotApi.DEFAULT_CHAT_MODEL).build();
|
||||
return new MoonshotChatModel(moonshotApi, options, getFunctionCallbackResolver(), DEFAULT_RETRY_TEMPLATE);
|
||||
return MoonshotChatModel.builder()
|
||||
.moonshotApi(moonshotApiBuilder.build())
|
||||
.defaultOptions(options)
|
||||
.toolCallingManager(getToolCallingManager())
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -456,33 +488,32 @@ public class AiModelFactoryImpl implements AiModelFactory {
|
|||
}
|
||||
|
||||
/**
|
||||
* 可参考 {@link OpenAiAutoConfiguration} 的 openAiChatModel 方法
|
||||
* 可参考 {@link OpenAiChatAutoConfiguration} 的 openAiChatModel 方法
|
||||
*/
|
||||
private static OpenAiChatModel buildOpenAiChatModel(String openAiToken, String url) {
|
||||
url = StrUtil.blankToDefault(url, OpenAiApiConstants.DEFAULT_BASE_URL);
|
||||
OpenAiApi openAiApi = OpenAiApi.builder().baseUrl(url).apiKey(openAiToken).build();
|
||||
return OpenAiChatModel.builder().openAiApi(openAiApi).toolCallingManager(getToolCallingManager()).build();
|
||||
return OpenAiChatModel.builder()
|
||||
.openAiApi(openAiApi)
|
||||
.toolCallingManager(getToolCallingManager())
|
||||
.build();
|
||||
}
|
||||
|
||||
// TODO @芋艿:手头暂时没密钥,使用建议再测试下
|
||||
/**
|
||||
* 可参考 {@link AzureOpenAiAutoConfiguration}
|
||||
* 可参考 {@link AzureOpenAiChatAutoConfiguration}
|
||||
*/
|
||||
private static AzureOpenAiChatModel buildAzureOpenAiChatModel(String apiKey, String url) {
|
||||
AzureOpenAiAutoConfiguration azureOpenAiAutoConfiguration = new AzureOpenAiAutoConfiguration();
|
||||
// 创建 OpenAIClient 对象
|
||||
AzureOpenAiConnectionProperties connectionProperties = new AzureOpenAiConnectionProperties();
|
||||
connectionProperties.setApiKey(apiKey);
|
||||
connectionProperties.setEndpoint(url);
|
||||
OpenAIClientBuilder openAIClient = azureOpenAiAutoConfiguration.openAIClientBuilder(connectionProperties, null);
|
||||
// 获取 AzureOpenAiChatProperties 对象
|
||||
AzureOpenAiChatProperties chatProperties = SpringUtil.getBean(AzureOpenAiChatProperties.class);
|
||||
return azureOpenAiAutoConfiguration.azureOpenAiChatModel(openAIClient, chatProperties,
|
||||
getToolCallingManager(), null, null);
|
||||
// TODO @芋艿:使用前,请测试,暂时没密钥!!!
|
||||
OpenAIClientBuilder openAIClientBuilder = new OpenAIClientBuilder()
|
||||
.endpoint(url).credential(new KeyCredential(apiKey));
|
||||
return AzureOpenAiChatModel.builder()
|
||||
.openAIClientBuilder(openAIClientBuilder)
|
||||
.toolCallingManager(getToolCallingManager())
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 可参考 {@link OpenAiAutoConfiguration} 的 openAiImageModel 方法
|
||||
* 可参考 {@link OpenAiImageAutoConfiguration} 的 openAiImageModel 方法
|
||||
*/
|
||||
private OpenAiImageModel buildOpenAiImageModel(String openAiToken, String url) {
|
||||
url = StrUtil.blankToDefault(url, OpenAiApiConstants.DEFAULT_BASE_URL);
|
||||
|
@ -500,11 +531,14 @@ public class AiModelFactoryImpl implements AiModelFactory {
|
|||
}
|
||||
|
||||
/**
|
||||
* 可参考 {@link OllamaAutoConfiguration} 的 ollamaApi 方法
|
||||
* 可参考 {@link OllamaChatAutoConfiguration} 的 ollamaChatModel 方法
|
||||
*/
|
||||
private static OllamaChatModel buildOllamaChatModel(String url) {
|
||||
OllamaApi ollamaApi = new OllamaApi(url);
|
||||
return OllamaChatModel.builder().ollamaApi(ollamaApi).toolCallingManager(getToolCallingManager()).build();
|
||||
OllamaApi ollamaApi = OllamaApi.builder().baseUrl(url).build();
|
||||
return OllamaChatModel.builder()
|
||||
.ollamaApi(ollamaApi)
|
||||
.toolCallingManager(getToolCallingManager())
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -519,16 +553,16 @@ public class AiModelFactoryImpl implements AiModelFactory {
|
|||
// ========== 各种创建 EmbeddingModel 的方法 ==========
|
||||
|
||||
/**
|
||||
* 可参考 {@link DashScopeAutoConfiguration} 的 dashscopeEmbeddingModel 方法
|
||||
* 可参考 {@link DashScopeEmbeddingAutoConfiguration} 的 dashscopeEmbeddingModel 方法
|
||||
*/
|
||||
private DashScopeEmbeddingModel buildTongYiEmbeddingModel(String apiKey, String model) {
|
||||
DashScopeApi dashScopeApi = new DashScopeApi(apiKey);
|
||||
DashScopeApi dashScopeApi = DashScopeApi.builder().apiKey(apiKey).build();
|
||||
DashScopeEmbeddingOptions dashScopeEmbeddingOptions = DashScopeEmbeddingOptions.builder().withModel(model).build();
|
||||
return new DashScopeEmbeddingModel(dashScopeApi, MetadataMode.EMBED, dashScopeEmbeddingOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* 可参考 {@link ZhiPuAiAutoConfiguration} 的 zhiPuAiEmbeddingModel 方法
|
||||
* 可参考 {@link ZhiPuAiEmbeddingAutoConfiguration} 的 zhiPuAiEmbeddingModel 方法
|
||||
*/
|
||||
private ZhiPuAiEmbeddingModel buildZhiPuEmbeddingModel(String apiKey, String url, String model) {
|
||||
ZhiPuAiApi zhiPuAiApi = StrUtil.isEmpty(url) ? new ZhiPuAiApi(apiKey)
|
||||
|
@ -538,7 +572,7 @@ public class AiModelFactoryImpl implements AiModelFactory {
|
|||
}
|
||||
|
||||
/**
|
||||
* 可参考 {@link MiniMaxAutoConfiguration} 的 miniMaxEmbeddingModel 方法
|
||||
* 可参考 {@link MiniMaxEmbeddingAutoConfiguration} 的 miniMaxEmbeddingModel 方法
|
||||
*/
|
||||
private EmbeddingModel buildMiniMaxEmbeddingModel(String apiKey, String url, String model) {
|
||||
MiniMaxApi miniMaxApi = StrUtil.isEmpty(url)? new MiniMaxApi(apiKey)
|
||||
|
@ -548,7 +582,7 @@ public class AiModelFactoryImpl implements AiModelFactory {
|
|||
}
|
||||
|
||||
/**
|
||||
* 可参考 {@link QianFanAutoConfiguration} 的 qianFanEmbeddingModel 方法
|
||||
* 可参考 {@link QianFanEmbeddingAutoConfiguration} 的 qianFanEmbeddingModel 方法
|
||||
*/
|
||||
private QianFanEmbeddingModel buildYiYanEmbeddingModel(String key, String model) {
|
||||
List<String> keys = StrUtil.split(key, '|');
|
||||
|
@ -561,13 +595,16 @@ public class AiModelFactoryImpl implements AiModelFactory {
|
|||
}
|
||||
|
||||
private OllamaEmbeddingModel buildOllamaEmbeddingModel(String url, String model) {
|
||||
OllamaApi ollamaApi = new OllamaApi(url);
|
||||
OllamaApi ollamaApi = OllamaApi.builder().baseUrl(url).build();
|
||||
OllamaOptions ollamaOptions = OllamaOptions.builder().model(model).build();
|
||||
return OllamaEmbeddingModel.builder().ollamaApi(ollamaApi).defaultOptions(ollamaOptions).build();
|
||||
return OllamaEmbeddingModel.builder()
|
||||
.ollamaApi(ollamaApi)
|
||||
.defaultOptions(ollamaOptions)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 可参考 {@link OpenAiAutoConfiguration} 的 openAiEmbeddingModel 方法
|
||||
* 可参考 {@link OpenAiEmbeddingAutoConfiguration} 的 openAiEmbeddingModel 方法
|
||||
*/
|
||||
private OpenAiEmbeddingModel buildOpenAiEmbeddingModel(String openAiToken, String url, String model) {
|
||||
url = StrUtil.blankToDefault(url, OpenAiApiConstants.DEFAULT_BASE_URL);
|
||||
|
@ -576,21 +613,19 @@ public class AiModelFactoryImpl implements AiModelFactory {
|
|||
return new OpenAiEmbeddingModel(openAiApi, MetadataMode.EMBED, openAiEmbeddingProperties);
|
||||
}
|
||||
|
||||
// TODO @芋艿:手头暂时没密钥,使用建议再测试下
|
||||
/**
|
||||
* 可参考 {@link AzureOpenAiAutoConfiguration} 的 azureOpenAiEmbeddingModel 方法
|
||||
* 可参考 {@link AzureOpenAiEmbeddingAutoConfiguration} 的 azureOpenAiEmbeddingModel 方法
|
||||
*/
|
||||
private AzureOpenAiEmbeddingModel buildAzureOpenAiEmbeddingModel(String apiKey, String url, String model) {
|
||||
AzureOpenAiAutoConfiguration azureOpenAiAutoConfiguration = new AzureOpenAiAutoConfiguration();
|
||||
// 创建 OpenAIClient 对象
|
||||
AzureOpenAiConnectionProperties connectionProperties = new AzureOpenAiConnectionProperties();
|
||||
connectionProperties.setApiKey(apiKey);
|
||||
connectionProperties.setEndpoint(url);
|
||||
OpenAIClientBuilder openAIClient = azureOpenAiAutoConfiguration.openAIClientBuilder(connectionProperties, null);
|
||||
// TODO @芋艿:手头暂时没密钥,使用建议再测试下
|
||||
AzureOpenAiEmbeddingAutoConfiguration azureOpenAiAutoConfiguration = new AzureOpenAiEmbeddingAutoConfiguration();
|
||||
// 创建 OpenAIClientBuilder 对象
|
||||
OpenAIClientBuilder openAIClientBuilder = new OpenAIClientBuilder()
|
||||
.endpoint(url).credential(new KeyCredential(apiKey));
|
||||
// 获取 AzureOpenAiChatProperties 对象
|
||||
AzureOpenAiEmbeddingProperties embeddingProperties = SpringUtil.getBean(AzureOpenAiEmbeddingProperties.class);
|
||||
return azureOpenAiAutoConfiguration.azureOpenAiEmbeddingModel(openAIClient, embeddingProperties,
|
||||
null, null);
|
||||
return azureOpenAiAutoConfiguration.azureOpenAiEmbeddingModel(openAIClientBuilder, embeddingProperties,
|
||||
getObservationRegistry(), getEmbeddingModelObservationConvention());
|
||||
}
|
||||
|
||||
// ========== 各种创建 VectorStore 的方法 ==========
|
||||
|
@ -655,12 +690,12 @@ public class AiModelFactoryImpl implements AiModelFactory {
|
|||
Map<String, Class<?>> metadataFields) {
|
||||
// 创建 JedisPooled 对象
|
||||
RedisProperties redisProperties = SpringUtils.getBean(RedisProperties.class);
|
||||
JedisPooled jedisPooled = new JedisPooled(redisProperties.getHost(), redisProperties.getPort());
|
||||
JedisPooled jedisPooled = new JedisPooled(redisProperties.getHost(), redisProperties.getPort(),
|
||||
redisProperties.getUsername(), redisProperties.getPassword());
|
||||
// 创建 RedisVectorStoreProperties 对象
|
||||
RedisVectorStoreAutoConfiguration configuration = new RedisVectorStoreAutoConfiguration();
|
||||
RedisVectorStoreProperties properties = SpringUtil.getBean(RedisVectorStoreProperties.class);
|
||||
RedisVectorStore redisVectorStore = RedisVectorStore.builder(jedisPooled, embeddingModel)
|
||||
.indexName(properties.getIndex()).prefix(properties.getPrefix())
|
||||
.indexName(properties.getIndexName()).prefix(properties.getPrefix())
|
||||
.initializeSchema(properties.isInitializeSchema())
|
||||
.metadataFields(convertList(metadataFields.entrySet(), entry -> {
|
||||
String fieldName = entry.getKey();
|
||||
|
@ -730,10 +765,12 @@ public class AiModelFactoryImpl implements AiModelFactory {
|
|||
|
||||
private static ObjectProvider<VectorStoreObservationConvention> getCustomObservationConvention() {
|
||||
return new ObjectProvider<>() {
|
||||
|
||||
@Override
|
||||
public VectorStoreObservationConvention getObject() throws BeansException {
|
||||
return new DefaultVectorStoreObservationConvention();
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -745,8 +782,15 @@ public class AiModelFactoryImpl implements AiModelFactory {
|
|||
return SpringUtil.getBean(ToolCallingManager.class);
|
||||
}
|
||||
|
||||
private static FunctionCallbackResolver getFunctionCallbackResolver() {
|
||||
return SpringUtil.getBean(FunctionCallbackResolver.class);
|
||||
private static ObjectProvider<EmbeddingModelObservationConvention> getEmbeddingModelObservationConvention() {
|
||||
return new ObjectProvider<>() {
|
||||
|
||||
@Override
|
||||
public EmbeddingModelObservationConvention getObject() throws BeansException {
|
||||
return SpringUtil.getBean(EmbeddingModelObservationConvention.class);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,45 +0,0 @@
|
|||
package cn.iocoder.yudao.module.ai.framework.ai.core.model.deepseek;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* DeepSeek {@link ChatModel} 实现类
|
||||
*
|
||||
* @author fansili
|
||||
*/
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class DeepSeekChatModel implements ChatModel {
|
||||
|
||||
public static final String BASE_URL = "https://api.deepseek.com";
|
||||
|
||||
public static final String MODEL_DEFAULT = "deepseek-chat";
|
||||
|
||||
/**
|
||||
* 兼容 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();
|
||||
}
|
||||
|
||||
}
|
|
@ -46,94 +46,94 @@ import java.util.List;
|
|||
*/
|
||||
public class SiliconFlowImageModel implements ImageModel {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(SiliconFlowImageModel.class);
|
||||
private static final Logger logger = LoggerFactory.getLogger(SiliconFlowImageModel.class);
|
||||
|
||||
private static final ImageModelObservationConvention DEFAULT_OBSERVATION_CONVENTION = new DefaultImageModelObservationConvention();
|
||||
private static final ImageModelObservationConvention DEFAULT_OBSERVATION_CONVENTION = new DefaultImageModelObservationConvention();
|
||||
|
||||
private final SiliconFlowImageOptions defaultOptions;
|
||||
private final SiliconFlowImageOptions defaultOptions;
|
||||
|
||||
private final RetryTemplate retryTemplate;
|
||||
private final RetryTemplate retryTemplate;
|
||||
|
||||
private final SiliconFlowImageApi siliconFlowImageApi;
|
||||
private final SiliconFlowImageApi siliconFlowImageApi;
|
||||
|
||||
private final ObservationRegistry observationRegistry;
|
||||
private final ObservationRegistry observationRegistry;
|
||||
|
||||
@Setter
|
||||
private ImageModelObservationConvention observationConvention = DEFAULT_OBSERVATION_CONVENTION;
|
||||
private ImageModelObservationConvention observationConvention = DEFAULT_OBSERVATION_CONVENTION;
|
||||
|
||||
public SiliconFlowImageModel(SiliconFlowImageApi siliconFlowImageApi) {
|
||||
this(siliconFlowImageApi, SiliconFlowImageOptions.builder().build(), RetryUtils.DEFAULT_RETRY_TEMPLATE);
|
||||
}
|
||||
public SiliconFlowImageModel(SiliconFlowImageApi siliconFlowImageApi) {
|
||||
this(siliconFlowImageApi, SiliconFlowImageOptions.builder().build(), RetryUtils.DEFAULT_RETRY_TEMPLATE);
|
||||
}
|
||||
|
||||
public SiliconFlowImageModel(SiliconFlowImageApi siliconFlowImageApi, SiliconFlowImageOptions options, RetryTemplate retryTemplate) {
|
||||
this(siliconFlowImageApi, options, retryTemplate, ObservationRegistry.NOOP);
|
||||
}
|
||||
public SiliconFlowImageModel(SiliconFlowImageApi siliconFlowImageApi, SiliconFlowImageOptions options, RetryTemplate retryTemplate) {
|
||||
this(siliconFlowImageApi, options, retryTemplate, ObservationRegistry.NOOP);
|
||||
}
|
||||
|
||||
public SiliconFlowImageModel(SiliconFlowImageApi siliconFlowImageApi, SiliconFlowImageOptions options, RetryTemplate retryTemplate,
|
||||
public SiliconFlowImageModel(SiliconFlowImageApi siliconFlowImageApi, SiliconFlowImageOptions options, RetryTemplate retryTemplate,
|
||||
ObservationRegistry observationRegistry) {
|
||||
Assert.notNull(siliconFlowImageApi, "OpenAiImageApi must not be null");
|
||||
Assert.notNull(options, "options must not be null");
|
||||
Assert.notNull(retryTemplate, "retryTemplate must not be null");
|
||||
Assert.notNull(observationRegistry, "observationRegistry must not be null");
|
||||
this.siliconFlowImageApi = siliconFlowImageApi;
|
||||
this.defaultOptions = options;
|
||||
this.retryTemplate = retryTemplate;
|
||||
this.observationRegistry = observationRegistry;
|
||||
}
|
||||
Assert.notNull(siliconFlowImageApi, "OpenAiImageApi must not be null");
|
||||
Assert.notNull(options, "options must not be null");
|
||||
Assert.notNull(retryTemplate, "retryTemplate must not be null");
|
||||
Assert.notNull(observationRegistry, "observationRegistry must not be null");
|
||||
this.siliconFlowImageApi = siliconFlowImageApi;
|
||||
this.defaultOptions = options;
|
||||
this.retryTemplate = retryTemplate;
|
||||
this.observationRegistry = observationRegistry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImageResponse call(ImagePrompt imagePrompt) {
|
||||
@Override
|
||||
public ImageResponse call(ImagePrompt imagePrompt) {
|
||||
SiliconFlowImageOptions requestImageOptions = mergeOptions(imagePrompt.getOptions(), this.defaultOptions);
|
||||
SiliconFlowImageApi.SiliconflowImageRequest imageRequest = createRequest(imagePrompt, requestImageOptions);
|
||||
|
||||
var observationContext = ImageModelObservationContext.builder()
|
||||
.imagePrompt(imagePrompt)
|
||||
.provider(SiliconFlowApiConstants.PROVIDER_NAME)
|
||||
.requestOptions(imagePrompt.getOptions())
|
||||
.build();
|
||||
var observationContext = ImageModelObservationContext.builder()
|
||||
.imagePrompt(imagePrompt)
|
||||
.provider(SiliconFlowApiConstants.PROVIDER_NAME)
|
||||
.imagePrompt(imagePrompt)
|
||||
.build();
|
||||
|
||||
return ImageModelObservationDocumentation.IMAGE_MODEL_OPERATION
|
||||
.observation(this.observationConvention, DEFAULT_OBSERVATION_CONVENTION, () -> observationContext,
|
||||
this.observationRegistry)
|
||||
.observe(() -> {
|
||||
ResponseEntity<OpenAiImageApi.OpenAiImageResponse> imageResponseEntity = this.retryTemplate
|
||||
.execute(ctx -> this.siliconFlowImageApi.createImage(imageRequest));
|
||||
return ImageModelObservationDocumentation.IMAGE_MODEL_OPERATION
|
||||
.observation(this.observationConvention, DEFAULT_OBSERVATION_CONVENTION, () -> observationContext,
|
||||
this.observationRegistry)
|
||||
.observe(() -> {
|
||||
ResponseEntity<OpenAiImageApi.OpenAiImageResponse> imageResponseEntity = this.retryTemplate
|
||||
.execute(ctx -> this.siliconFlowImageApi.createImage(imageRequest));
|
||||
|
||||
ImageResponse imageResponse = convertResponse(imageResponseEntity, imageRequest);
|
||||
ImageResponse imageResponse = convertResponse(imageResponseEntity, imageRequest);
|
||||
|
||||
observationContext.setResponse(imageResponse);
|
||||
observationContext.setResponse(imageResponse);
|
||||
|
||||
return imageResponse;
|
||||
});
|
||||
}
|
||||
return imageResponse;
|
||||
});
|
||||
}
|
||||
|
||||
private SiliconFlowImageApi.SiliconflowImageRequest createRequest(ImagePrompt imagePrompt,
|
||||
private SiliconFlowImageApi.SiliconflowImageRequest createRequest(ImagePrompt imagePrompt,
|
||||
SiliconFlowImageOptions requestImageOptions) {
|
||||
String instructions = imagePrompt.getInstructions().get(0).getText();
|
||||
String instructions = imagePrompt.getInstructions().get(0).getText();
|
||||
|
||||
SiliconFlowImageApi.SiliconflowImageRequest imageRequest = new SiliconFlowImageApi.SiliconflowImageRequest(instructions,
|
||||
SiliconFlowImageApi.SiliconflowImageRequest imageRequest = new SiliconFlowImageApi.SiliconflowImageRequest(instructions,
|
||||
SiliconFlowApiConstants.DEFAULT_IMAGE_MODEL);
|
||||
|
||||
return ModelOptionsUtils.merge(requestImageOptions, imageRequest, SiliconFlowImageApi.SiliconflowImageRequest.class);
|
||||
}
|
||||
return ModelOptionsUtils.merge(requestImageOptions, imageRequest, SiliconFlowImageApi.SiliconflowImageRequest.class);
|
||||
}
|
||||
|
||||
private ImageResponse convertResponse(ResponseEntity<OpenAiImageApi.OpenAiImageResponse> imageResponseEntity,
|
||||
SiliconFlowImageApi.SiliconflowImageRequest siliconflowImageRequest) {
|
||||
OpenAiImageApi.OpenAiImageResponse imageApiResponse = imageResponseEntity.getBody();
|
||||
if (imageApiResponse == null) {
|
||||
logger.warn("No image response returned for request: {}", siliconflowImageRequest);
|
||||
return new ImageResponse(List.of());
|
||||
}
|
||||
private ImageResponse convertResponse(ResponseEntity<OpenAiImageApi.OpenAiImageResponse> imageResponseEntity,
|
||||
SiliconFlowImageApi.SiliconflowImageRequest siliconflowImageRequest) {
|
||||
OpenAiImageApi.OpenAiImageResponse imageApiResponse = imageResponseEntity.getBody();
|
||||
if (imageApiResponse == null) {
|
||||
logger.warn("No image response returned for request: {}", siliconflowImageRequest);
|
||||
return new ImageResponse(List.of());
|
||||
}
|
||||
|
||||
List<ImageGeneration> imageGenerationList = imageApiResponse.data()
|
||||
.stream()
|
||||
.map(entry -> new ImageGeneration(new Image(entry.url(), entry.b64Json()),
|
||||
new OpenAiImageGenerationMetadata(entry.revisedPrompt())))
|
||||
.toList();
|
||||
List<ImageGeneration> imageGenerationList = imageApiResponse.data()
|
||||
.stream()
|
||||
.map(entry -> new ImageGeneration(new Image(entry.url(), entry.b64Json()),
|
||||
new OpenAiImageGenerationMetadata(entry.revisedPrompt())))
|
||||
.toList();
|
||||
|
||||
ImageResponseMetadata openAiImageResponseMetadata = new ImageResponseMetadata(imageApiResponse.created());
|
||||
return new ImageResponse(imageGenerationList, openAiImageResponseMetadata);
|
||||
}
|
||||
ImageResponseMetadata openAiImageResponseMetadata = new ImageResponseMetadata(imageApiResponse.created());
|
||||
return new ImageResponse(imageGenerationList, openAiImageResponseMetadata);
|
||||
}
|
||||
|
||||
private SiliconFlowImageOptions mergeOptions(@Nullable ImageOptions runtimeOptions, SiliconFlowImageOptions defaultOptions) {
|
||||
var runtimeOptionsForProvider = ModelOptionsUtils.copyToTarget(runtimeOptions, ImageOptions.class,
|
||||
|
|
|
@ -29,12 +29,12 @@ import cn.iocoder.yudao.module.infra.api.file.FileApi;
|
|||
import com.alibaba.cloud.ai.dashscope.image.DashScopeImageOptions;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springaicommunity.qianfan.QianFanImageOptions;
|
||||
import org.springframework.ai.image.ImageModel;
|
||||
import org.springframework.ai.image.ImageOptions;
|
||||
import org.springframework.ai.image.ImagePrompt;
|
||||
import org.springframework.ai.image.ImageResponse;
|
||||
import org.springframework.ai.openai.OpenAiImageOptions;
|
||||
import org.springframework.ai.qianfan.QianFanImageOptions;
|
||||
import org.springframework.ai.stabilityai.api.StabilityAiImageOptions;
|
||||
import org.springframework.ai.zhipuai.ZhiPuAiImageOptions;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
|
@ -140,10 +140,10 @@ public class AiImageServiceImpl implements AiImageService {
|
|||
private static ImageOptions buildImageOptions(AiImageDrawReqVO draw, AiModelDO model) {
|
||||
if (ObjUtil.equal(model.getPlatform(), AiPlatformEnum.OPENAI.getPlatform())) {
|
||||
// https://platform.openai.com/docs/api-reference/images/create
|
||||
return OpenAiImageOptions.builder().withModel(model.getModel())
|
||||
.withHeight(draw.getHeight()).withWidth(draw.getWidth())
|
||||
.withStyle(MapUtil.getStr(draw.getOptions(), "style")) // 风格
|
||||
.withResponseFormat("b64_json")
|
||||
return OpenAiImageOptions.builder().model(model.getModel())
|
||||
.height(draw.getHeight()).width(draw.getWidth())
|
||||
.style(MapUtil.getStr(draw.getOptions(), "style")) // 风格
|
||||
.responseFormat("b64_json")
|
||||
.build();
|
||||
} else if (ObjUtil.equal(model.getPlatform(), AiPlatformEnum.SILICON_FLOW.getPlatform())) {
|
||||
// https://docs.siliconflow.cn/cn/api-reference/images/images-generations
|
||||
|
|
|
@ -7,6 +7,8 @@ import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
|
|||
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
|
||||
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
|
||||
import com.fasterxml.jackson.annotation.JsonClassDescription;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.annotation.JsonPropertyDescription;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
@ -17,7 +19,7 @@ import org.springframework.stereotype.Component;
|
|||
import java.util.function.BiFunction;
|
||||
|
||||
/**
|
||||
* 工具:当前用户信息查询
|
||||
* 工具:用户信息查询
|
||||
*
|
||||
* 同时,也是展示 ToolContext 上下文的使用
|
||||
*
|
||||
|
@ -31,8 +33,17 @@ public class UserProfileQueryToolFunction
|
|||
private AdminUserApi adminUserApi;
|
||||
|
||||
@Data
|
||||
@JsonClassDescription("当前用户信息查询")
|
||||
public static class Request { }
|
||||
@JsonClassDescription("用户信息查询")
|
||||
public static class Request {
|
||||
|
||||
/**
|
||||
* 用户编号
|
||||
*/
|
||||
@JsonProperty(value = "id")
|
||||
@JsonPropertyDescription("用户编号,例如说:1。如果查询自己,则 id 为空")
|
||||
private Long id;
|
||||
|
||||
}
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
|
@ -61,13 +72,19 @@ public class UserProfileQueryToolFunction
|
|||
|
||||
@Override
|
||||
public Response apply(Request request, ToolContext toolContext) {
|
||||
LoginUser loginUser = (LoginUser) toolContext.getContext().get(AiUtils.TOOL_CONTEXT_LOGIN_USER);
|
||||
Long tenantId = (Long) toolContext.getContext().get(AiUtils.TOOL_CONTEXT_TENANT_ID);
|
||||
if (loginUser == null | tenantId == null) {
|
||||
return null;
|
||||
if (tenantId == null) {
|
||||
return new Response();
|
||||
}
|
||||
if (request.getId() == null) {
|
||||
LoginUser loginUser = (LoginUser) toolContext.getContext().get(AiUtils.TOOL_CONTEXT_LOGIN_USER);
|
||||
if (loginUser == null) {
|
||||
return new Response();
|
||||
}
|
||||
request.setId(loginUser.getId());
|
||||
}
|
||||
return TenantUtils.execute(tenantId, () -> {
|
||||
AdminUserRespDTO user = adminUserApi.getUser(loginUser.getId()).getCheckedData();
|
||||
AdminUserRespDTO user = adminUserApi.getUser(request.getId()).getCheckedData();
|
||||
return BeanUtils.toBean(user, Response.class);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -2,18 +2,18 @@ package cn.iocoder.yudao.module.ai.util;
|
|||
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.module.ai.enums.model.AiPlatformEnum;
|
||||
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
|
||||
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
|
||||
import cn.iocoder.yudao.module.ai.enums.model.AiPlatformEnum;
|
||||
import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatOptions;
|
||||
import org.springaicommunity.moonshot.MoonshotChatOptions;
|
||||
import org.springaicommunity.qianfan.QianFanChatOptions;
|
||||
import org.springframework.ai.azure.openai.AzureOpenAiChatOptions;
|
||||
import org.springframework.ai.chat.messages.*;
|
||||
import org.springframework.ai.chat.prompt.ChatOptions;
|
||||
import org.springframework.ai.minimax.MiniMaxChatOptions;
|
||||
import org.springframework.ai.moonshot.MoonshotChatOptions;
|
||||
import org.springframework.ai.ollama.api.OllamaOptions;
|
||||
import org.springframework.ai.openai.OpenAiChatOptions;
|
||||
import org.springframework.ai.qianfan.QianFanChatOptions;
|
||||
import org.springframework.ai.zhipuai.ZhiPuAiChatOptions;
|
||||
|
||||
import java.util.Collections;
|
||||
|
@ -43,18 +43,18 @@ public class AiUtils {
|
|||
switch (platform) {
|
||||
case TONG_YI:
|
||||
return DashScopeChatOptions.builder().withModel(model).withTemperature(temperature).withMaxToken(maxTokens)
|
||||
.withFunctions(toolNames).withToolContext(toolContext).build();
|
||||
.withToolNames(toolNames).withToolContext(toolContext).build();
|
||||
case YI_YAN:
|
||||
return QianFanChatOptions.builder().model(model).temperature(temperature).maxTokens(maxTokens).build();
|
||||
case ZHI_PU:
|
||||
return ZhiPuAiChatOptions.builder().model(model).temperature(temperature).maxTokens(maxTokens)
|
||||
.functions(toolNames).toolContext(toolContext).build();
|
||||
.toolNames(toolNames).toolContext(toolContext).build();
|
||||
case MINI_MAX:
|
||||
return MiniMaxChatOptions.builder().model(model).temperature(temperature).maxTokens(maxTokens)
|
||||
.functions(toolNames).toolContext(toolContext).build();
|
||||
.toolNames(toolNames).toolContext(toolContext).build();
|
||||
case MOONSHOT:
|
||||
return MoonshotChatOptions.builder().model(model).temperature(temperature).maxTokens(maxTokens)
|
||||
.functions(toolNames).toolContext(toolContext).build();
|
||||
.toolNames(toolNames).toolContext(toolContext).build();
|
||||
case OPENAI:
|
||||
case DEEP_SEEK: // 复用 OpenAI 客户端
|
||||
case DOU_BAO: // 复用 OpenAI 客户端
|
||||
|
|
|
@ -20,8 +20,8 @@ spring:
|
|||
# 数据源配置项
|
||||
autoconfigure:
|
||||
exclude:
|
||||
- org.springframework.ai.autoconfigure.vectorstore.qdrant.QdrantVectorStoreAutoConfiguration # 禁用 AI 模块的 Qdrant,手动创建
|
||||
- org.springframework.ai.autoconfigure.vectorstore.milvus.MilvusVectorStoreAutoConfiguration # 禁用 AI 模块的 Milvus,手动创建
|
||||
- org.springframework.ai.vectorstore.qdrant.autoconfigure.QdrantVectorStoreAutoConfiguration # 禁用 AI 模块的 Qdrant,手动创建
|
||||
- org.springframework.ai.vectorstore.milvus.autoconfigure.MilvusVectorStoreAutoConfiguration # 禁用 AI 模块的 Milvus,手动创建
|
||||
datasource:
|
||||
druid: # Druid 【监控】相关的全局配置
|
||||
web-stat-filter:
|
||||
|
|
|
@ -21,8 +21,8 @@ spring:
|
|||
autoconfigure:
|
||||
exclude:
|
||||
- de.codecentric.boot.admin.client.config.SpringBootAdminClientAutoConfiguration # 禁用 Spring Boot Admin 的 Client 的自动配置
|
||||
- org.springframework.ai.autoconfigure.vectorstore.qdrant.QdrantVectorStoreAutoConfiguration # 禁用 AI 模块的 Qdrant,手动创建
|
||||
- org.springframework.ai.autoconfigure.vectorstore.milvus.MilvusVectorStoreAutoConfiguration # 禁用 AI 模块的 Milvus,手动创建
|
||||
- org.springframework.ai.vectorstore.qdrant.autoconfigure.QdrantVectorStoreAutoConfiguration # 禁用 AI 模块的 Qdrant,手动创建
|
||||
- org.springframework.ai.vectorstore.milvus.autoconfigure.MilvusVectorStoreAutoConfiguration # 禁用 AI 模块的 Milvus,手动创建
|
||||
datasource:
|
||||
druid: # Druid 【监控】相关的全局配置
|
||||
web-stat-filter:
|
||||
|
|
|
@ -107,7 +107,7 @@ spring:
|
|||
vectorstore: # 向量存储
|
||||
redis:
|
||||
initialize-schema: true
|
||||
index: knowledge_index # Redis 中向量索引的名称:用于存储和检索向量数据的索引标识符,所有相关的向量搜索操作都会基于这个索引进行
|
||||
index-name: knowledge_index # Redis 中向量索引的名称:用于存储和检索向量数据的索引标识符,所有相关的向量搜索操作都会基于这个索引进行
|
||||
prefix: "knowledge_segment:" # Redis 中存储向量数据的键名前缀:这个前缀会添加到每个存储在 Redis 中的向量数据键名前,每个 document 都是一个 hash 结构
|
||||
qdrant:
|
||||
initialize-schema: true
|
||||
|
@ -145,13 +145,14 @@ spring:
|
|||
api-key: xxxx
|
||||
moonshot: # 月之暗灭(KIMI)
|
||||
api-key: sk-abc
|
||||
deepseek: # DeepSeek
|
||||
api-key: sk-e94db327cc7d457d99a8de8810fc6b12
|
||||
chat:
|
||||
options:
|
||||
model: deepseek-chat
|
||||
|
||||
yudao:
|
||||
ai:
|
||||
deep-seek: # DeepSeek
|
||||
enable: true
|
||||
api-key: sk-e94db327cc7d457d99a8de8810fc6b12
|
||||
model: deepseek-chat
|
||||
doubao: # 字节豆包
|
||||
enable: true
|
||||
api-key: 5c1b5747-26d2-4ebd-a4e0-dd0e8d8b4272
|
||||
|
|
|
@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.ai.framework.ai.core.model.chat;
|
|||
|
||||
import com.azure.ai.openai.OpenAIClientBuilder;
|
||||
import com.azure.core.credential.AzureKeyCredential;
|
||||
import com.azure.core.util.ClientOptions;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.ai.azure.openai.AzureOpenAiChatModel;
|
||||
|
@ -17,7 +16,7 @@ import reactor.core.publisher.Flux;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.springframework.ai.autoconfigure.azure.openai.AzureOpenAiChatProperties.DEFAULT_DEPLOYMENT_NAME;
|
||||
import static org.springframework.ai.model.azure.openai.autoconfigure.AzureOpenAiChatProperties.DEFAULT_DEPLOYMENT_NAME;
|
||||
|
||||
/**
|
||||
* {@link AzureOpenAiChatModel} 集成测试
|
||||
|
@ -29,10 +28,13 @@ public class AzureOpenAIChatModelTests {
|
|||
// TODO @芋艿:晚点在调整
|
||||
private final OpenAIClientBuilder openAiApi = new OpenAIClientBuilder()
|
||||
.endpoint("https://eastusprejade.openai.azure.com")
|
||||
.credential(new AzureKeyCredential("xxx"))
|
||||
.clientOptions((new ClientOptions()).setApplicationId("spring-ai"));
|
||||
private final AzureOpenAiChatModel chatModel = new AzureOpenAiChatModel(openAiApi,
|
||||
AzureOpenAiChatOptions.builder().deploymentName(DEFAULT_DEPLOYMENT_NAME).build());
|
||||
.credential(new AzureKeyCredential("xxx"));
|
||||
private final AzureOpenAiChatModel chatModel = AzureOpenAiChatModel.builder()
|
||||
.openAIClientBuilder(openAiApi)
|
||||
.defaultOptions(AzureOpenAiChatOptions.builder()
|
||||
.deploymentName(DEFAULT_DEPLOYMENT_NAME)
|
||||
.build())
|
||||
.build();
|
||||
|
||||
@Test
|
||||
@Disabled
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package cn.iocoder.yudao.module.ai.framework.ai.core.model.chat;
|
||||
|
||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.baichuan.BaiChuanChatModel;
|
||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.deepseek.DeepSeekChatModel;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.ai.chat.messages.Message;
|
||||
|
@ -35,7 +34,7 @@ public class BaiChuanChatModelTests {
|
|||
.build())
|
||||
.build();
|
||||
|
||||
private final DeepSeekChatModel chatModel = new DeepSeekChatModel(openAiChatModel);
|
||||
private final BaiChuanChatModel chatModel = new BaiChuanChatModel(openAiChatModel);
|
||||
|
||||
@Test
|
||||
@Disabled
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package cn.iocoder.yudao.module.ai.framework.ai.core.model.chat;
|
||||
|
||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.deepseek.DeepSeekChatModel;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.ai.chat.messages.Message;
|
||||
|
@ -8,9 +7,9 @@ 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 org.springframework.ai.deepseek.DeepSeekChatModel;
|
||||
import org.springframework.ai.deepseek.DeepSeekChatOptions;
|
||||
import org.springframework.ai.deepseek.api.DeepSeekApi;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -23,19 +22,16 @@ import java.util.List;
|
|||
*/
|
||||
public class DeepSeekChatModelTests {
|
||||
|
||||
private final OpenAiChatModel openAiChatModel = OpenAiChatModel.builder()
|
||||
.openAiApi(OpenAiApi.builder()
|
||||
.baseUrl(DeepSeekChatModel.BASE_URL)
|
||||
.apiKey("sk-e52047409b144d97b791a6a46a2d") // apiKey
|
||||
private final DeepSeekChatModel chatModel = DeepSeekChatModel.builder()
|
||||
.deepSeekApi(DeepSeekApi.builder()
|
||||
.apiKey("sk-eaf4172a057344dd9bc64b1f806b6axx") // apiKey
|
||||
.build())
|
||||
.defaultOptions(OpenAiChatOptions.builder()
|
||||
.defaultOptions(DeepSeekChatOptions.builder()
|
||||
.model("deepseek-chat") // 模型
|
||||
.temperature(0.7)
|
||||
.build())
|
||||
.build();
|
||||
|
||||
private final DeepSeekChatModel chatModel = new DeepSeekChatModel(openAiChatModel);
|
||||
|
||||
@Test
|
||||
@Disabled
|
||||
public void testCall() {
|
||||
|
|
|
@ -1,20 +1,6 @@
|
|||
package cn.iocoder.yudao.module.ai.framework.ai.core.model.chat;
|
||||
|
||||
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.ollama.OllamaChatModel;
|
||||
import org.springframework.ai.ollama.api.OllamaApi;
|
||||
import org.springframework.ai.ollama.api.OllamaModel;
|
||||
import org.springframework.ai.ollama.api.OllamaOptions;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* {@link OllamaChatModel} 集成测试
|
||||
|
@ -23,43 +9,43 @@ import java.util.List;
|
|||
*/
|
||||
public class LlamaChatModelTests {
|
||||
|
||||
private final OllamaChatModel chatModel = OllamaChatModel.builder()
|
||||
.ollamaApi(new OllamaApi("http://127.0.0.1:11434")) // Ollama 服务地址
|
||||
.defaultOptions(OllamaOptions.builder()
|
||||
.model(OllamaModel.LLAMA3.getName()) // 模型
|
||||
.build())
|
||||
.build();
|
||||
|
||||
@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);
|
||||
System.out.println(response.getResult().getOutput());
|
||||
}
|
||||
|
||||
@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(response -> {
|
||||
// System.out.println(response);
|
||||
System.out.println(response.getResult().getOutput());
|
||||
}).then().block();
|
||||
}
|
||||
// private final OllamaChatModel chatModel = OllamaChatModel.builder()
|
||||
// .ollamaApi(new OllamaApi("http://127.0.0.1:11434")) // Ollama 服务地址
|
||||
// .defaultOptions(OllamaOptions.builder()
|
||||
// .model(OllamaModel.LLAMA3.getName()) // 模型
|
||||
// .build())
|
||||
// .build();
|
||||
//
|
||||
// @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);
|
||||
// System.out.println(response.getResult().getOutput());
|
||||
// }
|
||||
//
|
||||
// @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(response -> {
|
||||
//// System.out.println(response);
|
||||
// System.out.println(response.getResult().getOutput());
|
||||
// }).then().block();
|
||||
// }
|
||||
|
||||
}
|
||||
|
|
|
@ -2,14 +2,14 @@ package cn.iocoder.yudao.module.ai.framework.ai.core.model.chat;
|
|||
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springaicommunity.moonshot.MoonshotChatModel;
|
||||
import org.springaicommunity.moonshot.MoonshotChatOptions;
|
||||
import org.springaicommunity.moonshot.api.MoonshotApi;
|
||||
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.moonshot.MoonshotChatModel;
|
||||
import org.springframework.ai.moonshot.MoonshotChatOptions;
|
||||
import org.springframework.ai.moonshot.api.MoonshotApi;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -22,11 +22,15 @@ import java.util.List;
|
|||
*/
|
||||
public class MoonshotChatModelTests {
|
||||
|
||||
private final MoonshotChatModel chatModel = new MoonshotChatModel(
|
||||
new MoonshotApi("sk-aHYYV1SARscItye5QQRRNbXij4fy65Ee7pNZlC9gsSQnUKXA"), // 密钥
|
||||
MoonshotChatOptions.builder()
|
||||
.model("moonshot-v1-8k") // 模型
|
||||
.build());
|
||||
private final MoonshotChatModel chatModel = MoonshotChatModel.builder()
|
||||
.moonshotApi(MoonshotApi.builder()
|
||||
.apiKey("sk-aHYYV1SARscItye5QQRRNbXij4fy65Ee7pNZlC9gsSQnUKXA") // 密钥
|
||||
.build())
|
||||
.defaultOptions(MoonshotChatOptions.builder()
|
||||
.model("kimi-k2-0711-preview") // 模型
|
||||
.build())
|
||||
.build();
|
||||
|
||||
@Test
|
||||
@Disabled
|
||||
public void testCall() {
|
||||
|
|
|
@ -23,7 +23,9 @@ import java.util.List;
|
|||
public class OllamaChatModelTests {
|
||||
|
||||
private final OllamaChatModel chatModel = OllamaChatModel.builder()
|
||||
.ollamaApi(new OllamaApi("http://127.0.0.1:11434")) // Ollama 服务地址
|
||||
.ollamaApi(OllamaApi.builder()
|
||||
.baseUrl("http://127.0.0.1:11434") // Ollama 服务地址
|
||||
.build())
|
||||
.defaultOptions(OllamaOptions.builder()
|
||||
// .model("qwen") // 模型(https://ollama.com/library/qwen)
|
||||
.model("deepseek-r1") // 模型(https://ollama.com/library/deepseek-r1)
|
||||
|
|
|
@ -25,10 +25,10 @@ public class OpenAIChatModelTests {
|
|||
private final OpenAiChatModel chatModel = OpenAiChatModel.builder()
|
||||
.openAiApi(OpenAiApi.builder()
|
||||
.baseUrl("https://api.holdai.top")
|
||||
.apiKey("sk-aN6nWn3fILjrgLFT0fC4Aa60B72e4253826c77B29dC94f17") // apiKey
|
||||
.apiKey("sk-PytRecQlmjEteoa2RRN6cGnwslo72UUPLQVNEMS6K9yjbmpD") // apiKey
|
||||
.build())
|
||||
.defaultOptions(OpenAiChatOptions.builder()
|
||||
.model(OpenAiApi.ChatModel.GPT_4_O) // 模型
|
||||
.model(OpenAiApi.ChatModel.GPT_4_1_NANO) // 模型
|
||||
.temperature(0.7)
|
||||
.build())
|
||||
.build();
|
||||
|
|
|
@ -22,14 +22,17 @@ import java.util.List;
|
|||
*/
|
||||
public class TongYiChatModelTests {
|
||||
|
||||
private final DashScopeChatModel chatModel = new DashScopeChatModel(
|
||||
new DashScopeApi("sk-7d903764249848cfa912733146da12d1"),
|
||||
DashScopeChatOptions.builder()
|
||||
private final DashScopeChatModel chatModel = DashScopeChatModel.builder()
|
||||
.dashScopeApi(DashScopeApi.builder()
|
||||
.apiKey("sk-47aa124781be4bfb95244cc62f63f7d0")
|
||||
.build())
|
||||
.defaultOptions( DashScopeChatOptions.builder()
|
||||
.withModel("qwen1.5-72b-chat") // 模型
|
||||
// .withModel("deepseek-r1") // 模型(deepseek-r1)
|
||||
// .withModel("deepseek-v3") // 模型(deepseek-v3)
|
||||
// .withModel("deepseek-r1-distill-qwen-1.5b") // 模型(deepseek-r1-distill-qwen-1.5b)
|
||||
.build());
|
||||
.build())
|
||||
.build();
|
||||
|
||||
@Test
|
||||
@Disabled
|
||||
|
|
|
@ -2,13 +2,13 @@ package cn.iocoder.yudao.module.ai.framework.ai.core.model.chat;
|
|||
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springaicommunity.qianfan.QianFanChatModel;
|
||||
import org.springaicommunity.qianfan.QianFanChatOptions;
|
||||
import org.springaicommunity.qianfan.api.QianFanApi;
|
||||
import org.springframework.ai.chat.messages.Message;
|
||||
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.qianfan.QianFanChatModel;
|
||||
import org.springframework.ai.qianfan.QianFanChatOptions;
|
||||
import org.springframework.ai.qianfan.api.QianFanApi;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -23,9 +23,9 @@ import java.util.List;
|
|||
public class YiYanChatModelTests {
|
||||
|
||||
private final QianFanChatModel chatModel = new QianFanChatModel(
|
||||
new QianFanApi("qS8k8dYr2nXunagK4SSU8Xjj", "pHGbx51ql2f0hOyabQvSZezahVC3hh3e"), // 密钥
|
||||
new QianFanApi("DGnyzREuaY7av7c38bOM9Ji2", "9aR8myflEOPDrEeLhoXv0FdqANOAyIZW"), // 密钥
|
||||
QianFanChatOptions.builder()
|
||||
.model(QianFanApi.ChatModel.ERNIE_4_0_8K_Preview.getValue())
|
||||
.model("ERNIE-4.5-8K-Preview")
|
||||
.build()
|
||||
);
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ public class OpenAiImageModelTests {
|
|||
|
||||
private final OpenAiImageModel imageModel = new OpenAiImageModel(OpenAiImageApi.builder()
|
||||
.baseUrl("https://api.holdai.top") // apiKey
|
||||
.apiKey("sk-aN6nWn3fILjrgLFT0fC4Aa60B72e4253826c77B29dC94f17")
|
||||
.apiKey("sk-PytRecQlmjEteoa2RRN6cGnwslo72UUPLQVNEMS6K9yjbmpD")
|
||||
.build());
|
||||
|
||||
@Test
|
||||
|
@ -26,8 +26,8 @@ public class OpenAiImageModelTests {
|
|||
public void testCall() {
|
||||
// 准备参数
|
||||
ImageOptions options = OpenAiImageOptions.builder()
|
||||
.withModel(OpenAiImageApi.ImageModel.DALL_E_2.getValue()) // 这个模型比较便宜
|
||||
.withHeight(256).withWidth(256)
|
||||
.model(OpenAiImageApi.ImageModel.DALL_E_2.getValue()) // 这个模型比较便宜
|
||||
.height(256).width(256)
|
||||
.build();
|
||||
ImagePrompt prompt = new ImagePrompt("中国长城!", options);
|
||||
|
||||
|
|
|
@ -2,11 +2,11 @@ package cn.iocoder.yudao.module.ai.framework.ai.core.model.image;
|
|||
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springaicommunity.qianfan.QianFanImageModel;
|
||||
import org.springaicommunity.qianfan.QianFanImageOptions;
|
||||
import org.springaicommunity.qianfan.api.QianFanImageApi;
|
||||
import org.springframework.ai.image.ImagePrompt;
|
||||
import org.springframework.ai.image.ImageResponse;
|
||||
import org.springframework.ai.qianfan.QianFanImageModel;
|
||||
import org.springframework.ai.qianfan.QianFanImageOptions;
|
||||
import org.springframework.ai.qianfan.api.QianFanImageApi;
|
||||
|
||||
import static cn.iocoder.yudao.module.ai.framework.ai.core.model.image.StabilityAiImageModelTests.viewImage;
|
||||
|
||||
|
|
|
@ -31,8 +31,8 @@ public class StabilityAiImageModelTests {
|
|||
public void testCall() {
|
||||
// 准备参数
|
||||
ImageOptions options = OpenAiImageOptions.builder()
|
||||
.withModel("stable-diffusion-v1-6")
|
||||
.withHeight(320).withWidth(320)
|
||||
.model("stable-diffusion-v1-6")
|
||||
.height(320).width(320)
|
||||
.build();
|
||||
ImagePrompt prompt = new ImagePrompt("great wall", options);
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package cn.iocoder.yudao.module.ai.framework.ai.core.model.ppt.wdd;
|
||||
|
||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.wenduoduo.api.WenDuoDuoPptApi;
|
||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.wenduoduo.api.WenDuoDuoPptApi;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package cn.iocoder.yudao.module.ai.framework.ai.core.model.ppt.xunfei;
|
||||
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.xinghuo.api.XunFeiPptApi;
|
||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||
import cn.iocoder.yudao.module.ai.framework.ai.core.model.xinghuo.api.XunFeiPptApi;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.mock.web.MockMultipartFile;
|
||||
|
|
|
@ -6,8 +6,8 @@ server:
|
|||
spring:
|
||||
autoconfigure:
|
||||
exclude:
|
||||
- org.springframework.ai.autoconfigure.vectorstore.qdrant.QdrantVectorStoreAutoConfiguration # 禁用 AI 模块的 Qdrant,手动创建
|
||||
- org.springframework.ai.autoconfigure.vectorstore.milvus.MilvusVectorStoreAutoConfiguration # 禁用 AI 模块的 Milvus,手动创建
|
||||
- org.springframework.ai.vectorstore.qdrant.autoconfigure.QdrantVectorStoreAutoConfiguration # 禁用 AI 模块的 Qdrant,手动创建
|
||||
- org.springframework.ai.vectorstore.milvus.autoconfigure.MilvusVectorStoreAutoConfiguration # 禁用 AI 模块的 Milvus,手动创建
|
||||
# 数据源配置项
|
||||
datasource:
|
||||
druid: # Druid 【监控】相关的全局配置
|
||||
|
|
|
@ -10,8 +10,8 @@ spring:
|
|||
- de.codecentric.boot.admin.server.ui.config.AdminServerUiAutoConfiguration # 禁用 Spring Boot Admin 的 Server UI 的自动配置
|
||||
- de.codecentric.boot.admin.server.cloud.config.AdminServerDiscoveryAutoConfiguration # 禁用 Spring Boot Admin 的 Server 的自动配置
|
||||
- de.codecentric.boot.admin.client.config.SpringBootAdminClientAutoConfiguration # 禁用 Spring Boot Admin 的 Client 的自动配置
|
||||
- org.springframework.ai.autoconfigure.vectorstore.qdrant.QdrantVectorStoreAutoConfiguration # 禁用 AI 模块的 Qdrant,手动创建
|
||||
- org.springframework.ai.autoconfigure.vectorstore.milvus.MilvusVectorStoreAutoConfiguration # 禁用 AI 模块的 Milvus,手动创建
|
||||
- org.springframework.ai.vectorstore.qdrant.autoconfigure.QdrantVectorStoreAutoConfiguration # 禁用 AI 模块的 Qdrant,手动创建
|
||||
- org.springframework.ai.vectorstore.milvus.autoconfigure.MilvusVectorStoreAutoConfiguration # 禁用 AI 模块的 Milvus,手动创建
|
||||
# 数据源配置项
|
||||
datasource:
|
||||
druid: # Druid 【监控】相关的全局配置
|
||||
|
|
|
@ -174,7 +174,7 @@ spring:
|
|||
vectorstore: # 向量存储
|
||||
redis:
|
||||
initialize-schema: true
|
||||
index: knowledge_index # Redis 中向量索引的名称:用于存储和检索向量数据的索引标识符,所有相关的向量搜索操作都会基于这个索引进行
|
||||
index-name: knowledge_index # Redis 中向量索引的名称:用于存储和检索向量数据的索引标识符,所有相关的向量搜索操作都会基于这个索引进行
|
||||
prefix: "knowledge_segment:" # Redis 中存储向量数据的键名前缀:这个前缀会添加到每个存储在 Redis 中的向量数据键名前,每个 document 都是一个 hash 结构
|
||||
qdrant:
|
||||
initialize-schema: true
|
||||
|
@ -212,13 +212,14 @@ spring:
|
|||
api-key: xxxx
|
||||
moonshot: # 月之暗灭(KIMI)
|
||||
api-key: sk-abc
|
||||
deepseek: # DeepSeek
|
||||
api-key: sk-e94db327cc7d457d99a8de8810fc6b12
|
||||
chat:
|
||||
options:
|
||||
model: deepseek-chat
|
||||
|
||||
yudao:
|
||||
ai:
|
||||
deep-seek: # DeepSeek
|
||||
enable: true
|
||||
api-key: sk-e94db327cc7d457d99a8de8810fc6b12
|
||||
model: deepseek-chat
|
||||
doubao: # 字节豆包
|
||||
enable: true
|
||||
api-key: 5c1b5747-26d2-4ebd-a4e0-dd0e8d8b4272
|
||||
|
|
Loading…
Reference in New Issue