Commit 8f0c5998aad17f50faca1ae857616c98e1bc47f6
1 parent
f0e4e535
【解决todo】Chat Stream 处理失败的逻辑
Showing
4 changed files
with
12 additions
and
4 deletions
yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/ErrorCodeConstants.java
| @@ -32,6 +32,7 @@ public interface ErrorCodeConstants { | @@ -32,6 +32,7 @@ public interface ErrorCodeConstants { | ||
| 32 | 32 | ||
| 33 | // ========== API 聊天消息 1-040-004-000 ========== | 33 | // ========== API 聊天消息 1-040-004-000 ========== |
| 34 | ErrorCode AI_CHAT_MESSAGE_NOT_EXIST = new ErrorCode(1_040_004_000, "消息不存在!"); | 34 | ErrorCode AI_CHAT_MESSAGE_NOT_EXIST = new ErrorCode(1_040_004_000, "消息不存在!"); |
| 35 | + ErrorCode AI_CHAT_STREAM_ERROR = new ErrorCode(1_040_004_001, "Stream 对话异常!"); | ||
| 35 | 36 | ||
| 36 | // midjourney | 37 | // midjourney |
| 37 | 38 |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java
| @@ -58,7 +58,7 @@ public class AiChatMessageController { | @@ -58,7 +58,7 @@ public class AiChatMessageController { | ||
| 58 | @Operation(summary = "发送消息(流式)", description = "流式返回,响应较快") | 58 | @Operation(summary = "发送消息(流式)", description = "流式返回,响应较快") |
| 59 | @PostMapping(value = "/send-stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE) | 59 | @PostMapping(value = "/send-stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE) |
| 60 | @PermitAll // 解决 SSE 最终响应的时候,会被 Access Denied 拦截的问题 | 60 | @PermitAll // 解决 SSE 最终响应的时候,会被 Access Denied 拦截的问题 |
| 61 | - public Flux<AiChatMessageSendRespVO> sendChatMessageStream(@Validated @RequestBody AiChatMessageSendReqVO sendReqVO) { | 61 | + public Flux<CommonResult<AiChatMessageSendRespVO>> sendChatMessageStream(@Validated @RequestBody AiChatMessageSendReqVO sendReqVO) { |
| 62 | return chatMessageService.sendChatMessageStream(sendReqVO, getLoginUserId()); | 62 | return chatMessageService.sendChatMessageStream(sendReqVO, getLoginUserId()); |
| 63 | } | 63 | } |
| 64 | 64 |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageService.java
| 1 | package cn.iocoder.yudao.module.ai.service.chat; | 1 | package cn.iocoder.yudao.module.ai.service.chat; |
| 2 | 2 | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||
| 3 | import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.*; | 4 | import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.*; |
| 4 | import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO; | 5 | import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO; |
| 5 | import reactor.core.publisher.Flux; | 6 | import reactor.core.publisher.Flux; |
| @@ -28,7 +29,7 @@ public interface AiChatMessageService { | @@ -28,7 +29,7 @@ public interface AiChatMessageService { | ||
| 28 | * @param userId 用户编号 | 29 | * @param userId 用户编号 |
| 29 | * @return 发送结果 | 30 | * @return 发送结果 |
| 30 | */ | 31 | */ |
| 31 | - Flux<AiChatMessageSendRespVO> sendChatMessageStream(AiChatMessageSendReqVO sendReqVO, Long userId); | 32 | + Flux<CommonResult<AiChatMessageSendRespVO>> sendChatMessageStream(AiChatMessageSendReqVO sendReqVO, Long userId); |
| 32 | 33 | ||
| 33 | /** | 34 | /** |
| 34 | * 获得指定会话的消息列表 | 35 | * 获得指定会话的消息列表 |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImpl.java
| @@ -5,13 +5,17 @@ import cn.hutool.core.util.ObjUtil; | @@ -5,13 +5,17 @@ import cn.hutool.core.util.ObjUtil; | ||
| 5 | import cn.hutool.core.util.StrUtil; | 5 | import cn.hutool.core.util.StrUtil; |
| 6 | import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; | 6 | import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; |
| 7 | import cn.iocoder.yudao.framework.ai.core.factory.AiClientFactory; | 7 | import cn.iocoder.yudao.framework.ai.core.factory.AiClientFactory; |
| 8 | +import cn.iocoder.yudao.framework.common.exception.ErrorCode; | ||
| 9 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||
| 8 | 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; | ||
| 9 | import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendRespVO; | 12 | import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendRespVO; |
| 10 | import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; | 13 | import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; |
| 11 | import cn.iocoder.yudao.module.ai.service.model.AiApiKeyService; | 14 | import cn.iocoder.yudao.module.ai.service.model.AiApiKeyService; |
| 12 | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | 15 | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; |
| 13 | import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; | 16 | import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; |
| 14 | import jakarta.annotation.Resource; | 17 | import jakarta.annotation.Resource; |
| 18 | +import org.reactivestreams.Publisher; | ||
| 15 | import org.springframework.ai.chat.ChatResponse; | 19 | import org.springframework.ai.chat.ChatResponse; |
| 16 | import org.springframework.ai.chat.StreamingChatClient; | 20 | import org.springframework.ai.chat.StreamingChatClient; |
| 17 | import org.springframework.ai.chat.messages.*; | 21 | import org.springframework.ai.chat.messages.*; |
| @@ -107,7 +111,7 @@ public class AiChatMessageServiceImpl implements AiChatMessageService { | @@ -107,7 +111,7 @@ public class AiChatMessageServiceImpl implements AiChatMessageService { | ||
| 107 | } | 111 | } |
| 108 | 112 | ||
| 109 | @Override | 113 | @Override |
| 110 | - public Flux<AiChatMessageSendRespVO> sendChatMessageStream(AiChatMessageSendReqVO sendReqVO, Long userId) { | 114 | + public Flux<CommonResult<AiChatMessageSendRespVO>> sendChatMessageStream(AiChatMessageSendReqVO sendReqVO, Long userId) { |
| 111 | // 1.1 校验对话存在 | 115 | // 1.1 校验对话存在 |
| 112 | AiChatConversationDO conversation = chatConversationService.validateExists(sendReqVO.getConversationId()); | 116 | AiChatConversationDO conversation = chatConversationService.validateExists(sendReqVO.getConversationId()); |
| 113 | if (ObjUtil.notEqual(conversation.getUserId(), userId)) { | 117 | if (ObjUtil.notEqual(conversation.getUserId(), userId)) { |
| @@ -145,12 +149,14 @@ public class AiChatMessageServiceImpl implements AiChatMessageService { | @@ -145,12 +149,14 @@ public class AiChatMessageServiceImpl implements AiChatMessageService { | ||
| 145 | o -> o.setUserAvatar(user.getAvatar())); | 149 | o -> o.setUserAvatar(user.getAvatar())); |
| 146 | AiChatMessageSendRespVO.Message receive = BeanUtils.toBean(assistantMessage, AiChatMessageSendRespVO.Message.class, | 150 | AiChatMessageSendRespVO.Message receive = BeanUtils.toBean(assistantMessage, AiChatMessageSendRespVO.Message.class, |
| 147 | o -> o.setRoleAvatar(role != null ? role.getAvatar() : null)).setContent(newContent); | 151 | o -> o.setRoleAvatar(role != null ? role.getAvatar() : null)).setContent(newContent); |
| 148 | - return new AiChatMessageSendRespVO().setSend(send).setReceive(receive); | 152 | + return CommonResult.success(new AiChatMessageSendRespVO().setSend(send).setReceive(receive)); |
| 149 | }).doOnComplete(() -> { | 153 | }).doOnComplete(() -> { |
| 150 | chatMessageMapper.updateById(new AiChatMessageDO().setId(assistantMessage.getId()).setContent(contentBuffer.toString())); | 154 | chatMessageMapper.updateById(new AiChatMessageDO().setId(assistantMessage.getId()).setContent(contentBuffer.toString())); |
| 151 | }).doOnError(throwable -> { | 155 | }).doOnError(throwable -> { |
| 152 | log.error("[sendChatMessageStream][userId({}) sendReqVO({}) 发生异常]", userId, sendReqVO, throwable); | 156 | log.error("[sendChatMessageStream][userId({}) sendReqVO({}) 发生异常]", userId, sendReqVO, throwable); |
| 153 | chatMessageMapper.updateById(new AiChatMessageDO().setId(assistantMessage.getId()).setContent(throwable.getMessage())); | 157 | chatMessageMapper.updateById(new AiChatMessageDO().setId(assistantMessage.getId()).setContent(throwable.getMessage())); |
| 158 | + }).onErrorResume( error -> { | ||
| 159 | + return Flux.just(CommonResult.error(ErrorCodeConstants.AI_CHAT_STREAM_ERROR)); | ||
| 154 | }); | 160 | }); |
| 155 | } | 161 | } |
| 156 | 162 |