tsurumure 6 месяцев назад
Родитель
Сommit
81e12e65f2

+ 27 - 0
db/ai_chat_model.sql

@@ -0,0 +1,27 @@
+/**
+Source Server Version: 8.0.31
+Source Database: backendsys
+Date: 2023/05/23 17:09:22
+*/
+
+DROP TABLE IF EXISTS `ai_chat_model`;
+CREATE TABLE `ai_chat_model` (
+    PRIMARY KEY (`id`),
+    `id` BIGINT AUTO_INCREMENT COMMENT 'ID',
+    `parent_id` BIGINT DEFAULT '-1' COMMENT '父ID',
+    `label` VARCHAR(255) COMMENT '模型名称',
+    `value` VARCHAR(255) COMMENT '模型 (HUNYUAN-混元, DEEPSEEK_API, DEEPSEEK_R1)',
+    `disabled` TINYINT(1) DEFAULT '1' COMMENT '是否禁用 (-1可用, 1禁用)',
+    `status` TINYINT(1) DEFAULT '1' COMMENT '状态 (-1禁用, 1启用)'
+) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='AI对话模型表';
+
+INSERT INTO ai_chat_model(id, parent_id, label, value, disabled, status) VALUES
+    (1, -1, 'DEEPSEEK_R1', 'DeepSeek R1', -1, 1),
+        (2, 1, 'deepseek-r1:1.5b', 'deepseek-r1:1.5b', -1, 1),
+        (3, 1, 'deepseek-r1:70b', 'deepseek-r1:70b', -1, 1),
+        (4, 1, 'deepseek-r1:671b', 'deepseek-r1:671b', 1, 1),
+    (5, -1, 'DEEPSEEK_API', 'DeepSeek API', -1, 1),
+        (6, 5, 'deepseek-chat', 'deepseek-chat', -1, 1),
+        (7, 5, 'deepseek-reasoner', 'deepseek-reasoner', -1, 1),
+    (8, -1, '混元大模型', 'HUNYUAN', -1, 1)
+;

+ 31 - 0
src/main/java/com/backendsys/modules/ai/chat/controller/ChatModelController.java

@@ -0,0 +1,31 @@
+package com.backendsys.modules.ai.chat.controller;
+
+import com.backendsys.modules.ai.chat.entity.ChatHistory;
+import com.backendsys.modules.ai.chat.service.ChatHistoryService;
+import com.backendsys.modules.ai.chat.service.ChatModelService;
+import com.backendsys.modules.common.config.security.utils.SecurityUtil;
+import com.backendsys.modules.common.utils.Result;
+import io.swagger.v3.oas.annotations.Operation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RestController;
+
+@Validated
+@RestController
+public class ChatModelController {
+
+    @Autowired
+    private ChatModelService chatModelService;
+
+    @Operation(summary = "获取模型列表")
+    @PreAuthorize("@sr.hasPermission('31')")
+    @GetMapping("/api/ai/chat/getChatModelList")
+    public Result getChatModelList() {
+        return Result.success().put("data", chatModelService.selectChatModelList());
+    }
+
+}

+ 14 - 0
src/main/java/com/backendsys/modules/ai/chat/dao/ChatModelDao.java

@@ -0,0 +1,14 @@
+package com.backendsys.modules.ai.chat.dao;
+
+import com.backendsys.modules.ai.chat.entity.ChatModel;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+
+@Mapper
+public interface ChatModelDao extends BaseMapper<ChatModel> {
+
+    List<ChatModel> selectChatModelList(ChatModel chatModel);
+
+}

+ 23 - 0
src/main/java/com/backendsys/modules/ai/chat/entity/ChatModel.java

@@ -0,0 +1,23 @@
+package com.backendsys.modules.ai.chat.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+@TableName("ai_chat_model")
+public class ChatModel {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private Long parent_id;
+    private String label;
+    private String value;
+    @TableField(exist = false)
+    private List<ChatModel> children;
+    private Integer disabled;
+    private Integer status;
+}

+ 11 - 0
src/main/java/com/backendsys/modules/ai/chat/service/ChatModelService.java

