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,6 +36,8 @@ public class QianWenChatClient implements ChatClient, StreamingChatClient { | ||
| 36 | 36 | ||
| 37 | private QianWenOptions qianWenOptions; | 37 | private QianWenOptions qianWenOptions; |
| 38 | 38 | ||
| 39 | + | ||
| 40 | + public QianWenChatClient() {} | ||
| 39 | public QianWenChatClient(QianWenApi qianWenApi) { | 41 | public QianWenChatClient(QianWenApi qianWenApi) { |
| 40 | this.qianWenApi = qianWenApi; | 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,7 +14,6 @@ import cn.iocoder.yudao.framework.ai.chatyiyan.api.YiYanApi; | ||
| 14 | import cn.iocoder.yudao.framework.ai.exception.AiException; | 14 | import cn.iocoder.yudao.framework.ai.exception.AiException; |
| 15 | import org.springframework.beans.BeansException; | 15 | import org.springframework.beans.BeansException; |
| 16 | import org.springframework.beans.factory.InitializingBean; | 16 | import org.springframework.beans.factory.InitializingBean; |
| 17 | -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; | ||
| 18 | import org.springframework.boot.autoconfigure.AutoConfiguration; | 17 | import org.springframework.boot.autoconfigure.AutoConfiguration; |
| 19 | import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; | 18 | import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; |
| 20 | import org.springframework.boot.context.properties.EnableConfigurationProperties; | 19 | import org.springframework.boot.context.properties.EnableConfigurationProperties; |
| @@ -23,6 +22,7 @@ import org.springframework.context.ApplicationContextAware; | @@ -23,6 +22,7 @@ import org.springframework.context.ApplicationContextAware; | ||
| 23 | import org.springframework.context.annotation.Bean; | 22 | import org.springframework.context.annotation.Bean; |
| 24 | import org.springframework.context.support.GenericApplicationContext; | 23 | import org.springframework.context.support.GenericApplicationContext; |
| 25 | 24 | ||
| 25 | +import java.util.HashMap; | ||
| 26 | import java.util.Map; | 26 | import java.util.Map; |
| 27 | 27 | ||
| 28 | /** | 28 | /** |
| @@ -36,11 +36,33 @@ import java.util.Map; | @@ -36,11 +36,33 @@ import java.util.Map; | ||
| 36 | @EnableConfigurationProperties(YudaoAiProperties.class) | 36 | @EnableConfigurationProperties(YudaoAiProperties.class) |
| 37 | public class YudaoAiAutoConfiguration { | 37 | public class YudaoAiAutoConfiguration { |
| 38 | 38 | ||
| 39 | - // TODO @芋艿:我看sharding jdbc 差不多这么玩的 | ||
| 40 | @Bean | 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 | public static class InitChatClient implements InitializingBean, ApplicationContextAware { | 68 | public static class InitChatClient implements InitializingBean, ApplicationContextAware { |
| @@ -53,26 +75,8 @@ public class YudaoAiAutoConfiguration { | @@ -53,26 +75,8 @@ public class YudaoAiAutoConfiguration { | ||
| 53 | } | 75 | } |
| 54 | 76 | ||
| 55 | @Override | 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 | System.err.println(applicationContext.getBean("qianWen")); | 81 | System.err.println(applicationContext.getBean("qianWen")); |
| 78 | System.err.println(applicationContext.getBean("yiYan")); | 82 | System.err.println(applicationContext.getBean("yiYan")); |
| @@ -84,53 +88,41 @@ public class YudaoAiAutoConfiguration { | @@ -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 | if (AiPlatformEnum.XING_HUO == chatProperties.getAiPlatform()) { | 92 | if (AiPlatformEnum.XING_HUO == chatProperties.getAiPlatform()) { |
| 91 | YudaoAiProperties.XingHuoProperties xingHuoProperties = (YudaoAiProperties.XingHuoProperties) chatProperties; | 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 | } else if (AiPlatformEnum.QIAN_WEN == chatProperties.getAiPlatform()) { | 102 | } else if (AiPlatformEnum.QIAN_WEN == chatProperties.getAiPlatform()) { |
| 104 | YudaoAiProperties.QianWenProperties qianWenProperties = (YudaoAiProperties.QianWenProperties) chatProperties; | 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 | } else if (AiPlatformEnum.YI_YAN == chatProperties.getAiPlatform()) { | 114 | } else if (AiPlatformEnum.YI_YAN == chatProperties.getAiPlatform()) { |
| 118 | YudaoAiProperties.YiYanProperties yiYanProperties = (YudaoAiProperties.YiYanProperties) chatProperties; | 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 | +} |