Commit 2adb5accc4e132059d3c06c0d6bbd183a19e5bcc

Authored by cherishsince
1 parent 44f7c841

【优化】ai chat client自动配置和初始化。

yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiClientNameEnum.java deleted
1 -package cn.iocoder.yudao.module.ai.enums;  
2 -  
3 -import lombok.AllArgsConstructor;  
4 -import lombok.Getter;  
5 -  
6 -/**  
7 - * ai client 名字  
8 - *  
9 - * 这个需要根据配置文件起的来决定  
10 - *  
11 - * @author fansili  
12 - * @time 2024/4/14 16:02  
13 - * @since 1.0  
14 - */  
15 -@AllArgsConstructor  
16 -@Getter  
17 -public enum AiClientNameEnum {  
18 -  
19 - QIAN_WEN("qianWen", "千问模型!"),  
20 - YI_YAN_3_5_8K("yiYan3_5_8k", "文心一言(3.5-8k)"),  
21 - XING_HUO("xingHuo", "星火模型!"),  
22 -  
23 - ;  
24 -  
25 - private String name;  
26 -  
27 - private String message;  
28 -  
29 - public static AiClientNameEnum valueOfName(String name) {  
30 - for (AiClientNameEnum nameEnum : AiClientNameEnum.values()) {  
31 - if (nameEnum.getName().equals(name)) {  
32 - return nameEnum;  
33 - }  
34 - }  
35 - throw new IllegalArgumentException("Invalid MessageType value: " + name);  
36 - }  
37 -}  
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/config/AiChatClientFactory.java 0 → 100644
  1 +package cn.iocoder.yudao.module.ai.config;
  2 +
  3 +import cn.iocoder.yudao.framework.ai.AiPlatformEnum;
  4 +import cn.iocoder.yudao.framework.ai.chat.ChatClient;
  5 +import cn.iocoder.yudao.framework.ai.chat.StreamingChatClient;
  6 +import cn.iocoder.yudao.framework.ai.chatqianwen.QianWenChatClient;
  7 +import cn.iocoder.yudao.framework.ai.chatxinghuo.XingHuoChatClient;
  8 +import cn.iocoder.yudao.framework.ai.chatyiyan.YiYanChatClient;
  9 +import org.springframework.beans.factory.annotation.Autowired;
  10 +import org.springframework.context.ApplicationContext;
  11 +import org.springframework.stereotype.Component;
  12 +
  13 +/**
  14 + * factory
  15 + *
  16 + * @author fansili
  17 + * @time 2024/4/25 17:36
  18 + * @since 1.0
  19 + */
  20 +@Component
  21 +public class AiChatClientFactory {
  22 +
  23 + @Autowired
  24 + private ApplicationContext applicationContext;
  25 +
  26 + public ChatClient getChatClient(AiPlatformEnum platformEnum) {
  27 + if (AiPlatformEnum.QIAN_WEN == platformEnum) {
  28 + return applicationContext.getBean(QianWenChatClient.class);
  29 + } else if (AiPlatformEnum.YI_YAN == platformEnum) {
  30 + return applicationContext.getBean(YiYanChatClient.class);
  31 + } else if (AiPlatformEnum.XING_HUO == platformEnum) {
  32 + return applicationContext.getBean(XingHuoChatClient.class);
  33 + }
  34 + throw new IllegalArgumentException("不支持的 chat client!");
  35 + }
  36 +
  37 + // TODO yunai 要不再加一个接口,让他们拥有 ChatClient、StreamingChatClient 功能
  38 + public StreamingChatClient getStreamingChatClient(AiPlatformEnum platformEnum) {
  39 + if (AiPlatformEnum.QIAN_WEN == platformEnum) {
  40 + return applicationContext.getBean(QianWenChatClient.class);
  41 + } else if (AiPlatformEnum.YI_YAN == platformEnum) {
  42 + return applicationContext.getBean(YiYanChatClient.class);
  43 + } else if (AiPlatformEnum.XING_HUO == platformEnum) {
  44 + return applicationContext.getBean(XingHuoChatClient.class);
  45 + }
  46 + throw new IllegalArgumentException("不支持的 chat client!");
  47 + }
  48 +}
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java
1 package cn.iocoder.yudao.module.ai.service.impl; 1 package cn.iocoder.yudao.module.ai.service.impl;
2 2
3 import cn.hutool.core.exceptions.ExceptionUtil; 3 import cn.hutool.core.exceptions.ExceptionUtil;
  4 +import cn.iocoder.yudao.framework.ai.AiPlatformEnum;
  5 +import cn.iocoder.yudao.framework.ai.chat.ChatClient;
