Commit 96a743157d481ef742f7237b9e30a8f453bb0fb5
1 parent
2fbb9f88
feat:【ai 大模型】增加 anthropic 接入
Showing
7 changed files
with
98 additions
and
3 deletions
yudao-module-ai/pom.xml
| @@ -86,6 +86,11 @@ | @@ -86,6 +86,11 @@ | ||
| 86 | </dependency> | 86 | </dependency> |
| 87 | <dependency> | 87 | <dependency> |
| 88 | <groupId>org.springframework.ai</groupId> | 88 | <groupId>org.springframework.ai</groupId> |
| 89 | + <artifactId>spring-ai-starter-model-anthropic</artifactId> | ||
| 90 | + <version>${spring-ai.version}</version> | ||
| 91 | + </dependency> | ||
| 92 | + <dependency> | ||
| 93 | + <groupId>org.springframework.ai</groupId> | ||
| 89 | <artifactId>spring-ai-starter-model-deepseek</artifactId> | 94 | <artifactId>spring-ai-starter-model-deepseek</artifactId> |
| 90 | <version>${spring-ai.version}</version> | 95 | <version>${spring-ai.version}</version> |
| 91 | </dependency> | 96 | </dependency> |
yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/enums/model/AiPlatformEnum.java
| @@ -33,6 +33,7 @@ public enum AiPlatformEnum implements ArrayValuable<String> { | @@ -33,6 +33,7 @@ public enum AiPlatformEnum implements ArrayValuable<String> { | ||
| 33 | 33 | ||
| 34 | OPENAI("OpenAI", "OpenAI"), // OpenAI 官方 | 34 | OPENAI("OpenAI", "OpenAI"), // OpenAI 官方 |
| 35 | AZURE_OPENAI("AzureOpenAI", "AzureOpenAI"), // OpenAI 微软 | 35 | AZURE_OPENAI("AzureOpenAI", "AzureOpenAI"), // OpenAI 微软 |
| 36 | + ANTHROPIC("Anthropic", "Anthropic"), // Anthropic Claude | ||
| 36 | OLLAMA("Ollama", "Ollama"), | 37 | OLLAMA("Ollama", "Ollama"), |
| 37 | 38 | ||
| 38 | STABLE_DIFFUSION("StableDiffusion", "StableDiffusion"), // Stability AI | 39 | STABLE_DIFFUSION("StableDiffusion", "StableDiffusion"), // Stability AI |
yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/AiModelFactoryImpl.java
| @@ -67,6 +67,7 @@ import org.springframework.ai.minimax.MiniMaxChatOptions; | @@ -67,6 +67,7 @@ import org.springframework.ai.minimax.MiniMaxChatOptions; | ||
| 67 | import org.springframework.ai.minimax.MiniMaxEmbeddingModel; | 67 | import org.springframework.ai.minimax.MiniMaxEmbeddingModel; |
| 68 | import org.springframework.ai.minimax.MiniMaxEmbeddingOptions; | 68 | import org.springframework.ai.minimax.MiniMaxEmbeddingOptions; |
| 69 | import org.springframework.ai.minimax.api.MiniMaxApi; | 69 | import org.springframework.ai.minimax.api.MiniMaxApi; |
| 70 | +import org.springframework.ai.model.anthropic.autoconfigure.AnthropicChatAutoConfiguration; | ||
| 70 | import org.springframework.ai.model.azure.openai.autoconfigure.AzureOpenAiChatAutoConfiguration; | 71 | import org.springframework.ai.model.azure.openai.autoconfigure.AzureOpenAiChatAutoConfiguration; |
| 71 | import org.springframework.ai.model.azure.openai.autoconfigure.AzureOpenAiEmbeddingAutoConfiguration; | 72 | import org.springframework.ai.model.azure.openai.autoconfigure.AzureOpenAiEmbeddingAutoConfiguration; |
| 72 | import org.springframework.ai.model.azure.openai.autoconfigure.AzureOpenAiEmbeddingProperties; | 73 | import org.springframework.ai.model.azure.openai.autoconfigure.AzureOpenAiEmbeddingProperties; |
| @@ -93,6 +94,8 @@ import org.springframework.ai.openai.OpenAiImageModel; | @@ -93,6 +94,8 @@ import org.springframework.ai.openai.OpenAiImageModel; | ||
| 93 | import org.springframework.ai.openai.api.OpenAiApi; | 94 | import org.springframework.ai.openai.api.OpenAiApi; |
| 94 | import org.springframework.ai.openai.api.OpenAiImageApi; | 95 | import org.springframework.ai.openai.api.OpenAiImageApi; |
| 95 | import org.springframework.ai.openai.api.common.OpenAiApiConstants; | 96 | import org.springframework.ai.openai.api.common.OpenAiApiConstants; |
| 97 | +import org.springframework.ai.anthropic.AnthropicChatModel; | ||
| 98 | +import org.springframework.ai.anthropic.api.AnthropicApi; | ||
| 96 | import org.springframework.ai.stabilityai.StabilityAiImageModel; | 99 | import org.springframework.ai.stabilityai.StabilityAiImageModel; |
| 97 | import org.springframework.ai.stabilityai.api.StabilityAiApi; | 100 | import org.springframework.ai.stabilityai.api.StabilityAiApi; |
| 98 | import org.springframework.ai.vectorstore.SimpleVectorStore; | 101 | import org.springframework.ai.vectorstore.SimpleVectorStore; |
| @@ -168,6 +171,8 @@ public class AiModelFactoryImpl implements AiModelFactory { | @@ -168,6 +171,8 @@ public class AiModelFactoryImpl implements AiModelFactory { | ||
| 168 | return buildOpenAiChatModel(apiKey, url); | 171 | return buildOpenAiChatModel(apiKey, url); |
| 169 | case AZURE_OPENAI: | 172 | case AZURE_OPENAI: |
| 170 | return buildAzureOpenAiChatModel(apiKey, url); | 173 | return buildAzureOpenAiChatModel(apiKey, url); |
| 174 | + case ANTHROPIC: | ||
| 175 | + return buildAnthropicChatModel(apiKey, url); | ||
| 171 | case OLLAMA: | 176 | case OLLAMA: |
| 172 | return buildOllamaChatModel(url); | 177 | return buildOllamaChatModel(url); |
| 173 | default: | 178 | default: |
| @@ -206,6 +211,8 @@ public class AiModelFactoryImpl implements AiModelFactory { | @@ -206,6 +211,8 @@ public class AiModelFactoryImpl implements AiModelFactory { | ||
| 206 | return SpringUtil.getBean(OpenAiChatModel.class); | 211 | return SpringUtil.getBean(OpenAiChatModel.class); |
| 207 | case AZURE_OPENAI: | 212 | case AZURE_OPENAI: |
| 208 | return SpringUtil.getBean(AzureOpenAiChatModel.class); | 213 | return SpringUtil.getBean(AzureOpenAiChatModel.class); |
| 214 | + case ANTHROPIC: | ||
| 215 | + return SpringUtil.getBean(AnthropicChatModel.class); | ||
| 209 | case OLLAMA: | 216 | case OLLAMA: |
| 210 | return SpringUtil.getBean(OllamaChatModel.class); | 217 | return SpringUtil.getBean(OllamaChatModel.class); |
| 211 | default: | 218 | default: |
| @@ -513,6 +520,21 @@ public class AiModelFactoryImpl implements AiModelFactory { | @@ -513,6 +520,21 @@ public class AiModelFactoryImpl implements AiModelFactory { | ||
| 513 | } | 520 | } |
| 514 | 521 | ||
| 515 | /** | 522 | /** |
| 523 | + * 可参考 {@link AnthropicChatAutoConfiguration} 的 anthropicApi 方法 | ||
| 524 | + */ | ||
| 525 | + private static AnthropicChatModel buildAnthropicChatModel(String apiKey, String url) { | ||
| 526 | + AnthropicApi.Builder builder = AnthropicApi.builder().apiKey(apiKey); | ||
| 527 | + if (StrUtil.isNotEmpty(url)) { | ||
| 528 | + builder.baseUrl(url); | ||
| 529 | + } | ||
| 530 | + AnthropicApi anthropicApi = builder.build(); | ||
| 531 | + return AnthropicChatModel.builder() | ||
| 532 | + .anthropicApi(anthropicApi) | ||
| 533 | + .toolCallingManager(getToolCallingManager()) | ||
| 534 | + .build(); | ||
| 535 | + } | ||
| 536 | + | ||
| 537 | + /** | ||
| 516 | * 可参考 {@link OpenAiImageAutoConfiguration} 的 openAiImageModel 方法 | 538 | * 可参考 {@link OpenAiImageAutoConfiguration} 的 openAiImageModel 方法 |
| 517 | */ | 539 | */ |
| 518 | private OpenAiImageModel buildOpenAiImageModel(String openAiToken, String url) { | 540 | private OpenAiImageModel buildOpenAiImageModel(String openAiToken, String url) { |
yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/util/AiUtils.java
| @@ -8,6 +8,7 @@ import cn.iocoder.yudao.module.ai.enums.model.AiPlatformEnum; | @@ -8,6 +8,7 @@ import cn.iocoder.yudao.module.ai.enums.model.AiPlatformEnum; | ||
| 8 | import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatOptions; | 8 | import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatOptions; |
| 9 | import org.springaicommunity.moonshot.MoonshotChatOptions; | 9 | import org.springaicommunity.moonshot.MoonshotChatOptions; |
| 10 | import org.springaicommunity.qianfan.QianFanChatOptions; | 10 | import org.springaicommunity.qianfan.QianFanChatOptions; |
| 11 | +import org.springframework.ai.anthropic.AnthropicChatOptions; | ||
| 11 | import org.springframework.ai.azure.openai.AzureOpenAiChatOptions; | 12 | import org.springframework.ai.azure.openai.AzureOpenAiChatOptions; |
| 12 | import org.springframework.ai.chat.messages.*; | 13 | import org.springframework.ai.chat.messages.*; |
| 13 | import org.springframework.ai.chat.prompt.ChatOptions; | 14 | import org.springframework.ai.chat.prompt.ChatOptions; |
| @@ -67,6 +68,9 @@ public class AiUtils { | @@ -67,6 +68,9 @@ public class AiUtils { | ||
| 67 | case AZURE_OPENAI: | 68 | case AZURE_OPENAI: |
| 68 | return AzureOpenAiChatOptions.builder().deploymentName(model).temperature(temperature).maxTokens(maxTokens) | 69 | return AzureOpenAiChatOptions.builder().deploymentName(model).temperature(temperature).maxTokens(maxTokens) |
| 69 | .toolNames(toolNames).toolContext(toolContext).build(); | 70 | .toolNames(toolNames).toolContext(toolContext).build(); |
| 71 | + case ANTHROPIC: | ||
| 72 | + return AnthropicChatOptions.builder().model(model).temperature(temperature).maxTokens(maxTokens) | ||
| 73 | + .toolNames(toolNames).toolContext(toolContext).build(); | ||
| 70 | case OLLAMA: | 74 | case OLLAMA: |
| 71 | return OllamaOptions.builder().model(model).temperature(temperature).numPredict(maxTokens) | 75 | return OllamaOptions.builder().model(model).temperature(temperature).numPredict(maxTokens) |
| 72 | .toolNames(toolNames).toolContext(toolContext).build(); | 76 | .toolNames(toolNames).toolContext(toolContext).build(); |
yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/chat/AnthropicChatModelTest.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.ai.framework.ai.core.model.chat; | ||
| 2 | + | ||
| 3 | +import org.junit.jupiter.api.Disabled; | ||
| 4 | +import org.junit.jupiter.api.Test; | ||
| 5 | +import org.springframework.ai.anthropic.AnthropicChatModel; | ||
| 6 | +import org.springframework.ai.anthropic.api.AnthropicApi; | ||
| 7 | +import org.springframework.ai.chat.messages.Message; | ||
| 8 | +import org.springframework.ai.chat.messages.SystemMessage; | ||
| 9 | +import org.springframework.ai.chat.messages.UserMessage; | ||
| 10 | +import org.springframework.ai.chat.model.ChatResponse; | ||
| 11 | +import org.springframework.ai.chat.prompt.Prompt; | ||
| 12 | +import reactor.core.publisher.Flux; | ||
| 13 | + | ||
| 14 | +import java.util.ArrayList; | ||
| 15 | +import java.util.List; | ||
| 16 | + | ||
| 17 | +/** | ||
| 18 | + * {@link AnthropicChatModel} 集成测试类 | ||
| 19 | + * | ||
| 20 | + * @author 芋道源码 | ||
| 21 | + */ | ||
| 22 | +public class AnthropicChatModelTest { | ||
| 23 | + | ||
| 24 | + private final AnthropicChatModel chatModel = AnthropicChatModel.builder() | ||
| 25 | + .anthropicApi(AnthropicApi.builder() | ||
| 26 | + .apiKey("sk-muubv7cXeLw0Etgs743f365cD5Ea44429946Fa7e672d8942") | ||
| 27 | + .baseUrl("https://aihubmix.com") | ||
| 28 | + .build()) | ||
| 29 | + .build(); | ||
| 30 | + | ||
| 31 | + @Test | ||
| 32 | + @Disabled | ||
| 33 | + public void testCall() { | ||
| 34 | + // 准备参数 | ||
| 35 | + List<Message> messages = new ArrayList<>(); | ||
| 36 | + messages.add(new SystemMessage("你是一个优质的文言文作者,用文言文描述着各城市的人文风景。")); | ||
| 37 | + messages.add(new UserMessage("1 + 1 = ?")); | ||
| 38 | + | ||
| 39 | + // 调用 | ||
| 40 | + ChatResponse response = chatModel.call(new Prompt(messages)); | ||
| 41 | + // 打印结果 | ||
| 42 | + System.out.println(response); | ||
| 43 | + } | ||
| 44 | + | ||
| 45 | + @Test | ||
| 46 | + @Disabled | ||
| 47 | + public void testStream() { | ||
| 48 | + // 准备参数 | ||
| 49 | + List<Message> messages = new ArrayList<>(); | ||
| 50 | + messages.add(new SystemMessage("你是一个优质的文言文作者,用文言文描述着各城市的人文风景。")); | ||
| 51 | + messages.add(new UserMessage("1 + 1 = ?")); | ||
| 52 | + | ||
| 53 | + // 调用 | ||
| 54 | + Flux<ChatResponse> flux = chatModel.stream(new Prompt(messages)); | ||
| 55 | + // 打印结果 | ||
| 56 | + flux.doOnNext(System.out::println).then().block(); | ||
| 57 | + } | ||
| 58 | + | ||
| 59 | +} |
yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/image/TongYiImagesModelTest.java
| @@ -16,8 +16,11 @@ import org.springframework.ai.image.ImageResponse; | @@ -16,8 +16,11 @@ import org.springframework.ai.image.ImageResponse; | ||
| 16 | */ | 16 | */ |
| 17 | public class TongYiImagesModelTest { | 17 | public class TongYiImagesModelTest { |
| 18 | 18 | ||
| 19 | - private final DashScopeImageModel imageModel = new DashScopeImageModel( | ||
| 20 | - new DashScopeImageApi("sk-7d903764249848cfa912733146da12d1")); | 19 | + private final DashScopeImageModel imageModel = DashScopeImageModel.builder() |
| 20 | + .dashScopeApi(DashScopeImageApi.builder() | ||
| 21 | + .apiKey("sk-47aa124781be4bfb95244cc62f63f7d0") | ||
| 22 | + .build()) | ||
| 23 | + .build(); | ||
| 21 | 24 | ||
| 22 | @Test | 25 | @Test |
| 23 | @Disabled | 26 | @Disabled |
yudao-server/src/main/resources/application.yaml
| @@ -175,7 +175,8 @@ spring: | @@ -175,7 +175,8 @@ spring: | ||
| 175 | azure: # OpenAI 微软 | 175 | azure: # OpenAI 微软 |
| 176 | openai: | 176 | openai: |
| 177 | endpoint: https://eastusprejade.openai.azure.com | 177 | endpoint: https://eastusprejade.openai.azure.com |
| 178 | - api-key: xxx | 178 | + anthropic: # Anthropic Claude |
| 179 | + api-key: sk-muubv7cXeLw0Etgs743f365cD5Ea44429946Fa7e672d8942 | ||
| 179 | ollama: | 180 | ollama: |
| 180 | base-url: http://127.0.0.1:11434 | 181 | base-url: http://127.0.0.1:11434 |
| 181 | chat: | 182 | chat: |