@@ -0,0 +1,11 @@
+package com.backendsys.modules.ai.chat.service;
+
+import com.backendsys.modules.ai.chat.entity.ChatModel;
+
+import java.util.List;
+
+public interface ChatModelService {
+
+    List<ChatModel> selectChatModelList();
+
+}

+ 66 - 0
src/main/java/com/backendsys/modules/ai/chat/service/impl/ChatModelServiceImpl.java

@@ -0,0 +1,66 @@
+package com.backendsys.modules.ai.chat.service.impl;
+
+import com.backendsys.modules.ai.chat.dao.ChatModelDao;
+import com.backendsys.modules.ai.chat.entity.ChatModel;
+import com.backendsys.modules.ai.chat.service.ChatModelService;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Service
+public class ChatModelServiceImpl implements ChatModelService {
+
+    @Autowired
+    private ChatModelDao chatModelDao;
+
+    /**
+     * 将平铺的列表转换为树型结构
+     * @param list 平铺的列表
+     * @return 树型结构的列表
+     */
+    private List<ChatModel> convertToTree(List<ChatModel> list) {
+        // 创建一个map,用于存储id和对应的ChatModel对象
+        Map<Long, ChatModel> nodeMap = new HashMap<>();
+        List<ChatModel> rootNodes = new ArrayList<>(); // 存储顶级节点
+
+        // 遍历列表,将所有节点放入map中
+        for (ChatModel node : list) {
+            nodeMap.put(node.getId(), node);
+        }
+
+        // 遍历列表,为每个节点找到其父节点
+        for (ChatModel node : list) {
+            Long parentId = node.getParent_id();
+            if (parentId == -1) {
+                // 如果parent_id为-1,说明是顶级节点
+                rootNodes.add(node);
+            } else {
+                // 如果不是顶级节点,找到其父节点并添加到父节点的children中
+                ChatModel parentNode = nodeMap.get(parentId);
+                if (parentNode != null) {
+                    if (parentNode.getChildren() == null) {
+                        parentNode.setChildren(new ArrayList<>());
+                    }
+                    parentNode.getChildren().add(node);
+                }
+            }
+        }
+
+        return rootNodes;
+    }
+
+
+    @Override
+    public List<ChatModel> selectChatModelList() {
+        List<ChatModel> list = chatModelDao.selectList(new LambdaQueryWrapper<ChatModel>().eq(ChatModel::getStatus, 1));
+        return convertToTree(list);
+    }
+
+
+
+}

+ 4 - 4
src/main/java/com/backendsys/modules/ai/chat/service/impl/ChatServiceImpl.java

