Commit e0f08a0f02b5bb53b7f3e6201469eb3a5767bf40

Authored by YunaiV
1 parent 6c094aaf

【代码优化】AI:将 ChatClient 替换成 ChatModel,和 Spring AI 对齐

yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImpl.java
@@ -70,7 +70,7 @@ public class AiChatMessageServiceImpl implements AiChatMessageService { @@ -70,7 +70,7 @@ public class AiChatMessageServiceImpl implements AiChatMessageService {
70 List<AiChatMessageDO> historyMessages = chatMessageMapper.selectListByConversationId(conversation.getId()); 70 List<AiChatMessageDO> historyMessages = chatMessageMapper.selectListByConversationId(conversation.getId());
71 // 1.2 校验模型 71 // 1.2 校验模型
72 AiChatModelDO model = chatModalService.validateChatModel(conversation.getModelId()); 72 AiChatModelDO model = chatModalService.validateChatModel(conversation.getModelId());
73 - ChatModel chatClient = apiKeyService.getChatClient(model.getKeyId()); 73 + ChatModel chatModel = apiKeyService.getChatModel(model.getKeyId());
74 74
75 // 2. 插入 user 发送消息 75 // 2. 插入 user 发送消息
76 AiChatMessageDO userMessage = createChatMessage(conversation.getId(), null, model, 76 AiChatMessageDO userMessage = createChatMessage(conversation.getId(), null, model,
@@ -82,7 +82,7 @@ public class AiChatMessageServiceImpl implements AiChatMessageService { @@ -82,7 +82,7 @@ public class AiChatMessageServiceImpl implements AiChatMessageService {
82 82
83 // 3.2 创建 chat 需要的 Prompt 83 // 3.2 创建 chat 需要的 Prompt
84 Prompt prompt = buildPrompt(conversation, historyMessages, model, sendReqVO); 84 Prompt prompt = buildPrompt(conversation, historyMessages, model, sendReqVO);
85 - ChatResponse chatResponse = chatClient.call(prompt); 85 + ChatResponse chatResponse = chatModel.call(prompt);
86 86
87 // 3.3 段式返回 87 // 3.3 段式返回
88 String newContent = chatResponse.getResult().getOutput().getContent(); 88 String newContent = chatResponse.getResult().getOutput().getContent();
@@ -101,7 +101,7 @@ public class AiChatMessageServiceImpl implements AiChatMessageService { @@ -101,7 +101,7 @@ public class AiChatMessageServiceImpl implements AiChatMessageService {
101 List<AiChatMessageDO> historyMessages = chatMessageMapper.selectListByConversationId(conversation.getId()); 101 List<AiChatMessageDO> historyMessages = chatMessageMapper.selectListByConversationId(conversation.getId());
102 // 1.2 校验模型 102 // 1.2 校验模型
103 AiChatModelDO model = chatModalService.validateChatModel(conversation.getModelId()); 103 AiChatModelDO model = chatModalService.validateChatModel(conversation.getModelId());
104 - StreamingChatModel chatClient = apiKeyService.getChatClient(model.getKeyId()); 104 + StreamingChatModel chatModel = apiKeyService.getChatModel(model.getKeyId());
105 105
106 // 2. 插入 user 发送消息 106 // 2. 插入 user 发送消息
107 AiChatMessageDO userMessage = createChatMessage(conversation.getId(), null, model, 107 AiChatMessageDO userMessage = createChatMessage(conversation.getId(), null, model,
@@ -113,7 +113,7 @@ public class AiChatMessageServiceImpl implements AiChatMessageService { @@ -113,7 +113,7 @@ public class AiChatMessageServiceImpl implements AiChatMessageService {
113 113
114 // 3.2 创建 chat 需要的 Prompt 114 // 3.2 创建 chat 需要的 Prompt
115 Prompt prompt = buildPrompt(conversation, historyMessages, model, sendReqVO); 115 Prompt prompt = buildPrompt(conversation, historyMessages, model, sendReqVO);
116 - Flux<ChatResponse> streamResponse = chatClient.stream(prompt); 116 + Flux<ChatResponse> streamResponse = chatModel.stream(prompt);
117 117
118 // 3.3 流式返回 118 // 3.3 流式返回
119 // TODO 注意:Schedulers.immediate() 目的是,避免默认 Schedulers.parallel() 并发消费 chunk 导致 SSE 响应前端会乱序问题 119 // TODO 注意:Schedulers.immediate() 目的是,避免默认 Schedulers.parallel() 并发消费 chunk 导致 SSE 响应前端会乱序问题
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java
@@ -98,8 +98,8 @@ public class AiImageServiceImpl implements AiImageService { @@ -98,8 +98,8 @@ public class AiImageServiceImpl implements AiImageService {
98 // 1.1 构建请求 98 // 1.1 构建请求
99 ImageOptions request = buildImageOptions(req); 99 ImageOptions request = buildImageOptions(req);
100 // 1.2 执行请求 100 // 1.2 执行请求
101 - ImageModel imageClient = apiKeyService.getImageClient(AiPlatformEnum.validatePlatform(req.getPlatform()));  
102 - ImageResponse response = imageClient.call(new ImagePrompt(req.getPrompt(), request)); 101 + ImageModel imageModel = apiKeyService.getImageModel(AiPlatformEnum.validatePlatform(req.getPlatform()));
  102 + ImageResponse response = imageModel.call(new ImagePrompt(req.getPrompt(), request));
103 103
104 // 2. 上传到文件服务 104 // 2. 上传到文件服务
105 byte[] fileContent = Base64.decode(response.getResult().getOutput().getB64Json()); 105 byte[] fileContent = Base64.decode(response.getResult().getOutput().getB64Json());
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyService.java
@@ -81,17 +81,17 @@ public interface AiApiKeyService { @@ -81,17 +81,17 @@ public interface AiApiKeyService {
81 * @param id 编号 81 * @param id 编号
82 * @return ChatModel 对象 82 * @return ChatModel 对象
83 */ 83 */
84 - ChatModel getChatClient(Long id); 84 + ChatModel getChatModel(Long id);
85 85
86 /** 86 /**
87 - * 获得 ImageClient 对象 87 + * 获得 ImageModel 对象
88 * 88 *
89 * TODO 可优化点:目前默认获取 platform 对应的第一个开启的配置用于绘画;后续可以支持配置选择 89 * TODO 可优化点:目前默认获取 platform 对应的第一个开启的配置用于绘画;后续可以支持配置选择
90 * 90 *
91 * @param platform 平台 91 * @param platform 平台
92 - * @return ImageClient 对象 92 + * @return ImageModel 对象
93 */ 93 */
94 - ImageModel getImageClient(AiPlatformEnum platform); 94 + ImageModel getImageModel(AiPlatformEnum platform);
95 95
96 /** 96 /**
97 * 获得 MidjourneyApi 对象 97 * 获得 MidjourneyApi 对象
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiApiKeyServiceImpl.java
1 package cn.iocoder.yudao.module.ai.service.model; 1 package cn.iocoder.yudao.module.ai.service.model;
2 2
3 import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; 3 import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum;
4 -import cn.iocoder.yudao.framework.ai.core.factory.AiClientFactory; 4 +import cn.iocoder.yudao.framework.ai.core.factory.AiModelFactory;
5 import cn.iocoder.yudao.framework.ai.core.model.midjourney.api.MidjourneyApi; 5 import cn.iocoder.yudao.framework.ai.core.model.midjourney.api.MidjourneyApi;
6 import cn.iocoder.yudao.framework.ai.core.model.suno.api.SunoApi; 6 import cn.iocoder.yudao.framework.ai.core.model.suno.api.SunoApi;
7 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 7 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
@@ -35,7 +35,7 @@ public class AiApiKeyServiceImpl implements AiApiKeyService { @@ -35,7 +35,7 @@ public class AiApiKeyServiceImpl implements AiApiKeyService {
35 private AiApiKeyMapper apiKeyMapper; 35 private AiApiKeyMapper apiKeyMapper;
36 36
37 @Resource 37 @Resource
38 - private AiClientFactory clientFactory; 38 + private AiModelFactory modelFactory;
39 39
40 @Override 40 @Override
41 public Long createApiKey(AiApiKeySaveReqVO createReqVO) { 41 public Long createApiKey(AiApiKeySaveReqVO createReqVO) {
@@ -98,19 +98,19 @@ public class AiApiKeyServiceImpl implements AiApiKeyService { @@ -98,19 +98,19 @@ public class AiApiKeyServiceImpl implements AiApiKeyService {
98 // ========== 与 spring-ai 集成 ========== 98 // ========== 与 spring-ai 集成 ==========
99 99
100 @Override 100 @Override
101 - public ChatModel getChatClient(Long id) { 101 + public ChatModel getChatModel(Long id) {
102 AiApiKeyDO apiKey = validateApiKey(id); 102 AiApiKeyDO apiKey = validateApiKey(id);
103 AiPlatformEnum platform = AiPlatformEnum.validatePlatform(apiKey.getPlatform()); 103 AiPlatformEnum platform = AiPlatformEnum.validatePlatform(apiKey.getPlatform());
104 - return clientFactory.getOrCreateChatClient(platform, apiKey.getApiKey(), apiKey.getUrl()); 104 + return modelFactory.getOrCreateChatClient(platform, apiKey.getApiKey(), apiKey.getUrl());
105 } 105 }
106 106
107 @Override 107 @Override
108 - public ImageModel getImageClient(AiPlatformEnum platform) { 108 + public ImageModel getImageModel(AiPlatformEnum platform) {
109 AiApiKeyDO apiKey = apiKeyMapper.selectFirstByPlatformAndStatus(platform.getName(), CommonStatusEnum.ENABLE.getStatus()); 109 AiApiKeyDO apiKey = apiKeyMapper.selectFirstByPlatformAndStatus(platform.getName(), CommonStatusEnum.ENABLE.getStatus());
110 if (apiKey == null) { 110 if (apiKey == null) {
111 throw exception(API_KEY_IMAGE_NODE_FOUND, platform.getName()); 111 throw exception(API_KEY_IMAGE_NODE_FOUND, platform.getName());
112 } 112 }
113 - return clientFactory.getOrCreateImageClient(platform, apiKey.getApiKey(), apiKey.getUrl()); 113 + return modelFactory.getOrCreateImageModel(platform, apiKey.getApiKey(), apiKey.getUrl());
114 } 114 }
115 115
116 @Override 116 @Override
@@ -120,7 +120,7 @@ public class AiApiKeyServiceImpl implements AiApiKeyService { @@ -120,7 +120,7 @@ public class AiApiKeyServiceImpl implements AiApiKeyService {
120 if (apiKey == null) { 120 if (apiKey == null) {
121 throw exception(API_KEY_MIDJOURNEY_NOT_FOUND); 121 throw exception(API_KEY_MIDJOURNEY_NOT_FOUND);
122 } 122 }
123 - return clientFactory.getOrCreateMidjourneyApi(apiKey.getApiKey(), apiKey.getUrl()); 123 + return modelFactory.getOrCreateMidjourneyApi(apiKey.getApiKey(), apiKey.getUrl());
124 } 124 }
125 125
126 @Override 126 @Override
@@ -130,7 +130,7 @@ public class AiApiKeyServiceImpl implements AiApiKeyService { @@ -130,7 +130,7 @@ public class AiApiKeyServiceImpl implements AiApiKeyService {
130 if (apiKey == null) { 130 if (apiKey == null) {
131 throw exception(API_KEY_SUNO_NOT_FOUND); 131 throw exception(API_KEY_SUNO_NOT_FOUND);
132 } 132 }
133 - return clientFactory.getOrCreateSunoApi(apiKey.getApiKey(), apiKey.getUrl()); 133 + return modelFactory.getOrCreateSunoApi(apiKey.getApiKey(), apiKey.getUrl());
134 } 134 }
135 135
136 } 136 }
137 \ No newline at end of file 137 \ No newline at end of file
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/write/AiWriteServiceImpl.java
@@ -54,7 +54,7 @@ public class AiWriteServiceImpl implements AiWriteService { @@ -54,7 +54,7 @@ public class AiWriteServiceImpl implements AiWriteService {
54 public Flux<CommonResult<String>> generateWriteContent(AiWriteGenerateReqVO generateReqVO, Long userId) { 54 public Flux<CommonResult<String>> generateWriteContent(AiWriteGenerateReqVO generateReqVO, Long userId) {
55 // 1.1 校验模型 TODO 芋艿 是不是取默认的模型也ok?;那可以,有限拿 chatRole 的角色;如果没有,则获取默认的; 55 // 1.1 校验模型 TODO 芋艿 是不是取默认的模型也ok?;那可以,有限拿 chatRole 的角色;如果没有,则获取默认的;
56 AiChatModelDO model = chatModalService.getRequiredDefaultChatModel(); 56 AiChatModelDO model = chatModalService.getRequiredDefaultChatModel();
57 - StreamingChatModel chatClient = apiKeyService.getChatClient(model.getKeyId()); 57 + StreamingChatModel chatModel = apiKeyService.getChatModel(model.getKeyId());
58 AiPlatformEnum platform = AiPlatformEnum.validatePlatform(model.getPlatform()); 58 AiPlatformEnum platform = AiPlatformEnum.validatePlatform(model.getPlatform());
59 59
60 // 1.2 插入写作信息 60 // 1.2 插入写作信息
@@ -65,7 +65,7 @@ public class AiWriteServiceImpl implements AiWriteService { @@ -65,7 +65,7 @@ public class AiWriteServiceImpl implements AiWriteService {
65 // 2.1 构建提示词 65 // 2.1 构建提示词
66 ChatOptions chatOptions = AiUtils.buildChatOptions(platform, model.getModel(), model.getTemperature(), model.getMaxTokens()); 66 ChatOptions chatOptions = AiUtils.buildChatOptions(platform, model.getModel(), model.getTemperature(), model.getMaxTokens());
67 Prompt prompt = new Prompt(buildWritingPrompt(generateReqVO), chatOptions); 67 Prompt prompt = new Prompt(buildWritingPrompt(generateReqVO), chatOptions);
68 - Flux<ChatResponse> streamResponse = chatClient.stream(prompt); 68 + Flux<ChatResponse> streamResponse = chatModel.stream(prompt);
69 69
70 // 2.2 流式返回 70 // 2.2 流式返回
71 StringBuffer contentBuffer = new StringBuffer(); 71 StringBuffer contentBuffer = new StringBuffer();
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java
1 package cn.iocoder.yudao.framework.ai.config; 1 package cn.iocoder.yudao.framework.ai.config;
2 2
3 -import cn.iocoder.yudao.framework.ai.core.factory.AiClientFactory;  
4 -import cn.iocoder.yudao.framework.ai.core.factory.AiClientFactoryImpl; 3 +import cn.iocoder.yudao.framework.ai.core.factory.AiModelFactory;
  4 +import cn.iocoder.yudao.framework.ai.core.factory.AiModelFactoryImpl;
5 import cn.iocoder.yudao.framework.ai.core.model.deepseek.DeepSeekChatClient; 5 import cn.iocoder.yudao.framework.ai.core.model.deepseek.DeepSeekChatClient;
6 import cn.iocoder.yudao.framework.ai.core.model.deepseek.DeepSeekChatOptions; 6 import cn.iocoder.yudao.framework.ai.core.model.deepseek.DeepSeekChatOptions;
7 import cn.iocoder.yudao.framework.ai.core.model.midjourney.api.MidjourneyApi; 7 import cn.iocoder.yudao.framework.ai.core.model.midjourney.api.MidjourneyApi;
@@ -28,8 +28,8 @@ import org.springframework.context.annotation.Import; @@ -28,8 +28,8 @@ import org.springframework.context.annotation.Import;
28 public class YudaoAiAutoConfiguration { 28 public class YudaoAiAutoConfiguration {
29 29
30 @Bean 30 @Bean
31 - public AiClientFactory aiClientFactory() {  
32 - return new AiClientFactoryImpl(); 31 + public AiModelFactory aiModelFactory() {
  32 + return new AiModelFactoryImpl();
33 } 33 }
34 34
35 // ========== 各种 AI Client 创建 ========== 35 // ========== 各种 AI Client 创建 ==========
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactory.java renamed to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiModelFactory.java
@@ -7,11 +7,11 @@ import org.springframework.ai.chat.model.ChatModel; @@ -7,11 +7,11 @@ import org.springframework.ai.chat.model.ChatModel;
7 import org.springframework.ai.image.ImageModel; 7 import org.springframework.ai.image.ImageModel;
8 8
9 /** 9 /**
10 - * AI 客户端工厂的接口类 10 + * AI Model 模型工厂的接口类
11 * 11 *
12 * @author fansili 12 * @author fansili
13 */ 13 */
14 -public interface AiClientFactory { 14 +public interface AiModelFactory {
15 15
16 /** 16 /**
17 * 基于指定配置,获得 ChatModel 对象 17 * 基于指定配置,获得 ChatModel 对象
@@ -33,29 +33,29 @@ public interface AiClientFactory { @@ -33,29 +33,29 @@ public interface AiClientFactory {
33 * @param platform 平台 33 * @param platform 平台
34 * @return ChatModel 对象 34 * @return ChatModel 对象
35 */ 35 */
36 - ChatModel getDefaultChatClient(AiPlatformEnum platform); 36 + ChatModel getDefaultChatModel(AiPlatformEnum platform);
37 37
38 /** 38 /**
39 - * 基于默认配置,获得 ImageClient 对象 39 + * 基于默认配置,获得 ImageModel 对象
40 * 40 *
41 * 默认配置,指的是在 application.yaml 配置文件中的 spring.ai 相关的配置 41 * 默认配置,指的是在 application.yaml 配置文件中的 spring.ai 相关的配置
42 * 42 *
43 * @param platform 平台 43 * @param platform 平台
44 - * @return ImageClient 对象 44 + * @return ImageModel 对象
45 */ 45 */
46 - ImageModel getDefaultImageClient(AiPlatformEnum platform); 46 + ImageModel getDefaultImageModel(AiPlatformEnum platform);
47 47
48 /** 48 /**
49 - * 基于指定配置,获得 ImageClient 对象 49 + * 基于指定配置,获得 ImageModel 对象
50 * 50 *
51 * 如果不存在,则进行创建 51 * 如果不存在,则进行创建
52 * 52 *
53 * @param platform 平台 53 * @param platform 平台
54 * @param apiKey API KEY 54 * @param apiKey API KEY
55 * @param url API URL 55 * @param url API URL
56 - * @return ImageClient 对象 56 + * @return ImageModel 对象
57 */ 57 */
58 - ImageModel getOrCreateImageClient(AiPlatformEnum platform, String apiKey, String url); 58 + ImageModel getOrCreateImageModel(AiPlatformEnum platform, String apiKey, String url);
59 59
60 /** 60 /**
61 * 基于指定配置,获得 MidjourneyApi 对象 61 * 基于指定配置,获得 MidjourneyApi 对象
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiClientFactoryImpl.java renamed to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiModelFactoryImpl.java
@@ -43,11 +43,11 @@ import org.springframework.web.client.RestClient; @@ -43,11 +43,11 @@ import org.springframework.web.client.RestClient;
43 import java.util.List; 43 import java.util.List;
44 44
45 /** 45 /**
46 - * AI 客户端工厂的实现类 46 + * AI Model 模型工厂的实现类
47 * 47 *
48 * @author 芋道源码 48 * @author 芋道源码
49 */ 49 */
50 -public class AiClientFactoryImpl implements AiClientFactory { 50 +public class AiModelFactoryImpl implements AiModelFactory {
51 51
52 @Override 52 @Override
53 public ChatModel getOrCreateChatClient(AiPlatformEnum platform, String apiKey, String url) { 53 public ChatModel getOrCreateChatClient(AiPlatformEnum platform, String apiKey, String url) {
@@ -55,8 +55,6 @@ public class AiClientFactoryImpl implements AiClientFactory { @@ -55,8 +55,6 @@ public class AiClientFactoryImpl implements AiClientFactory {
55 return Singleton.get(cacheKey, (Func0<ChatModel>) () -> { 55 return Singleton.get(cacheKey, (Func0<ChatModel>) () -> {
56 //noinspection EnhancedSwitchMigration 56 //noinspection EnhancedSwitchMigration
57 switch (platform) { 57 switch (platform) {
58 - case OPENAI:  
59 - return buildOpenAiChatClient(apiKey, url);  
60 case OLLAMA: 58 case OLLAMA:
61 return buildOllamaChatClient(url); 59 return buildOllamaChatClient(url);
62 case YI_YAN: 60 case YI_YAN:
@@ -67,6 +65,8 @@ public class AiClientFactoryImpl implements AiClientFactory { @@ -67,6 +65,8 @@ public class AiClientFactoryImpl implements AiClientFactory {
67 return buildQianWenChatClient(apiKey); 65 return buildQianWenChatClient(apiKey);
68 case DEEP_SEEK: 66 case DEEP_SEEK:
69 return buildDeepSeekChatClient(apiKey); 67 return buildDeepSeekChatClient(apiKey);
  68 + case OPENAI:
  69 + return buildOpenAiChatModel(apiKey, url);
70 default: 70 default:
71 throw new IllegalArgumentException(StrUtil.format("未知平台({})", platform)); 71 throw new IllegalArgumentException(StrUtil.format("未知平台({})", platform));
72 } 72 }
@@ -74,11 +74,9 @@ public class AiClientFactoryImpl implements AiClientFactory { @@ -74,11 +74,9 @@ public class AiClientFactoryImpl implements AiClientFactory {
74 } 74 }
75 75
76 @Override 76 @Override
77 - public ChatModel getDefaultChatClient(AiPlatformEnum platform) { 77 + public ChatModel getDefaultChatModel(AiPlatformEnum platform) {
78 //noinspection EnhancedSwitchMigration 78 //noinspection EnhancedSwitchMigration
79 switch (platform) { 79 switch (platform) {
80 - case OPENAI:  
81 - return SpringUtil.getBean(OpenAiChatModel.class);  
82 case OLLAMA: 80 case OLLAMA:
83 return SpringUtil.getBean(OllamaChatModel.class); 81 return SpringUtil.getBean(OllamaChatModel.class);
84 case YI_YAN: 82 case YI_YAN:
@@ -87,13 +85,15 @@ public class AiClientFactoryImpl implements AiClientFactory { @@ -87,13 +85,15 @@ public class AiClientFactoryImpl implements AiClientFactory {
87 return SpringUtil.getBean(XingHuoChatClient.class); 85 return SpringUtil.getBean(XingHuoChatClient.class);
88 case QIAN_WEN: 86 case QIAN_WEN:
89 return SpringUtil.getBean(TongYiChatModel.class); 87 return SpringUtil.getBean(TongYiChatModel.class);
  88 + case OPENAI:
  89 + return SpringUtil.getBean(OpenAiChatModel.class);
90 default: 90 default:
91 throw new IllegalArgumentException(StrUtil.format("未知平台({})", platform)); 91 throw new IllegalArgumentException(StrUtil.format("未知平台({})", platform));
92 } 92 }
93 } 93 }
94 94
95 @Override 95 @Override
96 - public ImageModel getDefaultImageClient(AiPlatformEnum platform) { 96 + public ImageModel getDefaultImageModel(AiPlatformEnum platform) {
97 //noinspection EnhancedSwitchMigration 97 //noinspection EnhancedSwitchMigration
98 switch (platform) { 98 switch (platform) {
99 case OPENAI: 99 case OPENAI:
@@ -106,11 +106,11 @@ public class AiClientFactoryImpl implements AiClientFactory { @@ -106,11 +106,11 @@ public class AiClientFactoryImpl implements AiClientFactory {
106 } 106 }
107 107
108 @Override 108 @Override
109 - public ImageModel getOrCreateImageClient(AiPlatformEnum platform, String apiKey, String url) { 109 + public ImageModel getOrCreateImageModel(AiPlatformEnum platform, String apiKey, String url) {
110 //noinspection EnhancedSwitchMigration 110 //noinspection EnhancedSwitchMigration
111 switch (platform) { 111 switch (platform) {
112 case OPENAI: 112 case OPENAI:
113 - return buildOpenAiImageClient(apiKey, url); 113 + return buildOpenAiImageModel(apiKey, url);
114 case STABLE_DIFFUSION: 114 case STABLE_DIFFUSION:
115 return buildStabilityAiImageClient(apiKey, url); 115 return buildStabilityAiImageClient(apiKey, url);
116 default: 116 default:
@@ -145,13 +145,22 @@ public class AiClientFactoryImpl implements AiClientFactory { @@ -145,13 +145,22 @@ public class AiClientFactoryImpl implements AiClientFactory {
145 /** 145 /**
146 * 可参考 {@link OpenAiAutoConfiguration} 146 * 可参考 {@link OpenAiAutoConfiguration}
147 */ 147 */
148 - private static OpenAiChatModel buildOpenAiChatClient(String openAiToken, String url) { 148 + private static OpenAiChatModel buildOpenAiChatModel(String openAiToken, String url) {
149 url = StrUtil.blankToDefault(url, ApiUtils.DEFAULT_BASE_URL); 149 url = StrUtil.blankToDefault(url, ApiUtils.DEFAULT_BASE_URL);
150 OpenAiApi openAiApi = new OpenAiApi(url, openAiToken); 150 OpenAiApi openAiApi = new OpenAiApi(url, openAiToken);
151 return new OpenAiChatModel(openAiApi); 151 return new OpenAiChatModel(openAiApi);
152 } 152 }
153 153
154 /** 154 /**
  155 + * 可参考 {@link OpenAiAutoConfiguration}
  156 + */
  157 + private OpenAiImageModel buildOpenAiImageModel(String openAiToken, String url) {
  158 + url = StrUtil.blankToDefault(url, ApiUtils.DEFAULT_BASE_URL);
  159 + OpenAiImageApi openAiApi = new OpenAiImageApi(url, openAiToken, RestClient.builder());
  160 + return new OpenAiImageModel(openAiApi);
  161 + }
  162 +
  163 + /**
155 * 可参考 {@link OllamaAutoConfiguration} 164 * 可参考 {@link OllamaAutoConfiguration}
156 */ 165 */
157 private static OllamaChatModel buildOllamaChatClient(String url) { 166 private static OllamaChatModel buildOllamaChatClient(String url) {
@@ -200,12 +209,6 @@ public class AiClientFactoryImpl implements AiClientFactory { @@ -200,12 +209,6 @@ public class AiClientFactoryImpl implements AiClientFactory {
200 return new TongYiAutoConfiguration().tongYiChatClient(generation, chatOptions, connectionProperties); 209 return new TongYiAutoConfiguration().tongYiChatClient(generation, chatOptions, connectionProperties);
201 } 210 }
202 211
203 - private OpenAiImageModel buildOpenAiImageClient(String openAiToken, String url) {  
204 - url = StrUtil.blankToDefault(url, ApiUtils.DEFAULT_BASE_URL);  
205 - OpenAiImageApi openAiApi = new OpenAiImageApi(url, openAiToken, RestClient.builder());  
206 - return new OpenAiImageModel(openAiApi);  
207 - }  
208 -  
209 private StabilityAiImageModel buildStabilityAiImageClient(String apiKey, String url) { 212 private StabilityAiImageModel buildStabilityAiImageClient(String apiKey, String url) {
210 url = StrUtil.blankToDefault(url, StabilityAiApi.DEFAULT_BASE_URL); 213 url = StrUtil.blankToDefault(url, StabilityAiApi.DEFAULT_BASE_URL);
211 StabilityAiApi stabilityAiApi = new StabilityAiApi(apiKey, StabilityAiApi.DEFAULT_IMAGE_MODEL, url); 214 StabilityAiApi stabilityAiApi = new StabilityAiApi(apiKey, StabilityAiApi.DEFAULT_IMAGE_MODEL, url);