Commit 44bcc9476d7a3a1cdbebfab206640b2dac470c48

Authored by YunaiV
1 parent 6ccd0ca6

【功能新增】AI:增加 QdrantVectorStore 向量库的接入

yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/knowledge/AiKnowledgeDocumentServiceImpl.java
@@ -54,7 +54,6 @@ public class AiKnowledgeDocumentServiceImpl implements AiKnowledgeDocumentServic @@ -54,7 +54,6 @@ public class AiKnowledgeDocumentServiceImpl implements AiKnowledgeDocumentServic
54 private AiKnowledgeService knowledgeService; 54 private AiKnowledgeService knowledgeService;
55 55
56 @Override 56 @Override
57 - @Transactional(rollbackFor = Exception.class)  
58 public Long createKnowledgeDocument(AiKnowledgeDocumentCreateReqVO createReqVO) { 57 public Long createKnowledgeDocument(AiKnowledgeDocumentCreateReqVO createReqVO) {
59 // 1. 校验参数 58 // 1. 校验参数
60 knowledgeService.validateKnowledgeExists(createReqVO.getKnowledgeId()); 59 knowledgeService.validateKnowledgeExists(createReqVO.getKnowledgeId());
@@ -74,7 +73,6 @@ public class AiKnowledgeDocumentServiceImpl implements AiKnowledgeDocumentServic @@ -74,7 +73,6 @@ public class AiKnowledgeDocumentServiceImpl implements AiKnowledgeDocumentServic
74 } 73 }
75 74
76 @Override 75 @Override
77 - @Transactional(rollbackFor = Exception.class)  
78 public List<Long> createKnowledgeDocumentList(AiKnowledgeDocumentCreateListReqVO createListReqVO) { 76 public List<Long> createKnowledgeDocumentList(AiKnowledgeDocumentCreateListReqVO createListReqVO) {
79 // 1. 校验参数 77 // 1. 校验参数
80 knowledgeService.validateKnowledgeExists(createListReqVO.getKnowledgeId()); 78 knowledgeService.validateKnowledgeExists(createListReqVO.getKnowledgeId());
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/knowledge/AiKnowledgeSegmentServiceImpl.java
@@ -115,6 +115,7 @@ public class AiKnowledgeSegmentServiceImpl implements AiKnowledgeSegmentService @@ -115,6 +115,7 @@ public class AiKnowledgeSegmentServiceImpl implements AiKnowledgeSegmentService
115 segmentMapper.updateById(newSegment); 115 segmentMapper.updateById(newSegment);
116 // 3.2 重新向量化,必须开启状态 116 // 3.2 重新向量化,必须开启状态
117 if (CommonStatusEnum.isEnable(oldSegment.getStatus())) { 117 if (CommonStatusEnum.isEnable(oldSegment.getStatus())) {
  118 + newSegment.setKnowledgeId(oldSegment.getKnowledgeId()).setDocumentId(oldSegment.getDocumentId());
118 writeVectorStore(vectorStore, newSegment, new Document(newSegment.getContent())); 119 writeVectorStore(vectorStore, newSegment, new Document(newSegment.getContent()));
119 } 120 }
120 } 121 }
@@ -156,9 +157,10 @@ public class AiKnowledgeSegmentServiceImpl implements AiKnowledgeSegmentService @@ -156,9 +157,10 @@ public class AiKnowledgeSegmentServiceImpl implements AiKnowledgeSegmentService
156 157
157 private void writeVectorStore(VectorStore vectorStore, AiKnowledgeSegmentDO segmentDO, Document segment) { 158 private void writeVectorStore(VectorStore vectorStore, AiKnowledgeSegmentDO segmentDO, Document segment) {
158 // 1. 向量存储 159 // 1. 向量存储
159 - segment.getMetadata().put(VECTOR_STORE_METADATA_KNOWLEDGE_ID, segmentDO.getKnowledgeId());  
160 - segment.getMetadata().put(VECTOR_STORE_METADATA_DOCUMENT_ID, segmentDO.getDocumentId());  
161 - segment.getMetadata().put(VECTOR_STORE_METADATA_SEGMENT_ID, segmentDO.getId()); 160 + // 为什么要 toString 呢?因为部分 VectorStore 实现,不支持 Long 类型,例如说 QdrantVectorStore
  161 + segment.getMetadata().put(VECTOR_STORE_METADATA_KNOWLEDGE_ID, segmentDO.getKnowledgeId().toString());
  162 + segment.getMetadata().put(VECTOR_STORE_METADATA_DOCUMENT_ID, segmentDO.getDocumentId().toString());
  163 + segment.getMetadata().put(VECTOR_STORE_METADATA_SEGMENT_ID, segmentDO.getId().toString());
162 vectorStore.add(List.of(segment)); 164 vectorStore.add(List.of(segment));
163 165
164 // 2. 更新向量 ID 166 // 2. 更新向量 ID
@@ -190,7 +192,8 @@ public class AiKnowledgeSegmentServiceImpl implements AiKnowledgeSegmentService @@ -190,7 +192,8 @@ public class AiKnowledgeSegmentServiceImpl implements AiKnowledgeSegmentService
190 .similarityThreshold( 192 .similarityThreshold(
191 ObjUtil.defaultIfNull(reqBO.getSimilarityThreshold(), knowledge.getSimilarityThreshold())) 193 ObjUtil.defaultIfNull(reqBO.getSimilarityThreshold(), knowledge.getSimilarityThreshold()))
192 .filterExpression(new FilterExpressionBuilder() 194 .filterExpression(new FilterExpressionBuilder()
193 - .eq(VECTOR_STORE_METADATA_KNOWLEDGE_ID, reqBO.getKnowledgeId()).build()) 195 + .eq(VECTOR_STORE_METADATA_KNOWLEDGE_ID, reqBO.getKnowledgeId().toString())
  196 + .build())
194 .build()); 197 .build());
195 if (CollUtil.isEmpty(documents)) { 198 if (CollUtil.isEmpty(documents)) {
196 return ListUtil.empty(); 199 return ListUtil.empty();
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiModelServiceImpl.java
@@ -16,8 +16,8 @@ import jakarta.annotation.Resource; @@ -16,8 +16,8 @@ import jakarta.annotation.Resource;
16 import org.springframework.ai.chat.model.ChatModel; 16 import org.springframework.ai.chat.model.ChatModel;
17 import org.springframework.ai.embedding.EmbeddingModel; 17 import org.springframework.ai.embedding.EmbeddingModel;
18 import org.springframework.ai.image.ImageModel; 18 import org.springframework.ai.image.ImageModel;
19 -import org.springframework.ai.vectorstore.SimpleVectorStore;  
20 import org.springframework.ai.vectorstore.VectorStore; 19 import org.springframework.ai.vectorstore.VectorStore;
  20 +import org.springframework.ai.vectorstore.qdrant.QdrantVectorStore;
21 import org.springframework.stereotype.Service; 21 import org.springframework.stereotype.Service;
22 import org.springframework.validation.annotation.Validated; 22 import org.springframework.validation.annotation.Validated;
23 23
@@ -162,7 +162,8 @@ public class AiModelServiceImpl implements AiModelService { @@ -162,7 +162,8 @@ public class AiModelServiceImpl implements AiModelService {
162 platform, apiKey.getApiKey(), apiKey.getUrl(), model.getModel()); 162 platform, apiKey.getApiKey(), apiKey.getUrl(), model.getModel());
163 163
164 // 创建或获取 VectorStore 对象 164 // 创建或获取 VectorStore 对象
165 - return modelFactory.getOrCreateVectorStore(SimpleVectorStore.class, embeddingModel); 165 +// return modelFactory.getOrCreateVectorStore(SimpleVectorStore.class, embeddingModel);
  166 + return modelFactory.getOrCreateVectorStore(QdrantVectorStore.class, embeddingModel);
166 } 167 }
167 168
168 } 169 }
169 \ No newline at end of file 170 \ No newline at end of file
yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml
@@ -70,6 +70,7 @@ @@ -70,6 +70,7 @@
70 <groupId>${spring-ai.groupId}</groupId> 70 <groupId>${spring-ai.groupId}</groupId>
71 <artifactId>spring-ai-qdrant-store</artifactId> 71 <artifactId>spring-ai-qdrant-store</artifactId>
72 <version>${spring-ai.version}</version> 72 <version>${spring-ai.version}</version>
  73 +<!-- <optional>true</optional>-->