@@ -130,20 +130,20 @@ public class ChatServiceImpl implements ChatService {
 
 
                 ChatResult chatResult = null;
-                // ------------------------------------------------------------
+                // -- [Deepseek R1] -------------------------------------------------------
                 if ("DEEPSEEK_R1".equals(model)) {
                     chatResult = ollamaUtil.chatDeepSeek(user_id, model_version, prompt, chatList);
                 }
+                // -- [Deepseek Api] ------------------------------------------------------
                 if ("DEEPSEEK_API".equals(model)) {
                     // [DeepSeek] 发起对话
                     chatResult = deepSeekClient.chatCompletion(user_id, model_version, prompt, chatList);
                 }
-                // ------------------------------------------------------------
+                // -- [腾讯混元大模型] -------------------------------------------------------
                 if ("HUNYUAN".equals(model)) {
-                    // [混元] 发起对话
                     chatResult = hunYuanClient.chatCompletion(user_id, prompt, chatList);
                 }
-                // ------------------------------------------------------------
+                // ------------------------------------------------------------------------
 
                 // [INSERT][思考] THINK
                 String reasoningContent = chatResult.getReasoning_content();

+ 31 - 28
src/main/java/com/backendsys/modules/sdk/deepseek/service/impl/DeepSeekClientImpl.java

@@ -55,19 +55,24 @@ public class DeepSeekClientImpl implements DeepSeekClient {
     @Override
     public ChatResult chatCompletion(Long user_id, String model, String prompt, List<Chat> chatList) {
 
-        long contentDuration = 0L;
+        long replyDuration = 0L;
 
         ChatResult chatResult = new ChatResult();
         try {
             System.out.println("向模型: " + model + " 提问: " + prompt);
 
+            // 记录请求开始时间
+            long allStartTime = System.currentTimeMillis();
+
             // 【多轮对话】
             // https://api-docs.deepseek.com/zh-cn/guides/multi_round_chat
 
-            // - 接口做最大问答限制 (1-字数限制, 2-次数限制)
-
+            // - (还没做) 接口做最大问答限制 (1-字数限制, 2-次数限制)
+            // - (还没做) 超过50条记录的限制
 
             // 加入上下文历史对话
+            System.out.println("---------------------- 历史对话: ----------------------");
+
             List<DSRequestMessage> messages = new ArrayList<>();
             if (chatList != null && !chatList.isEmpty()) {
                 chatList.stream().forEach(chat -> {
@@ -82,7 +87,7 @@ public class DeepSeekClientImpl implements DeepSeekClient {
             // 新的对话内容
             messages.add(new DSRequestMessage("user", prompt));
 
-            System.out.println("---------------------- 历史对话: ----------------------");
+            // 输出全部对话内容
             messages.stream().forEach(msg -> {
                 System.out.println("[" + msg.getRole() + "]: " + msg.getContent());
             });
@@ -97,9 +102,6 @@ public class DeepSeekClientImpl implements DeepSeekClient {
             body.setMessages(messages);
             body.setStream(true);
 
-            // 记录请求开始时间
-            long allStartTime = System.currentTimeMillis();
-
             // 调用 Deepseek API
             try (CloseableHttpClient client = HttpClients.createDefault()) {
 
@@ -117,8 +119,9 @@ public class DeepSeekClientImpl implements DeepSeekClient {
                 ) {
 
                     long apiDuration = System.currentTimeMillis() - allStartTime;   // 接口耗时
-                    long thinkStartTime = 0L;                                       // 开始思考
-                    long reasoningContentDuration = 0L;                             // 思考耗时
+                    
+                    long thinkStartTime = 0L;                            // 开始思考时间
+                    long thinkDuration = 0L;                             // 思考耗时
                     Boolean isThinking = false;
 
                     System.out.println("API 调用耗时: " + apiDuration + " 毫秒");
@@ -128,8 +131,8 @@ public class DeepSeekClientImpl implements DeepSeekClient {
                     ChatSseMessage chatLoadingSseMessage = new ChatSseMessage("LOADING", "正在思考");
                     sseUtil.send(user_id, new SseResponse(SseResponseEnum.DEEPSEEK, chatLoadingSseMessage).toJsonStr());
 
-                    StringBuilder allContent = new StringBuilder();
-                    StringBuilder allReasoningContent = new StringBuilder();
+                    StringBuilder allReplyContent = new StringBuilder();
+                    StringBuilder allThinkContent = new StringBuilder();
 
                     String line;
                     while ((line = reader.readLine()) != null) {
@@ -174,7 +177,7 @@ public class DeepSeekClientImpl implements DeepSeekClient {
                                 sseUtil.send(user_id, new SseResponse(SseResponseEnum.DEEPSEEK, chatSseMessage).toJsonStr());
 
                                 // 收集推理内容
-                                allReasoningContent.append(reasoning_content);
+                                allThinkContent.append(reasoning_content);
                             }
 
                             // [回答] Reply
@@ -184,12 +187,12 @@ public class DeepSeekClientImpl implements DeepSeekClient {
                                 // 停止思考,并计算思考耗时
                                 if (isThinking) {
                                     isThinking = false;
-                                    reasoningContentDuration = thinkStartTime - allStartTime;
-                                    System.out.println("推理耗时: " + reasoningContentDuration + "毫秒");
+                                    thinkDuration = thinkStartTime - allStartTime;
+                                    System.out.println("推理耗时: " + thinkDuration + "毫秒");
                                     System.out.println("-----------------------------------------------");
 
                                     // [SSE] 发送消息
-                                    ChatSseMessage chatSseMessage = new ChatSseMessage("THINK", "[DONE][THINK]", reasoningContentDuration);
+                                    ChatSseMessage chatSseMessage = new ChatSseMessage("THINK", "[DONE][THINK]", thinkDuration);
                                     sseUtil.send(user_id, new SseResponse(SseResponseEnum.DEEPSEEK, chatSseMessage).toJsonStr());
 
                                 }
@@ -201,7 +204,7 @@ public class DeepSeekClientImpl implements DeepSeekClient {
                                 sseUtil.send(user_id, new SseResponse(SseResponseEnum.DEEPSEEK, chatSseMessage).toJsonStr());
 
                                 // 收集回答内容
-                                allContent.append(content);
+                                allReplyContent.append(content);
                             }
 
 
@@ -209,27 +212,27 @@ public class DeepSeekClientImpl implements DeepSeekClient {
                     }
 
                     System.out.println("-------------------- 结束流式回答. --------------------");
-                    contentDuration = System.currentTimeMillis() - allStartTime;
+                    replyDuration = System.currentTimeMillis() - allStartTime;
 
-                    System.out.println("全部推理: " + allReasoningContent);
-                    System.out.println("全部回答: " + allContent);
-                    System.out.println("总输出耗时: " + contentDuration + " 毫秒");
+                    System.out.println("全部推理: " + allThinkContent);
+                    System.out.println("全部回答: " + allReplyContent);
+                    System.out.println("总输出耗时: " + replyDuration + " 毫秒");
 
 //                    // [SSE] 发送消息
-//                    ChatSseMessage chatSseMessage = new ChatSseMessage("REPLY", "[DONE][REPLY]", contentDuration);
+//                    ChatSseMessage chatSseMessage = new ChatSseMessage("REPLY", "[DONE][REPLY]", replyDuration);
 //                    sseUtil.send(user_id, new SseResponse(SseResponseEnum.DEEPSEEK, chatSseMessage).toJsonStr());
 
-                    chatResult.setReasoning_content(allReasoningContent.toString());
-                    chatResult.setReasoning_duration(reasoningContentDuration);
-                    chatResult.setContent(allContent.toString());
-                    chatResult.setContent_duration(contentDuration);
+                    chatResult.setReasoning_content(allThinkContent.toString());
+                    chatResult.setReasoning_duration(thinkDuration);
+                    chatResult.setContent(allReplyContent.toString());
+                    chatResult.setContent_duration(replyDuration);
                     return chatResult;
 
                 }
             } catch (Exception e) {
                 System.out.println(e.getMessage());
                 // [SSE] 发送消息
-                ChatSseMessage chatSseMessage = new ChatSseMessage("REPLY", e.getMessage(), contentDuration);
+                ChatSseMessage chatSseMessage = new ChatSseMessage("REPLY", e.getMessage(), replyDuration);
                 sseUtil.send(user_id, new SseResponse(SseResponseEnum.DEEPSEEK, chatSseMessage).toJsonStr());
 
                 chatResult.setContent(e.getMessage());
@@ -238,14 +241,14 @@ public class DeepSeekClientImpl implements DeepSeekClient {
         } catch (Exception e) {
             System.out.println(e.getMessage());
             // [SSE] 发送消息
-            ChatSseMessage chatSseMessage = new ChatSseMessage("REPLY", e.getMessage(), contentDuration);
+            ChatSseMessage chatSseMessage = new ChatSseMessage("REPLY", e.getMessage(), replyDuration);
             sseUtil.send(user_id, new SseResponse(SseResponseEnum.DEEPSEEK, chatSseMessage).toJsonStr());
 
             chatResult.setContent(e.getMessage());
             return chatResult;
         } finally {
             // [SSE] 发送消息
-            ChatSseMessage chatSseMessage = new ChatSseMessage("REPLY", "[DONE][REPLY]", contentDuration);
+            ChatSseMessage chatSseMessage = new ChatSseMessage("REPLY", "[DONE][REPLY]", replyDuration);
             sseUtil.send(user_id, new SseResponse(SseResponseEnum.DEEPSEEK, chatSseMessage).toJsonStr());
         }
 

+ 82 - 29
src/main/java/com/backendsys/modules/sdk/deepseek/utils/OllamaUtil.java

@@ -1,6 +1,7 @@
 package com.backendsys.modules.sdk.deepseek.utils;
 
 import cn.hutool.core.convert.Convert;
+import cn.hutool.core.util.StrUtil;
 import com.alibaba.fastjson.JSONObject;
 import com.backendsys.modules.ai.chat.entity.Chat;
 import com.backendsys.modules.ai.chat.entity.ChatResult;
@@ -55,7 +56,12 @@ public class OllamaUtil {
         try {
             System.out.println("向模型: " + model + " 提问: " + prompt);
 
-            // - 接口做最大问答限制 (1-字数限制, 2-次数限制)
+            // 记录请求开始时间
+            long allStartTime = System.currentTimeMillis();
+
+            // 加入上下文历史对话
+            System.out.println("---------------------- 历史对话: ----------------------");
+            System.out.println("-----------------------------------------------------");
 
 
 
@@ -71,15 +77,13 @@ public class OllamaUtil {
                 String requestBody = objectMapper.writeValueAsString(requestMap);
                 request.setEntity(new StringEntity(requestBody, StandardCharsets.UTF_8));
 
-                // 记录请求开始时间
-                long allStartTime = System.currentTimeMillis();
-
                 try (CloseableHttpResponse response = client.execute(request);
                      BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), StandardCharsets.UTF_8))) {
 
                     long apiDuration = System.currentTimeMillis() - allStartTime;   // 接口耗时
-                    long thinkStartTime = 0L;                                       // 开始思考
-                    long reasoningContentDuration = 0L;                             // 思考耗时
+
+                    long thinkStartTime = 0L;                            // 开始思考时间
+                    long thinkDuration = 0L;                             // 思考耗时
                     Boolean isThinking = false;
 
                     System.out.println("API 调用耗时: " + apiDuration + " 毫秒");
@@ -89,16 +93,13 @@ public class OllamaUtil {
                     ChatSseMessage chatLoadingSseMessage = new ChatSseMessage("LOADING", "正在思考");
                     sseUtil.send(user_id, new SseResponse(SseResponseEnum.DEEPSEEK, chatLoadingSseMessage).toJsonStr());
 
-                    StringBuilder allContent = new StringBuilder();
-                    StringBuilder allReasoningContent = new StringBuilder();
+                    StringBuilder allReplyContent = new StringBuilder();
+                    StringBuilder allThinkContent = new StringBuilder();
 
                     String line;
                     while ((line = reader.readLine()) != null) {
 
-
-
-
-                        // System.out.println(line);
+                         System.out.println(line);
                         /*
                             ---------------------- line ----------------------
                             {"model":"deepseek-r1:1.5b","created_at":"2025-03-05T10:51:17.443189986Z","response":"\u003cthink\u003e","done":false}
@@ -107,18 +108,57 @@ public class OllamaUtil {
 
                         // 每行数据可以是一个JSON对象,根据实际情况处理
                         JSONObject resJson = JSONObject.parseObject(line);
-                        String responseContent = resJson.getString("response");
+                        String content = resJson.getString("response");
 
-                        System.out.println("content: " + responseContent);
+                        // System.out.println("content: " + content);
                         // content: <think>
                         // content: </think>
 
-                        String dataStr = (new SseResponse(SseResponseEnum.DEEPSEEK, responseContent)).toJsonStr();
-                        sseUtil.send(user_id, dataStr);
-
-
-
-
+                        // 开始思考
+                        if (content.contains("<think>")) {
+                            isThinking = true;
+                            thinkStartTime = System.currentTimeMillis();
+                        }
+                        // 停止思考,并计算思考耗时
+                        if (content.contains("</think>")) {
+                            isThinking = false;
+                            thinkDuration = thinkStartTime - allStartTime;
+                            System.out.println("推理耗时: " + thinkDuration + "毫秒");
+                            System.out.println("-----------------------------------------------");
+
+                            // [SSE] 发送消息
+                            ChatSseMessage chatSseMessage = new ChatSseMessage("THINK", "[DONE][THINK]", thinkDuration);
+                            sseUtil.send(user_id, new SseResponse(SseResponseEnum.DEEPSEEK, chatSseMessage).toJsonStr());
+
+                        }
+
+                        // [思考] Think
+                        if (isThinking) {
+                            System.out.println("think: " + content);
+
+                            if (!content.contains("<think>") && !content.contains("\n\n")) {
+                                // [SSE] 发送消息
+                                ChatSseMessage chatSseMessage = new ChatSseMessage("THINK", content);
+                                sseUtil.send(user_id, new SseResponse(SseResponseEnum.DEEPSEEK, chatSseMessage).toJsonStr());
+
+                                // 收集推理内容
+                                allThinkContent.append(content);
+                            }
+                        }
+
+                        // [回答] Reply
+                        if (!isThinking) {
+                            System.out.println("content: " + content);
+
+                            if (!content.contains("</think>") && !content.contains("\n\n")) {
+                                // [SSE] 发送消息
+                                ChatSseMessage chatSseMessage = new ChatSseMessage("REPLY", content);
+                                sseUtil.send(user_id, new SseResponse(SseResponseEnum.DEEPSEEK, chatSseMessage).toJsonStr());
+
+                                // 收集回答内容
+                                allReplyContent.append(content);
+                            }
+                        }
 
                     }
 
@@ -126,27 +166,40 @@ public class OllamaUtil {
                     System.out.println("-------------------- 结束流式回答. --------------------");
                     contentDuration = System.currentTimeMillis() - allStartTime;
 
-                    System.out.println("全部推理: " + allReasoningContent);
-                    System.out.println("全部回答: " + allContent);
+                    System.out.println("全部推理: " + allThinkContent);
+                    System.out.println("全部回答: " + allReplyContent);
                     System.out.println("总输出耗时: " + contentDuration + " 毫秒");
 
-                    chatResult.setReasoning_content(allReasoningContent.toString());
-                    chatResult.setReasoning_duration(reasoningContentDuration);
-                    chatResult.setContent(allContent.toString());
+                    System.out.println("-----");
+                    System.out.println("Think content: " + allThinkContent.toString());
+                    System.out.println("Think content length: " + allThinkContent.toString().length());
+                    System.out.println("Think content is not empty: " + StrUtil.isNotEmpty(allThinkContent.toString()));
+                    System.out.println("-----");
+
+                    if (StrUtil.isNotEmpty(allThinkContent.toString())) {
+                        chatResult.setReasoning_content(allThinkContent.toString());
+                        chatResult.setReasoning_duration(thinkDuration);
+                    }
+                    chatResult.setContent(allReplyContent.toString());
                     chatResult.setContent_duration(contentDuration);
+
                     return chatResult;
 
                 } catch (Exception e) {
-                    System.out.println(e.getMessage());
+                    System.out.println("Exception(1): " + e.getMessage());
+                    String message = e.getMessage();
+                    if (message.contains("failed to respond")) {
+                        message = "系统繁忙,请稍后再试 (Failed to respond)";
+                    }
                     // [SSE] 发送消息
-                    ChatSseMessage chatSseMessage = new ChatSseMessage("REPLY", e.getMessage(), contentDuration);
+                    ChatSseMessage chatSseMessage = new ChatSseMessage("REPLY", message, contentDuration);
                     sseUtil.send(user_id, new SseResponse(SseResponseEnum.DEEPSEEK, chatSseMessage).toJsonStr());
 
                     chatResult.setContent(e.getMessage());
                     return chatResult;
                 }
             } catch (Exception e) {
-                System.out.println(e.getMessage());
+                System.out.println("Exception(2): " + e.getMessage());
                 // [SSE] 发送消息
                 ChatSseMessage chatSseMessage = new ChatSseMessage("REPLY", e.getMessage(), contentDuration);
                 sseUtil.send(user_id, new SseResponse(SseResponseEnum.DEEPSEEK, chatSseMessage).toJsonStr());
@@ -157,7 +210,7 @@ public class OllamaUtil {
 
 
         } catch (Exception e) {
-            System.out.println(e.getMessage());
+            System.out.println("Exception(3): " + e.getMessage());
             // [SSE] 发送消息
             ChatSseMessage chatSseMessage = new ChatSseMessage("REPLY", e.getMessage(), contentDuration);
             sseUtil.send(user_id, new SseResponse(SseResponseEnum.DEEPSEEK, chatSseMessage).toJsonStr());

+ 26 - 23
src/main/java/com/backendsys/modules/sdk/tencentcloud/huanyuan/service/impl/HunYuanClientImpl.java

@@ -59,7 +59,7 @@ public class HunYuanClientImpl implements HunYuanClient {
     @Override
     public ChatResult chatCompletion(Long user_id, String prompt, List<Chat> chatList) {
 
-        long contentDuration = 0L;
+        long replyDuration = 0L;
 
         ChatResult chatResult = new ChatResult();
         try {
@@ -67,42 +67,45 @@ public class HunYuanClientImpl implements HunYuanClient {
             // System.out.println("向模型: " + model + " 提问: " + prompt);
             System.out.println("向混元模型 提问: " + prompt);
 
-            Credential cred = new Credential(SECRET_ID, SECRET_KEY);
-            ClientProfile clientProfile = new ClientProfile();
-            HunyuanClient client = new HunyuanClient(cred, REGION, clientProfile);
+            // 记录请求开始时间
+            long allStartTime = System.currentTimeMillis();
 
             // 加入上下文历史对话
+            System.out.println("---------------------- 历史对话: ----------------------");
+
             List<Message> messages = new ArrayList<>();
             if (chatList != null && !chatList.isEmpty()) {
                 chatList.stream().forEach(chat -> {
-//                if (!"THINK".equals(chat.getContent_type())) {    // 混元没有 THINK
+                    // 混元没有 THINK
                     messages.add(setMessage(chat.getRole(), chat.getContent()));
-//                }
                 });
                 // 反转列表
-                 Collections.reverse(messages);
+                Collections.reverse(messages);
             }
 
             // 新的对话内容
             messages.add(setMessage("user", prompt));
 
-            System.out.println("---------------------- 历史对话: ----------------------");
+            // 输出全部对话内容
             messages.stream().forEach(msg -> {
                 System.out.println("[" + msg.getRole() + "]: " + msg.getContent());
             });
             System.out.println("-----------------------------------------------------");
 
-            // 构建请求体
+
+            // [混元大模型]
+            Credential cred = new Credential(SECRET_ID, SECRET_KEY);
+            ClientProfile clientProfile = new ClientProfile();
+            HunyuanClient client = new HunyuanClient(cred, REGION, clientProfile);
+
             ChatStdRequest req = new ChatStdRequest();
             req.setMessages(ArrayUtil.toArray(messages, Message.class));
 
             ChatStdResponse resp = client.ChatStd(req);     // 发送对话 (标准版)
-//            ChatProResponse resp = client.ChatPro(req);     // 发送对话 (标准版)
+//            ChatProResponse resp = client.ChatPro(req);     // 发送对话 (专业版)
 
-            // 记录请求开始时间
-            long allStartTime = System.currentTimeMillis();
 
-            StringBuilder allContent = new StringBuilder();
+            StringBuilder allReplyContent = new StringBuilder();
             for (SSEResponseModel.SSE e : resp) {
 
 //                 System.out.println(e.Data);
@@ -129,24 +132,24 @@ public class HunYuanClientImpl implements HunYuanClient {
                 sseUtil.send(user_id, new SseResponse(SseResponseEnum.HUNYUAN, chatSseMessage).toJsonStr());
 
                 // 收集回答内容
-                allContent.append(content);
+                allReplyContent.append(content);
 
             }
 
             System.out.println("-------------------- 结束流式回答. --------------------");
-            contentDuration = System.currentTimeMillis() - allStartTime;
+            replyDuration = System.currentTimeMillis() - allStartTime;
 
-            System.out.println("全部回答: " + allContent);
-            System.out.println("总输出耗时: " + contentDuration + " 毫秒");
+            System.out.println("全部回答: " + allReplyContent);
+            System.out.println("总输出耗时: " + replyDuration + " 毫秒");
 
-            chatResult.setContent(allContent.toString());
-            chatResult.setContent_duration(contentDuration);
+            chatResult.setContent(allReplyContent.toString());
+            chatResult.setContent_duration(replyDuration);
             return chatResult;
 
         } catch (TencentCloudSDKException e) {
             System.out.println("TencentCloudSDKException: " + e.getMessage());
             // [SSE] 发送消息
-            ChatSseMessage chatSseMessage = new ChatSseMessage("REPLY", e.getMessage(), contentDuration);
+            ChatSseMessage chatSseMessage = new ChatSseMessage("REPLY", e.getMessage(), replyDuration);
             sseUtil.send(user_id, new SseResponse(SseResponseEnum.HUNYUAN, chatSseMessage).toJsonStr());
 
             chatResult.setContent(e.getMessage());
@@ -154,7 +157,7 @@ public class HunYuanClientImpl implements HunYuanClient {
         } catch (JsonMappingException e) {
             System.out.println("JsonMappingException: " + e.getMessage());
             // [SSE] 发送消息
-            ChatSseMessage chatSseMessage = new ChatSseMessage("REPLY", e.getMessage(), contentDuration);
+            ChatSseMessage chatSseMessage = new ChatSseMessage("REPLY", e.getMessage(), replyDuration);
             sseUtil.send(user_id, new SseResponse(SseResponseEnum.HUNYUAN, chatSseMessage).toJsonStr());
 
             chatResult.setContent(e.getMessage());
@@ -162,14 +165,14 @@ public class HunYuanClientImpl implements HunYuanClient {
         } catch (JsonProcessingException e) {
             System.out.println("JsonProcessingException: " + e.getMessage());
             // [SSE] 发送消息
-            ChatSseMessage chatSseMessage = new ChatSseMessage("REPLY", e.getMessage(), contentDuration);
+            ChatSseMessage chatSseMessage = new ChatSseMessage("REPLY", e.getMessage(), replyDuration);
             sseUtil.send(user_id, new SseResponse(SseResponseEnum.HUNYUAN, chatSseMessage).toJsonStr());
 
             chatResult.setContent(e.getMessage());
             return chatResult;
         } finally {
             // [SSE] 发送消息
-            ChatSseMessage chatSseMessage = new ChatSseMessage("REPLY", "[DONE][REPLY]", contentDuration);
+            ChatSseMessage chatSseMessage = new ChatSseMessage("REPLY", "[DONE][REPLY]", replyDuration);
             sseUtil.send(user_id, new SseResponse(SseResponseEnum.HUNYUAN, chatSseMessage).toJsonStr());
         }
 

+ 1 - 1
src/main/resources/application-local.yml

@@ -164,7 +164,7 @@ baidu:
 ai:
   config:
     deepseek:
-      # domain: http://localhost:11434
+#      domain: http://localhost:11434
       domain: https://1wd05129tf963.vicp.fun
 
 deepseek:

+ 4 - 1
src/main/resources/mapper/ai/chat/ChatHistoryDao.xml

@@ -26,8 +26,11 @@
     </resultMap>
 
     <!-- 查 列表 -->
+    <!-- COUNT(c.id) chat_count -->
     <select id="selectChatHistoryList" resultMap="resultMapChatHistory">
-        SELECT <include refid="includeChatHistory" />, COUNT(c.id) chat_count
+        SELECT
+            <include refid="includeChatHistory" />,
+            SUM(CASE WHEN c.content_type IS NULL OR c.content_type != 'THINK' THEN 1 ELSE 0 END) AS chat_count
         FROM ai_chat_history ch
         LEFT JOIN ai_chat c ON c.history_code = ch.history_code
         <where>