Commit fd0e0de164310dd463d11253ade9e01dc55f851d

Authored by YunaiV
2 parents 2fefcf88 2a01f6b9

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
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 31 @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
32 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 9 import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendRespVO;
10 10 import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO;
11 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 14 import jakarta.annotation.Resource;
13 15 import org.springframework.ai.chat.ChatResponse;
14 16 import org.springframework.ai.chat.StreamingChatClient;
15 17 import org.springframework.ai.chat.messages.*;
16 18 import org.springframework.ai.chat.prompt.ChatOptions;
17 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 22 import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageRespVO;
19 23 import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendReqVO;
20 24 import cn.iocoder.yudao.module.ai.convert.AiChatMessageConvert;
... ... @@ -65,6 +69,9 @@ public class AiChatServiceImpl implements AiChatService {
65 69 @Resource
66 70 private AiApiKeyService apiKeyService;
67 71  
  72 + @Resource
  73 + private AdminUserApi adminUserApi;
  74 +
68 75 @Transactional(rollbackFor = Exception.class)
69 76 public AiChatMessageRespVO chat(AiChatMessageSendReqVO req) {
70 77 return null; // TODO 芋艿:一起改
... ... @@ -130,14 +137,19 @@ public class AiChatServiceImpl implements AiChatService {
130 137  
131 138 // 3.3 流式返回
132 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 145 StringBuffer contentBuffer = new StringBuffer();
134 146 return streamResponse.publishOn(Schedulers.single()).map(chunk -> {
135 147 String newContent = chunk.getResult() != null ? chunk.getResult().getOutput().getContent() : null;
136 148 newContent = StrUtil.nullToDefault(newContent, ""); // 避免 null 的 情况
137 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 153 }).doOnComplete(() -> {
142 154 chatMessageMapper.updateById(new AiChatMessageDO().setId(assistantMessage.getId()).setContent(contentBuffer.toString()));
143 155 }).doOnError(throwable -> {
... ... @@ -236,6 +248,8 @@ public class AiChatServiceImpl implements AiChatService {
236 248 Map<Long, AiChatRoleDO> roleMap = roleList.stream().collect(Collectors.toMap(AiChatRoleDO::getId, o -> o));
237 249 // 转换 AiChatMessageRespVO
238 250 List<AiChatMessageRespVO> aiChatMessageRespList = AiChatMessageConvert.INSTANCE.convertAiChatMessageRespVOList(aiChatMessageDOList);
  251 + // 获取用户信息
  252 + AdminUserRespDTO user = adminUserApi.getUser(SecurityFrameworkUtils.getLoginUserId());
239 253 // 设置用户头像 和 模型头像
240 254 return aiChatMessageRespList.stream().map(item -> {
241 255 // 设置 role 头像
... ... @@ -243,6 +257,10 @@ public class AiChatServiceImpl implements AiChatService {
243 257 AiChatRoleDO role = roleMap.get(item.getRoleId());
244 258 item.setRoleAvatar(role.getAvatar());
245 259 }
  260 + // 设置 user 头像
  261 + if (user != null) {
  262 + item.setUserAvatar(user.getAvatar());
  263 + }
246 264 return item;
247 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
... ... @@ -40,5 +40,9 @@ public class AdminUserRespDTO {
40 40 * 手机号码
41 41 */
42 42 private String mobile;
  43 + /**
  44 + * 用户头像
  45 + */
  46 + private String avatar;
43 47  
44 48 }
... ...