|
@@ -7,12 +7,13 @@ import com.alibaba.dashscope.common.Role;
|
|
|
import com.alibaba.dashscope.exception.ApiException;
|
|
|
import com.alibaba.dashscope.exception.InputRequiredException;
|
|
|
import com.alibaba.dashscope.exception.NoApiKeyException;
|
|
|
-import com.fasterxml.jackson.databind.JsonNode;
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
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.AiSession;
|
|
|
+import com.usky.ai.service.vo.AiStreamOutputVO;
|
|
|
import com.usky.common.security.utils.SecurityUtils;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
@@ -59,28 +60,24 @@ public class AiChatController {
|
|
|
|
|
|
// 阿里百炼通义千问大模型
|
|
|
@PostMapping(value = "/aliTyqw", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
|
|
|
- public ResponseEntity<StreamingResponseBody> send1(@RequestBody String content, @RequestParam(required = false) String sessionId) throws NoApiKeyException, InputRequiredException {
|
|
|
+ public ResponseEntity<StreamingResponseBody> send1(@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 (sessionId == null || sessionId.isEmpty()) {
|
|
|
+ if (object.containsKey("sessionId")) {
|
|
|
+ sessionId = object.get("sessionId").toString();
|
|
|
+ } else {
|
|
|
sessionId = java.util.UUID.randomUUID().toString();
|
|
|
}
|
|
|
-
|
|
|
+// log.info("会话ID:{}", sessionId);
|
|
|
+// System.out.println("会话ID:" + sessionId);
|
|
|
// 解析 JSON 并提取 "content" 字段的值
|
|
|
String questionText;
|
|
|
- try {
|
|
|
- JsonNode jsonNode = objectMapper.readTree(content);
|
|
|
- questionText = jsonNode.get("content").asText(); // 提取 "content" 字段的值
|
|
|
- } catch (IOException e) {
|
|
|
- log.error("Error parsing JSON content", e);
|
|
|
- return ResponseEntity.badRequest().body(outputStream -> {
|
|
|
- outputStream.write("data: Invalid JSON format\n\n".getBytes(StandardCharsets.UTF_8));
|
|
|
- outputStream.flush();
|
|
|
- });
|
|
|
- }
|
|
|
+ questionText = content; // 提取 "content" 字段的值
|
|
|
|
|
|
// 检查是否已经存在相同的 sessionId
|
|
|
boolean exists = aiSessionMapper.existsBySessionId(sessionId);
|
|
@@ -128,7 +125,7 @@ public class AiChatController {
|
|
|
.messages(messages)
|
|
|
.resultFormat(GenerationParam.ResultFormat.MESSAGE)
|
|
|
.apiKey(apiKey)
|
|
|
- .incrementalOutput(true) // 开启增量输出[^1^]
|
|
|
+ .incrementalOutput(true) // 开启增量输出
|
|
|
.build();
|
|
|
|
|
|
String finalSessionId = sessionId;
|
|
@@ -139,13 +136,35 @@ public class AiChatController {
|
|
|
try {
|
|
|
// 调用流式接口
|
|
|
generation.streamCall(param).blockingForEach(chunk -> {
|
|
|
- // 获取每次生成的内容
|
|
|
- String partialAnswer = chunk.getOutput().getChoices().get(0).getMessage().getContent();
|
|
|
- // 将部分内容写入输出流
|
|
|
- outputStream.write(("data: " + partialAnswer + "\n\n").getBytes(StandardCharsets.UTF_8));
|
|
|
- outputStream.flush();
|
|
|
- // 累加到完整回答内容中
|
|
|
- completeAnswer.append(partialAnswer);
|
|
|
+ try {
|
|
|
+ // 获取每次生成的内容
|
|
|
+ String partialAnswer = chunk.getOutput().getChoices().get(0).getMessage().getContent();
|
|
|
+
|
|
|
+ // 检查内容是否为空,如果为空则跳过
|
|
|
+ if (partialAnswer == null || partialAnswer.trim().isEmpty()) {
|
|
|
+ return; // 如果内容为空,直接返回,不进行后续操作
|
|
|
+ }
|
|
|
+
|
|
|
+ // 构建输出对象
|
|
|
+ AiStreamOutputVO aiStreamOutputVO = new AiStreamOutputVO();
|
|
|
+ aiStreamOutputVO.setSessionId(finalSessionId);
|
|
|
+ aiStreamOutputVO.setReasoningContent(partialAnswer);
|
|
|
+
|
|
|
+ // 转换为 JSON 字符串
|
|
|
+ String newString = objectMapper.writeValueAsString(aiStreamOutputVO);
|
|
|
+
|
|
|
+ // 写入输出流
|
|
|
+ outputStream.write(("data: " + newString + "\n\n").getBytes(StandardCharsets.UTF_8));
|
|
|
+ outputStream.flush(); // 确保立即发送到前端
|
|
|
+
|
|
|
+ // 累加到完整回答内容中
|
|
|
+ completeAnswer.append(partialAnswer);
|
|
|
+
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("Error processing chunk", e);
|
|
|
+ outputStream.write(("data: Error processing chunk\n\n").getBytes(StandardCharsets.UTF_8));
|
|
|
+ outputStream.flush();
|
|
|
+ }
|
|
|
});
|
|
|
|
|
|
// 流式接口调用完成后,将完整回答存入数据库
|
|
@@ -154,7 +173,7 @@ public class AiChatController {
|
|
|
aiQuestion.setSessionId(finalSessionId);
|
|
|
aiQuestion.setUserId(userId);
|
|
|
aiQuestion.setUserName(userName);
|
|
|
- aiQuestion.setQuestion(questionText); // 存入提取的文本
|
|
|
+ aiQuestion.setQuestion(questionText);
|
|
|
aiQuestion.setAnswer(completeAnswer.toString());
|
|
|
aiQuestion.setAskTime(LocalDateTime.now());
|
|
|
aiQuestionMapper.save(aiQuestion);
|
|
@@ -163,9 +182,7 @@ public class AiChatController {
|
|
|
log.error("Error processing request", e);
|
|
|
outputStream.write(("data: Error processing request\n\n").getBytes(StandardCharsets.UTF_8));
|
|
|
outputStream.flush();
|
|
|
- } catch (NoApiKeyException e) {
|
|
|
- throw new RuntimeException(e);
|
|
|
- } catch (InputRequiredException e) {
|
|
|
+ } catch (NoApiKeyException | InputRequiredException e) {
|
|
|
throw new RuntimeException(e);
|
|
|
}
|
|
|
});
|
|
@@ -173,28 +190,24 @@ public class AiChatController {
|
|
|
|
|
|
// 阿里百炼DeepSeek大模型
|
|
|
@PostMapping(value = "/aliDeepSeek", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
|
|
|
- public ResponseEntity<StreamingResponseBody> send2(@RequestBody String content, @RequestParam(required = false) String sessionId) throws NoApiKeyException, InputRequiredException {
|
|
|
+ public ResponseEntity<StreamingResponseBody> send2(@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 (sessionId == null || sessionId.isEmpty()) {
|
|
|
+ if (object.containsKey("sessionId")) {
|
|
|
+ sessionId = object.get("sessionId").toString();
|
|
|
+ } else {
|
|
|
sessionId = java.util.UUID.randomUUID().toString();
|
|
|
}
|
|
|
-
|
|
|
+// log.info("会话ID:{}", sessionId);
|
|
|
+// System.out.println("会话ID:" + sessionId);
|
|
|
// 解析 JSON 并提取 "content" 字段的值
|
|
|
String questionText;
|
|
|
- try {
|
|
|
- JsonNode jsonNode = objectMapper.readTree(content);
|
|
|
- questionText = jsonNode.get("content").asText(); // 提取 "content" 字段的值
|
|
|
- } catch (IOException e) {
|
|
|
- log.error("Error parsing JSON content", e);
|
|
|
- return ResponseEntity.badRequest().body(outputStream -> {
|
|
|
- outputStream.write("data: Invalid JSON format\n\n".getBytes(StandardCharsets.UTF_8));
|
|
|
- outputStream.flush();
|
|
|
- });
|
|
|
- }
|
|
|
+ questionText = content; // 提取 "content" 字段的值
|
|
|
|
|
|
// 检查是否已经存在相同的 sessionId
|
|
|
boolean exists = aiSessionMapper.existsBySessionId(sessionId);
|
|
@@ -253,13 +266,35 @@ public class AiChatController {
|
|
|
try {
|
|
|
// 调用流式接口
|
|
|
generation.streamCall(param).blockingForEach(chunk -> {
|
|
|
- // 获取每次生成的内容
|
|
|
- String partialAnswer = chunk.getOutput().getChoices().get(0).getMessage().getContent();
|
|
|
- // 将部分内容写入输出流
|
|
|
- outputStream.write(("data: " + partialAnswer + "\n\n").getBytes(StandardCharsets.UTF_8));
|
|
|
- outputStream.flush();
|
|
|
- // 累加到完整回答内容中
|
|
|
- completeAnswer.append(partialAnswer);
|
|
|
+ try {
|
|
|
+ // 获取每次生成的内容
|
|
|
+ String partialAnswer = chunk.getOutput().getChoices().get(0).getMessage().getContent();
|
|
|
+
|
|
|
+ // 检查内容是否为空,如果为空则跳过
|
|
|
+ if (partialAnswer == null || partialAnswer.trim().isEmpty()) {
|
|
|
+ return; // 如果内容为空,直接返回,不进行后续操作
|
|
|
+ }
|
|
|
+
|
|
|
+ // 构建输出对象
|
|
|
+ AiStreamOutputVO aiStreamOutputVO = new AiStreamOutputVO();
|
|
|
+ aiStreamOutputVO.setSessionId(finalSessionId);
|
|
|
+ aiStreamOutputVO.setReasoningContent(partialAnswer);
|
|
|
+
|
|
|
+ // 转换为 JSON 字符串
|
|
|
+ String newString = objectMapper.writeValueAsString(aiStreamOutputVO);
|
|
|
+
|
|
|
+ // 写入输出流
|
|
|
+ outputStream.write(("data: " + newString + "\n\n").getBytes(StandardCharsets.UTF_8));
|
|
|
+ outputStream.flush(); // 确保立即发送到前端
|
|
|
+
|
|
|
+ // 累加到完整回答内容中
|
|
|
+ completeAnswer.append(partialAnswer);
|
|
|
+
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("Error processing chunk", e);
|
|
|
+ outputStream.write(("data: Error processing chunk\n\n").getBytes(StandardCharsets.UTF_8));
|
|
|
+ outputStream.flush();
|
|
|
+ }
|
|
|
});
|
|
|
|
|
|
// 流式接口调用完成后,将完整回答存入数据库
|
|
@@ -268,7 +303,7 @@ public class AiChatController {
|
|
|
aiQuestion.setSessionId(finalSessionId);
|
|
|
aiQuestion.setUserId(userId);
|
|
|
aiQuestion.setUserName(userName);
|
|
|
- aiQuestion.setQuestion(questionText); // 存入提取的文本
|
|
|
+ aiQuestion.setQuestion(questionText);
|
|
|
aiQuestion.setAnswer(completeAnswer.toString());
|
|
|
aiQuestion.setAskTime(LocalDateTime.now());
|
|
|
aiQuestionMapper.save(aiQuestion);
|
|
@@ -277,9 +312,7 @@ public class AiChatController {
|
|
|
log.error("Error processing request", e);
|
|
|
outputStream.write(("data: Error processing request\n\n").getBytes(StandardCharsets.UTF_8));
|
|
|
outputStream.flush();
|
|
|
- } catch (NoApiKeyException e) {
|
|
|
- throw new RuntimeException(e);
|
|
|
- } catch (InputRequiredException e) {
|
|
|
+ } catch (NoApiKeyException | InputRequiredException e) {
|
|
|
throw new RuntimeException(e);
|
|
|
}
|
|
|
});
|