4 import cn.iocoder.yudao.framework.ai.chat.ChatResponse; 6 import cn.iocoder.yudao.framework.ai.chat.ChatResponse;
  7 +import cn.iocoder.yudao.framework.ai.chat.StreamingChatClient;
5 import cn.iocoder.yudao.framework.ai.chat.messages.MessageType; 8 import cn.iocoder.yudao.framework.ai.chat.messages.MessageType;
6 import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt; 9 import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt;
7 -import cn.iocoder.yudao.framework.ai.config.AiClient;  
8 import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; 10 import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
  11 +import cn.iocoder.yudao.module.ai.config.AiChatClientFactory;
9 import cn.iocoder.yudao.module.ai.controller.Utf8SseEmitter; 12 import cn.iocoder.yudao.module.ai.controller.Utf8SseEmitter;
10 import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatMessageDO; 13 import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatMessageDO;
11 -import cn.iocoder.yudao.module.ai.enums.AiClientNameEnum;  
12 import cn.iocoder.yudao.module.ai.mapper.AiChatConversationMapper; 14 import cn.iocoder.yudao.module.ai.mapper.AiChatConversationMapper;
13 import cn.iocoder.yudao.module.ai.mapper.AiChatMessageMapper; 15 import cn.iocoder.yudao.module.ai.mapper.AiChatMessageMapper;
14 import cn.iocoder.yudao.module.ai.mapper.AiChatRoleMapper; 16 import cn.iocoder.yudao.module.ai.mapper.AiChatRoleMapper;
@@ -38,7 +40,7 @@ import java.util.function.Consumer; @@ -38,7 +40,7 @@ import java.util.function.Consumer;
38 @AllArgsConstructor 40 @AllArgsConstructor
39 public class AiChatServiceImpl implements AiChatService { 41 public class AiChatServiceImpl implements AiChatService {
40 42
41 - private final AiClient aiClient; 43 + private final AiChatClientFactory aiChatClientFactory;
42 private final AiChatRoleMapper aiChatRoleMapper; 44 private final AiChatRoleMapper aiChatRoleMapper;
43 private final AiChatMessageMapper aiChatMessageMapper; 45 private final AiChatMessageMapper aiChatMessageMapper;
44 private final AiChatConversationMapper aiChatConversationMapper; 46 private final AiChatConversationMapper aiChatConversationMapper;
@@ -54,7 +56,7 @@ public class AiChatServiceImpl implements AiChatService { @@ -54,7 +56,7 @@ public class AiChatServiceImpl implements AiChatService {
54 public String chat(AiChatReq req) { 56 public String chat(AiChatReq req) {
55 Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); 57 Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
56 // 获取 client 类型 58 // 获取 client 类型
57 - AiClientNameEnum clientNameEnum = AiClientNameEnum.valueOfName(req.getModal()); 59 + AiPlatformEnum platformEnum = AiPlatformEnum.valueOfPlatform(req.getModal());
58 // 获取对话信息 60 // 获取对话信息
59 AiChatConversationRes conversationRes = chatConversationService.getConversation(req.getConversationId()); 61 AiChatConversationRes conversationRes = chatConversationService.getConversation(req.getConversationId());
60 // 保存 chat message 62 // 保存 chat message
@@ -67,7 +69,8 @@ public class AiChatServiceImpl implements AiChatService { @@ -67,7 +69,8 @@ public class AiChatServiceImpl implements AiChatService {
67 req.setTopP(req.getTopP()); 69 req.setTopP(req.getTopP());
68 req.setTemperature(req.getTemperature()); 70 req.setTemperature(req.getTemperature());
69 // 发送 call 调用 71 // 发送 call 调用
70 - ChatResponse call = aiClient.call(prompt, clientNameEnum.getName()); 72 + ChatClient chatClient = aiChatClientFactory.getChatClient(platformEnum);
  73 + ChatResponse call = chatClient.call(prompt);
71 content = call.getResult().getOutput().getContent(); 74 content = call.getResult().getOutput().getContent();
72 // 更新 conversation 75 // 更新 conversation
73 76
@@ -128,7 +131,7 @@ public class AiChatServiceImpl implements AiChatService { @@ -128,7 +131,7 @@ public class AiChatServiceImpl implements AiChatService {
128 public void chatStream(AiChatReq req, Utf8SseEmitter sseEmitter) { 131 public void chatStream(AiChatReq req, Utf8SseEmitter sseEmitter) {
129 Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); 132 Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
130 // 获取 client 类型 133 // 获取 client 类型
131 - AiClientNameEnum clientNameEnum = AiClientNameEnum.valueOfName(req.getModal()); 134 + AiPlatformEnum platformEnum = AiPlatformEnum.valueOfPlatform(req.getModal());
132 // 获取对话信息 135 // 获取对话信息
133 AiChatConversationRes conversationRes = chatConversationService.getConversation(req.getConversationId()); 136 AiChatConversationRes conversationRes = chatConversationService.getConversation(req.getConversationId());
134 // 创建 chat 需要的 Prompt 137 // 创建 chat 需要的 Prompt
@@ -138,7 +141,8 @@ public class AiChatServiceImpl implements AiChatService { @@ -138,7 +141,8 @@ public class AiChatServiceImpl implements AiChatService {
138 req.setTemperature(req.getTemperature()); 141 req.setTemperature(req.getTemperature());
139 // 保存 chat message 142 // 保存 chat message
140 saveChatMessage(req, conversationRes, loginUserId); 143 saveChatMessage(req, conversationRes, loginUserId);
141 - Flux<ChatResponse> streamResponse = aiClient.stream(prompt, clientNameEnum.getName()); 144 + StreamingChatClient streamingChatClient = aiChatClientFactory.getStreamingChatClient(platformEnum);
  145 + Flux<ChatResponse> streamResponse = streamingChatClient.stream(prompt);
142 146
143 StringBuffer contentBuffer = new StringBuffer(); 147 StringBuffer contentBuffer = new StringBuffer();
144 streamResponse.subscribe( 148 streamResponse.subscribe(
yudao-module-ai/yudao-module-ai-biz/src/main/resources/http/chat.http
@@ -16,7 +16,7 @@ tenant-id: 1 @@ -16,7 +16,7 @@ tenant-id: 1
16 } 16 }
17 17
18 ### chat call 18 ### chat call
19 -GET {{baseUrl}}/ai/chat?modal=qianWen&conversationId=1781604279872581644&prompt=中国好看吗? 19 +GET {{baseUrl}}/ai/chat?modal=qianwen&conversationId=1781604279872581644&prompt=中国好看吗?
20 Authorization: {{token}} 20 Authorization: {{token}}
21 21
22 22
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/AiPlatformEnum.java
@@ -3,10 +3,6 @@ package cn.iocoder.yudao.framework.ai; @@ -3,10 +3,6 @@ package cn.iocoder.yudao.framework.ai;
3 import lombok.AllArgsConstructor; 3 import lombok.AllArgsConstructor;
4 import lombok.Getter; 4 import lombok.Getter;
5 5
6 -import java.util.Arrays;  
7 -import java.util.Map;  
8 -import java.util.stream.Collectors;  
9 -  
10 /** 6 /**
11 * 讯飞星火 模型 7 * 讯飞星火 模型
12 * 8 *
@@ -24,15 +20,22 @@ import java.util.stream.Collectors; @@ -24,15 +20,22 @@ import java.util.stream.Collectors;
24 public enum AiPlatformEnum { 20 public enum AiPlatformEnum {
25 21
26 22
27 - YI_YAN("yiyan"),  
28 - QIAN_WEN("qianwen"),  
29 - XING_HUO("xinghuo"), 23 + YI_YAN("yiyan", "一言"),
  24 + QIAN_WEN("qianwen", "千问"),
  25 + XING_HUO("xinghuo", "星火"),
30 26
31 ; 27 ;
32 28
33 - public static final Map<String, AiPlatformEnum> mapValues  
34 - = Arrays.stream(values()).collect(Collectors.toMap(AiPlatformEnum::name, o -> o));  
35 -  
36 - private String value; 29 + private String platform;
  30 + private String name;
  31 +
  32 + public static AiPlatformEnum valueOfPlatform(String platform) {
  33 + for (AiPlatformEnum itemEnum : AiPlatformEnum.values()) {
  34 + if (itemEnum.getPlatform().equals(platform)) {
  35 + return itemEnum;
  36 + }
  37 + }
  38 + throw new IllegalArgumentException("Invalid MessageType value: " + platform);
  39 + }
37 40
38 } 41 }
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/AiClient.java deleted
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
1 package cn.iocoder.yudao.framework.ai.config; 1 package cn.iocoder.yudao.framework.ai.config;
2 2
3 -import cn.hutool.core.bean.BeanUtil;  
4 -import cn.iocoder.yudao.framework.ai.AiPlatformEnum;  
5 import cn.iocoder.yudao.framework.ai.chatqianwen.QianWenChatClient; 3 import cn.iocoder.yudao.framework.ai.chatqianwen.QianWenChatClient;
6 import cn.iocoder.yudao.framework.ai.chatqianwen.QianWenOptions; 4 import cn.iocoder.yudao.framework.ai.chatqianwen.QianWenOptions;
7 import cn.iocoder.yudao.framework.ai.chatqianwen.api.QianWenApi; 5 import cn.iocoder.yudao.framework.ai.chatqianwen.api.QianWenApi;
@@ -11,15 +9,11 @@ import cn.iocoder.yudao.framework.ai.chatxinghuo.api.XingHuoApi; @@ -11,15 +9,11 @@ import cn.iocoder.yudao.framework.ai.chatxinghuo.api.XingHuoApi;
11 import cn.iocoder.yudao.framework.ai.chatyiyan.YiYanChatClient; 9 import cn.iocoder.yudao.framework.ai.chatyiyan.YiYanChatClient;
12 import cn.iocoder.yudao.framework.ai.chatyiyan.YiYanOptions; 10 import cn.iocoder.yudao.framework.ai.chatyiyan.YiYanOptions;
13 import cn.iocoder.yudao.framework.ai.chatyiyan.api.YiYanApi; 11 import cn.iocoder.yudao.framework.ai.chatyiyan.api.YiYanApi;
14 -import cn.iocoder.yudao.framework.ai.exception.AiException;  
15 import org.springframework.boot.autoconfigure.AutoConfiguration; 12 import org.springframework.boot.autoconfigure.AutoConfiguration;
16 -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; 13 +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
17 import org.springframework.boot.context.properties.EnableConfigurationProperties; 14 import org.springframework.boot.context.properties.EnableConfigurationProperties;
18 import org.springframework.context.annotation.Bean; 15 import org.springframework.context.annotation.Bean;
19 16
20 -import java.util.HashMap;  
21 -import java.util.Map;  
22 -  
23 /** 17 /**
24 * ai 自动配置 18 * ai 自动配置
25 * 19 *
@@ -32,86 +26,46 @@ import java.util.Map; @@ -32,86 +26,46 @@ import java.util.Map;
32 public class YudaoAiAutoConfiguration { 26 public class YudaoAiAutoConfiguration {
33 27
34 @Bean 28 @Bean
35 - @ConditionalOnMissingBean(value = AiClient.class)  
36 - public AiClient aiClient(YudaoAiProperties yudaoAiProperties) {  
37 - Map<String, Object> chatClientMap = buildChatClientMap(yudaoAiProperties);  
38 - return new YudaoAiClient(chatClientMap);  
39 - }  
40 -  
41 - public Map<String, Object> buildChatClientMap(YudaoAiProperties yudaoAiProperties) {  
42 - Map<String, Object> chatMap = new HashMap<>();  
43 - for (Map.Entry<String, Map<String, Object>> properties : yudaoAiProperties.entrySet()) {  
44 - String beanName = properties.getKey();  
45 - Map<String, Object> aiPlatformMap = properties.getValue();  
46 -  
47 - // 检查平台类型是否正确  
48 - String aiPlatform = String.valueOf(aiPlatformMap.get("aiPlatform"));  
49 - if (!AiPlatformEnum.mapValues.containsKey(aiPlatform)) {  
50 - throw new AiException("AI平台名称错误! 可以参考 AiPlatformEnum 类!");  
51 - }  
52 - // 获取平台类型  
53 - AiPlatformEnum aiPlatformEnum = AiPlatformEnum.mapValues.get(aiPlatform);  
54 - // 获取 chat properties  
55 - YudaoAiProperties.ChatProperties chatProperties = getChatProperties(aiPlatformEnum, aiPlatformMap);  
56 - // 创建客户端  
57 - Object chatClient = createChatClient(chatProperties);  
58 - chatMap.put(beanName, chatClient);  
59 - }  
60 - return chatMap; 29 + @ConditionalOnProperty(value = "yudao.ai.xinghuo.enable", havingValue = "true")
  30 + public XingHuoChatClient xingHuoChatClient(YudaoAiProperties yudaoAiProperties) {
  31 + YudaoAiProperties.XingHuoProperties xingHuoProperties = yudaoAiProperties.getXinghuo();
  32 + return new XingHuoChatClient(
  33 + new XingHuoApi(
  34 + xingHuoProperties.getAppId(),
  35 + xingHuoProperties.getAppKey(),
  36 + xingHuoProperties.getSecretKey()
  37 + ),
  38 + new XingHuoOptions().setChatModel(xingHuoProperties.getChatModel())
  39 + );
61 } 40 }
62 41
63 - private static Object createChatClient(YudaoAiProperties.ChatProperties chatProperties) {  
64 - if (AiPlatformEnum.XING_HUO == chatProperties.getAiPlatform()) {  
65 - YudaoAiProperties.XingHuoProperties xingHuoProperties = (YudaoAiProperties.XingHuoProperties) chatProperties;  
66 - return new XingHuoChatClient(  
67 - new XingHuoApi(  
68 - xingHuoProperties.getAppId(),  
69 - xingHuoProperties.getAppKey(),  
70 - xingHuoProperties.getSecretKey()  
71 - ),  
72 - new XingHuoOptions().setChatModel(xingHuoProperties.getChatModel())  
73 - );  
74 - } else if (AiPlatformEnum.QIAN_WEN == chatProperties.getAiPlatform()) {  
75 - YudaoAiProperties.QianWenProperties qianWenProperties = (YudaoAiProperties.QianWenProperties) chatProperties;  
76 - return new QianWenChatClient(  
77 - new QianWenApi(  
78 - qianWenProperties.getAccessKeyId(),  
79 - qianWenProperties.getAccessKeySecret(),  
80 - qianWenProperties.getAgentKey(),  
81 - qianWenProperties.getEndpoint()  
82 - ),  
83 - new QianWenOptions()  
84 - .setAppId(qianWenProperties.getAppId())  
85 - );  
86 - } else if (AiPlatformEnum.YI_YAN == chatProperties.getAiPlatform()) {  
87 - YudaoAiProperties.YiYanProperties yiYanProperties = (YudaoAiProperties.YiYanProperties) chatProperties;  
88 - return new YiYanChatClient(  
89 - new YiYanApi(  
90 - yiYanProperties.getAppKey(),  
91 - yiYanProperties.getSecretKey(),  
92 - yiYanProperties.getChatModel(),  
93 - yiYanProperties.getRefreshTokenSecondTime()  
94 - ),  
95 - new YiYanOptions().setMax_output_tokens(2048));  
96 - }  
97 - throw new AiException("不支持的Ai类型!"); 42 + @Bean
  43 + @ConditionalOnProperty(value = "yudao.ai.qianwen.enable", havingValue = "true")
  44 + public QianWenChatClient qianWenChatClient(YudaoAiProperties yudaoAiProperties) {
  45 + YudaoAiProperties.QianWenProperties qianWenProperties = yudaoAiProperties.getQianwen();
  46 + return new QianWenChatClient(
  47 + new QianWenApi(
  48 + qianWenProperties.getAccessKeyId(),
  49 + qianWenProperties.getAccessKeySecret(),
  50 + qianWenProperties.getAgentKey(),
  51 + qianWenProperties.getEndpoint()
  52 + ),
  53 + new QianWenOptions()
  54 + .setAppId(qianWenProperties.getAppId())
  55 + );
98 } 56 }
99 57
100 -  
101 - private static YudaoAiProperties.ChatProperties getChatProperties(AiPlatformEnum aiPlatformEnum, Map<String, Object> aiPlatformMap) {  
102 - if (AiPlatformEnum.XING_HUO == aiPlatformEnum) {  
103 - YudaoAiProperties.XingHuoProperties xingHuoProperties = new YudaoAiProperties.XingHuoProperties();  
104 - BeanUtil.fillBeanWithMap(aiPlatformMap, xingHuoProperties, true);  
105 - return xingHuoProperties;  
106 - } else if (AiPlatformEnum.YI_YAN == aiPlatformEnum) {  
107 - YudaoAiProperties.YiYanProperties yiYanProperties = new YudaoAiProperties.YiYanProperties();  
108 - BeanUtil.fillBeanWithMap(aiPlatformMap, yiYanProperties, true);  
109 - return yiYanProperties;  
110 - } else if (AiPlatformEnum.QIAN_WEN == aiPlatformEnum) {  
111 - YudaoAiProperties.QianWenProperties qianWenProperties = new YudaoAiProperties.QianWenProperties();  
112 - BeanUtil.fillBeanWithMap(aiPlatformMap, qianWenProperties, true);  
113 - return qianWenProperties;  
114 - }  
115 - throw new AiException("不支持的Ai类型!"); 58 + @Bean
  59 + @ConditionalOnProperty(value = "yudao.ai.yiyan.enable", havingValue = "true")
  60 + public YiYanChatClient yiYanChatClient(YudaoAiProperties yudaoAiProperties) {
  61 + YudaoAiProperties.YiYanProperties yiYanProperties = yudaoAiProperties.getYiyan();
  62 + return new YiYanChatClient(
  63 + new YiYanApi(
  64 + yiYanProperties.getAppKey(),
  65 + yiYanProperties.getSecretKey(),
  66 + yiYanProperties.getChatModel(),
  67 + yiYanProperties.getRefreshTokenSecondTime()
  68 + ),
  69 + new YiYanOptions().setMax_output_tokens(2048));
116 } 70 }
117 } 71 }
118 \ No newline at end of file 72 \ No newline at end of file
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiClient.java deleted
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 -}  
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiImageProperties.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.ai.config;
  2 +
  3 +import cn.iocoder.yudao.framework.ai.AiPlatformEnum;
  4 +import cn.iocoder.yudao.framework.ai.chatxinghuo.XingHuoChatModel;
  5 +import cn.iocoder.yudao.framework.ai.chatxinghuo.XingHuoOptions;
  6 +import cn.iocoder.yudao.framework.ai.chatyiyan.YiYanChatModel;
  7 +import lombok.Data;
  8 +import lombok.experimental.Accessors;
  9 +import org.springframework.boot.context.properties.ConfigurationProperties;
  10 +
  11 +import java.util.LinkedHashMap;
  12 +import java.util.Map;
  13 +
  14 +/**
  15 + * ai 自动配置
  16 + *
  17 + * @author fansili
  18 + * @time 2024/4/12 16:29
  19 + * @since 1.0
  20 + */
  21 +
  22 +@Data
  23 +@Accessors(chain = true)
  24 +public class YudaoAiImageProperties extends LinkedHashMap<String, Map<String, Object>> {
  25 +
  26 + private String initType;
  27 + private QianWenProperties qianwen;
  28 + private XingHuoOptions xinghuo;
  29 + private YiYanProperties yiyan;
  30 +
  31 + @Data
  32 + @Accessors(chain = true)
  33 + public static class QianWenProperties extends ChatProperties {
  34 + /**
  35 + * 阿里云:服务器接入点
  36 + */
  37 + private String endpoint = "bailian.cn-beijing.aliyuncs.com";
  38 + /**
  39 + * 阿里云:权限 accessKeyId
  40 + */
  41 + private String accessKeyId;
  42 + /**
  43 + * 阿里云:权限 accessKeySecret
  44 + */
  45 + private String accessKeySecret;
  46 + /**
  47 + * 阿里云:agentKey
  48 + */
  49 + private String agentKey;
  50 + /**
  51 + * 阿里云:agentKey(相当于应用id)
  52 + */
  53 + private String appId;
  54 +
  55 + }
  56 +
  57 + @Data
  58 + @Accessors(chain = true)
  59 + public static class XingHuoProperties extends ChatProperties {
  60 + private String appId;
  61 + private String appKey;
  62 + private String secretKey;
  63 + private XingHuoChatModel chatModel;
  64 + }
  65 +
  66 + @Data
  67 + @Accessors(chain = true)
  68 + public static class YiYanProperties extends ChatProperties {
  69 + /**
  70 + * appKey
  71 + */
  72 + private String appKey;
  73 + /**
  74 + * secretKey
  75 + */
  76 + private String secretKey;
  77 + /**
  78 + * 模型
  79 + */
  80 + private YiYanChatModel chatModel = YiYanChatModel.ERNIE4_3_5_8K;
  81 + /**
  82 + * token 刷新时间(默认 86400 = 24小时)
  83 + */
  84 + private int refreshTokenSecondTime = 86400;
  85 + }
  86 +
  87 + @Data
  88 + @Accessors(chain = true)
  89 + public static class ChatProperties {
  90 +
  91 + private AiPlatformEnum aiPlatform;
  92 +
  93 + private Float temperature;
  94 +
  95 + private Float topP;
  96 +
  97 + private Integer topK;
  98 + }
  99 +}
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiProperties.java
@@ -7,9 +7,6 @@ import lombok.Data; @@ -7,9 +7,6 @@ import lombok.Data;
7 import lombok.experimental.Accessors; 7 import lombok.experimental.Accessors;
8 import org.springframework.boot.context.properties.ConfigurationProperties; 8 import org.springframework.boot.context.properties.ConfigurationProperties;
9 9
10 -import java.util.LinkedHashMap;  
11 -import java.util.Map;  
12 -  
13 /** 10 /**
14 * ai 自动配置 11 * ai 自动配置
15 * 12 *
@@ -18,17 +15,21 @@ import java.util.Map; @@ -18,17 +15,21 @@ import java.util.Map;
18 * @since 1.0 15 * @since 1.0
19 */ 16 */
20 @Data 17 @Data
  18 +@Accessors(chain = true)
21 @ConfigurationProperties(prefix = "yudao.ai") 19 @ConfigurationProperties(prefix = "yudao.ai")
22 -public class YudaoAiProperties extends LinkedHashMap<String, Map<String, Object>> { 20 +public class YudaoAiProperties {
23 21
24 -// private QianWenProperties qianWen;  
25 -// private XingHuoProperties xingHuo;  
26 -// private YiYanProperties yiYan; 22 + private String initSource;
  23 + private QianWenProperties qianwen;
  24 + private XingHuoProperties xinghuo;
  25 + private YiYanProperties yiyan;
27 26
28 @Data 27 @Data
29 @Accessors(chain = true) 28 @Accessors(chain = true)
30 public static class ChatProperties { 29 public static class ChatProperties {
31 30
  31 + private boolean enable = false;
  32 +
32 private AiPlatformEnum aiPlatform; 33 private AiPlatformEnum aiPlatform;
33 34
34 private Float temperature; 35 private Float temperature;
yudao-server/src/main/resources/application-local.yaml
@@ -224,7 +224,9 @@ wx: @@ -224,7 +224,9 @@ wx:
224 # 芋道配置项,设置当前项目所有自定义的配置 224 # 芋道配置项,设置当前项目所有自定义的配置
225 yudao: 225 yudao:
226 ai: 226 ai:
227 - qianWen: 227 + initSource: yaml
  228 + qianwen:
  229 + enable: true
228 aiPlatform: QIAN_WEN 230 aiPlatform: QIAN_WEN
229 temperature: 1 231 temperature: 1
230 topP: 1 232 topP: 1
@@ -234,7 +236,8 @@ yudao: @@ -234,7 +236,8 @@ yudao:
234 accessKeySecret: ZJ0JQeyjzxxm5CfeTV6k1wNE9UsvZP 236 accessKeySecret: ZJ0JQeyjzxxm5CfeTV6k1wNE9UsvZP
235 agentKey: f0c1088824594f589c8f10567ccd929f_p_efm 237 agentKey: f0c1088824594f589c8f10567ccd929f_p_efm
236 appId: 5f14955f201a44eb8dbe0c57250a32ce 238 appId: 5f14955f201a44eb8dbe0c57250a32ce
237 - xingHuo: 239 + xinghuo:
  240 + enable: true
238 aiPlatform: XING_HUO 241 aiPlatform: XING_HUO
239 temperature: 1 242 temperature: 1
240 topP: 1 243 topP: 1
@@ -243,7 +246,8 @@ yudao: @@ -243,7 +246,8 @@ yudao:
243 appKey: cb6415c19d6162cda07b47316fcb0416 246 appKey: cb6415c19d6162cda07b47316fcb0416
244 secretKey: Y2JiYTIxZjA3MDMxMjNjZjQzYzVmNzdh 247 secretKey: Y2JiYTIxZjA3MDMxMjNjZjQzYzVmNzdh
245 chatModel: XING_HUO_3_5 248 chatModel: XING_HUO_3_5
246 - yiYan3_5_8k: 249 + yiyan:
  250 + enable: true
247 aiPlatform: YI_YAN 251 aiPlatform: YI_YAN
248 temperature: 1 252 temperature: 1
249 topP: 1 253 topP: 1
@@ -252,6 +256,7 @@ yudao: @@ -252,6 +256,7 @@ yudao:
252 secretKey: R9mYF9dl9KASgi5RUq0FQt3wRisSnOcK 256 secretKey: R9mYF9dl9KASgi5RUq0FQt3wRisSnOcK
253 refreshTokenSecondTime: 86400 257 refreshTokenSecondTime: 86400
254 chatModel: ERNIE4_3_5_8K 258 chatModel: ERNIE4_3_5_8K
  259 +
255 captcha: 260 captcha:
256 enable: false # 本地环境,暂时关闭图片验证码,方便登录等接口的测试; 261 enable: false # 本地环境,暂时关闭图片验证码,方便登录等接口的测试;
257 security: 262 security: