Browse Source

Dev 联网搜索

tsurumure 5 months ago
parent
commit
0adc1d4d71

+ 1 - 1
db/__ds_chat.sql

@@ -14,7 +14,7 @@
 #     `user_nickname` VARCHAR(255) COMMENT '用户名',
 #     `role` VARCHAR(255) COMMENT '对话角色 (user, assistant, system, tool)',
 #     `content` VARCHAR(5000) NOT NULL COMMENT '对话内容',
-#     `content_type` VARCHAR(255) NOT NULL COMMENT '对话内容类型 (THINK: 思考, REPLY: 回复)',
+#     `content_type` VARCHAR(255) NOT NULL COMMENT '对话内容类型 (LOADING-加载中, SEARCH-搜索, REPLY-回复, REPLY-回复, REPLY_ABORT-回复中止, THINK-思考, THINK_ABORT-思考中止)',
 #     `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
 #     INDEX `idx_history_code` (`history_code`),
 #     INDEX `idx_user_id` (`user_id`),

+ 1 - 1
db/ai_chat.sql

@@ -12,7 +12,7 @@ CREATE TABLE `ai_chat` (
     `model` VARCHAR(255) COMMENT '模型 (HUNYUAN-混元, DEEPSEEK_API, OLLAMA)',
     `model_version` VARCHAR(255) COMMENT '模型版本 (deepseek-chat, deepseek-reasoner, deepseek-r1:1.5b)',
     `role` VARCHAR(255) COMMENT '对话角色 ("user", "assistant")',
-    `content_type` VARCHAR(255) COMMENT '对话内容类型 (THINK: 思考, REPLY: 回复)',
+    `content_type` VARCHAR(255) COMMENT '对话内容类型 (LOADING-加载中, SEARCH-搜索, REPLY-回复, REPLY-回复, REPLY_ABORT-回复中止, THINK-思考, THINK_ABORT-思考中止)',
     `content` TEXT NOT NULL COMMENT '对话内容',
     `duration` BIGINT COMMENT '耗时',
     `user_id` BIGINT COMMENT '用户ID',

+ 1 - 1
src/main/java/com/backendsys/modules/ai/chat/entity/Chat.java

@@ -47,7 +47,7 @@ public class Chat {
     @Size(max = 5000, message = "对话内容长度不超过 {max} 字符", groups = { Create.class })
     @NotEmpty(message = "对话内容不能为空", groups = { Create.class })
     private String content;
-    private String content_type;    // 对话内容类型 (THINK: 思考, REPLY: 回复)
+    private String content_type;    // 对话内容类型 (LOADING-加载中, SEARCH-搜索, REPLY-回复, REPLY-回复, REPLY_ABORT-回复中止, THINK-思考, THINK_ABORT-思考中止)
     private Long duration;
 
     @TableField(exist = false)

+ 1 - 1
src/main/java/com/backendsys/modules/ai/chat/entity/ChatSseMessage.java

@@ -9,7 +9,7 @@ public class ChatSseMessage {
 
     private String history_code;
     private String content;
-    private String content_type;    // (LOADING-加载中, REPLY-回复, REPLY-回复, REPLY_ABORT-回复中止, THINK-思考, THINK_ABORT-思考中止)
+    private String content_type;    // (LOADING-加载中, SEARCH-搜索, REPLY-回复, REPLY-回复, REPLY_ABORT-回复中止, THINK-思考, THINK_ABORT-思考中止)
     private Long duration;
 
     public ChatSseMessage(String contentType, String content) {

+ 2 - 3
src/main/java/com/backendsys/modules/ai/chat/service/impl/ChatHistoryServiceImpl.java

@@ -54,13 +54,12 @@ public class ChatHistoryServiceImpl implements ChatHistoryService {
         chatHistoryDao.updateById(chatHistoryDetail);
 
         List<Chat> chatList = chatDao.selectList(new LambdaQueryWrapper<Chat>()
-                .eq(Chat::getDel_flag, -1)
-                .eq(Chat::getHistory_code, history_code));
+            .eq(Chat::getDel_flag, -1)
+            .eq(Chat::getHistory_code, history_code));
         if (chatList != null && !chatList.isEmpty()) {
             chatList.stream().forEach(chat -> {
                 // [软删除] 删除对话
                 chat.setDel_flag(1);
-                System.out.println(chat);
                 chatDao.updateById(chat);
             });
         }

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

@@ -140,7 +140,6 @@ public class ChatServiceImpl implements ChatService {
                         .orderByDesc(Chat::getCreate_time)
                         .orderByDesc(Chat::getId)
                 );
-                System.out.println("chatList size: " + chatList.size());
 
                 // [INSERT][提问] 内容
                 Chat userChat = new Chat();
@@ -159,6 +158,8 @@ public class ChatServiceImpl implements ChatService {
                 chatCompletionParam.setChatList(chatList);
                 chatCompletionParam.setInternet(chat.getInternet());
 
+                System.out.println(chatCompletionParam);
+
                 if ("OLLAMA".equals(tag)) {
                     chatResult = ollamaUtil.chatCompletion(chatCompletionParam);
                 }
@@ -185,7 +186,7 @@ public class ChatServiceImpl implements ChatService {
                         BeanUtil.copyProperties(chat, internetChat);
                         //
                         internetChat.setRole("system");
-                        internetChat.setContent("INTERNET");
+                        internetChat.setContent_type("SEARCH");
                         internetChat.setContent(internetContent);
                         internetChat.setDuration(chatResult.getInternet_duration());
                         chatDao.insert(internetChat);

+ 26 - 4
src/main/java/com/backendsys/modules/sdk/bocha/service/impl/BochaServiceImpl.java

@@ -137,13 +137,35 @@ public class BochaServiceImpl implements BochaService {
         if (!bochaResultList.isEmpty()) {
             int index = 1;
             StringBuilder context = new StringBuilder();
+            context.append("{");
             for (BochaResult item : bochaResultList) {
-                context.append("标题: ").append(item.getName()).append("\n");
-                context.append("引用: ").append(item.getSummary()).append("\n");
-                context.append("链接: ").append(item.getUrl()).append("\n\n");
-//                context.append("引用").append(index).append(": ").append(item.getSummary()).append(";\n");
+                context.append("\"" + index + "\":{"+
+                        "\"name\":\"" + item.getName() + "\"," +
+                        "\"summary\":\"" + item.getSummary() + "\"," +
+                        "\"site_icon\":\"" + item.getSiteIcon() + "\"," +
+                        "\"site_name\":\"" + item.getSiteName() + "\"," +
+                        "\"url\":\"" + item.getUrl() + "\"" +
+                    "}" +
+                    ((index == bochaResultList.size()) ? "": ",")
+                );
+
+//                context.append("{"+
+//                    "\"name\":\"" + item.getName() + "\"," +
+//                    "\"summary\":\"" + item.getSummary() + "\"" +
+//                    "\"url\":\"" + item.getUrl() + "\"" +
+//                "},");
+
+//                context.append("标题: ").append(item.getName()).append("\n");
+//                context.append("引用: ").append(item.getSummary()).append("\n");
+//                context.append("链接: ").append(item.getUrl()).append("\n\n");
+
+//                context.append("#quote-start# 引用" + index + ": ")
+//                        .append(item.getSummary())
+//                        .append("#quote-end#;");
+
                 index++;
             }
+            context.append("}");
             // 将搜索结果作为上下文添加到消息中
             return context.toString();
         }

+ 19 - 10
src/main/java/com/backendsys/modules/sdk/deepseek/utils/OllamaUtil.java

@@ -88,6 +88,7 @@ public class OllamaUtil {
             System.out.println("---- 历史对话 (history_code): " + history_code + " ----");
 
             List<DSRequestMessage> messages = new ArrayList<>();
+
             if (chatList != null && !chatList.isEmpty()) {
                 chatList.stream().forEach(chat -> {
                     if (!"THINK".equals(chat.getContent_type())) {
@@ -98,10 +99,12 @@ public class OllamaUtil {
                 Collections.reverse(messages);
             }
 
+            // 【要把搜索到的内容塞到 'user' 里?】
+
             // -- [博查] Web Search API ----------------------------------------------
             if (internet) {
 
-                // 博查、统计接口时间、设置返回参数
+                // 远程查询、统计接口时间、设置返回参数
                 long internetStartTime = System.currentTimeMillis();
                 JsonNode searchResult = bochaService.WebSearch(new BochaParam(prompt));
                 String context = bochaService.WebSearchToString(searchResult);
@@ -111,6 +114,12 @@ public class OllamaUtil {
 
                 // 将搜索结果作为上下文添加到消息中
                 messages.add(new DSRequestMessage("system", context));
+                messages.add(new DSRequestMessage("user", "在回答时引用以上全部数据进行分析")); // 的 "name"、"summary"
+                messages.add(new DSRequestMessage("assistant", "好的"));
+
+                // [SSE] 发送消息
+                ChatSseMessage chatSearchSseMessage = new ChatSseMessage("SEARCH", context, null, history_code);
+                sseUtil.send(user_id, new SseResponse(SseResponseEnum.OLLAMA, chatSearchSseMessage).toJsonStr());
             }
             // -----------------------------------------------------------------------
 
@@ -190,7 +199,7 @@ public class OllamaUtil {
 
                     // [SSE] 发送消息
                     ChatSseMessage chatLoadingSseMessage = new ChatSseMessage("LOADING", "正在思考", null, history_code);
-                    sseUtil.send(user_id, new SseResponse(SseResponseEnum.DEEPSEEK, chatLoadingSseMessage).toJsonStr());
+                    sseUtil.send(user_id, new SseResponse(SseResponseEnum.OLLAMA, chatLoadingSseMessage).toJsonStr());
 
                     String line;
                     while ((line = reader.readLine()) != null) {
@@ -226,9 +235,9 @@ public class OllamaUtil {
                         String errJsonMessage = resJson.getString("error");
                         if (errJsonMessage != null) {
                             // [SSE] 发送消息
-                            sseUtil.send(user_id, new SseResponse(SseResponseEnum.DEEPSEEK, new ChatSseMessage("REPLY", errJsonMessage, contentDuration, history_code)).toJsonStr());
+                            sseUtil.send(user_id, new SseResponse(SseResponseEnum.OLLAMA, new ChatSseMessage("REPLY", errJsonMessage, contentDuration, history_code)).toJsonStr());
                             // [SSE] 发送消息 (完成)
-                            sseUtil.send(user_id, new SseResponse(SseResponseEnum.DEEPSEEK, new ChatSseMessage("REPLY", "[DONE][REPLY]", contentDuration, history_code)).toJsonStr());
+                            sseUtil.send(user_id, new SseResponse(SseResponseEnum.OLLAMA, new ChatSseMessage("REPLY", "[DONE][REPLY]", contentDuration, history_code)).toJsonStr());
                             //
                             chatResult.setContent(errJsonMessage);
                             return chatResult;
@@ -258,7 +267,7 @@ public class OllamaUtil {
                             if (allThinkContent.length() > 0){
                                 // [SSE] 发送消息
                                 ChatSseMessage chatSseMessage = new ChatSseMessage("THINK", "[DONE][THINK]", thinkDuration, history_code);
-                                sseUtil.send(user_id, new SseResponse(SseResponseEnum.DEEPSEEK, chatSseMessage).toJsonStr());
+                                sseUtil.send(user_id, new SseResponse(SseResponseEnum.OLLAMA, chatSseMessage).toJsonStr());
                             }
 
                         }
@@ -268,7 +277,7 @@ public class OllamaUtil {
                             if (!content.contains("<think>") && !content.contains("\n\n") && !content.contains("\n")) {
                                 // [SSE] 发送消息
                                 ChatSseMessage chatSseMessage = new ChatSseMessage("THINK", content, null, history_code);
-                                sseUtil.send(user_id, new SseResponse(SseResponseEnum.DEEPSEEK, chatSseMessage).toJsonStr());
+                                sseUtil.send(user_id, new SseResponse(SseResponseEnum.OLLAMA, chatSseMessage).toJsonStr());
                                 // 收集推理内容
                                 allThinkContent.append(content);
                             }
@@ -286,7 +295,7 @@ public class OllamaUtil {
 
                                     // [SSE] 发送消息
                                     ChatSseMessage chatSseMessage = new ChatSseMessage("REPLY", content, null, history_code);
-                                    sseUtil.send(user_id, new SseResponse(SseResponseEnum.DEEPSEEK, chatSseMessage).toJsonStr());
+                                    sseUtil.send(user_id, new SseResponse(SseResponseEnum.OLLAMA, chatSseMessage).toJsonStr());
                                     // 收集回答内容
                                     allReplyContent.append(content);
 
@@ -325,7 +334,7 @@ public class OllamaUtil {
                     // [SSE] 发送消息
                     String contentType = (isThinking ? "THINK_ABORT" : "REPLY_ABORT");
                     ChatSseMessage chatSseMessage = new ChatSseMessage(contentType, message, contentDuration, history_code);
-                    sseUtil.send(user_id, new SseResponse(SseResponseEnum.DEEPSEEK, chatSseMessage).toJsonStr());
+                    sseUtil.send(user_id, new SseResponse(SseResponseEnum.OLLAMA, chatSseMessage).toJsonStr());
 
 //                    chatResult.setContent(e.getMessage());
 
@@ -350,7 +359,7 @@ public class OllamaUtil {
                 // [SSE] 发送消息
                 String contentType = (isThinking ? "THINK_ABORT" : "REPLY_ABORT");
                 ChatSseMessage chatSseMessage = new ChatSseMessage(contentType, e.getMessage(), contentDuration, history_code);
-                sseUtil.send(user_id, new SseResponse(SseResponseEnum.DEEPSEEK, chatSseMessage).toJsonStr());
+                sseUtil.send(user_id, new SseResponse(SseResponseEnum.OLLAMA, chatSseMessage).toJsonStr());
 
                 redisUtil.delete(requestOfRedisKey);
 
@@ -360,7 +369,7 @@ public class OllamaUtil {
 
                 // [SSE] 发送消息 (完成)
                 ChatSseMessage chatSseMessage = new ChatSseMessage("REPLY", "[DONE][REPLY]", contentDuration, history_code);
-                sseUtil.send(user_id, new SseResponse(SseResponseEnum.DEEPSEEK, chatSseMessage).toJsonStr());
+                sseUtil.send(user_id, new SseResponse(SseResponseEnum.OLLAMA, chatSseMessage).toJsonStr());
 
             }
 

+ 1 - 0
src/main/java/com/backendsys/modules/sse/entity/SseResponseEnum.java

@@ -7,6 +7,7 @@ public enum SseResponseEnum {
     LOGOUT("logout", "退出登录"),
     NOTICE("notice", "通知"),
     UPLOAD("upload", "上传"),
+    OLLAMA("ollama", "Ollama"),
     DEEPSEEK("deepseek", "Deepseek"),
     HUNYUAN("hunyuan", "Hunyuan");