|
|
@@ -1,23 +1,25 @@
|
|
|
package com.njuzr.eaibackend.service;
|
|
|
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
|
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
|
|
import com.njuzr.eaibackend.exception.MyException;
|
|
|
import com.njuzr.eaibackend.mapper.*;
|
|
|
import com.njuzr.eaibackend.po.*;
|
|
|
-import com.njuzr.eaibackend.utils.FileUtil;
|
|
|
-import lombok.AllArgsConstructor;
|
|
|
-import lombok.Data;
|
|
|
-import lombok.NoArgsConstructor;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.apache.commons.lang3.time.StopWatch;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.beans.factory.annotation.Qualifier;
|
|
|
import org.springframework.http.HttpStatus;
|
|
|
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.transaction.annotation.Propagation;
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
|
|
|
import java.util.ArrayList;
|
|
|
import java.util.Comparator;
|
|
|
import java.util.Date;
|
|
|
import java.util.List;
|
|
|
-import java.util.stream.Collectors;
|
|
|
+import java.util.concurrent.CompletableFuture;
|
|
|
|
|
|
/**
|
|
|
* @author BaiBai
|
|
|
@@ -109,16 +111,25 @@ public class AIEvaluationService {
|
|
|
|
|
|
private final EvaluationMapper evaluationMapper;
|
|
|
|
|
|
- private final FileUtil fileUtil = new FileUtil();
|
|
|
+ private final EvaluationMapperServiceImpl evaluationMapperServiceImpl;
|
|
|
|
|
|
@Autowired
|
|
|
- public AIEvaluationService(AIRequestService aiRequestService, StudentAssignmentMapper studentAssignmentMapper, AssignmentMapper assignmentMapper, OverallEvaluationMapper overallEvaluationMapper, SentenceEvaluationMapper sentenceEvaluationMapper, EvaluationMapper evaluationMapper) {
|
|
|
+ @Qualifier("aiTaskExecutor")
|
|
|
+ private ThreadPoolTaskExecutor aiTaskExecutor;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ public AIEvaluationService(AIRequestService aiRequestService, StudentAssignmentMapper studentAssignmentMapper, AssignmentMapper assignmentMapper, OverallEvaluationMapper overallEvaluationMapper, SentenceEvaluationMapper sentenceEvaluationMapper, EvaluationMapper evaluationMapper, EvaluationMapperServiceImpl evaluationMapperServiceImpl) {
|
|
|
this.aiRequestService = aiRequestService;
|
|
|
this.studentAssignmentMapper = studentAssignmentMapper;
|
|
|
this.assignmentMapper = assignmentMapper;
|
|
|
this.overallEvaluationMapper = overallEvaluationMapper;
|
|
|
this.sentenceEvaluationMapper = sentenceEvaluationMapper;
|
|
|
this.evaluationMapper = evaluationMapper;
|
|
|
+ this.evaluationMapperServiceImpl = evaluationMapperServiceImpl;
|
|
|
+ }
|
|
|
+
|
|
|
+ public CompletableFuture<AIEntry> evaluationAsync(Long assignmentId, Long studentId) {
|
|
|
+ return CompletableFuture.supplyAsync(() -> evaluation(assignmentId, studentId), aiTaskExecutor);
|
|
|
}
|
|
|
/**
|
|
|
* AI作文整体智能批改
|
|
|
@@ -126,91 +137,73 @@ public class AIEvaluationService {
|
|
|
* @param studentId
|
|
|
* @return
|
|
|
*/
|
|
|
- public AIEntry rewrite(Long assignmentId, Long studentId) {
|
|
|
- // 1 通过assignmentId和studentId找到engagement,获取当前文件链接
|
|
|
- Engagement engagement = studentAssignmentMapper.findEngagementByStudentIdAndAssignmentId(studentId, assignmentId);
|
|
|
- if(engagement == null)
|
|
|
- throw MyException.create(HttpStatus.BAD_REQUEST, "作业参与不存在");
|
|
|
+ public AIEntry evaluation(Long assignmentId, Long studentId) {
|
|
|
+ StopWatch sw = StopWatch.createStarted();
|
|
|
|
|
|
- // 通过assignmentId找到作业,获取作业描述
|
|
|
+ Engagement engagement = studentAssignmentMapper.findEngagementByStudentIdAndAssignmentId(studentId, assignmentId);
|
|
|
+ if(engagement == null) throw MyException.create(HttpStatus.BAD_REQUEST, "作业参与不存在");
|
|
|
Assignment assignment = assignmentMapper.selectById(assignmentId);
|
|
|
- if (assignment == null)
|
|
|
- throw MyException.create(HttpStatus.BAD_REQUEST, "作业不存在");
|
|
|
-
|
|
|
- // 确定当前批改没有进行过
|
|
|
- Evaluation evaluationJudge = evaluationMapper.selectOne(new QueryWrapper<Evaluation>()
|
|
|
- .eq("assignment_id", assignmentId)
|
|
|
- .eq("student_id", studentId)
|
|
|
- .eq("version", engagement.getVersion()));
|
|
|
- if(evaluationJudge != null && evaluationJudge.getOverall() == 1){
|
|
|
- throw MyException.create(HttpStatus.BAD_REQUEST, "作业已进行过AI分析");
|
|
|
- }
|
|
|
-
|
|
|
- String assignmentDescription = assignment.getDescription();
|
|
|
-
|
|
|
- // 2 找到学生作业内容
|
|
|
- String content = engagement.getTextContent();
|
|
|
- log.info("作文内容为:" + content);
|
|
|
-
|
|
|
- // 3 构造提示词
|
|
|
- String prompt = String.format(REWRITE_PROMPT_TEMPLATE, assignmentDescription, content);
|
|
|
- log.info("内置提示词为:"+ prompt);
|
|
|
+ if (assignment == null) throw MyException.create(HttpStatus.BAD_REQUEST, "作业不存在");
|
|
|
+ Evaluation evaluationJudge = evaluationMapperServiceImpl.getByVersion(assignmentId, studentId, engagement.getVersion());
|
|
|
+ if(evaluationJudge != null && evaluationJudge.getOverall() != null) throw MyException.create(HttpStatus.BAD_REQUEST, "作业已进行过AI分析");
|
|
|
|
|
|
- // 4 请求AI
|
|
|
- List<AIEntry> entry = new ArrayList<>();
|
|
|
- entry.add(new AIEntry("user", prompt));
|
|
|
- AIRequestService.AIResponse response = aiRequestService.requestChatGLM4(entry);
|
|
|
+ if(evaluationJudge == null) initEvaluationRecord(assignmentId, studentId, engagement);
|
|
|
|
|
|
- // 5 获取返回数据
|
|
|
+ String prompt = String.format(REWRITE_PROMPT_TEMPLATE, assignment.getDescription(), engagement.getTextContent());
|
|
|
+ AIRequestService.AIResponse response = requestAI(prompt, 0);
|
|
|
String retContent;
|
|
|
String role;
|
|
|
- Long timestamp;
|
|
|
try {
|
|
|
retContent = response.getChoices().get(0).getMessage().getContent();
|
|
|
role = response.getChoices().get(0).getMessage().getRole();
|
|
|
- timestamp = response.getCreated();
|
|
|
- log.info("AI返回的数据为:"+retContent);
|
|
|
+ log.info("evaluation requestAI Response:"+retContent);
|
|
|
} catch (Exception e) {
|
|
|
- log.error("AI请求返回的数据内容有误,数据为{}", response);
|
|
|
+ log.error("evaluation requestAI error: {}", response);
|
|
|
throw new MyException(HttpStatus.INTERNAL_SERVER_ERROR.value(), HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase()+":"+"请求失败");
|
|
|
}
|
|
|
|
|
|
-
|
|
|
- // 6 存储数据,已修改为MySQL存储。历史版本使用MangoDB,可前往仓库查看。
|
|
|
- // 6.1 存储评价
|
|
|
- OverallEvaluation overallEvaluation = new OverallEvaluation();
|
|
|
- overallEvaluation.setStudentId(studentId);
|
|
|
- overallEvaluation.setAssignmentId(assignmentId);
|
|
|
- overallEvaluation.setContent(content);
|
|
|
- overallEvaluation.setEvaluation(retContent);
|
|
|
- // 评价的版本跟随作业版本
|
|
|
- overallEvaluation.setVersion(engagement.getVersion());
|
|
|
+ OverallEvaluation overallEvaluation = new OverallEvaluation()
|
|
|
+ .setStudentId(studentId)
|
|
|
+ .setAssignmentId(assignmentId)
|
|
|
+ .setContent(engagement.getTextContent())
|
|
|
+ .setEvaluation(retContent)
|
|
|
+ .setVersion(engagement.getVersion());
|
|
|
overallEvaluationMapper.insert(overallEvaluation);
|
|
|
|
|
|
- // 6.2 存储版本信息
|
|
|
- Evaluation evaluationJudge2 = evaluationMapper.selectOne(new QueryWrapper<Evaluation>()
|
|
|
- .eq("assignment_id", assignmentId)
|
|
|
+ evaluationMapperServiceImpl.update(new UpdateWrapper<Evaluation>()
|
|
|
+ .set("overall", 1)
|
|
|
.eq("student_id", studentId)
|
|
|
+ .eq("assignment_id", assignmentId)
|
|
|
.eq("version", engagement.getVersion()));
|
|
|
- if(evaluationJudge2 == null){
|
|
|
- Evaluation evaluation = new Evaluation();
|
|
|
- evaluation.setTime(new Date());
|
|
|
- evaluation.setAssignmentId(assignmentId);
|
|
|
- evaluation.setStudentId(studentId);
|
|
|
- evaluation.setVersion(engagement.getVersion());
|
|
|
- evaluation.setSentence(0);
|
|
|
- evaluation.setOverall(1);
|
|
|
- evaluationMapper.insert(evaluation);
|
|
|
- } else {
|
|
|
- evaluationJudge.setOverall(1);
|
|
|
- evaluationMapper.updateById(evaluationJudge);
|
|
|
- }
|
|
|
-
|
|
|
|
|
|
+ log.info("evaluation cost: {}", sw.formatTime());
|
|
|
return new AIEntry(role, retContent);
|
|
|
|
|
|
}
|
|
|
|
|
|
+ private void initEvaluationRecord(Long assignmentId, Long studentId, Engagement engagement) {
|
|
|
+ Evaluation evaluation = new Evaluation()
|
|
|
+ .setTime(new Date())
|
|
|
+ .setAssignmentId(assignmentId)
|
|
|
+ .setStudentId(studentId)
|
|
|
+ .setVersion(engagement.getVersion())
|
|
|
+ .setSentence(0)
|
|
|
+ .setOverall(0);
|
|
|
+ evaluationMapperServiceImpl.save(evaluation);
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ private AIRequestService.AIResponse requestAI(String prompt, int retryTime) {
|
|
|
+ List<AIEntry> entry = new ArrayList<>();
|
|
|
+ entry.add(new AIEntry("user", prompt));
|
|
|
+ AIRequestService.AIResponse response = aiRequestService.requestChatGLM4(entry);
|
|
|
+ if(response == null && retryTime < 3) {
|
|
|
+ log.info("requestAI failed, retryTime: {}", retryTime + 1);
|
|
|
+ return requestAI(prompt, retryTime + 1);
|
|
|
+ }
|
|
|
+ return response;
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* AI作业逐句智能批改
|
|
|
* @param assignmentId
|