Commit 17103201142db3317a73cfdad4f422a689cbeeb9

Authored by YunaiV
1 parent 12b82b72

【优化】AI:对话的头像交给前端拼接

yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java
@@ -6,17 +6,16 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult; @@ -6,17 +6,16 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult;
6 import cn.iocoder.yudao.framework.common.pojo.PageResult; 6 import cn.iocoder.yudao.framework.common.pojo.PageResult;
7 import cn.iocoder.yudao.framework.common.util.collection.MapUtils; 7 import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
8 import cn.iocoder.yudao.framework.common.util.object.BeanUtils; 8 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
9 -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationPageReqVO;  
10 -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationRespVO;  
11 -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.*; 9 +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessagePageReqVO;
  10 +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageRespVO;
  11 +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendReqVO;
  12 +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendRespVO;
12 import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; 13 import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO;
13 import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO; 14 import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO;
14 import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; 15 import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO;
15 import cn.iocoder.yudao.module.ai.service.chat.AiChatConversationService; 16 import cn.iocoder.yudao.module.ai.service.chat.AiChatConversationService;
16 import cn.iocoder.yudao.module.ai.service.chat.AiChatMessageService; 17 import cn.iocoder.yudao.module.ai.service.chat.AiChatMessageService;
17 import cn.iocoder.yudao.module.ai.service.model.AiChatRoleService; 18 import cn.iocoder.yudao.module.ai.service.model.AiChatRoleService;
18 -import cn.iocoder.yudao.module.system.api.user.AdminUserApi;  
19 -import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;  
20 import io.swagger.v3.oas.annotations.Operation; 19 import io.swagger.v3.oas.annotations.Operation;
21 import io.swagger.v3.oas.annotations.Parameter; 20 import io.swagger.v3.oas.annotations.Parameter;
22 import io.swagger.v3.oas.annotations.tags.Tag; 21 import io.swagger.v3.oas.annotations.tags.Tag;
@@ -34,7 +33,6 @@ import java.util.List; @@ -34,7 +33,6 @@ import java.util.List;
34 import java.util.Map; 33 import java.util.Map;
35 34
36 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 35 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
37 -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;  
38 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; 36 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
39 import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; 37 import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
40 38
@@ -51,9 +49,6 @@ public class AiChatMessageController { @@ -51,9 +49,6 @@ public class AiChatMessageController {
51 @Resource 49 @Resource
52 private AiChatRoleService chatRoleService; 50 private AiChatRoleService chatRoleService;
53 51
54 - @Resource  
55 - private AdminUserApi adminUserApi;  
56 -  
57 @Operation(summary = "发送消息(段式)", description = "一次性返回,响应较慢") 52 @Operation(summary = "发送消息(段式)", description = "一次性返回,响应较慢")
58 @PostMapping("/send") 53 @PostMapping("/send")
59 public CommonResult<AiChatMessageRespVO> sendMessage(@Validated @RequestBody AiChatMessageSendReqVO sendReqVO) { 54 public CommonResult<AiChatMessageRespVO> sendMessage(@Validated @RequestBody AiChatMessageSendReqVO sendReqVO) {
@@ -77,17 +72,7 @@ public class AiChatMessageController { @@ -77,17 +72,7 @@ public class AiChatMessageController {
77 return success(Collections.emptyList()); 72 return success(Collections.emptyList());
78 } 73 }
79 List<AiChatMessageDO> messageList = chatMessageService.getChatMessageListByConversationId(conversationId); 74 List<AiChatMessageDO> messageList = chatMessageService.getChatMessageListByConversationId(conversationId);
80 - if (CollUtil.isEmpty(messageList)) {  
81 - return success(Collections.emptyList());  
82 - }  
83 -  
84 - // 拼接数据  
85 - Map<Long, AiChatRoleDO> roleMap = chatRoleService.getChatRoleMap(convertSet(messageList, AiChatMessageDO::getRoleId));  
86 - AdminUserRespDTO user = adminUserApi.getUser(getLoginUserId());  
87 - return success(BeanUtils.toBean(messageList, AiChatMessageRespVO.class, respVO -> {  
88 - MapUtils.findAndThen(roleMap, respVO.getRoleId(), role -> respVO.setRoleAvatar(role.getAvatar()));  
89 - respVO.setUserAvatar(user.getAvatar());  
90 - })); 75 + return success(BeanUtils.toBean(messageList, AiChatMessageRespVO.class));
91 } 76 }
92 77
93 @Operation(summary = "删除消息") 78 @Operation(summary = "删除消息")
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageRespVO.java
@@ -44,13 +44,7 @@ public class AiChatMessageRespVO { @@ -44,13 +44,7 @@ public class AiChatMessageRespVO {
44 44
45 // ========== 仅在【对话管理】时加载 ========== 45 // ========== 仅在【对话管理】时加载 ==========
46 46
47 - @Schema(description = "用户头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "http://xxx")  
48 - private String userAvatar;  
49 -  
50 @Schema(description = "角色名字", example = "小黄") 47 @Schema(description = "角色名字", example = "小黄")
51 private String roleName; 48 private String roleName;
52 49
53 - @Schema(description = "角色头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png")  
54 - private String roleAvatar;  
55 -  
56 } 50 }
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/chat/AiChatConversationMapper.java
@@ -17,11 +17,8 @@ import java.util.List; @@ -17,11 +17,8 @@ import java.util.List;
17 @Mapper 17 @Mapper
18 public interface AiChatConversationMapper extends BaseMapperX<AiChatConversationDO> { 18 public interface AiChatConversationMapper extends BaseMapperX<AiChatConversationDO> {
19 19
20 - // TODO @fan:建议这里不排序哈;交给他们前端排序  
21 default List<AiChatConversationDO> selectListByUserId(Long userId) { 20 default List<AiChatConversationDO> selectListByUserId(Long userId) {
22 - return selectList(new LambdaQueryWrapperX<AiChatConversationDO>()  
23 - .eq(AiChatConversationDO::getUserId, userId)  
24 - .orderByAsc(AiChatConversationDO::getCreateTime)); 21 + return selectList(AiChatConversationDO::getUserId, userId);
25 } 22 }
26 23
27 default List<AiChatConversationDO> selectListByUserIdAndPinned(Long userId, boolean pinned) { 24 default List<AiChatConversationDO> selectListByUserIdAndPinned(Long userId, boolean pinned) {
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImpl.java
@@ -9,29 +9,25 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult; @@ -9,29 +9,25 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult;
9 import cn.iocoder.yudao.framework.common.pojo.PageResult; 9 import cn.iocoder.yudao.framework.common.pojo.PageResult;
10 import cn.iocoder.yudao.framework.common.util.object.BeanUtils; 10 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
11 import cn.iocoder.yudao.module.ai.ErrorCodeConstants; 11 import cn.iocoder.yudao.module.ai.ErrorCodeConstants;
12 -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationPageReqVO;  
13 import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessagePageReqVO; 12 import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessagePageReqVO;
14 -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendRespVO;  
15 -import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO;  
16 -import cn.iocoder.yudao.module.ai.service.model.AiApiKeyService;  
17 -import cn.iocoder.yudao.module.system.api.user.AdminUserApi;  
18 -import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;  
19 -import jakarta.annotation.Resource;  
20 -import org.springframework.ai.chat.ChatResponse;  
21 -import org.springframework.ai.chat.StreamingChatClient;  
22 -import org.springframework.ai.chat.messages.*;  
23 -import org.springframework.ai.chat.prompt.ChatOptions;  
24 -import org.springframework.ai.chat.prompt.Prompt;  
25 -import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;  
26 import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageRespVO; 13 import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageRespVO;
27 import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendReqVO; 14 import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendReqVO;
  15 +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendRespVO;
  16 +import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO;
28 import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO; 17 import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO;
29 import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; 18 import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO;
30 import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; 19 import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO;
31 import cn.iocoder.yudao.module.ai.dal.mysql.chat.AiChatMessageMapper; 20 import cn.iocoder.yudao.module.ai.dal.mysql.chat.AiChatMessageMapper;
  21 +import cn.iocoder.yudao.module.ai.service.model.AiApiKeyService;
32 import cn.iocoder.yudao.module.ai.service.model.AiChatModelService; 22 import cn.iocoder.yudao.module.ai.service.model.AiChatModelService;
33 import cn.iocoder.yudao.module.ai.service.model.AiChatRoleService; 23 import cn.iocoder.yudao.module.ai.service.model.AiChatRoleService;
  24 +import jakarta.annotation.Resource;
34 import lombok.extern.slf4j.Slf4j; 25 import lombok.extern.slf4j.Slf4j;
  26 +import org.springframework.ai.chat.ChatResponse;
  27 +import org.springframework.ai.chat.StreamingChatClient;
  28 +import org.springframework.ai.chat.messages.*;
  29 +import org.springframework.ai.chat.prompt.ChatOptions;
  30 +import org.springframework.ai.chat.prompt.Prompt;
35 import org.springframework.stereotype.Service; 31 import org.springframework.stereotype.Service;
36 import org.springframework.transaction.annotation.Transactional; 32 import org.springframework.transaction.annotation.Transactional;
37 import reactor.core.publisher.Flux; 33 import reactor.core.publisher.Flux;
@@ -70,9 +66,6 @@ public class AiChatMessageServiceImpl implements AiChatMessageService { @@ -70,9 +66,6 @@ public class AiChatMessageServiceImpl implements AiChatMessageService {
70 @Resource 66 @Resource
71 private AiApiKeyService apiKeyService; 67 private AiApiKeyService apiKeyService;
72 68
73 - @Resource  
74 - private AdminUserApi adminUserApi;  
75 -  
76 @Transactional(rollbackFor = Exception.class) 69 @Transactional(rollbackFor = Exception.class)
77 public AiChatMessageRespVO sendMessage(AiChatMessageSendReqVO req) { 70 public AiChatMessageRespVO sendMessage(AiChatMessageSendReqVO req) {
78 return null; // TODO 芋艿:一起改 71 return null; // TODO 芋艿:一起改
@@ -124,7 +117,6 @@ public class AiChatMessageServiceImpl implements AiChatMessageService { @@ -124,7 +117,6 @@ public class AiChatMessageServiceImpl implements AiChatMessageService {
124 AiChatModelDO model = chatModalService.validateChatModel(conversation.getModelId()); 117 AiChatModelDO model = chatModalService.validateChatModel(conversation.getModelId());
125 StreamingChatClient chatClient = apiKeyService.getStreamingChatClient(model.getKeyId()); 118 StreamingChatClient chatClient = apiKeyService.getStreamingChatClient(model.getKeyId());
126 // 1.3 获取用户头像、角色头像 119 // 1.3 获取用户头像、角色头像
127 - AdminUserRespDTO user = adminUserApi.getUser(SecurityFrameworkUtils.getLoginUserId());  
128 AiChatRoleDO role = conversation.getRoleId() != null ? chatRoleService.getChatRole(conversation.getRoleId()) : null; 120 AiChatRoleDO role = conversation.getRoleId() != null ? chatRoleService.getChatRole(conversation.getRoleId()) : null;
129 121
130 // 2. 插入 user 发送消息 122 // 2. 插入 user 发送消息
@@ -147,11 +139,8 @@ public class AiChatMessageServiceImpl implements AiChatMessageService { @@ -147,11 +139,8 @@ public class AiChatMessageServiceImpl implements AiChatMessageService {
147 newContent = StrUtil.nullToDefault(newContent, ""); // 避免 null 的 情况 139 newContent = StrUtil.nullToDefault(newContent, ""); // 避免 null 的 情况
148 contentBuffer.append(newContent); 140 contentBuffer.append(newContent);
149 // 响应结果 141 // 响应结果
150 - AiChatMessageSendRespVO.Message send = BeanUtils.toBean(userMessage, AiChatMessageSendRespVO.Message.class,  
151 - o -> o.setUserAvatar(user.getAvatar()));  
152 - AiChatMessageSendRespVO.Message receive = BeanUtils.toBean(assistantMessage, AiChatMessageSendRespVO.Message.class,  
153 - o -> o.setRoleAvatar(role != null ? role.getAvatar() : null)).setContent(newContent);  
154 - return success(new AiChatMessageSendRespVO().setSend(send).setReceive(receive)); 142 + return success(new AiChatMessageSendRespVO().setSend(BeanUtils.toBean(userMessage, AiChatMessageSendRespVO.Message.class))
  143 + .setReceive(BeanUtils.toBean(assistantMessage, AiChatMessageSendRespVO.Message.class).setContent(newContent)));
155 }).doOnComplete(() -> { 144 }).doOnComplete(() -> {
156 chatMessageMapper.updateById(new AiChatMessageDO().setId(assistantMessage.getId()).setContent(contentBuffer.toString())); 145 chatMessageMapper.updateById(new AiChatMessageDO().setId(assistantMessage.getId()).setContent(contentBuffer.toString()));
157 }).doOnError(throwable -> { 146 }).doOnError(throwable -> {