Commit 97df2755f985fa7d9d92613a3236e4933d0480ad

Authored by cherishsince
1 parent 652a8f96

增加yudao ai client

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 +}