|
@@ -0,0 +1,536 @@
|
|
|
+package com.usky.ai.controller.web;
|
|
|
+
|
|
|
+import com.alibaba.dashscope.aigc.generation.Generation;
|
|
|
+import com.alibaba.dashscope.aigc.generation.GenerationParam;
|
|
|
+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.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.AiQuestionItem;
|
|
|
+import com.usky.ai.service.AiSession;
|
|
|
+import com.usky.ai.service.vo.AiStreamOutputVO;
|
|
|
+import com.usky.common.core.bean.ApiResult;
|
|
|
+import com.usky.common.security.utils.SecurityUtils;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.beans.factory.annotation.Value;
|
|
|
+import org.springframework.http.HttpStatus;
|
|
|
+import org.springframework.http.MediaType;
|
|
|
+import org.springframework.http.ResponseEntity;
|
|
|
+import org.springframework.web.bind.annotation.*;
|
|
|
+import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
|
|
|
+
|
|
|
+import javax.annotation.Resource;
|
|
|
+import java.io.IOException;
|
|
|
+import java.nio.charset.StandardCharsets;
|
|
|
+import java.time.LocalDateTime;
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.List;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+@Slf4j
|
|
|
+@RestController
|
|
|
+@RequestMapping("/ai")
|
|
|
+public class AiChatController {
|
|
|
+
|
|
|
+ @Value("${ai.api.key}")
|
|
|
+ private String apiKey;
|
|
|
+
|
|
|
+ @Value("${airole}")
|
|
|
+ private String aiRole;
|
|
|
+
|
|
|
+ @Value("${aliTyqw.model}")
|
|
|
+ private String tyqwModel;
|
|
|
+
|
|
|
+ @Value("${aliDpsk.model}")
|
|
|
+ private String dpskModel;
|
|
|
+
|
|
|
+ @Value("${ai.historyLimit}")
|
|
|
+ private int Limit;
|
|
|
+
|
|
|
+ @Value("${ai.millis}")
|
|
|
+ private int millis;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private Generation generation;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private AiQuestionMapper aiQuestionMapper;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private AiSessionMapper aiSessionMapper;
|
|
|
+
|
|
|
+ private final ObjectMapper objectMapper = new ObjectMapper();
|
|
|
+
|
|
|
+ // 阿里百炼通义千问大模型(修改后)
|
|
|
+ @PostMapping(value = "/aliTyqw", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
|
|
|
+ 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 (object.containsKey("sessionId")) {
|
|
|
+ sessionId = object.get("sessionId").toString();
|
|
|
+ } else {
|
|
|
+ sessionId = java.util.UUID.randomUUID().toString();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 解析 JSON 并提取 "content" 字段的值
|
|
|
+ String questionText = content;
|
|
|
+
|
|
|
+ // 检查是否已经存在相同的 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);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 构建消息列表,包含角色定义、历史对话记录和用户新消息
|
|
|
+ List<Message> messages = new ArrayList<>();
|
|
|
+
|
|
|
+ // 插入角色定义(在对话历史的开头)
|
|
|
+ Message roleDefinition = Message.builder()
|
|
|
+ .role(Role.SYSTEM.getValue()) // 使用系统角色
|
|
|
+ .content(aiRole) // 定义角色的行为和风格
|
|
|
+ .build();
|
|
|
+ messages.add(roleDefinition); // 将角色定义插入到对话历史的开头
|
|
|
+
|
|
|
+ // 从数据库中获取历史对话记录
|
|
|
+ List<AiQuestion> questions = aiQuestionMapper.findQuestionsBySessionId(sessionId);
|
|
|
+
|
|
|
+ // 如果历史记录超过限制,则只取最近的记录
|
|
|
+ if (questions.size() > Limit) {
|
|
|
+ questions = questions.subList(questions.size() - Limit, questions.size());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 将历史对话记录转换为 AiQuestionItem 列表
|
|
|
+ List<AiQuestionItem> itemList = new ArrayList<>();
|
|
|
+ for (AiQuestion question : questions) {
|
|
|
+ AiQuestionItem userItem = new AiQuestionItem("user", question.getQuestion());
|
|
|
+ userItem.setId(question.getId());
|
|
|
+ userItem.setSessionId(question.getSessionId());
|
|
|
+ userItem.setUserId(question.getUserId());
|
|
|
+ userItem.setUserName(question.getUserName());
|
|
|
+ userItem.setAskTime(question.getAskTime());
|
|
|
+
|
|
|
+ AiQuestionItem assistantItem = new AiQuestionItem("assistant", question.getAnswer());
|
|
|
+ assistantItem.setId(question.getId());
|
|
|
+ assistantItem.setSessionId(question.getSessionId());
|
|
|
+ assistantItem.setUserId(question.getUserId());
|
|
|
+ assistantItem.setUserName(question.getUserName());
|
|
|
+ assistantItem.setAskTime(question.getAskTime());
|
|
|
+
|
|
|
+ itemList.add(userItem);
|
|
|
+ itemList.add(assistantItem);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 将 AiQuestionItem 列表转换为消息列表
|
|
|
+ for (AiQuestionItem item : itemList) {
|
|
|
+ Message message = Message.builder()
|
|
|
+ .role(item.getRole().equals("user") ? Role.USER.getValue() : Role.ASSISTANT.getValue())
|
|
|
+ .content(item.getContent() != null ? item.getContent() : item.getReasoningContent())
|
|
|
+ .build();
|
|
|
+ messages.add(message);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 添加用户的新消息
|
|
|
+ Message userMessage = Message.builder()
|
|
|
+ .role(Role.USER.getValue())
|
|
|
+ .content(questionText) // 使用提取的文本
|
|
|
+ .build();
|
|
|
+ messages.add(userMessage);
|
|
|
+
|
|
|
+ // 构建模型调用参数
|
|
|
+ GenerationParam param = GenerationParam.builder()
|
|
|
+ .model(tyqwModel)
|
|
|
+ .messages(messages)
|
|
|
+ .resultFormat(GenerationParam.ResultFormat.MESSAGE)
|
|
|
+ .topP(0.8)
|
|
|
+ .apiKey(apiKey)
|
|
|
+ .incrementalOutput(true) // 开启增量输出
|
|
|
+ .enableSearch(true) // 联网搜索
|
|
|
+ .build();
|
|
|
+
|
|
|
+ String finalSessionId = sessionId;
|
|
|
+ StringBuilder completeAnswer = new StringBuilder(); // 用于收集完整的回答内容
|
|
|
+ return ResponseEntity.ok()
|
|
|
+ .contentType(MediaType.TEXT_EVENT_STREAM)
|
|
|
+ .body(outputStream -> {
|
|
|
+ try {
|
|
|
+// 调用流式接口
|
|
|
+ generation.streamCall(param).blockingForEach(chunk -> {
|
|
|
+ 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);
|
|
|
+
|
|
|
+ // 添加延迟
|
|
|
+ try {
|
|
|
+ Thread.sleep(millis); // 延迟*毫秒
|
|
|
+ } catch (InterruptedException e) {
|
|
|
+ Thread.currentThread().interrupt();
|
|
|
+ log.error("Thread interrupted", e);
|
|
|
+ }
|
|
|
+
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("Error processing chunk", e);
|
|
|
+ outputStream.write(("data: Error processing chunk\n\n").getBytes(StandardCharsets.UTF_8));
|
|
|
+ outputStream.flush();
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ // 流式接口调用完成后,将完整回答存入数据库
|
|
|
+ AiQuestion aiQuestion = new AiQuestion();
|
|
|
+ aiQuestion.setModel(tyqwModel);
|
|
|
+ aiQuestion.setSessionId(finalSessionId);
|
|
|
+ aiQuestion.setUserId(userId);
|
|
|
+ aiQuestion.setUserName(userName);
|
|
|
+ aiQuestion.setQuestion(questionText);
|
|
|
+ aiQuestion.setAnswer(completeAnswer.toString());
|
|
|
+ aiQuestion.setAskTime(LocalDateTime.now());
|
|
|
+ aiQuestionMapper.save(aiQuestion);
|
|
|
+
|
|
|
+ } catch (ApiException e) {
|
|
|
+ log.error("Error processing request", e);
|
|
|
+ outputStream.write(("data: Error processing request\n\n").getBytes(StandardCharsets.UTF_8));
|
|
|
+ outputStream.flush();
|
|
|
+ } catch (NoApiKeyException | InputRequiredException e) {
|
|
|
+ throw new RuntimeException(e);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ // 阿里百炼DeepSeek大模型
|
|
|
+ @PostMapping(value = "/aliDeepSeek", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
|
|
|
+ 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 (object.containsKey("sessionId")) {
|
|
|
+ sessionId = object.get("sessionId").toString();
|
|
|
+ } else {
|
|
|
+ sessionId = java.util.UUID.randomUUID().toString();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 解析 JSON 并提取 "content" 字段的值
|
|
|
+ String questionText = content;
|
|
|
+
|
|
|
+ // 检查是否已经存在相同的 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);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 构建消息列表,包含角色定义、历史对话记录和用户新消息
|
|
|
+ List<Message> messages = new ArrayList<>();
|
|
|
+
|
|
|
+ // 插入角色定义(在对话历史的开头)
|
|
|
+ Message roleDefinition = Message.builder()
|
|
|
+ .role(Role.SYSTEM.getValue()) // 使用系统角色
|
|
|
+ .content(aiRole) // 定义角色的行为和风格
|
|
|
+ .build();
|
|
|
+ messages.add(roleDefinition); // 将角色定义插入到对话历史的开头
|
|
|
+
|
|
|
+ // 从数据库中获取历史对话记录
|
|
|
+ List<AiQuestion> questions = aiQuestionMapper.findQuestionsBySessionId(sessionId);
|
|
|
+
|
|
|
+ // 如果历史记录超过限制,则只取最近的记录
|
|
|
+ if (questions.size() > Limit) {
|
|
|
+ questions = questions.subList(questions.size() - Limit, questions.size());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 将历史对话记录转换为 AiQuestionItem 列表
|
|
|
+ List<AiQuestionItem> itemList = new ArrayList<>();
|
|
|
+ for (AiQuestion question : questions) {
|
|
|
+ AiQuestionItem userItem = new AiQuestionItem("user", question.getQuestion());
|
|
|
+ userItem.setId(question.getId());
|
|
|
+ userItem.setSessionId(question.getSessionId());
|
|
|
+ userItem.setUserId(question.getUserId());
|
|
|
+ userItem.setUserName(question.getUserName());
|
|
|
+ userItem.setAskTime(question.getAskTime());
|
|
|
+
|
|
|
+ AiQuestionItem assistantItem = new AiQuestionItem("assistant", question.getAnswer());
|
|
|
+ assistantItem.setId(question.getId());
|
|
|
+ assistantItem.setSessionId(question.getSessionId());
|
|
|
+ assistantItem.setUserId(question.getUserId());
|
|
|
+ assistantItem.setUserName(question.getUserName());
|
|
|
+ assistantItem.setAskTime(question.getAskTime());
|
|
|
+
|
|
|
+ itemList.add(userItem);
|
|
|
+ itemList.add(assistantItem);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 将 AiQuestionItem 列表转换为消息列表
|
|
|
+ for (AiQuestionItem item : itemList) {
|
|
|
+ Message message = Message.builder()
|
|
|
+ .role(item.getRole().equals("user") ? Role.USER.getValue() : Role.ASSISTANT.getValue())
|
|
|
+ .content(item.getContent() != null ? item.getContent() : item.getReasoningContent())
|
|
|
+ .build();
|
|
|
+ messages.add(message);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 添加用户的新消息
|
|
|
+ Message userMessage = Message.builder()
|
|
|
+ .role(Role.USER.getValue())
|
|
|
+ .content(questionText) // 使用提取的文本
|
|
|
+ .build();
|
|
|
+ messages.add(userMessage);
|
|
|
+
|
|
|
+ // 构建模型调用参数
|
|
|
+ GenerationParam param = GenerationParam.builder()
|
|
|
+ .model(dpskModel)
|
|
|
+ .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 {
|
|
|
+ // 调用流式接口
|
|
|
+ generation.streamCall(param).blockingForEach(chunk -> {
|
|
|
+ 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);
|
|
|
+
|
|
|
+ // 添加延迟
|
|
|
+ try {
|
|
|
+ Thread.sleep(millis); // 延迟*毫秒
|
|
|
+ } catch (InterruptedException e) {
|
|
|
+ Thread.currentThread().interrupt();
|
|
|
+ log.error("Thread interrupted", e);
|
|
|
+ }
|
|
|
+
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("Error processing chunk", e);
|
|
|
+ outputStream.write(("data: Error processing chunk\n\n").getBytes(StandardCharsets.UTF_8));
|
|
|
+ outputStream.flush();
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ // 流式接口调用完成后,将完整回答存入数据库
|
|
|
+ AiQuestion aiQuestion = new AiQuestion();
|
|
|
+ aiQuestion.setModel(dpskModel);
|
|
|
+ aiQuestion.setSessionId(finalSessionId);
|
|
|
+ aiQuestion.setUserId(userId);
|
|
|
+ aiQuestion.setUserName(userName);
|
|
|
+ aiQuestion.setQuestion(questionText);
|
|
|
+ aiQuestion.setAnswer(completeAnswer.toString());
|
|
|
+ aiQuestion.setAskTime(LocalDateTime.now());
|
|
|
+ aiQuestionMapper.save(aiQuestion);
|
|
|
+
|
|
|
+ } catch (ApiException e) {
|
|
|
+ log.error("Error processing request", e);
|
|
|
+ outputStream.write(("data: Error processing request\n\n").getBytes(StandardCharsets.UTF_8));
|
|
|
+ outputStream.flush();
|
|
|
+ } catch (NoApiKeyException | InputRequiredException e) {
|
|
|
+ throw new RuntimeException(e);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ @PostMapping(value = "/aliTyqw-test")
|
|
|
+ public ResponseEntity<AiStreamOutputVO> send3(@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 (object.containsKey("sessionId")) {
|
|
|
+ sessionId = object.get("sessionId").toString();
|
|
|
+ } else {
|
|
|
+ sessionId = java.util.UUID.randomUUID().toString();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 解析 JSON 并提取 "content" 字段的值
|
|
|
+ String questionText = content;
|
|
|
+
|
|
|
+ // 检查是否已经存在相同的 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);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 构建消息列表,包含角色定义、历史对话记录和用户新消息
|
|
|
+ List<Message> messages = new ArrayList<>();
|
|
|
+
|
|
|
+ // 插入角色定义(在对话历史的开头)
|
|
|
+ Message roleDefinition = Message.builder()
|
|
|
+ .role(Role.SYSTEM.getValue()) // 使用系统角色
|
|
|
+ .content(aiRole) // 定义角色的行为和风格
|
|
|
+ .build();
|
|
|
+ messages.add(roleDefinition); // 将角色定义插入到对话历史的开头
|
|
|
+
|
|
|
+ // 从数据库中获取历史对话记录
|
|
|
+ List<AiQuestion> questions = aiQuestionMapper.findQuestionsBySessionId(sessionId);
|
|
|
+
|
|
|
+ // 如果历史记录超过限制,则只取最近的记录
|
|
|
+ if (questions.size() > Limit) {
|
|
|
+ questions = questions.subList(questions.size() - Limit, questions.size());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 将历史对话记录转换为 AiQuestionItem 列表
|
|
|
+ List<AiQuestionItem> itemList = new ArrayList<>();
|
|
|
+ for (AiQuestion question : questions) {
|
|
|
+ AiQuestionItem userItem = new AiQuestionItem("user", question.getQuestion());
|
|
|
+ userItem.setId(question.getId());
|
|
|
+ userItem.setSessionId(question.getSessionId());
|
|
|
+ userItem.setUserId(question.getUserId());
|
|
|
+ userItem.setUserName(question.getUserName());
|
|
|
+ userItem.setAskTime(question.getAskTime());
|
|
|
+
|
|
|
+ AiQuestionItem assistantItem = new AiQuestionItem("assistant", question.getAnswer());
|
|
|
+ assistantItem.setId(question.getId());
|
|
|
+ assistantItem.setSessionId(question.getSessionId());
|
|
|
+ assistantItem.setUserId(question.getUserId());
|
|
|
+ assistantItem.setUserName(question.getUserName());
|
|
|
+ assistantItem.setAskTime(question.getAskTime());
|
|
|
+
|
|
|
+ itemList.add(userItem);
|
|
|
+ itemList.add(assistantItem);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 将 AiQuestionItem 列表转换为消息列表
|
|
|
+ for (AiQuestionItem item : itemList) {
|
|
|
+ Message message = Message.builder()
|
|
|
+ .role(item.getRole().equals("user") ? Role.USER.getValue() : Role.ASSISTANT.getValue())
|
|
|
+ .content(item.getContent() != null ? item.getContent() : item.getReasoningContent())
|
|
|
+ .build();
|
|
|
+ messages.add(message);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 添加用户的新消息
|
|
|
+ Message userMessage = Message.builder()
|
|
|
+ .role(Role.USER.getValue())
|
|
|
+ .content(questionText) // 使用提取的文本
|
|
|
+ .build();
|
|
|
+ messages.add(userMessage);
|
|
|
+
|
|
|
+ // 构建模型调用参数
|
|
|
+ GenerationParam param = GenerationParam.builder()
|
|
|
+ .model(tyqwModel)
|
|
|
+ .messages(messages)
|
|
|
+ .resultFormat(GenerationParam.ResultFormat.MESSAGE)
|
|
|
+ .topP(0.8)
|
|
|
+ .apiKey(apiKey)
|
|
|
+ .incrementalOutput(false) // 关闭增量输出
|
|
|
+ .enableSearch(true) // 联网搜索
|
|
|
+ .build();
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 调用非流式接口
|
|
|
+ String completeAnswer = generation.call(param).getOutput().getChoices().get(0).getMessage().getContent();
|
|
|
+
|
|
|
+ // 将完整回答存入数据库
|
|
|
+ AiQuestion aiQuestion = new AiQuestion();
|
|
|
+ aiQuestion.setModel(tyqwModel);
|
|
|
+ aiQuestion.setSessionId(sessionId);
|
|
|
+ aiQuestion.setUserId(userId);
|
|
|
+ aiQuestion.setUserName(userName);
|
|
|
+ aiQuestion.setQuestion(questionText);
|
|
|
+ aiQuestion.setAnswer(completeAnswer);
|
|
|
+ aiQuestion.setAskTime(LocalDateTime.now());
|
|
|
+ aiQuestionMapper.save(aiQuestion);
|
|
|
+
|
|
|
+ // 构建返回对象
|
|
|
+ AiStreamOutputVO aiStreamOutputVO = new AiStreamOutputVO();
|
|
|
+ aiStreamOutputVO.setSessionId(sessionId);
|
|
|
+ aiStreamOutputVO.setReasoningContent(completeAnswer);
|
|
|
+
|
|
|
+ // 返回完整回答给前端
|
|
|
+ return ResponseEntity.ok(aiStreamOutputVO);
|
|
|
+ } catch (ApiException e) {
|
|
|
+ log.error("Error processing request", e);
|
|
|
+
|
|
|
+ // 构建错误返回对象
|
|
|
+ AiStreamOutputVO aiStreamOutputVO = new AiStreamOutputVO();
|
|
|
+ aiStreamOutputVO.setSessionId(sessionId);
|
|
|
+ aiStreamOutputVO.setReasoningContent("Error processing request");
|
|
|
+
|
|
|
+ return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(aiStreamOutputVO);
|
|
|
+ } catch (NoApiKeyException | InputRequiredException e) {
|
|
|
+ throw new RuntimeException(e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|