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