73 </dependency> 74 </dependency>
74 75
75 <dependency> 76 <dependency>
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java
@@ -11,6 +11,7 @@ import cn.iocoder.yudao.framework.ai.core.model.siliconflow.SiliconFlowChatModel @@ -11,6 +11,7 @@ import cn.iocoder.yudao.framework.ai.core.model.siliconflow.SiliconFlowChatModel
11 import cn.iocoder.yudao.framework.ai.core.model.suno.api.SunoApi; 11 import cn.iocoder.yudao.framework.ai.core.model.suno.api.SunoApi;
12 import cn.iocoder.yudao.framework.ai.core.model.xinghuo.XingHuoChatModel; 12 import cn.iocoder.yudao.framework.ai.core.model.xinghuo.XingHuoChatModel;
13 import lombok.extern.slf4j.Slf4j; 13 import lombok.extern.slf4j.Slf4j;
  14 +import org.springframework.ai.autoconfigure.vectorstore.qdrant.QdrantVectorStoreProperties;
14 import org.springframework.ai.openai.OpenAiChatModel; 15 import org.springframework.ai.openai.OpenAiChatModel;
15 import org.springframework.ai.openai.OpenAiChatOptions; 16 import org.springframework.ai.openai.OpenAiChatOptions;
16 import org.springframework.ai.openai.api.OpenAiApi; 17 import org.springframework.ai.openai.api.OpenAiApi;
@@ -29,7 +30,9 @@ import org.springframework.context.annotation.Lazy; @@ -29,7 +30,9 @@ import org.springframework.context.annotation.Lazy;
29 * @author fansili 30 * @author fansili
30 */ 31 */
31 @AutoConfiguration 32 @AutoConfiguration
32 -@EnableConfigurationProperties(YudaoAiProperties.class) 33 +@EnableConfigurationProperties({YudaoAiProperties.class,
  34 + QdrantVectorStoreProperties.class // 解析 Qdrant 配置
  35 +})
33 @Slf4j 36 @Slf4j
34 public class YudaoAiAutoConfiguration { 37 public class YudaoAiAutoConfiguration {
35 38
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiModelFactoryImpl.java
@@ -5,6 +5,7 @@ import cn.hutool.core.lang.Assert; @@ -5,6 +5,7 @@ import cn.hutool.core.lang.Assert;
5 import cn.hutool.core.lang.Singleton; 5 import cn.hutool.core.lang.Singleton;
6 import cn.hutool.core.lang.func.Func0; 6 import cn.hutool.core.lang.func.Func0;
7 import cn.hutool.core.util.ArrayUtil; 7 import cn.hutool.core.util.ArrayUtil;
  8 +import cn.hutool.core.util.ReflectUtil;
8 import cn.hutool.core.util.RuntimeUtil; 9 import cn.hutool.core.util.RuntimeUtil;
9 import cn.hutool.core.util.StrUtil; 10 import cn.hutool.core.util.StrUtil;
10 import cn.hutool.extra.spring.SpringUtil; 11 import cn.hutool.extra.spring.SpringUtil;
@@ -26,6 +27,9 @@ import com.alibaba.cloud.ai.dashscope.embedding.DashScopeEmbeddingModel; @@ -26,6 +27,9 @@ import com.alibaba.cloud.ai.dashscope.embedding.DashScopeEmbeddingModel;
26 import com.alibaba.cloud.ai.dashscope.embedding.DashScopeEmbeddingOptions; 27 import com.alibaba.cloud.ai.dashscope.embedding.DashScopeEmbeddingOptions;
27 import com.alibaba.cloud.ai.dashscope.image.DashScopeImageModel; 28 import com.alibaba.cloud.ai.dashscope.image.DashScopeImageModel;
28 import com.azure.ai.openai.OpenAIClientBuilder; 29 import com.azure.ai.openai.OpenAIClientBuilder;
  30 +import io.micrometer.observation.ObservationRegistry;
  31 +import io.qdrant.client.QdrantClient;
  32 +import io.qdrant.client.QdrantGrpcClient;
29 import lombok.SneakyThrows; 33 import lombok.SneakyThrows;
30 import org.springframework.ai.autoconfigure.azure.openai.AzureOpenAiAutoConfiguration; 34 import org.springframework.ai.autoconfigure.azure.openai.AzureOpenAiAutoConfiguration;
31 import org.springframework.ai.autoconfigure.azure.openai.AzureOpenAiChatProperties; 35 import org.springframework.ai.autoconfigure.azure.openai.AzureOpenAiChatProperties;
@@ -33,11 +37,14 @@ import org.springframework.ai.autoconfigure.azure.openai.AzureOpenAiConnectionPr @@ -33,11 +37,14 @@ import org.springframework.ai.autoconfigure.azure.openai.AzureOpenAiConnectionPr
33 import org.springframework.ai.autoconfigure.ollama.OllamaAutoConfiguration; 37 import org.springframework.ai.autoconfigure.ollama.OllamaAutoConfiguration;
34 import org.springframework.ai.autoconfigure.openai.OpenAiAutoConfiguration; 38 import org.springframework.ai.autoconfigure.openai.OpenAiAutoConfiguration;
35 import org.springframework.ai.autoconfigure.qianfan.QianFanAutoConfiguration; 39 import org.springframework.ai.autoconfigure.qianfan.QianFanAutoConfiguration;
  40 +import org.springframework.ai.autoconfigure.vectorstore.qdrant.QdrantVectorStoreAutoConfiguration;
  41 +import org.springframework.ai.autoconfigure.vectorstore.qdrant.QdrantVectorStoreProperties;
36 import org.springframework.ai.autoconfigure.zhipuai.ZhiPuAiAutoConfiguration; 42 import org.springframework.ai.autoconfigure.zhipuai.ZhiPuAiAutoConfiguration;
37 import org.springframework.ai.autoconfigure.zhipuai.ZhiPuAiConnectionProperties; 43 import org.springframework.ai.autoconfigure.zhipuai.ZhiPuAiConnectionProperties;
38 import org.springframework.ai.azure.openai.AzureOpenAiChatModel; 44 import org.springframework.ai.azure.openai.AzureOpenAiChatModel;
39 import org.springframework.ai.chat.model.ChatModel; 45 import org.springframework.ai.chat.model.ChatModel;
40 import org.springframework.ai.document.MetadataMode; 46 import org.springframework.ai.document.MetadataMode;
  47 +import org.springframework.ai.embedding.BatchingStrategy;
41 import org.springframework.ai.embedding.EmbeddingModel; 48 import org.springframework.ai.embedding.EmbeddingModel;
42 import org.springframework.ai.image.ImageModel; 49 import org.springframework.ai.image.ImageModel;
43 import org.springframework.ai.ollama.OllamaChatModel; 50 import org.springframework.ai.ollama.OllamaChatModel;
@@ -57,10 +64,15 @@ import org.springframework.ai.stabilityai.StabilityAiImageModel; @@ -57,10 +64,15 @@ import org.springframework.ai.stabilityai.StabilityAiImageModel;
57 import org.springframework.ai.stabilityai.api.StabilityAiApi; 64 import org.springframework.ai.stabilityai.api.StabilityAiApi;
58 import org.springframework.ai.vectorstore.SimpleVectorStore; 65 import org.springframework.ai.vectorstore.SimpleVectorStore;
59 import org.springframework.ai.vectorstore.VectorStore; 66 import org.springframework.ai.vectorstore.VectorStore;
  67 +import org.springframework.ai.vectorstore.observation.DefaultVectorStoreObservationConvention;
  68 +import org.springframework.ai.vectorstore.observation.VectorStoreObservationConvention;
  69 +import org.springframework.ai.vectorstore.qdrant.QdrantVectorStore;
60 import org.springframework.ai.zhipuai.ZhiPuAiChatModel; 70 import org.springframework.ai.zhipuai.ZhiPuAiChatModel;
61 import org.springframework.ai.zhipuai.ZhiPuAiImageModel; 71 import org.springframework.ai.zhipuai.ZhiPuAiImageModel;
62 import org.springframework.ai.zhipuai.api.ZhiPuAiApi; 72 import org.springframework.ai.zhipuai.api.ZhiPuAiApi;
63 import org.springframework.ai.zhipuai.api.ZhiPuAiImageApi; 73 import org.springframework.ai.zhipuai.api.ZhiPuAiImageApi;
  74 +import org.springframework.beans.BeansException;
  75 +import org.springframework.beans.factory.ObjectProvider;
64 import org.springframework.web.client.RestClient; 76 import org.springframework.web.client.RestClient;
65 77
66 import java.io.File; 78 import java.io.File;
@@ -214,13 +226,14 @@ public class AiModelFactoryImpl implements AiModelFactory { @@ -214,13 +226,14 @@ public class AiModelFactoryImpl implements AiModelFactory {
214 226
215 @Override 227 @Override
216 public VectorStore getOrCreateVectorStore(Class<? extends VectorStore> type, EmbeddingModel embeddingModel) { 228 public VectorStore getOrCreateVectorStore(Class<? extends VectorStore> type, EmbeddingModel embeddingModel) {
217 - // String cacheKey = buildClientCacheKey(VectorStore.class, platform, apiKey,  
218 - // url);  
219 String cacheKey = buildClientCacheKey(VectorStore.class, embeddingModel, type); 229 String cacheKey = buildClientCacheKey(VectorStore.class, embeddingModel, type);
220 return Singleton.get(cacheKey, (Func0<VectorStore>) () -> { 230 return Singleton.get(cacheKey, (Func0<VectorStore>) () -> {
221 if (type == SimpleVectorStore.class) { 231 if (type == SimpleVectorStore.class) {
222 return buildSimpleVectorStore(embeddingModel); 232 return buildSimpleVectorStore(embeddingModel);
223 } 233 }
  234 + if (type == QdrantVectorStore.class) {
  235 + return buildQdrantVectorStore(embeddingModel);
  236 + }
224 throw new IllegalArgumentException(StrUtil.format("未知类型({})", type)); 237 throw new IllegalArgumentException(StrUtil.format("未知类型({})", type));
225 // TODO @芋艿:先临时使用 store 238 // TODO @芋艿:先临时使用 store
226 // TODO @芋艿:@xin:后续看看,是不是切到阿里云之类的 239 // TODO @芋艿:@xin:后续看看,是不是切到阿里云之类的
@@ -456,4 +469,38 @@ public class AiModelFactoryImpl implements AiModelFactory { @@ -456,4 +469,38 @@ public class AiModelFactoryImpl implements AiModelFactory {
456 return vectorStore; 469 return vectorStore;
457 } 470 }
458 471
  472 + private QdrantVectorStore buildQdrantVectorStore(EmbeddingModel embeddingModel) {
  473 + QdrantVectorStoreAutoConfiguration configuration = new QdrantVectorStoreAutoConfiguration();
  474 + QdrantVectorStoreProperties vectorStoreProperties = SpringUtil.getBean(QdrantVectorStoreProperties.class);
  475 + // 参考 QdrantVectorStoreAutoConfiguration 实现,创建 QdrantClient 对象
  476 + QdrantGrpcClient.Builder grpcClientBuilder = QdrantGrpcClient.newBuilder(
  477 + vectorStoreProperties.getHost(), vectorStoreProperties.getPort(), vectorStoreProperties.isUseTls());
  478 + if (StrUtil.isNotEmpty(vectorStoreProperties.getApiKey())) {
  479 + grpcClientBuilder.withApiKey(vectorStoreProperties.getApiKey());
  480 + }
  481 + QdrantClient qdrantClient = new QdrantClient(grpcClientBuilder.build());
  482 + // 参考 QdrantVectorStoreAutoConfiguration 实现,实现 batchingStrategy
  483 + BatchingStrategy batchingStrategy = ReflectUtil.invoke(configuration, "batchingStrategy");
  484 +
  485 + // 创建 QdrantVectorStore 对象
  486 + ObjectProvider<ObservationRegistry> observationRegistry = new ObjectProvider<>() {
  487 +
  488 + @Override
  489 + public ObservationRegistry getObject() throws BeansException {
  490 + return SpringUtil.getBean(ObservationRegistry.class);
  491 + }
  492 +
  493 + };
  494 + ObjectProvider <VectorStoreObservationConvention> customObservationConvention = new ObjectProvider<>() {
  495 +
  496 + @Override
  497 + public VectorStoreObservationConvention getObject() throws BeansException {
  498 + return new DefaultVectorStoreObservationConvention();
  499 + }
  500 +
  501 + };
  502 + return configuration.vectorStore(embeddingModel, vectorStoreProperties, qdrantClient,
  503 + observationRegistry, customObservationConvention, batchingStrategy);
  504 + }
  505 +
459 } 506 }
yudao-server/src/main/resources/application-dev.yaml
@@ -4,6 +4,11 @@ server: @@ -4,6 +4,11 @@ server:
4 --- #################### 数据库相关配置 #################### 4 --- #################### 数据库相关配置 ####################
5 5
6 spring: 6 spring:
  7 + spring:
  8 + autoconfigure:
  9 + exclude:
  10 + - org.springframework.ai.autoconfigure.vectorstore.qdrant.QdrantVectorStoreAutoConfiguration # 禁用 AI 模块的 Qdrant,手动创建
  11 + - org.springframework.ai.autoconfigure.vectorstore.milvus.MilvusVectorStoreAutoConfiguration # 禁用 AI 模块的 Milvus,手动创建
7 # 数据源配置项 12 # 数据源配置项
8 datasource: 13 datasource:
9 druid: # Druid 【监控】相关的全局配置 14 druid: # Druid 【监控】相关的全局配置
yudao-server/src/main/resources/application-local.yaml
@@ -3,13 +3,15 @@ server: @@ -3,13 +3,15 @@ server:
3 3
4 --- #################### 数据库相关配置 #################### 4 --- #################### 数据库相关配置 ####################
5 spring: 5 spring:
6 - # 数据源配置项  
7 autoconfigure: 6 autoconfigure:
8 exclude: 7 exclude:
9 - org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration # 默认 local 环境,不开启 Quartz 的自动配置 8 - org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration # 默认 local 环境,不开启 Quartz 的自动配置
10 - de.codecentric.boot.admin.server.config.AdminServerAutoConfiguration # 禁用 Spring Boot Admin 的 Server 的自动配置 9 - de.codecentric.boot.admin.server.config.AdminServerAutoConfiguration # 禁用 Spring Boot Admin 的 Server 的自动配置
11 - de.codecentric.boot.admin.server.ui.config.AdminServerUiAutoConfiguration # 禁用 Spring Boot Admin 的 Server UI 的自动配置 10 - de.codecentric.boot.admin.server.ui.config.AdminServerUiAutoConfiguration # 禁用 Spring Boot Admin 的 Server UI 的自动配置
12 - de.codecentric.boot.admin.client.config.SpringBootAdminClientAutoConfiguration # 禁用 Spring Boot Admin 的 Client 的自动配置 11 - de.codecentric.boot.admin.client.config.SpringBootAdminClientAutoConfiguration # 禁用 Spring Boot Admin 的 Client 的自动配置
  12 + - org.springframework.ai.autoconfigure.vectorstore.qdrant.QdrantVectorStoreAutoConfiguration # 禁用 AI 模块的 Qdrant,手动创建
  13 + - org.springframework.ai.autoconfigure.vectorstore.milvus.MilvusVectorStoreAutoConfiguration # 禁用 AI 模块的 Milvus,手动创建
  14 + # 数据源配置项
13 datasource: 15 datasource:
14 druid: # Druid 【监控】相关的全局配置 16 druid: # Druid 【监控】相关的全局配置
15 web-stat-filter: 17 web-stat-filter:
yudao-server/src/main/resources/application.yaml
@@ -151,6 +151,12 @@ spring: @@ -151,6 +151,12 @@ spring:
151 redis: 151 redis:
152 index: default-index 152 index: default-index
153 prefix: "default:" 153 prefix: "default:"
  154 + qdrant:
  155 + collection-name: knowledge_segment
  156 + host: 127.0.0.1
  157 + port: 6334
  158 + use-tls: false
  159 + api-key:
154 qianfan: # 文心一言 160 qianfan: # 文心一言
155 api-key: x0cuLZ7XsaTCU08vuJWO87Lg 161 api-key: x0cuLZ7XsaTCU08vuJWO87Lg
156 secret-key: R9mYF9dl9KASgi5RUq0FQt3wRisSnOcK 162 secret-key: R9mYF9dl9KASgi5RUq0FQt3wRisSnOcK