Explorar el Código

强生demo加入语音生成状态控制

liyanbo hace 1 mes
padre
commit
d513a1b7e1

+ 3 - 0
byzs-web/src/main/java/cn/iocoder/byzs/module/web/controller/admin/ai/vo/WebQSAiChatMessageSendReqVO.java

@@ -23,6 +23,9 @@ public class WebQSAiChatMessageSendReqVO {
     @Schema(description = "是否携带历史上下文", example = "true")
     private Boolean useContext;
 
+    @Schema(description = "是否生成并流式返回语音", example = "true")
+    private Boolean playAudio = Boolean.TRUE;
+
     @Schema(description = "已上传的附件列表,最多 5 个")
     @Valid
     @Size(max = 5, message = "单次最多上传 5 个附件")

+ 25 - 0
byzs-web/src/main/java/cn/iocoder/byzs/module/web/service/ai/WebQSAiServiceImpl.java

@@ -5,6 +5,7 @@ import cn.hutool.core.util.StrUtil;
 import cn.iocoder.byzs.framework.common.pojo.CommonResult;
 import cn.iocoder.byzs.framework.common.util.object.BeanUtils;
 import cn.iocoder.byzs.framework.tenant.core.util.TenantUtils;
+import cn.iocoder.byzs.module.ai.controller.admin.chat.vo.message.AiChatMessageSendReqVO;
 import cn.iocoder.byzs.module.ai.controller.admin.chat.vo.message.AiChatMessageSendRespVO;
 import cn.iocoder.byzs.module.ai.dal.dataobject.chat.AiChatConversationDO;
 import cn.iocoder.byzs.module.ai.dal.dataobject.chat.AiChatMessageDO;
@@ -14,6 +15,7 @@ import cn.iocoder.byzs.module.ai.dal.mysql.chat.AiChatMessageMapper;
 import cn.iocoder.byzs.module.ai.enums.ErrorCodeConstants;
 import cn.iocoder.byzs.module.ai.enums.model.AiPlatformEnum;
 import cn.iocoder.byzs.module.ai.service.chat.AiChatConversationService;
+import cn.iocoder.byzs.module.ai.service.chat.AiChatMessageService;
 import cn.iocoder.byzs.module.ai.service.model.AiApiKeyService;
 import cn.iocoder.byzs.module.ai.service.model.AiModelService;
 import cn.iocoder.byzs.module.web.controller.admin.ai.vo.WebQSAiChatMessageSendReqVO;
@@ -97,6 +99,8 @@ public class WebQSAiServiceImpl {
     @Resource
     private AiChatConversationService chatConversationService;
     @Resource
+    private AiChatMessageService chatMessageService;
+    @Resource
     private AiChatMessageMapper chatMessageMapper;
     @Resource
     private AiModelService modelService;
@@ -114,6 +118,11 @@ public class WebQSAiServiceImpl {
     public Flux<CommonResult<AiChatMessageSendRespVO>> sendChatMessageStream(
             WebQSAiChatMessageSendReqVO sendReqVO, Long userId, List<MultipartFile> multipartFiles) {
         List<MultipartFile> files = multipartFiles == null ? List.of() : multipartFiles;
+        if (sendReqVO.getAttachments() == null || sendReqVO.getAttachments().isEmpty()) {
+            if (files.isEmpty()) {
+                return sendTextChatMessageStream(sendReqVO, userId);
+            }
+        }
         int urlAttachmentCount = sendReqVO.getAttachments() == null ? 0 : sendReqVO.getAttachments().size();
         if (urlAttachmentCount + files.size() > MAX_ATTACHMENTS) {
             throw new IllegalArgumentException("单次最多上传 " + MAX_ATTACHMENTS + " 个附件");
@@ -205,6 +214,22 @@ public class WebQSAiServiceImpl {
                 });
     }
 
+    /**
+     * 纯文本请求复用通用聊天链路,以获得其稳定的增量输出、连接复用和可选 TTS 能力。
+     */
+    private Flux<CommonResult<AiChatMessageSendRespVO>> sendTextChatMessageStream(
+            WebQSAiChatMessageSendReqVO sendReqVO, Long userId) {
+        if (StrUtil.isBlank(sendReqVO.getContent())) {
+            throw new IllegalArgumentException("文本问答内容不能为空");
+        }
+        AiChatMessageSendReqVO textSendReqVO = new AiChatMessageSendReqVO();
+        textSendReqVO.setConversationId(sendReqVO.getConversationId());
+        textSendReqVO.setContent(sendReqVO.getContent());
+        textSendReqVO.setUseContext(sendReqVO.getUseContext());
+        textSendReqVO.setPlayAudio(sendReqVO.getPlayAudio());
+        return chatMessageService.sendChatMessageStream(textSendReqVO, userId);
+    }
+
     private void emitCompletedTextIfNecessary(StringBuilder answer, String completedText,
                                               reactor.core.publisher.FluxSink<CommonResult<AiChatMessageSendRespVO>> sink,
                                               AiChatMessageDO userMessage, AiChatMessageDO assistantMessage) {