|
@@ -1,11 +1,14 @@
|
|
|
package com.backendsys.modules.sdk.deepseek.utils;
|
|
|
|
|
|
import cn.hutool.core.convert.Convert;
|
|
|
+import cn.hutool.core.util.NumberUtil;
|
|
|
+import cn.hutool.core.util.ObjectUtil;
|
|
|
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;
|
|
|
import com.backendsys.modules.ai.chat.entity.ChatSseMessage;
|
|
|
+import com.backendsys.modules.common.config.redis.utils.RedisUtil;
|
|
|
import com.backendsys.modules.sdk.deepseek.entity.DSRequest;
|
|
|
import com.backendsys.modules.sdk.deepseek.entity.DSRequestMessage;
|
|
|
import com.backendsys.modules.sse.entity.SseResponse;
|
|
@@ -38,6 +41,8 @@ public class OllamaUtil {
|
|
|
|
|
|
@Autowired
|
|
|
private SseUtil sseUtil;
|
|
|
+ @Autowired
|
|
|
+ private RedisUtil redisUtil;
|
|
|
|
|
|
@Value("${spring.application.name}")
|
|
|
private String APPLICATION_NAME;
|
|
@@ -48,19 +53,17 @@ public class OllamaUtil {
|
|
|
/**
|
|
|
* 流式对话
|
|
|
*/
|
|
|
- public ChatResult chatDeepSeek(Long user_id, String model, String prompt, String history_code, List<Chat> chatList) {
|
|
|
+ public ChatResult chatCompletion(Long user_id, String model, String prompt, String history_code, List<Chat> chatList) {
|
|
|
|
|
|
- long contentDuration = 0L;
|
|
|
+ Long contentDuration = 0L;
|
|
|
|
|
|
ChatResult chatResult = new ChatResult();
|
|
|
- try {
|
|
|
+// try {
|
|
|
System.out.println("向模型: " + model + " 提问: " + prompt);
|
|
|
|
|
|
// 记录请求开始时间
|
|
|
long allStartTime = System.currentTimeMillis();
|
|
|
|
|
|
-
|
|
|
-
|
|
|
// 加入上下文历史对话
|
|
|
System.out.println("---- 历史对话 (history_code): " + history_code + " ----");
|
|
|
|
|
@@ -84,7 +87,11 @@ public class OllamaUtil {
|
|
|
});
|
|
|
System.out.println("---------------------------------------------------------------------");
|
|
|
|
|
|
-
|
|
|
+ // 定义作用于全局的变量
|
|
|
+ Boolean isThinking = false;
|
|
|
+ StringBuilder allReplyContent = new StringBuilder();
|
|
|
+ StringBuilder allThinkContent = new StringBuilder();
|
|
|
+ String requestOfRedisKey = APPLICATION_NAME + "-chat-history-" + history_code;
|
|
|
|
|
|
ObjectMapper objectMapper = new ObjectMapper();
|
|
|
try (CloseableHttpClient client = HttpClients.createDefault()) {
|
|
@@ -135,6 +142,7 @@ public class OllamaUtil {
|
|
|
|
|
|
request.setEntity(new StringEntity(requestBody, StandardCharsets.UTF_8));
|
|
|
|
|
|
+
|
|
|
try (CloseableHttpResponse response = client.execute(request);
|
|
|
BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), StandardCharsets.UTF_8))) {
|
|
|
|
|
@@ -142,7 +150,7 @@ public class OllamaUtil {
|
|
|
|
|
|
long thinkStartTime = 0L; // 开始思考时间
|
|
|
long thinkDuration = 0L; // 思考耗时
|
|
|
- Boolean isThinking = false;
|
|
|
+
|
|
|
|
|
|
System.out.println("API 调用耗时: " + apiDuration + " 毫秒");
|
|
|
System.out.println("---- 开始流式回答: ------------------------------------");
|
|
@@ -151,12 +159,20 @@ public class OllamaUtil {
|
|
|
ChatSseMessage chatLoadingSseMessage = new ChatSseMessage("LOADING", "正在思考");
|
|
|
sseUtil.send(user_id, new SseResponse(SseResponseEnum.DEEPSEEK, chatLoadingSseMessage).toJsonStr());
|
|
|
|
|
|
- StringBuilder allReplyContent = new StringBuilder();
|
|
|
- StringBuilder allThinkContent = new StringBuilder();
|
|
|
-
|
|
|
String line;
|
|
|
while ((line = reader.readLine()) != null) {
|
|
|
|
|
|
+
|
|
|
+ // 判断是否中止
|
|
|
+ if (ObjectUtil.isEmpty(redisUtil.getCacheObject(requestOfRedisKey))) {
|
|
|
+ System.out.println("中止!");
|
|
|
+ request.abort();
|
|
|
+ // 流程结束后,删除锁
|
|
|
+ redisUtil.delete(requestOfRedisKey);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
// System.out.println(line);
|
|
|
/*
|
|
|
---------------------- [Chat] line ----------------------
|
|
@@ -259,47 +275,74 @@ public class OllamaUtil {
|
|
|
chatResult.setContent(allReplyContent.toString());
|
|
|
chatResult.setContent_duration(contentDuration);
|
|
|
|
|
|
+ // [SSE] 发送消息 (完成)
|
|
|
+ ChatSseMessage chatSseMessage = new ChatSseMessage("REPLY", "[DONE][REPLY]", contentDuration);
|
|
|
+ sseUtil.send(user_id, new SseResponse(SseResponseEnum.DEEPSEEK, chatSseMessage).toJsonStr());
|
|
|
+
|
|
|
return chatResult;
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
System.out.println("Exception(1): " + e.getMessage());
|
|
|
String message = e.getMessage();
|
|
|
if (message.contains("failed to respond")) {
|
|
|
- message = "系统繁忙,请稍后再试 (Failed to respond)";
|
|
|
+ message = "(系统繁忙,请稍后再试)";
|
|
|
+ }
|
|
|
+ if (message.contains("Premature end of chunk coded message body: closing chunk expected")) {
|
|
|
+ message = "(请求中止)";
|
|
|
}
|
|
|
// [SSE] 发送消息
|
|
|
- ChatSseMessage chatSseMessage = new ChatSseMessage("REPLY", message, contentDuration);
|
|
|
+ String contentType = (isThinking ? "THINK_ABORT" : "REPLY_ABORT");
|
|
|
+ ChatSseMessage chatSseMessage = new ChatSseMessage(contentType, message, contentDuration);
|
|
|
sseUtil.send(user_id, new SseResponse(SseResponseEnum.DEEPSEEK, chatSseMessage).toJsonStr());
|
|
|
|
|
|
- chatResult.setContent(e.getMessage());
|
|
|
- e.printStackTrace();
|
|
|
+// chatResult.setContent(e.getMessage());
|
|
|
+
|
|
|
+ // 由于中止导致的错误信息叠加 (一并保存进数据库)
|
|
|
+ if (StrUtil.isNotEmpty(allThinkContent.toString())) {
|
|
|
+ if (isThinking) {
|
|
|
+ chatResult.setReasoning_content(allThinkContent.toString() + " " + message);
|
|
|
+ } else {
|
|
|
+ chatResult.setReasoning_content(allThinkContent.toString());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ chatResult.setContent(allReplyContent.toString() + " " + message);
|
|
|
+
|
|
|
+ redisUtil.delete(requestOfRedisKey);
|
|
|
|
|
|
return chatResult;
|
|
|
+
|
|
|
+// return chatResult;
|
|
|
}
|
|
|
} catch (Exception e) {
|
|
|
System.out.println("Exception(2): " + e.getMessage());
|
|
|
// [SSE] 发送消息
|
|
|
- ChatSseMessage chatSseMessage = new ChatSseMessage("REPLY", e.getMessage(), contentDuration);
|
|
|
+ String contentType = (isThinking ? "THINK_ABORT" : "REPLY_ABORT");
|
|
|
+ ChatSseMessage chatSseMessage = new ChatSseMessage(contentType, e.getMessage(), contentDuration);
|
|
|
sseUtil.send(user_id, new SseResponse(SseResponseEnum.DEEPSEEK, chatSseMessage).toJsonStr());
|
|
|
|
|
|
+ redisUtil.delete(requestOfRedisKey);
|
|
|
+
|
|
|
chatResult.setContent(e.getMessage());
|
|
|
return chatResult;
|
|
|
}
|
|
|
|
|
|
|
|
|
- } catch (Exception e) {
|
|
|
- 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());
|
|
|
-
|
|
|
- chatResult.setContent(e.getMessage());
|
|
|
- return chatResult;
|
|
|
- } finally {
|
|
|
- // [SSE] 发送消息
|
|
|
- ChatSseMessage chatSseMessage = new ChatSseMessage("REPLY", "[DONE][REPLY]", contentDuration);
|
|
|
- sseUtil.send(user_id, new SseResponse(SseResponseEnum.DEEPSEEK, chatSseMessage).toJsonStr());
|
|
|
- }
|
|
|
+// } catch (Exception e) {
|
|
|
+// 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());
|
|
|
+//
|
|
|
+// chatResult.setContent(e.getMessage());
|
|
|
+// return chatResult;
|
|
|
+// }
|
|
|
+
|
|
|
+// } finally {
|
|
|
+// System.out.println("Finally.");
|
|
|
+// // [SSE] 发送消息
|
|
|
+// ChatSseMessage chatSseMessage = new ChatSseMessage("REPLY", "[DONE][REPLY]", contentDuration);
|
|
|
+// sseUtil.send(user_id, new SseResponse(SseResponseEnum.DEEPSEEK, chatSseMessage).toJsonStr());
|
|
|
+// }
|
|
|
|
|
|
}
|
|
|
}
|