Commit 97df2755f985fa7d9d92613a3236e4933d0480ad
1 parent
652a8f96
增加yudao ai client
Showing
4 changed files
with
117 additions
and
60 deletions
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/chatqianwen/QianWenChatClient.java
| ... | ... | @@ -36,6 +36,8 @@ public class QianWenChatClient implements ChatClient, StreamingChatClient { |
| 36 | 36 | |
| 37 | 37 | private QianWenOptions qianWenOptions; |
| 38 | 38 | |
| 39 | + | |
| 40 | + public QianWenChatClient() {} | |
| 39 | 41 | public QianWenChatClient(QianWenApi qianWenApi) { |
| 40 | 42 | this.qianWenApi = qianWenApi; |
| 41 | 43 | } | ... | ... |
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/AiClient.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.ai.config; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.framework.ai.chat.ChatResponse; | |
| 4 | +import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt; | |
| 5 | +import reactor.core.publisher.Flux; | |
| 6 | + | |
| 7 | +/** | |
| 8 | + * ai client传入 | |
| 9 | + * | |
| 10 | + * @author fansili | |
| 11 | + * @time 2024/4/14 10:27 | |
| 12 | + * @since 1.0 | |
| 13 | + */ | |
| 14 | +public interface AiClient { | |
| 15 | + | |
| 16 | + ChatResponse call(Prompt prompt, String clientName); | |
| 17 | + | |
| 18 | + Flux<ChatResponse> stream(Prompt prompt, String clientName); | |
| 19 | +} | ... | ... |
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java
| ... | ... | @@ -14,7 +14,6 @@ import cn.iocoder.yudao.framework.ai.chatyiyan.api.YiYanApi; |
| 14 | 14 | import cn.iocoder.yudao.framework.ai.exception.AiException; |
| 15 | 15 | import org.springframework.beans.BeansException; |
| 16 | 16 | import org.springframework.beans.factory.InitializingBean; |
| 17 | -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; | |
| 18 | 17 | import org.springframework.boot.autoconfigure.AutoConfiguration; |
| 19 | 18 | import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; |
| 20 | 19 | import org.springframework.boot.context.properties.EnableConfigurationProperties; |
| ... | ... | @@ -23,6 +22,7 @@ import org.springframework.context.ApplicationContextAware; |
| 23 | 22 | import org.springframework.context.annotation.Bean; |
| 24 | 23 | import org.springframework.context.support.GenericApplicationContext; |
| 25 | 24 | |
| 25 | +import java.util.HashMap; | |
| 26 | 26 | import java.util.Map; |
| 27 | 27 | |
| 28 | 28 | /** |
| ... | ... | @@ -36,11 +36,33 @@ import java.util.Map; |
| 36 | 36 | @EnableConfigurationProperties(YudaoAiProperties.class) |
| 37 | 37 | public class YudaoAiAutoConfiguration { |
| 38 | 38 | |
| 39 | - // TODO @芋艿:我看sharding jdbc 差不多这么玩的 | |
| 40 | 39 | @Bean |
| 41 | - @ConditionalOnMissingBean(value = InitChatClient.class) | |
| 42 | - public InitChatClient initChatClient(YudaoAiProperties yudaoAiProperties) { | |
| 43 | - return new InitChatClient(yudaoAiProperties); | |
| 40 | + @ConditionalOnMissingBean(value = AiClient.class) | |
| 41 | + public AiClient aiClient(YudaoAiProperties yudaoAiProperties) { | |
| 42 | + Map<String, Object> chatClientMap = buildChatClientMap(yudaoAiProperties); | |
| 43 | + return new YudaoAiClient(chatClientMap); | |
| 44 | + } | |
| 45 | + | |
| 46 | + public Map<String, Object> buildChatClientMap(YudaoAiProperties yudaoAiProperties) { | |
| 47 | + Map<String, Object> chatMap = new HashMap<>(); | |
| 48 | + for (Map.Entry<String, Map<String, Object>> properties : yudaoAiProperties.entrySet()) { | |
| 49 | + String beanName = properties.getKey(); | |
| 50 | + Map<String, Object> aiPlatformMap = properties.getValue(); | |
| 51 | + | |
| 52 | + // 检查平台类型是否正确 | |
| 53 | + String aiPlatform = String.valueOf(aiPlatformMap.get("aiPlatform")); | |
| 54 | + if (!AiPlatformEnum.mapValues.containsKey(aiPlatform)) { | |
| 55 | + throw new AiException("AI平台名称错误! 可以参考 AiPlatformEnum 类!"); | |
| 56 | + } | |
| 57 | + // 获取平台类型 | |
| 58 | + AiPlatformEnum aiPlatformEnum = AiPlatformEnum.mapValues.get(aiPlatform); | |
| 59 | + // 获取 chat properties | |
| 60 | + YudaoAiProperties.ChatProperties chatProperties = getChatProperties(aiPlatformEnum, aiPlatformMap); | |
| 61 | + // 创建客户端 | |
| 62 | + Object chatClient = createChatClient(chatProperties); | |
| 63 | + chatMap.put(beanName, chatClient); | |
| 64 | + } | |
| 65 | + return chatMap; | |
| 44 | 66 | } |
| 45 | 67 | |
| 46 | 68 | public static class InitChatClient implements InitializingBean, ApplicationContextAware { |
| ... | ... | @@ -53,26 +75,8 @@ public class YudaoAiAutoConfiguration { |
| 53 | 75 | } |
| 54 | 76 | |
| 55 | 77 | @Override |
| 56 | - public void afterPropertiesSet() throws Exception { | |
| 57 | - for (Map.Entry<String, Map<String, Object>> properties : yudaoAiProperties.entrySet()) { | |
| 58 | - String beanName = properties.getKey(); | |
| 59 | - Map<String, Object> aiPlatformMap = properties.getValue(); | |
| 60 | - | |
| 61 | - // 检查平台类型是否正确 | |
| 62 | - String aiPlatform = String.valueOf(aiPlatformMap.get("aiPlatform")); | |
| 63 | - if (!AiPlatformEnum.mapValues.containsKey(aiPlatform)) { | |
| 64 | - throw new AiException("AI平台名称错误! 可以参考 AiPlatformEnum 类!"); | |
| 65 | - } | |
| 66 | - // 获取平台类型 | |
| 67 | - AiPlatformEnum aiPlatformEnum = AiPlatformEnum.mapValues.get(aiPlatform); | |
| 68 | - // 获取 chat properties | |
| 69 | - YudaoAiProperties.ChatProperties chatProperties = getChatProperties(aiPlatformEnum, aiPlatformMap); | |
| 70 | - // 创建客户端 | |
| 71 | - registerChatClient(applicationContext, chatProperties, beanName); | |
| 72 | -// applicationContext.refresh(); | |
| 73 | - | |
| 78 | + public void afterPropertiesSet() { | |
| 74 | 79 | |
| 75 | - } | |
| 76 | 80 | |
| 77 | 81 | System.err.println(applicationContext.getBean("qianWen")); |
| 78 | 82 | System.err.println(applicationContext.getBean("yiYan")); |
| ... | ... | @@ -84,53 +88,41 @@ public class YudaoAiAutoConfiguration { |
| 84 | 88 | } |
| 85 | 89 | } |
| 86 | 90 | |
| 87 | - private static void registerChatClient(GenericApplicationContext applicationContext, YudaoAiProperties.ChatProperties chatProperties, String beanName) { | |
| 88 | - ConfigurableListableBeanFactory beanFactory = applicationContext.getBeanFactory(); | |
| 89 | - Object wrapperBean = null; | |
| 91 | + private static Object createChatClient(YudaoAiProperties.ChatProperties chatProperties) { | |
| 90 | 92 | if (AiPlatformEnum.XING_HUO == chatProperties.getAiPlatform()) { |
| 91 | 93 | YudaoAiProperties.XingHuoProperties xingHuoProperties = (YudaoAiProperties.XingHuoProperties) chatProperties; |
| 92 | - wrapperBean = beanFactory.initializeBean( | |
| 93 | - new XingHuoChatClient( | |
| 94 | - new XingHuoApi( | |
| 95 | - xingHuoProperties.getAppId(), | |
| 96 | - xingHuoProperties.getAppKey(), | |
| 97 | - xingHuoProperties.getSecretKey() | |
| 98 | - ), | |
| 99 | - new XingHuoOptions().setChatModel(xingHuoProperties.getChatModel()) | |
| 94 | + return new XingHuoChatClient( | |
| 95 | + new XingHuoApi( | |
| 96 | + xingHuoProperties.getAppId(), | |
| 97 | + xingHuoProperties.getAppKey(), | |
| 98 | + xingHuoProperties.getSecretKey() | |
| 100 | 99 | ), |
| 101 | - beanName | |
| 100 | + new XingHuoOptions().setChatModel(xingHuoProperties.getChatModel()) | |
| 102 | 101 | ); |
| 103 | 102 | } else if (AiPlatformEnum.QIAN_WEN == chatProperties.getAiPlatform()) { |
| 104 | 103 | YudaoAiProperties.QianWenProperties qianWenProperties = (YudaoAiProperties.QianWenProperties) chatProperties; |
| 105 | - wrapperBean = beanFactory.initializeBean(new QianWenChatClient( | |
| 106 | - new QianWenApi( | |
| 107 | - qianWenProperties.getAccessKeyId(), | |
| 108 | - qianWenProperties.getAccessKeySecret(), | |
| 109 | - qianWenProperties.getAgentKey(), | |
| 110 | - qianWenProperties.getEndpoint() | |
| 111 | - ), | |
| 112 | - new QianWenOptions() | |
| 113 | - .setAppId(qianWenProperties.getAppId()) | |
| 104 | + return new QianWenChatClient( | |
| 105 | + new QianWenApi( | |
| 106 | + qianWenProperties.getAccessKeyId(), | |
| 107 | + qianWenProperties.getAccessKeySecret(), | |
| 108 | + qianWenProperties.getAgentKey(), | |
| 109 | + qianWenProperties.getEndpoint() | |
| 114 | 110 | ), |
| 115 | - beanName | |
| 111 | + new QianWenOptions() | |
| 112 | + .setAppId(qianWenProperties.getAppId()) | |
| 116 | 113 | ); |
| 117 | 114 | } else if (AiPlatformEnum.YI_YAN == chatProperties.getAiPlatform()) { |
| 118 | 115 | YudaoAiProperties.YiYanProperties yiYanProperties = (YudaoAiProperties.YiYanProperties) chatProperties; |
| 119 | - | |
| 120 | - wrapperBean = beanFactory.initializeBean(new YiYanChatClient( | |
| 121 | - new YiYanApi( | |
| 122 | - yiYanProperties.getAppKey(), | |
| 123 | - yiYanProperties.getSecretKey(), | |
| 124 | - yiYanProperties.getChatModel(), | |
| 125 | - yiYanProperties.getRefreshTokenSecondTime() | |
| 126 | - ), | |
| 127 | - new YiYanOptions().setMax_output_tokens(2048)), | |
| 128 | - beanName | |
| 129 | - ); | |
| 130 | - } | |
| 131 | - if (wrapperBean != null) { | |
| 132 | - beanFactory.registerSingleton(beanName, wrapperBean); | |
| 116 | + return new YiYanChatClient( | |
| 117 | + new YiYanApi( | |
| 118 | + yiYanProperties.getAppKey(), | |
| 119 | + yiYanProperties.getSecretKey(), | |
| 120 | + yiYanProperties.getChatModel(), | |
| 121 | + yiYanProperties.getRefreshTokenSecondTime() | |
| 122 | + ), | |
| 123 | + new YiYanOptions().setMax_output_tokens(2048)); | |
| 133 | 124 | } |
| 125 | + throw new AiException("不支持的Ai类型!"); | |
| 134 | 126 | } |
| 135 | 127 | |
| 136 | 128 | ... | ... |
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiClient.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.ai.config; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.framework.ai.chat.ChatClient; | |
| 4 | +import cn.iocoder.yudao.framework.ai.chat.ChatResponse; | |
| 5 | +import cn.iocoder.yudao.framework.ai.chat.StreamingChatClient; | |
| 6 | +import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt; | |
| 7 | +import cn.iocoder.yudao.framework.ai.exception.AiException; | |
| 8 | +import reactor.core.publisher.Flux; | |
| 9 | + | |
| 10 | +import java.util.Map; | |
| 11 | + | |
| 12 | +/** | |
| 13 | + * yudao ai client | |
| 14 | + * | |
| 15 | + * @author fansili | |
| 16 | + * @time 2024/4/14 10:27 | |
| 17 | + * @since 1.0 | |
| 18 | + */ | |
| 19 | +public class YudaoAiClient implements AiClient{ | |
| 20 | + | |
| 21 | + protected Map<String, Object> chatClientMap; | |
| 22 | + | |
| 23 | + public YudaoAiClient(Map<String, Object> chatClientMap) { | |
| 24 | + this.chatClientMap = chatClientMap; | |
| 25 | + } | |
| 26 | + | |
| 27 | + @Override | |
| 28 | + public ChatResponse call(Prompt prompt, String clientName) { | |
| 29 | + if (!chatClientMap.containsKey(clientName)) { | |
| 30 | + throw new AiException("clientName不存在!"); | |
| 31 | + } | |
| 32 | + ChatClient chatClient = (ChatClient) chatClientMap.get(clientName); | |
| 33 | + return chatClient.call(prompt); | |
| 34 | + } | |
| 35 | + | |
| 36 | + @Override | |
| 37 | + public Flux<ChatResponse> stream(Prompt prompt, String clientName) { | |
| 38 | + if (!chatClientMap.containsKey(clientName)) { | |
| 39 | + throw new AiException("clientName不存在!"); | |
| 40 | + } | |
| 41 | + StreamingChatClient streamingChatClient = (StreamingChatClient) chatClientMap.get(clientName); | |
| 42 | + return streamingChatClient.stream(prompt); | |
| 43 | + } | |
| 44 | +} | ... | ... |