Commit ee350b41 authored by 陈立彬's avatar 陈立彬

AI对练、AI问答扩展

parent c5c894d5
package cn.breeze.elleai.application.dto.inner;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serializable;
/**
* AI单题点评结果
*/
@Data
public class AiSingleEvaluateResultDto implements Serializable {
@Schema(description = "评分")
private Float score;
@Schema(description = "评价")
private String evaluation;
@Schema(description = "DIFY会话ID")
private String difySessionId;;
}
package cn.breeze.elleai.application.dto.inner;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serializable;
/**
* 考试流水缓存
*/
@Data
public class ExamineBusinessCacheDto implements Serializable {
/**
* 考试ID
*/
@Schema(description = "考试ID")
private Integer examineId;
/**
* 对练模式(0练习 1对练)
*/
@Schema(description = "对练模式(0练习 1对练)")
private Integer examineMode;
/**
* 用户ID
*/
@Schema(description = "用户ID")
private String userId;
/**
* 考试记录ID
*/
@Schema(description = "考试记录ID")
private Integer recordId;
/**
* 当前题目ID
*/
@Schema(description = "当前题目ID")
private Integer currentQuestionId;
/**
* 是否有下一题
*/
@Schema(description = "是否有下一题")
private boolean hasNext;
}
package cn.breeze.elleai.application.service;
import cn.breeze.elleai.application.dto.inner.AiSingleEvaluateResultDto;
import com.alibaba.fastjson2.JSONObject;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
/**
* AI平台扩展服务
*/
@Slf4j
@Component
@RequiredArgsConstructor
public class AiPlatformExtensionService {
@Value("${dify.api_base}")
private String difyBase;
@Value("${dify.api_key}")
private String apiKey;
private final RestTemplate restTemplate = new RestTemplate();
/**
* 单题评分+点评
* @param sessionId
* @param userId
* @param question
* @param answer
* @param userAnswer
*/
public AiSingleEvaluateResultDto run4SingleEvaluate(String sessionId, String userId, String question, String answer, String userAnswer) {
Map<String, String> inputs = new HashMap<>();
inputs.put("scene", "single_evaluate");
inputs.put("question", question);
inputs.put("answer", answer);
JSONObject param = new JSONObject();
param.put("query", userAnswer);
param.put("inputs", inputs);
param.put("response_mode", "blocking");
param.put("conversation_id", "");
param.put("user", userId);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.setBearerAuth(apiKey);
log.info("异步请求参数1,sessionId = {}", sessionId);
log.info("异步请求参数2,req = {}", JSONObject.toJSONString(param));
HttpEntity<String> postEntity = new HttpEntity<>(param.toJSONString(), headers);
ResponseEntity<String> response = restTemplate.postForEntity(difyBase + "/chat-messages", postEntity, String.class);
String body = response.getBody();
log.info("执行结果:{}", body);
if(Objects.equals(response.getStatusCode(), HttpStatus.OK)) {
JSONObject bodyObject = JSONObject.parseObject(body);
String conversationId = bodyObject.getString("conversation_id");
JSONObject answerObject = JSONObject.parseObject(bodyObject.getString("answer"));
Float score = answerObject.getFloat("score");
String evaluation = answerObject.getString("evaluation");
AiSingleEvaluateResultDto result = new AiSingleEvaluateResultDto();
result.setEvaluation(evaluation);
result.setScore(score);
result.setDifySessionId(conversationId);
return result;
}
return null;
}
/**
* 考试总点评
* @param sessionId
* @param userId
* @param avgScore
* @param qaResultList
*/
public String run4TotalEvaluate(String sessionId, String userId, Float avgScore, List qaResultList) {
Map<String, Object> inputs = new HashMap<>();
inputs.put("scene", "total_evaluate");
inputs.put("avg_score", avgScore);
inputs.put("qa_result_list", qaResultList);
JSONObject param = new JSONObject();
param.put("query", "Not_Null");
param.put("inputs", inputs);
param.put("response_mode", "blocking");
param.put("conversation_id", "");
param.put("user", userId);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.setBearerAuth(apiKey);
log.info("异步请求参数1,sessionId = {}", sessionId);
log.info("异步请求参数2,req = {}", JSONObject.toJSONString(param));
HttpEntity<String> postEntity = new HttpEntity<>(param.toJSONString(), headers);
ResponseEntity<String> response = restTemplate.postForEntity(difyBase + "/chat-messages", postEntity, String.class);
String body = response.getBody();
log.info("执行结果:{}", body);
if(Objects.equals(response.getStatusCode(), HttpStatus.OK)) {
JSONObject bodyObject = JSONObject.parseObject(body);
String conversationId = bodyObject.getString("conversation_id");
JSONObject answerObject = JSONObject.parseObject(bodyObject.getString("answer"));
String evaluation = answerObject.getString("evaluation");
return evaluation;
}
return null;
}
}
...@@ -5,7 +5,7 @@ import cn.breeze.elleai.application.dto.request.*; ...@@ -5,7 +5,7 @@ import cn.breeze.elleai.application.dto.request.*;
import cn.breeze.elleai.application.dto.response.*; import cn.breeze.elleai.application.dto.response.*;
import cn.breeze.elleai.domain.sparring.model.request.QaAssistantRequestModel; import cn.breeze.elleai.domain.sparring.model.request.QaAssistantRequestModel;
import cn.breeze.elleai.domain.sparring.model.request.QaAssistantSaveModel; import cn.breeze.elleai.domain.sparring.model.request.QaAssistantSaveModel;
import cn.breeze.elleai.domain.sparring.model.request.UserQaHistoryRequestModel; import cn.breeze.elleai.domain.sparring.model.request.UserChatCompletionSaveModel;
import cn.breeze.elleai.domain.sparring.model.request.UserQaRequestModel; import cn.breeze.elleai.domain.sparring.model.request.UserQaRequestModel;
import cn.breeze.elleai.domain.sparring.model.response.QaAssistantResponseModel; import cn.breeze.elleai.domain.sparring.model.response.QaAssistantResponseModel;
import cn.breeze.elleai.domain.sparring.model.response.UserChatCompletionHistoryResponseModel; import cn.breeze.elleai.domain.sparring.model.response.UserChatCompletionHistoryResponseModel;
...@@ -14,6 +14,7 @@ import cn.breeze.elleai.domain.sparring.service.ChatCompletionService; ...@@ -14,6 +14,7 @@ import cn.breeze.elleai.domain.sparring.service.ChatCompletionService;
import cn.breeze.elleai.util.UserPrincipal; import cn.breeze.elleai.util.UserPrincipal;
import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.mybatisflex.core.paginate.Page; import com.mybatisflex.core.paginate.Page;
...@@ -259,29 +260,77 @@ public class AppChatCompletionService { ...@@ -259,29 +260,77 @@ public class AppChatCompletionService {
} }
/** /**
* AI问答会话分页查询 * 移动端历史会话明细
* @param userPrincipal
* @param chatCompletionId
* @param pageNo
* @param pageSize
* @return
*/
public PageResult<UserChatCompletionHistoryMobileDto> userQaHistoryMobilePaginQuery(UserPrincipal userPrincipal, Integer chatCompletionId, Integer pageNo, Integer pageSize) {
pageNo = Objects.isNull(pageNo) ? 1 : pageNo;
pageSize = Objects.isNull(pageSize) ? 10 : pageSize;
UserQaRequestDto req = new UserQaRequestDto();
req.setUserId(userPrincipal.getUserId());
Page<UserChatCompletionHistoryResponseModel> historyDetailPageResult = chatCompletionService.userQaHistoryDetailPaginQuery(chatCompletionId, pageNo, pageSize);
PageResult<UserChatCompletionHistoryMobileDto> pageResult = PageResult.of(pageNo, pageSize, (int) historyDetailPageResult.getTotalRow(), null);
if(Objects.nonNull(historyDetailPageResult) && CollectionUtil.isNotEmpty(historyDetailPageResult.getRecords())) {
List<UserChatCompletionHistoryMobileDto> items = historyDetailPageResult.getRecords().stream().map(v -> {
UserChatCompletionHistoryMobileDto dto = BeanUtil.copyProperties(v, UserChatCompletionHistoryMobileDto.class);
return dto;
}).collect(Collectors.toList());
pageResult.setItems(items);
}
return pageResult;
}
/**
* 用户提问
* @param request * @param request
* @return * @return
*/ */
public UserAskResultMobileDto userAsk(UserPrincipal userPrincipal, UserQaMobileRequestDto request) { public UserAskResultMobileDto userAsk(UserPrincipal userPrincipal, UserQaMobileRequestDto request) {
//TODO 生成sessionId
UserAskResultMobileDto result = new UserAskResultMobileDto(); UserAskResultMobileDto result = new UserAskResultMobileDto();
result.setChatCompletionId(1);
result.setReplyContent("moke ai reply."); // 更新会话信息
// 更新问答记录 UserChatCompletionSaveModel saveModel = new UserChatCompletionSaveModel();
// Integer recordId = chatCompletionService.saveUserQaSession(request.getUserId(), request.getSessionId()); saveModel.setUserId(userPrincipal.getUserId());
// saveModel.setUserName(userPrincipal.getUserName());
// // 保存问答详情 saveModel.setId(request.getChatCompletionId());
// String content = request.getContent(); saveModel.setLastQuestion(request.getContent());
// chatCompletionService.saveUserQaRecord(recordId, 0, content); saveModel.setShopId(userPrincipal.getShopId());
// saveModel.setShopName(userPrincipal.getShopName());
// return ask4Knowledge(request.getSessionId(), request.getUserId(), content); // 首次提问
if(Objects.isNull(request.getChatCompletionId())) {
saveModel.setCreateTime(new Date());
saveModel.setFirstQuestion(request.getContent());
saveModel.setSessionId(UUID.randomUUID().toString());
}
Integer recordId = chatCompletionService.saveUserQaSession(saveModel);
// 保存问答详情
chatCompletionService.saveUserQaRecord(recordId, 0, request.getContent());
// 问一下AI
String replyContent = ask4Knowledge(saveModel.getSessionId(), saveModel.getUserId(), request.getContent());
// 保存AI问答详情
chatCompletionService.saveUserQaRecord(recordId, 1, replyContent);
result.setChatCompletionId(recordId);
result.setReplyContent(replyContent);
return result; return result;
} }
public String ask4Knowledge(String sessionId, String userId, String question) { public String ask4Knowledge(String sessionId, String userId, String question) {
if(true) { if(true) {
return "moke ai reply."; return "moke ai reply.";
} }
......
...@@ -2,19 +2,24 @@ package cn.breeze.elleai.application.service; ...@@ -2,19 +2,24 @@ package cn.breeze.elleai.application.service;
import cn.breeze.elleai.application.dto.ApiResponse; import cn.breeze.elleai.application.dto.ApiResponse;
import cn.breeze.elleai.application.dto.PageResult; import cn.breeze.elleai.application.dto.PageResult;
import cn.breeze.elleai.application.dto.inner.AiSingleEvaluateResultDto;
import cn.breeze.elleai.application.dto.inner.ExamineBusinessCacheDto;
import cn.breeze.elleai.application.dto.request.*; import cn.breeze.elleai.application.dto.request.*;
import cn.breeze.elleai.application.dto.response.*; import cn.breeze.elleai.application.dto.response.*;
import cn.breeze.elleai.domain.sparring.model.request.*; import cn.breeze.elleai.domain.sparring.model.request.*;
import cn.breeze.elleai.domain.sparring.model.response.*; import cn.breeze.elleai.domain.sparring.model.response.*;
import cn.breeze.elleai.domain.sparring.service.ExamineService; import cn.breeze.elleai.domain.sparring.service.ExamineService;
import cn.breeze.elleai.exception.InternalException;
import cn.breeze.elleai.util.UserPrincipal; import cn.breeze.elleai.util.UserPrincipal;
import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Assert; import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.mybatisflex.core.paginate.Page; import com.mybatisflex.core.paginate.Page;
import io.micrometer.common.util.StringUtils; import io.micrometer.common.util.StringUtils;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.core.StringRedisTemplate;
...@@ -28,6 +33,7 @@ import java.util.*; ...@@ -28,6 +33,7 @@ import java.util.*;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.IntStream;
import static java.util.stream.Collectors.toMap; import static java.util.stream.Collectors.toMap;
...@@ -40,21 +46,17 @@ import static java.util.stream.Collectors.toMap; ...@@ -40,21 +46,17 @@ import static java.util.stream.Collectors.toMap;
@RequiredArgsConstructor @RequiredArgsConstructor
public class AppExamineService { public class AppExamineService {
private static String EXAM_REDIS_QUESTION_KEY = "EXAM_MASTER_QUESTION:%s:%s"; private static String EXAM_BUSINESS_REDIS_KEY = "examine:business:%s"; // 考试流水缓存信息(businessNo)
private static String EXAM_REDIS_SESSION_KEY = "EXAM_MASTER_SESSION:%d:%d:%s"; private static String EXAM_AI_TASK_REDIS_KEY = "examine:ai_task:%s"; // 考试AI点评任务执行状态(businessNo)
private static String EXAM_REDIS_CAS_KEY = "EXAM_MASTER_CURRENT_AI_SCORE:%d:%s";
private static String USER_SESSION_CONTEXT_KEY = "USER_SESSION_CONTEXT:%d:%s:%s";
private static String USER_SESSION_CONTEXT_COUNT = "USER_SESSION_CONTEXT_COUNT";
private final ExamineService examineService; private final ExamineService examineService;
private final StringRedisTemplate redisTemplate; private final StringRedisTemplate redisTemplate;
private final AiPlatformExtensionService extensionService;
/************************************************** 场景分类 **************************************************/ /************************************************** 场景分类 **************************************************/
...@@ -394,14 +396,14 @@ public class AppExamineService { ...@@ -394,14 +396,14 @@ public class AppExamineService {
/** /**
* QA列表查询 * QA列表查询
* @param request * @param examineId
* @return * @return
*/ */
public List<ExamineQaDto> examineQaList(ExamineQaRequestModel request) { public List<ExamineQaDto> examineQaList(Integer examineId) {
List<ExamineQaDto> resultList = new ArrayList<>(); List<ExamineQaDto> resultList = new ArrayList<>();
List<ExamineQaResponseModel> modelList = examineService.examineQaList(request); List<ExamineQaResponseModel> modelList = examineService.examineQaList(examineId);
if(CollectionUtil.isNotEmpty(modelList)) { if(CollectionUtil.isNotEmpty(modelList)) {
resultList = modelList.stream().map(v -> { resultList = modelList.stream().map(v -> {
...@@ -473,7 +475,7 @@ public class AppExamineService { ...@@ -473,7 +475,7 @@ public class AppExamineService {
examTotalCount = recordList.size(); examTotalCount = recordList.size();
practiceCount = examTotalCount - examTotalCount; practiceCount = examTotalCount - examTotalCount;
maxOverallScore = recordList.stream().mapToDouble(ExamineRecordResponseModel::getOverallScore).max().getAsDouble(); maxOverallScore = recordList.stream().filter(v -> Objects.nonNull(v.getOverallScore())).mapToDouble(ExamineRecordResponseModel::getOverallScore).max().getAsDouble();
} }
result.setExamCount(examCount); result.setExamCount(examCount);
result.setPracticeCount(practiceCount); result.setPracticeCount(practiceCount);
...@@ -995,92 +997,288 @@ public class AppExamineService { ...@@ -995,92 +997,288 @@ public class AppExamineService {
/************************************************** 移动端对练 **************************************************/ /************************************************** 移动端对练 **************************************************/
public ExamineQaDifyDto getCurrentQuestion(Integer examineId, String sessionId, String userId) { /**
ExamineQaDifyDto result = new ExamineQaDifyDto(); * 开始考试,并返回考试流水号&第一道题目
* @param userPrincipal
* @param request
* @return
*/
public ExamineStartResultDto startExamine(UserPrincipal userPrincipal, StartExamineMobileRequestDto request) {
String redisKey = String.format(EXAM_REDIS_QUESTION_KEY, sessionId, userId); String userId = userPrincipal.getUserId();
String currentQuestion = redisTemplate.opsForValue().get(redisKey); Integer examineId = request.getExamineId();
Integer examineMode = request.getExamineMode();
String businessNo = UUID.randomUUID().toString();
log.info("获取当前出题,rediskey = {}, value = {}", redisKey, currentQuestion); ExamineStartResultDto result = new ExamineStartResultDto();
if(StringUtils.isNotEmpty(currentQuestion)) { result.setBusinessNo(businessNo);
// 获取缓存考试会话信息
String examBusinessKey = String.format(EXAM_BUSINESS_REDIS_KEY, businessNo);
ExamineBusinessCacheDto businessCache = getExamBusinessCache(businessNo);
if(Objects.isNull(businessCache)) {
businessCache = new ExamineBusinessCacheDto();
businessCache.setExamineId(examineId);
businessCache.setExamineMode(examineMode);
businessCache.setUserId(userId);
}
ExamineQaResponseModel model = examineService.examineQaDetail(Integer.valueOf(currentQuestion)); // 当前出题
if(Objects.nonNull(model)) { Integer currentQuestionId = businessCache.getCurrentQuestionId();
ExamineSceneCategoryResponseModel category = examineService.sceneCategoryDetail(model.getCategoryId()); if(Objects.isNull(currentQuestionId)) {
List<ExamineQaResponseModel> examineQaList = examineService.examineQaList(examineId);
if(CollectionUtil.isNotEmpty(examineQaList)) {
ExamineQaResponseModel model = examineQaList.get(0);
currentQuestionId = model.getId();
result.setQuestionId(currentQuestionId);
result.setQuestion(model.getQuestion()); result.setQuestion(model.getQuestion());
result.setAnswer(model.getAnswer()); result.setAnswer(model.getAnswer());
result.setProject(category.getName()); result.setNext(examineQaList.size() > 1 ? true : false);
result.setCode(category.getName());
result.setQuestionId(model.getId());
result.setNext(true);
// 保存题目信息?
businessCache.setCurrentQuestionId(currentQuestionId);
businessCache.setHasNext(result.isNext());
} }
} }
// 缓存
redisTemplate.opsForValue().set(examBusinessKey, JSONObject.toJSONString(businessCache), 1, TimeUnit.DAYS);
return result; return result;
} }
/** /**
* 开始考试,获取出 * 获取下一
* @param examineId * @param userPrincipal
* @param userId * @param examineId 对练ID
* @param examineMode * @param businessNo 考试流水号
* @return * @return
*/ */
public ExamineStartResultDto startExamine(UserPrincipal userPrincipal, StartExamineMobileRequestDto request) { public ExamineStartResultDto getNextQuestion(UserPrincipal userPrincipal, Integer examineId, String businessNo) {
String userId = userPrincipal.getUserId();
ExamineStartResultDto result = new ExamineStartResultDto(); ExamineStartResultDto result = new ExamineStartResultDto();
result.setBusinessNo(UUID.randomUUID().toString()); result.setBusinessNo(businessNo);
result.setQuestionId(1);
result.setQuestion("请问毛巾都是干净的嘛?");
result.setAnswer("是的");
result.setNext(true);
// // 获取缓存考试会话信息
// String examSessionKey = String.format(EXAM_REDIS_SESSION_KEY, examineId, examineMode, userId);
// String sessionId = redisTemplate.opsForValue().get(examSessionKey);
// if(StrUtil.isEmptyIfStr(sessionId)) {
// // 生成sessionId
// sessionId = UUID.randomUUID().toString();
// redisTemplate.opsForValue().set(examSessionKey, sessionId, 1, TimeUnit.DAYS);
// }
//
// // 获取缓存考题信息
// String questionKey = String.format(EXAM_REDIS_QUESTION_KEY, examineId, examineMode, userId, sessionId);
//
//
// ExamineQaRequestModel req = null;
// examineService.examineQaList(req);
// // 根据分类获取考题
// ExamineResponseModel model = examineService.examineDetail(examineId);
// if(Objects.nonNull(model)) {
// Long maxQuestionId = qaRecordMapper.selectSessionMaxQuestionId(tenant, sessionId, userId);
// maxQuestionId = Objects.nonNull(maxQuestionId) ? maxQuestionId : 0;
// ElehKnowledgeDo knowledgeDo = knowledgeMapper.selectQuestion(tenant, tagDo.getId(), maxQuestionId);
// if(Objects.nonNull(knowledgeDo)) {
// result.setQuestion(knowledgeDo.getQuestion());
// result.setAnswer(knowledgeDo.getAnswer());
// result.setProject(tagDo.getName());
// result.setCode(tagDo.getCode());
// result.setQuestionId(knowledgeDo.getId());
// result.setNext(true);
//
// // 存储当前会话考试信息
// String redisKey = String.format(EXAM_REDIS_QUESTION_KEY, tenant, sessionId, userId);
// redisTemplate.opsForValue().set(redisKey, result.getQuestionId()+"", 10, TimeUnit.MINUTES);
//
// log.info("出题结果:result = {}, rediskey = {}", JSONObject.toJSONString(result), redisKey);
// }
// }
return result; // 获取缓存考试会话信息
String examBusinessKey = String.format(EXAM_BUSINESS_REDIS_KEY, businessNo);
ExamineBusinessCacheDto businessCache = getExamBusinessCache(businessNo);
if(Objects.isNull(businessCache)) {
throw new InternalException(-1, "获取不到考试流水信息");
}
// 当前出题
Integer currentQuestionId = businessCache.getCurrentQuestionId();
if(Objects.isNull(currentQuestionId)) {
throw new InternalException(-1, "获取上一题信息失败");
}
// 获取下一题
ExamineQaResponseModel nextQa = null;
boolean hasNext = false;
List<ExamineQaResponseModel> examineQaList = examineService.examineQaList(examineId);
if(CollectionUtil.isNotEmpty(examineQaList)) {
OptionalInt indexOpt = IntStream.range(0, examineQaList.size())
.filter(i -> examineQaList.get(i).getId() == currentQuestionId)
.findFirst();
if (indexOpt.isPresent()) {
int index = indexOpt.getAsInt();
nextQa = index + 1 < examineQaList.size() ? examineQaList.get(index + 1) : null;
int remainingNum = examineQaList.size() - index - 1;
hasNext = remainingNum > 1 ? true : false;
}
}
if(Objects.nonNull(nextQa)) {
// 返回结果
result.setNext(hasNext);
result.setQuestion(nextQa.getQuestion());
result.setAnswer(nextQa.getAnswer());
result.setQuestionId(nextQa.getId());
// 缓存
businessCache.setCurrentQuestionId(nextQa.getId());
businessCache.setHasNext(hasNext);
redisTemplate.opsForValue().set(examBusinessKey, JSONObject.toJSONString(businessCache), 1, TimeUnit.DAYS);
return result;
} else {
throw new InternalException(-1, "获取下一题信息有误");
}
}
/**
* 考试答题
* @param userPrincipal
* @param request
*/
public void submitAnswer(UserPrincipal userPrincipal, SubmitAnswerMobileRequestDto request) {
String userId = userPrincipal.getUserId();
Integer examineId = request.getExamineId();
String answer = request.getAnswer();
Integer questionId = request.getQuestionId();
String businessNo = request.getBusinessNo();
ExamineStartResultDto result = new ExamineStartResultDto();
result.setBusinessNo(businessNo);
// 获取缓存考试会话信息
String examBusinessKey = String.format(EXAM_BUSINESS_REDIS_KEY, businessNo);
ExamineBusinessCacheDto businessCache = getExamBusinessCache(businessNo);
if(Objects.isNull(businessCache)) {
throw new InternalException(-1, "获取不到对练信息");
}
// 获取题目信息
ExamineQaDto examineQaDto = qaDetail(questionId);
// 获取数据库考试信息
Integer recordId = null;
ExamineRecordResponseModel examineRecord = examineService.examineRecordDetail(businessNo);
if(Objects.isNull(examineRecord)) {
// 第一次答题,保存考试信息
ExamineRecordSaveModel saveModel = new ExamineRecordSaveModel();
saveModel.setUserId(userId);
saveModel.setUserName(userPrincipal.getUserName());
saveModel.setShopId(userPrincipal.getShopId());
saveModel.setShopName(userPrincipal.getShopName());
saveModel.setAnsweredNum(1);
saveModel.setExamineId(examineId);
saveModel.setExamineMode(businessCache.getExamineMode());
saveModel.setBusinessNo(businessNo);
examineService.saveExamineRecord(saveModel);
recordId = saveModel.getId();
} else {
recordId = examineRecord.getId();
// 更新答题数量
ExamineRecordSaveModel saveModel = new ExamineRecordSaveModel();
saveModel.setId(recordId);
saveModel.setAnsweredNum(examineRecord.getAnsweredNum() + 1);
examineService.saveExamineRecord(saveModel);
}
// 保存单题答题信息
ExamineRecordDetailSaveModel detailSaveModel = new ExamineRecordDetailSaveModel();
detailSaveModel.setRecordId(recordId);
detailSaveModel.setQaId(questionId);
detailSaveModel.setCreateTime(new Date());
detailSaveModel.setAnswer(answer);
// AI 点评
AiSingleEvaluateResultDto evaluateResultDto = extensionService.run4SingleEvaluate(businessNo, userId, examineQaDto.getQuestion(), examineQaDto.getAnswer(), answer);
if(Objects.nonNull(evaluateResultDto)) {
detailSaveModel.setScore(evaluateResultDto.getScore());
detailSaveModel.setEvaluation(evaluateResultDto.getEvaluation());
}
examineService.saveExamineRecordDetail(detailSaveModel);
// 更新缓存
businessCache.setRecordId(recordId);
redisTemplate.opsForValue().set(examBusinessKey, JSONObject.toJSONString(businessCache), 1, TimeUnit.DAYS);
// 最后一题答题,执行AI总点评
if(!businessCache.isHasNext()) {
// 获取答题结果
ExamineDetailRecordRequestModel requestModel = new ExamineDetailRecordRequestModel();
requestModel.setRecordId(recordId);
List<ExamineDetailRecordResponseModel> detailRecordList = examineService.examineDetailRecordList(requestModel);
if(CollectionUtil.isNotEmpty(detailRecordList)) {
// 计算综合评分
double totalScore = detailRecordList.stream().filter(v -> Objects.nonNull(v.getScore())).mapToDouble(ExamineDetailRecordResponseModel::getScore).sum();
Double avgScore = totalScore / detailRecordList.size();
// 执行综合点评
String overallEvaluation = extensionService.run4TotalEvaluate(businessNo, userId, null, null);
// 更新答题数量
ExamineRecordSaveModel saveModel = new ExamineRecordSaveModel();
saveModel.setId(recordId);
saveModel.setOverallEvaluation(overallEvaluation);
saveModel.setOverallScore(avgScore.floatValue());
examineService.saveExamineRecord(saveModel);
}
}
}
/**
* 获取下一题
* @param userPrincipal
* @param examineId 对练ID
* @param businessNo 考试流水号
* @return
*/
public ExamineFinalResultDto getExamineFinalResult(UserPrincipal userPrincipal, Integer examineId, String businessNo) {
String userId = userPrincipal.getUserId();
ExamineFinalResultDto result = new ExamineFinalResultDto();
// 获取缓存考试会话信息
String examBusinessKey = String.format(EXAM_BUSINESS_REDIS_KEY, businessNo);
ExamineBusinessCacheDto businessCache = getExamBusinessCache(businessNo);
if(Objects.isNull(businessCache)) {
throw new InternalException(-1, "获取不到考试流水信息");
}
// 当前出题
Integer currentQuestionId = businessCache.getCurrentQuestionId();
if(Objects.isNull(currentQuestionId)) {
throw new InternalException(-1, "获取上一题信息失败");
}
// 获取下一题
ExamineQaResponseModel nextQa = null;
boolean hasNext = false;
List<ExamineQaResponseModel> examineQaList = examineService.examineQaList(examineId);
if(CollectionUtil.isNotEmpty(examineQaList)) {
OptionalInt indexOpt = IntStream.range(0, examineQaList.size())
.filter(i -> examineQaList.get(i).getId() == currentQuestionId)
.findFirst();
if (indexOpt.isPresent()) {
int index = indexOpt.getAsInt();
nextQa = index + 1 < examineQaList.size() ? examineQaList.get(index + 1) : null;
int remainingNum = examineQaList.size() - index - 1;
hasNext = remainingNum > 1 ? true : false;
}
}
if(Objects.nonNull(nextQa)) {
// 返回结果
// result.setNext(hasNext);
// result.setQuestion(nextQa.getQuestion());
// result.setAnswer(nextQa.getAnswer());
// result.setQuestionId(nextQa.getId());
// 缓存
businessCache.setCurrentQuestionId(nextQa.getId());
businessCache.setHasNext(hasNext);
redisTemplate.opsForValue().set(examBusinessKey, JSONObject.toJSONString(businessCache), 1, TimeUnit.DAYS);
return result;
} else {
throw new InternalException(-1, "获取下一题信息有误");
}
}
/**
* 获取考试流水缓存信息
* @param businessNo
* @return
*/
private ExamineBusinessCacheDto getExamBusinessCache(String businessNo) {
// 获取缓存考试会话信息
String examBusinessKey = String.format(EXAM_BUSINESS_REDIS_KEY, businessNo);
String examBusinessCache = redisTemplate.opsForValue().get(examBusinessKey);
if(StrUtil.isNotEmpty(examBusinessCache)) {
return JSONObject.parseObject(examBusinessCache, ExamineBusinessCacheDto.class);
}
return null;
} }
} }
package cn.breeze.elleai; package cn.breeze.elleai.config;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
......
package cn.breeze.elleai; package cn.breeze.elleai.config;
import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j; import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
......
package cn.breeze.elleai; package cn.breeze.elleai.config;
import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.OpenAPI;
......
package cn.breeze.elleai.controller.extension; package cn.breeze.elleai.controller.extension;
import cn.breeze.elleai.application.dto.ApiResponse;
import cn.breeze.elleai.application.dto.response.AppRoleDto;
import cn.breeze.elleai.application.service.AiPlatformExtensionService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.UUID;
/** /**
* @author yangyw * @author yangyw
*/ */
...@@ -14,7 +22,28 @@ import org.springframework.web.bind.annotation.RestController; ...@@ -14,7 +22,28 @@ import org.springframework.web.bind.annotation.RestController;
@RequiredArgsConstructor @RequiredArgsConstructor
public class AiPlatformExtensionController { public class AiPlatformExtensionController {
private final AiPlatformExtensionService extensionService;
@Operation(summary = "单题点评")
@GetMapping("/single_evaluate")
public ApiResponse<String> singleEvaluate() {
String userId = UUID.randomUUID().toString();
String sessionId = UUID.randomUUID().toString();
String question = "问题";
String answer = "答案";
String userAnswer = "用户答案";
extensionService.run4SingleEvaluate(userId, sessionId, question, answer, userAnswer);
return ApiResponse.ok("SUCCESS");
}
@Operation(summary = "单题点评")
@GetMapping("/total_evaluate")
public ApiResponse<String> totalEvaluate() {
String userId = UUID.randomUUID().toString();
String sessionId = UUID.randomUUID().toString();
extensionService.run4TotalEvaluate(sessionId, userId, null, null);
return ApiResponse.ok("SUCCESS");
}
} }
...@@ -73,4 +73,15 @@ public class ChatCompletionMobileController { ...@@ -73,4 +73,15 @@ public class ChatCompletionMobileController {
result.setChatCompletionId(1); result.setChatCompletionId(1);
return ApiResponse.ok(result); return ApiResponse.ok(result);
} }
@Operation(summary = "历史对话详情")
@GetMapping("/history/detail")
public ApiResponse<PageResult<UserChatCompletionHistoryMobileDto>> historyDetail(@Parameter(hidden = true) UserPrincipal userPrincipal,
@Schema(description = "历史会话ID") @RequestParam("chat_completion_id") Integer chatCompletionId,
@Schema(description = "页码") @RequestParam("page_no") Integer pageNo,
@Schema(description = "分页数量") @RequestParam("page_size") Integer pageSize) {
PageResult<UserChatCompletionHistoryMobileDto> pageResult = chatCompletionService.userQaHistoryMobilePaginQuery(userPrincipal, chatCompletionId, pageNo, pageSize);
return ApiResponse.ok(pageResult);
}
} }
...@@ -85,6 +85,7 @@ public class ExamineMobileController { ...@@ -85,6 +85,7 @@ public class ExamineMobileController {
@PostMapping(value = "submit_answer") @PostMapping(value = "submit_answer")
public ApiResponse<String> submitAnswer(@Parameter(hidden = true) UserPrincipal userPrincipal, public ApiResponse<String> submitAnswer(@Parameter(hidden = true) UserPrincipal userPrincipal,
@RequestBody SubmitAnswerMobileRequestDto request) { @RequestBody SubmitAnswerMobileRequestDto request) {
examineService.submitAnswer(userPrincipal, request);
return ApiResponse.ok("SUCCESS"); return ApiResponse.ok("SUCCESS");
} }
...@@ -95,7 +96,7 @@ public class ExamineMobileController { ...@@ -95,7 +96,7 @@ public class ExamineMobileController {
@Schema(description = "对练ID") @RequestParam("examine_id") Integer examineId, @Schema(description = "对练ID") @RequestParam("examine_id") Integer examineId,
@Schema(description = "考试流水号") @RequestParam("business_no") String businessNo) { @Schema(description = "考试流水号") @RequestParam("business_no") String businessNo) {
ExamineStartResultDto result = new ExamineStartResultDto(); ExamineStartResultDto result = examineService.getNextQuestion(userPrincipal, examineId, businessNo);
return ApiResponse.ok(result); return ApiResponse.ok(result);
} }
...@@ -107,6 +108,7 @@ public class ExamineMobileController { ...@@ -107,6 +108,7 @@ public class ExamineMobileController {
@Operation(summary = "完成考试(触发最终结果更新)") @Operation(summary = "完成考试(触发最终结果更新)")
@PostMapping(value = "/complete_examine") @PostMapping(value = "/complete_examine")
public ApiResponse<String> updateExamResult(@RequestBody ExamineUpdateResultDto request) { public ApiResponse<String> updateExamResult(@RequestBody ExamineUpdateResultDto request) {
return ApiResponse.ok("SUCCESS"); return ApiResponse.ok("SUCCESS");
} }
......
package cn.breeze.elleai.domain.sparring.model.request;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
@Data
public class ExamineRecordDetailSaveModel implements Serializable {
private Integer id;
/**
* 对练记录ID
*/
private Integer recordId;
/**
* 题目ID
*/
private Integer qaId;
/**
* 评分
*/
private Float score;
/**
* 评价
*/
private String evaluation;
/**
* 员工回答
*/
private String answer;
/**
* 创建时间
*/
private Date createTime;
/**
* 更新时间
*/
private Date updateTime;
}
package cn.breeze.elleai.domain.sparring.model.request;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.KeyType;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
@Data
public class ExamineRecordSaveModel implements Serializable {
private Integer id;
/**
* 用户ID
*/
private String userId;
/**
* 用户名称
*/
private String userName;
/**
* 考试流水号
*/
private String businessNo;
/**
* 所属门店ID
*/
private String shopId;
/**
* 所属门店名称
*/
private String shopName;
/**
* 会话ID
*/
private String sessionId;
/**
* 对练ID
*/
private Integer examineId;
/**
* 对练模式(0练习 1对练)
*/
private Integer examineMode;
/**
* 已答题数量
*/
private Integer answeredNum;
/**
* 综合评分
*/
private Float overallScore;
/**
* 综合评价
*/
private String overallEvaluation;
/**
* 创建时间
*/
private Date createTime;
/**
* 更新时间
*/
private Date updateTime;
}
package cn.breeze.elleai.domain.sparring.model.request;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.KeyType;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
@Data
public class UserChatCompletionSaveModel implements Serializable {
private Integer id;
/**
* 用户ID
*/
private String userId;
/**
* 用户名称
*/
private String userName;
/**
* 所属门店ID
*/
private String shopId;
/**
* 所属门店名称
*/
private String shopName;
/**
* 会话ID
*/
private String sessionId;
/**
* 首次提问时间
*/
private String firstQuestion;
/**
* 最后一次提问
*/
private String lastQuestion;
/**
* 创建时间
*/
private Date createTime;
}
...@@ -24,6 +24,11 @@ public class ExamineRecordResponseModel implements Serializable { ...@@ -24,6 +24,11 @@ public class ExamineRecordResponseModel implements Serializable {
*/ */
private String userName; private String userName;
/**
* 考试流水号
*/
private String businessNo;
/** /**
* 所属门店ID * 所属门店ID
*/ */
......
package cn.breeze.elleai.domain.sparring.service; package cn.breeze.elleai.domain.sparring.service;
import cn.breeze.elleai.domain.sparring.model.request.QaAssistantRequestModel; import cn.breeze.elleai.domain.sparring.model.request.*;
import cn.breeze.elleai.domain.sparring.model.request.QaAssistantSaveModel;
import cn.breeze.elleai.domain.sparring.model.request.UserQaHistoryRequestModel;
import cn.breeze.elleai.domain.sparring.model.request.UserQaRequestModel;
import cn.breeze.elleai.domain.sparring.model.response.QaAssistantResponseModel; import cn.breeze.elleai.domain.sparring.model.response.QaAssistantResponseModel;
import cn.breeze.elleai.domain.sparring.model.response.UserChatCompletionHistoryResponseModel; import cn.breeze.elleai.domain.sparring.model.response.UserChatCompletionHistoryResponseModel;
import cn.breeze.elleai.domain.sparring.model.response.UserChatCompletionResponseModel; import cn.breeze.elleai.domain.sparring.model.response.UserChatCompletionResponseModel;
...@@ -20,11 +17,13 @@ public interface ChatCompletionService { ...@@ -20,11 +17,13 @@ public interface ChatCompletionService {
List<UserChatCompletionResponseModel> userQaList(UserQaRequestModel request); List<UserChatCompletionResponseModel> userQaList(UserQaRequestModel request);
List<UserChatCompletionHistoryResponseModel> userQaHistoryDetail(Integer sessionId); List<UserChatCompletionHistoryResponseModel> userQaHistoryDetail(Integer chatCompletionId);
Page<UserChatCompletionHistoryResponseModel> userQaHistoryDetailPaginQuery(Integer chatCompletionId, Integer pageNo, Integer pageSize);
UserChatCompletionResponseModel userQaDetail(UserQaRequestModel request); UserChatCompletionResponseModel userQaDetail(UserQaRequestModel request);
Integer saveUserQaSession(String userId, String sessionId); Integer saveUserQaSession(UserChatCompletionSaveModel dto);
void saveUserQaRecord(Integer chatCompletionId, Integer type, String content); void saveUserQaRecord(Integer chatCompletionId, Integer type, String content);
......
package cn.breeze.elleai.domain.sparring.service; package cn.breeze.elleai.domain.sparring.service;
import cn.breeze.elleai.domain.sparring.model.request.QaAssistantRequestModel; import cn.breeze.elleai.domain.sparring.model.request.*;
import cn.breeze.elleai.domain.sparring.model.request.QaAssistantSaveModel;
import cn.breeze.elleai.domain.sparring.model.request.UserQaHistoryRequestModel;
import cn.breeze.elleai.domain.sparring.model.request.UserQaRequestModel;
import cn.breeze.elleai.domain.sparring.model.response.QaAssistantResponseModel; import cn.breeze.elleai.domain.sparring.model.response.QaAssistantResponseModel;
import cn.breeze.elleai.domain.sparring.model.response.UserChatCompletionHistoryResponseModel; import cn.breeze.elleai.domain.sparring.model.response.UserChatCompletionHistoryResponseModel;
import cn.breeze.elleai.domain.sparring.model.response.UserChatCompletionResponseModel; import cn.breeze.elleai.domain.sparring.model.response.UserChatCompletionResponseModel;
...@@ -91,14 +88,26 @@ public class ChatCompletionServiceImpl implements ChatCompletionService{ ...@@ -91,14 +88,26 @@ public class ChatCompletionServiceImpl implements ChatCompletionService{
} }
@Override @Override
public List<UserChatCompletionHistoryResponseModel> userQaHistoryDetail(Integer sessionId) { public List<UserChatCompletionHistoryResponseModel> userQaHistoryDetail(Integer chatCompletionId) {
QueryWrapper queryWrapper = QueryWrapper.create(); QueryWrapper queryWrapper = QueryWrapper.create();
queryWrapper.where(USER_CHAT_COMPLETION_HISTORY_ENTITY.CHAT_COMPLETION_ID.eq(sessionId)); queryWrapper.where(USER_CHAT_COMPLETION_HISTORY_ENTITY.CHAT_COMPLETION_ID.eq(chatCompletionId));
queryWrapper.orderBy(USER_CHAT_COMPLETION_HISTORY_ENTITY.CREATE_TIME, true); queryWrapper.orderBy(USER_CHAT_COMPLETION_HISTORY_ENTITY.CREATE_TIME, true);
return chatCompletionHistoryMapper.selectListByQueryAs(queryWrapper, UserChatCompletionHistoryResponseModel.class); return chatCompletionHistoryMapper.selectListByQueryAs(queryWrapper, UserChatCompletionHistoryResponseModel.class);
} }
@Override
public Page<UserChatCompletionHistoryResponseModel> userQaHistoryDetailPaginQuery(Integer chatCompletionId, Integer pageNo, Integer pageSize) {
QueryWrapper queryWrapper = QueryWrapper.create();
queryWrapper.where(USER_CHAT_COMPLETION_HISTORY_ENTITY.CHAT_COMPLETION_ID.eq(chatCompletionId));
queryWrapper.orderBy(USER_CHAT_COMPLETION_HISTORY_ENTITY.CREATE_TIME, true);
Page<UserChatCompletionHistoryResponseModel> page = chatCompletionHistoryMapper.paginateAs(pageNo, pageSize, queryWrapper, UserChatCompletionHistoryResponseModel.class);
return page;
}
@Override @Override
public UserChatCompletionResponseModel userQaDetail(UserQaRequestModel request) { public UserChatCompletionResponseModel userQaDetail(UserQaRequestModel request) {
QueryWrapper queryWrapper = QueryWrapper.create(); QueryWrapper queryWrapper = QueryWrapper.create();
...@@ -109,10 +118,9 @@ public class ChatCompletionServiceImpl implements ChatCompletionService{ ...@@ -109,10 +118,9 @@ public class ChatCompletionServiceImpl implements ChatCompletionService{
} }
@Override @Override
public Integer saveUserQaSession(String userId, String sessionId) { public Integer saveUserQaSession(UserChatCompletionSaveModel dto) {
UserChatCompletionEntity entity = new UserChatCompletionEntity(); UserChatCompletionEntity entity = new UserChatCompletionEntity();
entity.setUserId(userId); BeanUtil.copyProperties(dto, entity);
entity.setSessionId(sessionId);
entity.setUpdateTime(new Date()); entity.setUpdateTime(new Date());
chatCompletionMapper.insertOrUpdateSelective(entity); chatCompletionMapper.insertOrUpdateSelective(entity);
return entity.getId(); return entity.getId();
......
...@@ -49,7 +49,7 @@ public interface ExamineService { ...@@ -49,7 +49,7 @@ public interface ExamineService {
*/ */
Page<ExamineQaResponseModel> examineQaPaginQuery(ExamineQaRequestModel request); Page<ExamineQaResponseModel> examineQaPaginQuery(ExamineQaRequestModel request);
List<ExamineQaResponseModel> examineQaList(ExamineQaRequestModel request); List<ExamineQaResponseModel> examineQaList(Integer examineId);
List<ExamineQaResponseModel> examineQaList(List<Integer> qaIds); List<ExamineQaResponseModel> examineQaList(List<Integer> qaIds);
...@@ -94,6 +94,12 @@ public interface ExamineService { ...@@ -94,6 +94,12 @@ public interface ExamineService {
ExamineRecordResponseModel examineRecordDetail(Integer id); ExamineRecordResponseModel examineRecordDetail(Integer id);
ExamineRecordResponseModel examineRecordDetail(String businessNo);
void saveExamineRecord(ExamineRecordSaveModel dto);
void saveExamineRecordDetail(ExamineRecordDetailSaveModel dto);
/***************************************** 资料库分类 *****************************************/ /***************************************** 资料库分类 *****************************************/
Page<WikiCategoryResponseModel> wikiCategoryPaginQuery(WikiCategoryRequestModel request); Page<WikiCategoryResponseModel> wikiCategoryPaginQuery(WikiCategoryRequestModel request);
......
...@@ -213,13 +213,16 @@ public class ExamineServiceImpl implements ExamineService { ...@@ -213,13 +213,16 @@ public class ExamineServiceImpl implements ExamineService {
} }
@Override @Override
public List<ExamineQaResponseModel> examineQaList(ExamineQaRequestModel request) { public List<ExamineQaResponseModel> examineQaList(Integer examineId) {
QueryWrapper queryWrapper = QueryWrapper.create() QueryWrapper queryWrapper = QueryWrapper.create();
.where(EXAMINE_QA_ENTITY.DELETED.eq(0)); queryWrapper.select(EXAMINE_QA_ENTITY.ALL_COLUMNS).from(EXAMINE_QA_ENTITY);
if(StrUtil.isNotEmpty(request.getName())) { queryWrapper.leftJoin(EXAMINE_QA_XREF_ENTITY).on(EXAMINE_QA_ENTITY.ID.eq(EXAMINE_QA_XREF_ENTITY.QA_ID))
queryWrapper.where(EXAMINE_QA_ENTITY.QUESTION.like("%"+request.getName()+"%")); .and(EXAMINE_QA_XREF_ENTITY.DELETED.eq(0));
} queryWrapper.where(EXAMINE_QA_ENTITY.DELETED.eq(0));
queryWrapper.where(EXAMINE_QA_XREF_ENTITY.EXAMINE_ID.eq(examineId));
queryWrapper.orderBy(EXAMINE_QA_XREF_ENTITY.CREATE_TIME, false);
System.out.println(queryWrapper.toSQL());
return qaMapper.selectListByQueryAs(queryWrapper, ExamineQaResponseModel.class); return qaMapper.selectListByQueryAs(queryWrapper, ExamineQaResponseModel.class);
} }
...@@ -457,6 +460,30 @@ public class ExamineServiceImpl implements ExamineService { ...@@ -457,6 +460,30 @@ public class ExamineServiceImpl implements ExamineService {
return userExamineRecordMapper.selectOneByQueryAs(queryWrapper, ExamineRecordResponseModel.class); return userExamineRecordMapper.selectOneByQueryAs(queryWrapper, ExamineRecordResponseModel.class);
} }
@Override
public ExamineRecordResponseModel examineRecordDetail(String businessNo) {
QueryWrapper queryWrapper = QueryWrapper.create()
.where(USER_EXAMINE_RECORD_ENTITY.BUSINESS_NO.eq(businessNo));
return userExamineRecordMapper.selectOneByQueryAs(queryWrapper, ExamineRecordResponseModel.class);
}
@Override
public void saveExamineRecord(ExamineRecordSaveModel dto) {
UserExamineRecordEntity entity = BeanUtil.toBean(dto, UserExamineRecordEntity.class);
entity.setUpdateTime(new Date());
userExamineRecordMapper.insertOrUpdateSelective(entity);
dto.setId(entity.getId());
}
@Override
public void saveExamineRecordDetail(ExamineRecordDetailSaveModel dto) {
UserExamineDetailRecordEntity entity = BeanUtil.toBean(dto, UserExamineDetailRecordEntity.class);
entity.setUpdateTime(new Date());
userExamineDetailRecordMapper.insertOrUpdateSelective(entity);
}
@Override @Override
public Page<WikiCategoryResponseModel> wikiCategoryPaginQuery(WikiCategoryRequestModel request) { public Page<WikiCategoryResponseModel> wikiCategoryPaginQuery(WikiCategoryRequestModel request) {
Integer pageNo = ObjectUtil.defaultIfNull(request.getPageNo(), 1); Integer pageNo = ObjectUtil.defaultIfNull(request.getPageNo(), 1);
......
...@@ -42,6 +42,11 @@ public class UserExamineRecordEntity implements Serializable { ...@@ -42,6 +42,11 @@ public class UserExamineRecordEntity implements Serializable {
*/ */
private String userName; private String userName;
/**
* 考试流水号
*/
private String businessNo;
/** /**
* 所属门店ID * 所属门店ID
*/ */
......
...@@ -34,6 +34,12 @@ public class UserExamineRecordTableDef extends TableDef { ...@@ -34,6 +34,12 @@ public class UserExamineRecordTableDef extends TableDef {
*/ */
public final QueryColumn USER_NAME = new QueryColumn(this, "user_name"); public final QueryColumn USER_NAME = new QueryColumn(this, "user_name");
/**
* 考试流水号
*/
public final QueryColumn BUSINESS_NO = new QueryColumn(this, "business_no");
/** /**
* 所属门店ID * 所属门店ID
*/ */
...@@ -92,7 +98,7 @@ public class UserExamineRecordTableDef extends TableDef { ...@@ -92,7 +98,7 @@ public class UserExamineRecordTableDef extends TableDef {
/** /**
* 默认字段,不包含逻辑删除或者 large 等字段。 * 默认字段,不包含逻辑删除或者 large 等字段。
*/ */
public final QueryColumn[] DEFAULT_COLUMNS = new QueryColumn[]{ID, USER_ID, USER_NAME, SHOP_ID, SHOP_NAME, SESSION_ID, EXAMINE_ID, EXAMINE_MODE, ANSWERED_NUM, OVERALL_SCORE, OVERALL_EVALUATION, CREATE_TIME, UPDATE_TIME}; public final QueryColumn[] DEFAULT_COLUMNS = new QueryColumn[]{ID, USER_ID, USER_NAME, BUSINESS_NO, SHOP_ID, SHOP_NAME, SESSION_ID, EXAMINE_ID, EXAMINE_MODE, ANSWERED_NUM, OVERALL_SCORE, OVERALL_EVALUATION, CREATE_TIME, UPDATE_TIME};
public UserExamineRecordTableDef() { public UserExamineRecordTableDef() {
super("", "ai_user_examine_record"); super("", "ai_user_examine_record");
......
...@@ -21,8 +21,8 @@ springdoc: ...@@ -21,8 +21,8 @@ springdoc:
swagger-ui: swagger-ui:
path: /swagger-ui.html path: /swagger-ui.html
dify: dify:
api_base: http://dify-api:5001/v1 api_base: https://app-api.tech.breezeai.cn/v1
api_key: app-ilgoEphXjLw0I7x7fGeCyKYk api_key: app-mJFu7K2wl3qEYsILkQBgRAKO
# token配置 # token配置
token: token:
# 令牌自定义标识 # 令牌自定义标识
......
...@@ -21,9 +21,16 @@ springdoc: ...@@ -21,9 +21,16 @@ springdoc:
swagger-ui: swagger-ui:
path: /swagger-ui.html path: /swagger-ui.html
dify: dify:
api_base: http://dify-api:5001/v1 api_base: https://app-api.tech.breezeai.cn/v1
api_key: app-ilgoEphXjLw0I7x7fGeCyKYk api_key: app-mJFu7K2wl3qEYsILkQBgRAKO
# token配置
token:
# 令牌自定义标识
header: Authorization
# 令牌密钥
secret: fhgaf%^$#%cHDFDhUHLKnhkhj
# 令牌有效期(默认30分钟)
expireTime: 2628000
--- ---
spring: spring:
config: config:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment