Commit 83bd96d6725b0769808ea5c83b43d54e04859c6e

Authored by YunaiV
1 parent b4538568

【功能新增】AI:集成 Azure 的 OpenAI 模型

yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/knowledge/DocServiceImpl.java
... ... @@ -7,7 +7,6 @@ import org.springframework.ai.reader.tika.TikaDocumentReader;
7 7 import org.springframework.ai.transformer.splitter.TokenTextSplitter;
8 8 import org.springframework.ai.vectorstore.RedisVectorStore;
9 9 import org.springframework.beans.factory.annotation.Value;
10   -import org.springframework.stereotype.Service;
11 10  
12 11 import java.util.List;
13 12  
... ... @@ -16,7 +15,7 @@ import java.util.List;
16 15 *
17 16 * @author xiaoxin
18 17 */
19   -@Service
  18 +//@Service // TODO 芋艿:临时注释,避免无法启动
20 19 @Slf4j
21 20 public class DocServiceImpl implements DocService {
22 21  
... ...
yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml
... ... @@ -23,7 +23,6 @@
23 23 <artifactId>spring-ai-zhipuai-spring-boot-starter</artifactId>
24 24 <version>${spring-ai.version}</version>
25 25 </dependency>
26   -
27 26 <dependency>
28 27 <groupId>org.springframework.ai</groupId>
29 28 <artifactId>spring-ai-openai-spring-boot-starter</artifactId>
... ... @@ -31,6 +30,11 @@
31 30 </dependency>
32 31 <dependency>
33 32 <groupId>org.springframework.ai</groupId>
  33 + <artifactId>spring-ai-azure-openai-spring-boot-starter</artifactId>
  34 + <version>${spring-ai.version}</version>
  35 + </dependency>
  36 + <dependency>
  37 + <groupId>org.springframework.ai</groupId>
34 38 <artifactId>spring-ai-ollama-spring-boot-starter</artifactId>
35 39 <version>${spring-ai.version}</version>
36 40 </dependency>
... ...
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java
... ... @@ -12,6 +12,7 @@ import com.alibaba.cloud.ai.tongyi.TongYiAutoConfiguration;
12 12 import lombok.extern.slf4j.Slf4j;
13 13 import org.springframework.ai.autoconfigure.vectorstore.redis.RedisVectorStoreProperties;
14 14 import org.springframework.ai.document.MetadataMode;
  15 +import org.springframework.ai.embedding.EmbeddingModel;
15 16 import org.springframework.ai.transformer.splitter.TokenTextSplitter;
16 17 import org.springframework.ai.transformers.TransformersEmbeddingModel;
17 18 import org.springframework.ai.vectorstore.RedisVectorStore;
... ... @@ -21,6 +22,7 @@ import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
21 22 import org.springframework.boot.context.properties.EnableConfigurationProperties;
22 23 import org.springframework.context.annotation.Bean;
23 24 import org.springframework.context.annotation.Import;
  25 +import org.springframework.context.annotation.Lazy;
24 26 import redis.clients.jedis.JedisPooled;
25 27  
26 28 /**
... ... @@ -82,7 +84,8 @@ public class YudaoAiAutoConfiguration {
82 84  
83 85 // ========== rag 相关 ==========
84 86 @Bean
85   - public TransformersEmbeddingModel transformersEmbeddingClient() {
  87 + @Lazy // TODO 芋艿:临时注释,避免无法启动
  88 + public EmbeddingModel transformersEmbeddingClient() {
86 89 return new TransformersEmbeddingModel(MetadataMode.EMBED);
87 90 }
88 91  
... ... @@ -90,6 +93,7 @@ public class YudaoAiAutoConfiguration {
90 93 * 我们启动有加载很多 Embedding 模型,不晓得取哪个好,先 new 个 TransformersEmbeddingModel 跑
91 94 */
92 95 @Bean
  96 + @Lazy // TODO 芋艿:临时注释,避免无法启动
93 97 public RedisVectorStore vectorStore(TransformersEmbeddingModel transformersEmbeddingModel, RedisVectorStoreProperties properties,
94 98 RedisProperties redisProperties) {
95 99 var config = RedisVectorStore.RedisVectorStoreConfig.builder()
... ... @@ -105,6 +109,7 @@ public class YudaoAiAutoConfiguration {
105 109 }
106 110  
107 111 @Bean
  112 + @Lazy // TODO 芋艿:临时注释,避免无法启动
108 113 public TokenTextSplitter tokenTextSplitter() {
109 114 return new TokenTextSplitter(500, 100, 5, 10000, true);
110 115 }
... ...
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java
... ... @@ -22,7 +22,8 @@ public enum AiPlatformEnum {
22 22  
23 23 // ========== 国外平台 ==========
24 24  
25   - OPENAI("OpenAI", "OpenAI"),
  25 + OPENAI("OpenAI", "OpenAI"), // OpenAI 官方
  26 + AZURE_OPENAI("AzureOpenAI", "AzureOpenAI"), // OpenAI 微软
26 27 OLLAMA("Ollama", "Ollama"),
27 28  
28 29 STABLE_DIFFUSION("StableDiffusion", "StableDiffusion"), // Stability AI
... ...
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiModelFactoryImpl.java
... ... @@ -21,6 +21,10 @@ import com.alibaba.cloud.ai.tongyi.image.TongYiImagesModel;
21 21 import com.alibaba.cloud.ai.tongyi.image.TongYiImagesProperties;
22 22 import com.alibaba.dashscope.aigc.generation.Generation;
23 23 import com.alibaba.dashscope.aigc.imagesynthesis.ImageSynthesis;
  24 +import com.azure.ai.openai.OpenAIClient;
  25 +import org.springframework.ai.autoconfigure.azure.openai.AzureOpenAiAutoConfiguration;
  26 +import org.springframework.ai.autoconfigure.azure.openai.AzureOpenAiChatProperties;
  27 +import org.springframework.ai.autoconfigure.azure.openai.AzureOpenAiConnectionProperties;
24 28 import org.springframework.ai.autoconfigure.ollama.OllamaAutoConfiguration;
25 29 import org.springframework.ai.autoconfigure.openai.OpenAiAutoConfiguration;
26 30 import org.springframework.ai.autoconfigure.qianfan.QianFanAutoConfiguration;
... ... @@ -31,6 +35,7 @@ import org.springframework.ai.autoconfigure.zhipuai.ZhiPuAiAutoConfiguration;
31 35 import org.springframework.ai.autoconfigure.zhipuai.ZhiPuAiChatProperties;
32 36 import org.springframework.ai.autoconfigure.zhipuai.ZhiPuAiConnectionProperties;
33 37 import org.springframework.ai.autoconfigure.zhipuai.ZhiPuAiImageProperties;
  38 +import org.springframework.ai.azure.openai.AzureOpenAiChatModel;
34 39 import org.springframework.ai.chat.model.ChatModel;
35 40 import org.springframework.ai.image.ImageModel;
36 41 import org.springframework.ai.model.function.FunctionCallbackContext;
... ... @@ -82,6 +87,8 @@ public class AiModelFactoryImpl implements AiModelFactory {
82 87 return buildXingHuoChatModel(apiKey);
83 88 case OPENAI:
84 89 return buildOpenAiChatModel(apiKey, url);
  90 + case AZURE_OPENAI:
  91 + return buildAzureOpenAiChatModel(apiKey, url);
85 92 case OLLAMA:
86 93 return buildOllamaChatModel(url);
87 94 default:
... ... @@ -106,6 +113,8 @@ public class AiModelFactoryImpl implements AiModelFactory {
106 113 return SpringUtil.getBean(XingHuoChatModel.class);
107 114 case OPENAI:
108 115 return SpringUtil.getBean(OpenAiChatModel.class);
  116 + case AZURE_OPENAI:
  117 + return SpringUtil.getBean(AzureOpenAiChatModel.class);
109 118 case OLLAMA:
110 119 return SpringUtil.getBean(OllamaChatModel.class);
111 120 default:
... ... @@ -269,6 +278,21 @@ public class AiModelFactoryImpl implements AiModelFactory {
269 278 }
270 279  
271 280 /**
  281 + * 可参考 {@link AzureOpenAiAutoConfiguration}
  282 + */
  283 + private static AzureOpenAiChatModel buildAzureOpenAiChatModel(String apiKey, String url) {
  284 + AzureOpenAiAutoConfiguration azureOpenAiAutoConfiguration = new AzureOpenAiAutoConfiguration();
  285 + // 创建 OpenAIClient 对象
  286 + AzureOpenAiConnectionProperties connectionProperties = new AzureOpenAiConnectionProperties();
  287 + connectionProperties.setApiKey(apiKey);
  288 + connectionProperties.setEndpoint(url);
  289 + OpenAIClient openAIClient = azureOpenAiAutoConfiguration.openAIClient(connectionProperties);
  290 + // 获取 AzureOpenAiChatProperties 对象
  291 + AzureOpenAiChatProperties chatProperties = SpringUtil.getBean(AzureOpenAiChatProperties.class);
  292 + return azureOpenAiAutoConfiguration.azureOpenAiChatModel(openAIClient, chatProperties, null, null);
  293 + }
  294 +
  295 + /**
272 296 * 可参考 {@link OpenAiAutoConfiguration}
273 297 */
274 298 private OpenAiImageModel buildOpenAiImageModel(String openAiToken, String url) {
... ...
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/util/AiUtils.java
... ... @@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum;
5 5 import cn.iocoder.yudao.framework.ai.core.model.deepseek.DeepSeekChatOptions;
6 6 import cn.iocoder.yudao.framework.ai.core.model.xinghuo.XingHuoChatOptions;
7 7 import com.alibaba.cloud.ai.tongyi.chat.TongYiChatOptions;
  8 +import org.springframework.ai.azure.openai.AzureOpenAiChatOptions;
8 9 import org.springframework.ai.chat.messages.*;
9 10 import org.springframework.ai.chat.prompt.ChatOptions;
10 11 import org.springframework.ai.ollama.api.OllamaOptions;
... ... @@ -35,6 +36,9 @@ public class AiUtils {
35 36 return XingHuoChatOptions.builder().model(model).temperature(temperatureF).maxTokens(maxTokens).build();
36 37 case OPENAI:
37 38 return OpenAiChatOptions.builder().withModel(model).withTemperature(temperatureF).withMaxTokens(maxTokens).build();
  39 + case AZURE_OPENAI:
  40 + // TODO 芋艿:貌似没 model 字段???!
  41 + return AzureOpenAiChatOptions.builder().withDeploymentName(model).withTemperature(temperatureF).withMaxTokens(maxTokens).build();
38 42 case OLLAMA:
39 43 return OllamaOptions.create().withModel(model).withTemperature(temperatureF).withNumPredict(maxTokens);
40 44 default:
... ...
yudao-server/src/main/resources/application.yaml
... ... @@ -162,9 +162,13 @@ spring:
162 162 secret-key: R9mYF9dl9KASgi5RUq0FQt3wRisSnOcK
163 163 zhipuai: # 智谱 AI
164 164 api-key: 32f84543e54eee31f8d56b2bd6020573.3vh9idLJZ2ZhxDEs
165   - openai:
  165 + openai: # OpenAI 官方
166 166 api-key: sk-yzKea6d8e8212c3bdd99f9f44ced1cae37c097e5aa3BTS7z
167 167 base-url: https://api.gptsapi.net
  168 + azure: # OpenAI 微软
  169 + openai:
  170 + endpoint: https://eastusprejade.openai.azure.com
  171 + api-key: xxx
168 172 ollama:
169 173 base-url: http://127.0.0.1:11434
170 174 chat:
... ...