Commit fd0e0de164310dd463d11253ade9e01dc55f851d
Merge remote-tracking branch 'origin/master-jdk21-ai' into master-jdk21-ai
# Conflicts: # yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java
Showing
3 changed files
with
31 additions
and
2 deletions
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageSendRespVO.java
| @@ -31,6 +31,13 @@ public class AiChatMessageSendRespVO { | @@ -31,6 +31,13 @@ public class AiChatMessageSendRespVO { | ||
| 31 | @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) | 31 | @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) |
| 32 | private LocalDateTime createTime; | 32 | private LocalDateTime createTime; |
| 33 | 33 | ||
| 34 | + // ========= 扩展字段 | ||
| 35 | + | ||
| 36 | + @Schema(description = "用户头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "http://xxx") | ||
| 37 | + private String userAvatar; | ||
| 38 | + | ||
| 39 | + @Schema(description = "角色头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "http://xxx") | ||
| 40 | + private String roleAvatar; | ||
| 34 | } | 41 | } |
| 35 | 42 | ||
| 36 | } | 43 | } |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/impl/AiChatServiceImpl.java
| @@ -9,12 +9,16 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | @@ -9,12 +9,16 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | ||
| 9 | import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendRespVO; | 9 | import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendRespVO; |
| 10 | import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; | 10 | import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; |
| 11 | import cn.iocoder.yudao.module.ai.service.model.AiApiKeyService; | 11 | import cn.iocoder.yudao.module.ai.service.model.AiApiKeyService; |
| 12 | +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | ||
| 13 | +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; | ||
| 12 | import jakarta.annotation.Resource; | 14 | import jakarta.annotation.Resource; |
| 13 | import org.springframework.ai.chat.ChatResponse; | 15 | import org.springframework.ai.chat.ChatResponse; |
| 14 | import org.springframework.ai.chat.StreamingChatClient; | 16 | import org.springframework.ai.chat.StreamingChatClient; |
| 15 | import org.springframework.ai.chat.messages.*; | 17 | import org.springframework.ai.chat.messages.*; |
| 16 | import org.springframework.ai.chat.prompt.ChatOptions; | 18 | import org.springframework.ai.chat.prompt.ChatOptions; |
| 17 | import org.springframework.ai.chat.prompt.Prompt; | 19 | import org.springframework.ai.chat.prompt.Prompt; |
| 20 | +import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; | ||
| 21 | +import cn.iocoder.yudao.module.ai.config.AiChatClientFactory; | ||
| 18 | import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageRespVO; | 22 | import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageRespVO; |
| 19 | import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendReqVO; | 23 | import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendReqVO; |
| 20 | import cn.iocoder.yudao.module.ai.convert.AiChatMessageConvert; | 24 | import cn.iocoder.yudao.module.ai.convert.AiChatMessageConvert; |
| @@ -65,6 +69,9 @@ public class AiChatServiceImpl implements AiChatService { | @@ -65,6 +69,9 @@ public class AiChatServiceImpl implements AiChatService { | ||
| 65 | @Resource | 69 | @Resource |
| 66 | private AiApiKeyService apiKeyService; | 70 | private AiApiKeyService apiKeyService; |
| 67 | 71 | ||
| 72 | + @Resource | ||
| 73 | + private AdminUserApi adminUserApi; | ||
| 74 | + | ||
| 68 | @Transactional(rollbackFor = Exception.class) | 75 | @Transactional(rollbackFor = Exception.class) |
| 69 | public AiChatMessageRespVO chat(AiChatMessageSendReqVO req) { | 76 | public AiChatMessageRespVO chat(AiChatMessageSendReqVO req) { |
| 70 | return null; // TODO 芋艿:一起改 | 77 | return null; // TODO 芋艿:一起改 |
| @@ -130,14 +137,19 @@ public class AiChatServiceImpl implements AiChatService { | @@ -130,14 +137,19 @@ public class AiChatServiceImpl implements AiChatService { | ||
| 130 | 137 | ||
| 131 | // 3.3 流式返回 | 138 | // 3.3 流式返回 |
| 132 | // 注意:Schedulers.immediate() 目的是,避免默认 Schedulers.parallel() 并发消费 chunk 导致 SSE 响应前端会乱序问题 | 139 | // 注意:Schedulers.immediate() 目的是,避免默认 Schedulers.parallel() 并发消费 chunk 导致 SSE 响应前端会乱序问题 |
| 140 | + | ||
| 141 | + // 3.4 获取用户头像、角色头像 | ||
| 142 | + AdminUserRespDTO user = adminUserApi.getUser(SecurityFrameworkUtils.getLoginUserId()); | ||
| 143 | + AiChatRoleDO chatRole = chatRoleService.getChatRole(assistantMessage.getRoleId()); | ||
| 144 | + | ||
| 133 | StringBuffer contentBuffer = new StringBuffer(); | 145 | StringBuffer contentBuffer = new StringBuffer(); |
| 134 | return streamResponse.publishOn(Schedulers.single()).map(chunk -> { | 146 | return streamResponse.publishOn(Schedulers.single()).map(chunk -> { |
| 135 | String newContent = chunk.getResult() != null ? chunk.getResult().getOutput().getContent() : null; | 147 | String newContent = chunk.getResult() != null ? chunk.getResult().getOutput().getContent() : null; |
| 136 | newContent = StrUtil.nullToDefault(newContent, ""); // 避免 null 的 情况 | 148 | newContent = StrUtil.nullToDefault(newContent, ""); // 避免 null 的 情况 |
| 137 | contentBuffer.append(newContent); | 149 | contentBuffer.append(newContent); |
| 138 | // 响应结果 | 150 | // 响应结果 |
| 139 | - return new AiChatMessageSendRespVO().setSend(BeanUtils.toBean(userMessage, AiChatMessageSendRespVO.Message.class)) | ||
| 140 | - .setReceive(BeanUtils.toBean(assistantMessage, AiChatMessageSendRespVO.Message.class).setContent(newContent)); | 151 | + return new AiChatMessageSendRespVO().setSend(BeanUtils.toBean(userMessage, AiChatMessageSendRespVO.Message.class).setUserAvatar(user.getAvatar())) |
| 152 | + .setReceive(BeanUtils.toBean(assistantMessage, AiChatMessageSendRespVO.Message.class).setContent(newContent).setRoleAvatar(chatRole == null ? null : chatRole.getAvatar())); | ||
| 141 | }).doOnComplete(() -> { | 153 | }).doOnComplete(() -> { |
| 142 | chatMessageMapper.updateById(new AiChatMessageDO().setId(assistantMessage.getId()).setContent(contentBuffer.toString())); | 154 | chatMessageMapper.updateById(new AiChatMessageDO().setId(assistantMessage.getId()).setContent(contentBuffer.toString())); |
| 143 | }).doOnError(throwable -> { | 155 | }).doOnError(throwable -> { |
| @@ -236,6 +248,8 @@ public class AiChatServiceImpl implements AiChatService { | @@ -236,6 +248,8 @@ public class AiChatServiceImpl implements AiChatService { | ||
| 236 | Map<Long, AiChatRoleDO> roleMap = roleList.stream().collect(Collectors.toMap(AiChatRoleDO::getId, o -> o)); | 248 | Map<Long, AiChatRoleDO> roleMap = roleList.stream().collect(Collectors.toMap(AiChatRoleDO::getId, o -> o)); |
| 237 | // 转换 AiChatMessageRespVO | 249 | // 转换 AiChatMessageRespVO |
| 238 | List<AiChatMessageRespVO> aiChatMessageRespList = AiChatMessageConvert.INSTANCE.convertAiChatMessageRespVOList(aiChatMessageDOList); | 250 | List<AiChatMessageRespVO> aiChatMessageRespList = AiChatMessageConvert.INSTANCE.convertAiChatMessageRespVOList(aiChatMessageDOList); |
| 251 | + // 获取用户信息 | ||
| 252 | + AdminUserRespDTO user = adminUserApi.getUser(SecurityFrameworkUtils.getLoginUserId()); | ||
| 239 | // 设置用户头像 和 模型头像 | 253 | // 设置用户头像 和 模型头像 |
| 240 | return aiChatMessageRespList.stream().map(item -> { | 254 | return aiChatMessageRespList.stream().map(item -> { |
| 241 | // 设置 role 头像 | 255 | // 设置 role 头像 |
| @@ -243,6 +257,10 @@ public class AiChatServiceImpl implements AiChatService { | @@ -243,6 +257,10 @@ public class AiChatServiceImpl implements AiChatService { | ||
| 243 | AiChatRoleDO role = roleMap.get(item.getRoleId()); | 257 | AiChatRoleDO role = roleMap.get(item.getRoleId()); |
| 244 | item.setRoleAvatar(role.getAvatar()); | 258 | item.setRoleAvatar(role.getAvatar()); |
| 245 | } | 259 | } |
| 260 | + // 设置 user 头像 | ||
| 261 | + if (user != null) { | ||
| 262 | + item.setUserAvatar(user.getAvatar()); | ||
| 263 | + } | ||
| 246 | return item; | 264 | return item; |
| 247 | }).collect(Collectors.toList()); | 265 | }).collect(Collectors.toList()); |
| 248 | } | 266 | } |
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/user/dto/AdminUserRespDTO.java