Ver Fonte

Merge branch 'modules-zjy' of uskycloud/usky-modules into master

gez há 3 dias atrás
pai
commit
02acd9b2f2

+ 237 - 21
service-ai/service-ai-biz/src/main/java/com/usky/ai/controller/web/AiChatController.java

@@ -12,6 +12,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
 import com.usky.ai.mapper.AiQuestionMapper;
 import com.usky.ai.mapper.AiSessionMapper;
 import com.usky.ai.service.AiQuestion;
+import com.usky.ai.service.AiQuestionItem;
 import com.usky.ai.service.AiSession;
 import com.usky.ai.service.vo.AiStreamOutputVO;
 import com.usky.common.core.bean.ApiResult;
@@ -19,6 +20,7 @@ import com.usky.common.security.utils.SecurityUtils;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
+import org.springframework.http.HttpStatus;
 import org.springframework.http.MediaType;
 import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.*;
@@ -52,6 +54,9 @@ public class AiChatController {
     @Value("${ai.historyLimit}")
     private int Limit;
 
+    @Value("${ai.millis}")
+    private int millis;
+
     @Resource
     private Generation generation;
 
@@ -96,7 +101,7 @@ public class AiChatController {
             aiSessionMapper.save(aiSession);
         }
 
-        // 构建消息列表,包含角色定义和用户新消息
+        // 构建消息列表,包含角色定义、历史对话记录和用户新消息
         List<Message> messages = new ArrayList<>();
 
         // 插入角色定义(在对话历史的开头)
@@ -106,6 +111,44 @@ public class AiChatController {
                 .build();
         messages.add(roleDefinition); // 将角色定义插入到对话历史的开头
 
+        // 从数据库中获取历史对话记录
+        List<AiQuestion> questions = aiQuestionMapper.findQuestionsBySessionId(sessionId);
+
+        // 如果历史记录超过限制,则只取最近的记录
+        if (questions.size() > Limit) {
+            questions = questions.subList(questions.size() - Limit, questions.size());
+        }
+
+        // 将历史对话记录转换为 AiQuestionItem 列表
+        List<AiQuestionItem> itemList = new ArrayList<>();
+        for (AiQuestion question : questions) {
+            AiQuestionItem userItem = new AiQuestionItem("user", question.getQuestion());
+            userItem.setId(question.getId());
+            userItem.setSessionId(question.getSessionId());
+            userItem.setUserId(question.getUserId());
+            userItem.setUserName(question.getUserName());
+            userItem.setAskTime(question.getAskTime());
+
+            AiQuestionItem assistantItem = new AiQuestionItem("assistant", question.getAnswer());
+            assistantItem.setId(question.getId());
+            assistantItem.setSessionId(question.getSessionId());
+            assistantItem.setUserId(question.getUserId());
+            assistantItem.setUserName(question.getUserName());
+            assistantItem.setAskTime(question.getAskTime());
+
+            itemList.add(userItem);
+            itemList.add(assistantItem);
+        }
+
+        // 将 AiQuestionItem 列表转换为消息列表
+        for (AiQuestionItem item : itemList) {
+            Message message = Message.builder()
+                    .role(item.getRole().equals("user") ? Role.USER.getValue() : Role.ASSISTANT.getValue())
+                    .content(item.getContent() != null ? item.getContent() : item.getReasoningContent())
+                    .build();
+            messages.add(message);
+        }
+
         // 添加用户的新消息
         Message userMessage = Message.builder()
                 .role(Role.USER.getValue())
@@ -130,7 +173,7 @@ public class AiChatController {
                 .contentType(MediaType.TEXT_EVENT_STREAM)
                 .body(outputStream -> {
                     try {
-                        // 调用流式接口
+// 调用流式接口
                         generation.streamCall(param).blockingForEach(chunk -> {
                             try {
                                 // 获取每次生成的内容
@@ -156,6 +199,14 @@ public class AiChatController {
                                 // 累加到完整回答内容中
                                 completeAnswer.append(partialAnswer);
 
+                                // 添加延迟
+                                try {
+                                    Thread.sleep(millis); // 延迟*毫秒
+                                } catch (InterruptedException e) {
+                                    Thread.currentThread().interrupt();
+                                    log.error("Thread interrupted", e);
+                                }
+
                             } catch (Exception e) {
                                 log.error("Error processing chunk", e);
                                 outputStream.write(("data: Error processing chunk\n\n").getBytes(StandardCharsets.UTF_8));
@@ -201,8 +252,7 @@ public class AiChatController {
         }
 
         // 解析 JSON 并提取 "content" 字段的值
-        String questionText;
-        questionText = content; // 提取 "content" 字段的值
+        String questionText = content;
 
         // 检查是否已经存在相同的 sessionId
         boolean exists = aiSessionMapper.existsBySessionId(sessionId);
@@ -218,29 +268,53 @@ public class AiChatController {
             aiSessionMapper.save(aiSession);
         }
 
-        // 获取当前用户的对话历史
-        List<AiQuestion> conversationHistory = aiQuestionMapper.findByUserIdAndSessionId(sessionId, userId);
-
-        // 只保留最近的几轮对话
-//        int historyLimit = Limit;
-//        if (conversationHistory.size() > historyLimit) {
-//            conversationHistory = conversationHistory.subList(conversationHistory.size() - historyLimit, conversationHistory.size());
-//        }
-
-        // 构建对话历史消息
-        List<Message> messages = conversationHistory.stream()
-                .map(q -> Message.builder()
-                        .role(q.getUserId().equals(userId) ? Role.USER.getValue() : Role.ASSISTANT.getValue())
-                        .content(q.getUserId().equals(userId) ? q.getQuestion() : q.getAnswer())
-                        .build())
-                .collect(Collectors.toList());
+        // 构建消息列表,包含角色定义、历史对话记录和用户新消息
+        List<Message> messages = new ArrayList<>();
 
         // 插入角色定义(在对话历史的开头)
         Message roleDefinition = Message.builder()
                 .role(Role.SYSTEM.getValue()) // 使用系统角色
                 .content(aiRole) // 定义角色的行为和风格
                 .build();
-        messages.add(0, roleDefinition); // 将角色定义插入到对话历史的开头
+        messages.add(roleDefinition); // 将角色定义插入到对话历史的开头
+
+        // 从数据库中获取历史对话记录
+        List<AiQuestion> questions = aiQuestionMapper.findQuestionsBySessionId(sessionId);
+
+        // 如果历史记录超过限制,则只取最近的记录
+        if (questions.size() > Limit) {
+            questions = questions.subList(questions.size() - Limit, questions.size());
+        }
+
+        // 将历史对话记录转换为 AiQuestionItem 列表
+        List<AiQuestionItem> itemList = new ArrayList<>();
+        for (AiQuestion question : questions) {
+            AiQuestionItem userItem = new AiQuestionItem("user", question.getQuestion());
+            userItem.setId(question.getId());
+            userItem.setSessionId(question.getSessionId());
+            userItem.setUserId(question.getUserId());
+            userItem.setUserName(question.getUserName());
+            userItem.setAskTime(question.getAskTime());
+
+            AiQuestionItem assistantItem = new AiQuestionItem("assistant", question.getAnswer());
+            assistantItem.setId(question.getId());
+            assistantItem.setSessionId(question.getSessionId());
+            assistantItem.setUserId(question.getUserId());
+            assistantItem.setUserName(question.getUserName());
+            assistantItem.setAskTime(question.getAskTime());
+
+            itemList.add(userItem);
+            itemList.add(assistantItem);
+        }
+
+        // 将 AiQuestionItem 列表转换为消息列表
+        for (AiQuestionItem item : itemList) {
+            Message message = Message.builder()
+                    .role(item.getRole().equals("user") ? Role.USER.getValue() : Role.ASSISTANT.getValue())
+                    .content(item.getContent() != null ? item.getContent() : item.getReasoningContent())
+                    .build();
+            messages.add(message);
+        }
 
         // 添加用户的新消息
         Message userMessage = Message.builder()
@@ -290,6 +364,14 @@ public class AiChatController {
                                 // 累加到完整回答内容中
                                 completeAnswer.append(partialAnswer);
 
+                                // 添加延迟
+                                try {
+                                    Thread.sleep(millis); // 延迟*毫秒
+                                } catch (InterruptedException e) {
+                                    Thread.currentThread().interrupt();
+                                    log.error("Thread interrupted", e);
+                                }
+
                             } catch (Exception e) {
                                 log.error("Error processing chunk", e);
                                 outputStream.write(("data: Error processing chunk\n\n").getBytes(StandardCharsets.UTF_8));
@@ -317,4 +399,138 @@ public class AiChatController {
                     }
                 });
     }
+
+    @PostMapping(value = "/aliTyqw-test")
+    public ResponseEntity<AiStreamOutputVO> send3(@RequestBody JSONObject object) throws NoApiKeyException, InputRequiredException {
+        // 获取当前登录用户的信息
+        Long userId = SecurityUtils.getUserId();
+        String userName = SecurityUtils.getLoginUser().getSysUser().getNickName();
+        String sessionId = null;
+        String content = object.get("content").toString();
+
+        // 如果没有传入 sessionId,则创建一个新的会话ID
+        if (object.containsKey("sessionId")) {
+            sessionId = object.get("sessionId").toString();
+        } else {
+            sessionId = java.util.UUID.randomUUID().toString();
+        }
+
+        // 解析 JSON 并提取 "content" 字段的值
+        String questionText = content;
+
+        // 检查是否已经存在相同的 sessionId
+        boolean exists = aiSessionMapper.existsBySessionId(sessionId);
+
+        if (!exists) {
+            // 创建新的 AiSession 实体并存入数据库
+            AiSession aiSession = new AiSession();
+            aiSession.setSessionId(sessionId);
+            aiSession.setUserId(userId);
+            aiSession.setUserName(userName);
+            aiSession.setQuestion(questionText);
+            aiSession.setAskTime(LocalDateTime.now());
+            aiSessionMapper.save(aiSession);
+        }
+
+        // 构建消息列表,包含角色定义、历史对话记录和用户新消息
+        List<Message> messages = new ArrayList<>();
+
+        // 插入角色定义(在对话历史的开头)
+        Message roleDefinition = Message.builder()
+                .role(Role.SYSTEM.getValue()) // 使用系统角色
+                .content(aiRole) // 定义角色的行为和风格
+                .build();
+        messages.add(roleDefinition); // 将角色定义插入到对话历史的开头
+
+        // 从数据库中获取历史对话记录
+        List<AiQuestion> questions = aiQuestionMapper.findQuestionsBySessionId(sessionId);
+
+        // 如果历史记录超过限制,则只取最近的记录
+        if (questions.size() > Limit) {
+            questions = questions.subList(questions.size() - Limit, questions.size());
+        }
+
+        // 将历史对话记录转换为 AiQuestionItem 列表
+        List<AiQuestionItem> itemList = new ArrayList<>();
+        for (AiQuestion question : questions) {
+            AiQuestionItem userItem = new AiQuestionItem("user", question.getQuestion());
+            userItem.setId(question.getId());
+            userItem.setSessionId(question.getSessionId());
+            userItem.setUserId(question.getUserId());
+            userItem.setUserName(question.getUserName());
+            userItem.setAskTime(question.getAskTime());
+
+            AiQuestionItem assistantItem = new AiQuestionItem("assistant", question.getAnswer());
+            assistantItem.setId(question.getId());
+            assistantItem.setSessionId(question.getSessionId());
+            assistantItem.setUserId(question.getUserId());
+            assistantItem.setUserName(question.getUserName());
+            assistantItem.setAskTime(question.getAskTime());
+
+            itemList.add(userItem);
+            itemList.add(assistantItem);
+        }
+
+        // 将 AiQuestionItem 列表转换为消息列表
+        for (AiQuestionItem item : itemList) {
+            Message message = Message.builder()
+                    .role(item.getRole().equals("user") ? Role.USER.getValue() : Role.ASSISTANT.getValue())
+                    .content(item.getContent() != null ? item.getContent() : item.getReasoningContent())
+                    .build();
+            messages.add(message);
+        }
+
+        // 添加用户的新消息
+        Message userMessage = Message.builder()
+                .role(Role.USER.getValue())
+                .content(questionText) // 使用提取的文本
+                .build();
+        messages.add(userMessage);
+
+        // 构建模型调用参数
+        GenerationParam param = GenerationParam.builder()
+                .model(tyqwModel)
+                .messages(messages)
+                .resultFormat(GenerationParam.ResultFormat.MESSAGE)
+                .topP(0.8)
+                .apiKey(apiKey)
+                .incrementalOutput(false) // 关闭增量输出
+                .enableSearch(true)  // 联网搜索
+                .build();
+
+        try {
+            // 调用非流式接口
+            String completeAnswer = generation.call(param).getOutput().getChoices().get(0).getMessage().getContent();
+
+            // 将完整回答存入数据库
+            AiQuestion aiQuestion = new AiQuestion();
+            aiQuestion.setModel(tyqwModel);
+            aiQuestion.setSessionId(sessionId);
+            aiQuestion.setUserId(userId);
+            aiQuestion.setUserName(userName);
+            aiQuestion.setQuestion(questionText);
+            aiQuestion.setAnswer(completeAnswer);
+            aiQuestion.setAskTime(LocalDateTime.now());
+            aiQuestionMapper.save(aiQuestion);
+
+            // 构建返回对象
+            AiStreamOutputVO aiStreamOutputVO = new AiStreamOutputVO();
+            aiStreamOutputVO.setSessionId(sessionId);
+            aiStreamOutputVO.setReasoningContent(completeAnswer);
+
+            // 返回完整回答给前端
+            return ResponseEntity.ok(aiStreamOutputVO);
+        } catch (ApiException e) {
+            log.error("Error processing request", e);
+
+            // 构建错误返回对象
+            AiStreamOutputVO aiStreamOutputVO = new AiStreamOutputVO();
+            aiStreamOutputVO.setSessionId(sessionId);
+            aiStreamOutputVO.setReasoningContent("Error processing request");
+
+            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(aiStreamOutputVO);
+        } catch (NoApiKeyException | InputRequiredException e) {
+            throw new RuntimeException(e);
+        }
+    }
 }