|
@@ -5,6 +5,7 @@ import com.alibaba.dashscope.aigc.generation.GenerationParam;
|
|
|
import com.alibaba.dashscope.aigc.generation.GenerationResult;
|
|
|
import com.alibaba.dashscope.common.Message;
|
|
|
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;
|
|
@@ -58,34 +59,33 @@ public class AiChatController {
|
|
|
// 如果没有传入 sessionId,则创建一个新的会话ID
|
|
|
if (sessionId == null || sessionId.isEmpty()) {
|
|
|
sessionId = java.util.UUID.randomUUID().toString();
|
|
|
+ }
|
|
|
|
|
|
+ // 解析 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();
|
|
|
+ });
|
|
|
+ }
|
|
|
|
|
|
- // 解析 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("Invalid JSON format".getBytes(StandardCharsets.UTF_8));
|
|
|
- outputStream.flush();
|
|
|
- });
|
|
|
- }
|
|
|
-
|
|
|
- // 检查是否已经存在相同的 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);
|
|
|
- }
|
|
|
+ // 检查是否已经存在相同的 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);
|
|
|
}
|
|
|
|
|
|
// 获取当前用户的对话历史
|
|
@@ -99,18 +99,13 @@ public class AiChatController {
|
|
|
.build())
|
|
|
.collect(Collectors.toList());
|
|
|
|
|
|
- // 解析 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("Invalid JSON format".getBytes(StandardCharsets.UTF_8));
|
|
|
- outputStream.flush();
|
|
|
- });
|
|
|
- }
|
|
|
+ // 插入角色定义(在对话历史的开头)
|
|
|
+ Message roleDefinition = Message.builder()
|
|
|
+ .role(Role.SYSTEM.getValue()) // 使用系统角色
|
|
|
+// .content("你是一个名为'永天小天Ai'的智能助手,擅长幽默和简洁的回答。") // 定义角色的行为和风格
|
|
|
+ .content("你是一个名为'小天Ai'的智能助手,擅长解答编程和技术问题。回答时请保持专业、清晰且简洁。") // 定义角色的行为和风格
|
|
|
+ .build();
|
|
|
+ messages.add(0, roleDefinition); // 将角色定义插入到对话历史的开头
|
|
|
|
|
|
// 添加用户的新消息
|
|
|
Message userMessage = Message.builder()
|
|
@@ -124,41 +119,46 @@ public class AiChatController {
|
|
|
.model("qwen-turbo")
|
|
|
.messages(messages)
|
|
|
.resultFormat(GenerationParam.ResultFormat.MESSAGE)
|
|
|
- .topP(0.8)
|
|
|
.apiKey(apiKey)
|
|
|
- .enableSearch(true)
|
|
|
+ .incrementalOutput(true) // 开启增量输出[^1^]
|
|
|
.build();
|
|
|
|
|
|
String finalSessionId = sessionId;
|
|
|
+ StringBuilder completeAnswer = new StringBuilder(); // 用于收集完整的回答内容
|
|
|
return ResponseEntity.ok()
|
|
|
.contentType(MediaType.TEXT_EVENT_STREAM)
|
|
|
.body(outputStream -> {
|
|
|
try {
|
|
|
- GenerationResult generationResult = generation.call(param);
|
|
|
-
|
|
|
- // 获取回答内容
|
|
|
- String answer = generationResult.getOutput().getChoices().get(0).getMessage().getContent();
|
|
|
-
|
|
|
- // 将回答内容写入输出流
|
|
|
- outputStream.write(answer.getBytes(StandardCharsets.UTF_8));
|
|
|
- outputStream.flush();
|
|
|
-
|
|
|
- // 创建实体并保存到数据库
|
|
|
+ // 调用流式接口
|
|
|
+ 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);
|
|
|
+ });
|
|
|
+
|
|
|
+ // 流式接口调用完成后,将完整回答存入数据库
|
|
|
AiQuestion aiQuestion = new AiQuestion();
|
|
|
aiQuestion.setModel("qwen-turbo");
|
|
|
aiQuestion.setSessionId(finalSessionId);
|
|
|
aiQuestion.setUserId(userId);
|
|
|
aiQuestion.setUserName(userName);
|
|
|
aiQuestion.setQuestion(questionText); // 存入提取的文本
|
|
|
- aiQuestion.setAnswer(answer);
|
|
|
+ aiQuestion.setAnswer(completeAnswer.toString());
|
|
|
aiQuestion.setAskTime(LocalDateTime.now());
|
|
|
aiQuestionMapper.save(aiQuestion);
|
|
|
- } catch (IOException | NoApiKeyException | InputRequiredException e) {
|
|
|
+
|
|
|
+ } catch (ApiException e) {
|
|
|
log.error("Error processing request", e);
|
|
|
- outputStream.write("Error processing request".getBytes(StandardCharsets.UTF_8));
|
|
|
+ outputStream.write(("data: Error processing request\n\n").getBytes(StandardCharsets.UTF_8));
|
|
|
outputStream.flush();
|
|
|
- } finally {
|
|
|
- outputStream.close();
|
|
|
+ } catch (NoApiKeyException e) {
|
|
|
+ throw new RuntimeException(e);
|
|
|
+ } catch (InputRequiredException e) {
|
|
|
+ throw new RuntimeException(e);
|
|
|
}
|
|
|
});
|
|
|
}
|
|
@@ -173,33 +173,33 @@ public class AiChatController {
|
|
|
// 如果没有传入 sessionId,则创建一个新的会话ID
|
|
|
if (sessionId == null || sessionId.isEmpty()) {
|
|
|
sessionId = java.util.UUID.randomUUID().toString();
|
|
|
+ }
|
|
|
|
|
|
- // 解析 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("Invalid JSON format".getBytes(StandardCharsets.UTF_8));
|
|
|
- outputStream.flush();
|
|
|
- });
|
|
|
- }
|
|
|
-
|
|
|
- // 检查是否已经存在相同的 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);
|
|
|
- }
|
|
|
+ // 解析 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();
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查是否已经存在相同的 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);
|
|
|
}
|
|
|
|
|
|
// 获取当前用户的对话历史
|
|
@@ -213,18 +213,13 @@ public class AiChatController {
|
|
|
.build())
|
|
|
.collect(Collectors.toList());
|
|
|
|
|
|
- // 解析 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("Invalid JSON format".getBytes(StandardCharsets.UTF_8));
|
|
|
- outputStream.flush();
|
|
|
- });
|
|
|
- }
|
|
|
+ // 插入角色定义(在对话历史的开头)
|
|
|
+ Message roleDefinition = Message.builder()
|
|
|
+ .role(Role.SYSTEM.getValue()) // 使用系统角色
|
|
|
+// .content("你是一个名为'永天小天Ai'的智能助手,擅长幽默和简洁的回答。") // 定义角色的行为和风格
|
|
|
+ .content("你是一个名为'小天Ai'的智能助手,擅长解答编程和技术问题。回答时请保持专业、清晰且简洁。") // 定义角色的行为和风格
|
|
|
+ .build();
|
|
|
+ messages.add(0, roleDefinition); // 将角色定义插入到对话历史的开头
|
|
|
|
|
|
// 添加用户的新消息
|
|
|
Message userMessage = Message.builder()
|
|
@@ -239,38 +234,45 @@ public class AiChatController {
|
|
|
.messages(messages)
|
|
|
.resultFormat(GenerationParam.ResultFormat.MESSAGE)
|
|
|
.apiKey(apiKey)
|
|
|
+ .incrementalOutput(true) // 开启增量输出[^1^]
|
|
|
.build();
|
|
|
|
|
|
String finalSessionId = sessionId;
|
|
|
+ StringBuilder completeAnswer = new StringBuilder(); // 用于收集完整的回答内容
|
|
|
return ResponseEntity.ok()
|
|
|
.contentType(MediaType.TEXT_EVENT_STREAM)
|
|
|
.body(outputStream -> {
|
|
|
try {
|
|
|
- GenerationResult generationResult = generation.call(param);
|
|
|
-
|
|
|
- // 获取回答内容
|
|
|
- String answer = generationResult.getOutput().getChoices().get(0).getMessage().getContent();
|
|
|
-
|
|
|
- // 将回答内容写入输出流
|
|
|
- outputStream.write(answer.getBytes(StandardCharsets.UTF_8));
|
|
|
- outputStream.flush();
|
|
|
-
|
|
|
- // 创建实体并保存到数据库
|
|
|
+ // 调用流式接口
|
|
|
+ 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);
|
|
|
+ });
|
|
|
+
|
|
|
+ // 流式接口调用完成后,将完整回答存入数据库
|
|
|
AiQuestion aiQuestion = new AiQuestion();
|
|
|
- aiQuestion.setModel("deepseek-v3");
|
|
|
+ aiQuestion.setModel("qwen-turbo");
|
|
|
aiQuestion.setSessionId(finalSessionId);
|
|
|
aiQuestion.setUserId(userId);
|
|
|
aiQuestion.setUserName(userName);
|
|
|
aiQuestion.setQuestion(questionText); // 存入提取的文本
|
|
|
- aiQuestion.setAnswer(answer);
|
|
|
+ aiQuestion.setAnswer(completeAnswer.toString());
|
|
|
aiQuestion.setAskTime(LocalDateTime.now());
|
|
|
aiQuestionMapper.save(aiQuestion);
|
|
|
- } catch (IOException | NoApiKeyException | InputRequiredException e) {
|
|
|
+
|
|
|
+ } catch (ApiException e) {
|
|
|
log.error("Error processing request", e);
|
|
|
- outputStream.write("Error processing request".getBytes(StandardCharsets.UTF_8));
|
|
|
+ outputStream.write(("data: Error processing request\n\n").getBytes(StandardCharsets.UTF_8));
|
|
|
outputStream.flush();
|
|
|
- } finally {
|
|
|
- outputStream.close();
|
|
|
+ } catch (NoApiKeyException e) {
|
|
|
+ throw new RuntimeException(e);
|
|
|
+ } catch (InputRequiredException e) {
|
|
|
+ throw new RuntimeException(e);
|
|
|
}
|
|
|
});
|
|
|
}
|