Parcourir la source

feat:优化逐句批改功能“

lalala il y a 4 mois
Parent
commit
debb3a19eb

+ 65 - 0
src/main/java/com/njuzr/eaibackend/constant/EvaluationPromptConstant.java

@@ -0,0 +1,65 @@
+package com.njuzr.eaibackend.constant;
+
+public class EvaluationPromptConstant {
+
+    public static final String OVERALL_EVALUATION_PROMPT = "你是一位专业的英语写作评分专家。请严格按照以下评分标准对作文进行评价。\n\n" +
+            "【评分维度与权重】(满分100分)\n" +
+            "- 内容与观点 (30分):主题相关性、观点明确性、论据充分性、逻辑连贯性\n" +
+            "- 词汇运用 (25分):词汇丰富度、高级词汇使用、词汇准确性、拼写正确性\n" +
+            "- 句型与语法 (25分):句型多样性、语法正确性、主谓一致、时态语态\n" +
+            "- 文章结构 (10分):开头结尾、段落衔接、过渡词使用\n" +
+            "- 语言风格 (10分):正式程度、表达流畅性、创意性\n\n" +
+            "【输出格式要求】\n" +
+            "请按以下Markdown格式输出评价结果:\n\n" +
+            "## 📊 总体评分\n" +
+            "**总分:XX分**\n\n" +
+            "| 维度 | 得分 | 评价 |\n" +
+            "|------|------|------|\n" +
+            "| 内容与观点 | XX/30 | 具体评语 |\n" +
+            "| 词汇运用 | XX/25 | 具体评语 |\n" +
+            "| 句型与语法 | XX/25 | 具体评语 |\n" +
+            "| 文章结构 | XX/10 | 具体评语 |\n" +
+            "| 语言风格 | XX/10 | 具体评语 |\n\n" +
+            "## ✨ 优点\n" +
+            "1. 优点1\n" +
+            "2. 优点2\n" +
+            "3. 优点3\n\n" +
+            "## 💡 改进建议\n" +
+            "1. 改进点1\n" +
+            "2. 改进点2\n" +
+            "3. 改进点3\n\n" +
+            "## 📝 总评\n" +
+            "一两句总体评价\n\n" +
+            "【注意事项】\n" +
+            "- 每个维度的评语要具体指出学生写得好的地方和具体问题\n" +
+            "- 优点和改进点各列出3条最具代表性的\n" +
+            "- 评分要有区分度,避免所有作文都是70-80分\n" +
+            "- 严格按照Markdown表格格式输出\n\n" +
+            "【作文信息】\n" +
+            "作业描述:%s\n\n" +
+            "学生作文:\n" +
+            "%s";
+
+    public static final String SENTENCE_EVALUATION_PROMPT = "你是一位专业的英语写作批改老师。请对以下句子进行批改。\n\n" +
+            "【批改维度】\n" +
+            "1. 词汇:拼写、词性、搭配、准确性\n" +
+            "2. 语法:时态、语态、主谓一致、句型结构\n" +
+            "3. 内容:与主题相关性、逻辑连贯性\n\n" +
+            "【输出格式】\n" +
+            "请严格按以下Markdown格式输出:\n\n" +
+            "## 句子批改\n\n" +
+            "**原句:** xxx\n\n" +
+            "**状态:** ✅ 正确 / ⚠️ 需改进\n\n" +
+            "**问题维度:** 词汇 / 语法 / 内容 / 无\n\n" +
+            "**修改建议:**\n" +
+            "修改后的句子(如果需要)\n\n" +
+            "**原因说明:**\n" +
+            "解释为什么这样改\n\n" +
+            "【作业信息】\n" +
+            "作业描述:%s\n\n" +
+            "学生作文全文:\n" +
+            "%s\n\n" +
+            "待批改的句子:\n" +
+            "%s";
+
+}

+ 37 - 10
src/main/java/com/njuzr/eaibackend/service/AIEvaluationService.java

@@ -2,7 +2,10 @@ 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.constant.EvaluationPromptConstant;
 import com.njuzr.eaibackend.constant.PromptConstant;
+import com.njuzr.eaibackend.dto.deepseek.DeepSeekMessage;
+import com.njuzr.eaibackend.dto.deepseek.DeepSeekResponse;
 import com.njuzr.eaibackend.exception.MyException;
 import com.njuzr.eaibackend.mapper.*;
 import com.njuzr.eaibackend.po.*;
@@ -36,6 +39,7 @@ public class AIEvaluationService {
     private static final int RETRY_COUNT = 3;
 
     private final AIRequestService aiRequestService;
+    private final DeepSeekService deepSeekService;
 
     private final StudentAssignmentMapper studentAssignmentMapper;
 
@@ -62,12 +66,14 @@ public class AIEvaluationService {
     private SentenceEvaluationMapperServiceImpl sentenceEvaluationMapperServiceImpl;
 
     @Autowired
-    public AIEvaluationService(AIRequestService aiRequestService, StudentAssignmentMapper studentAssignmentMapper,
+    public AIEvaluationService(AIRequestService aiRequestService, DeepSeekService deepSeekService,
+            StudentAssignmentMapper studentAssignmentMapper,
             AssignmentMapper assignmentMapper, OverallEvaluationMapper overallEvaluationMapper,
             SentenceEvaluationMapper sentenceEvaluationMapper, EvaluationMapper evaluationMapper,
             EvaluationMapperServiceImpl evaluationMapperServiceImpl,
             PlatformTransactionManager transactionManager) {
         this.aiRequestService = aiRequestService;
+        this.deepSeekService = deepSeekService;
         this.studentAssignmentMapper = studentAssignmentMapper;
         this.assignmentMapper = assignmentMapper;
         this.overallEvaluationMapper = overallEvaluationMapper;
@@ -148,14 +154,17 @@ public class AIEvaluationService {
             throw MyException.create(HttpStatus.BAD_REQUEST, "作业已进行过AI分析");
         }
         try {
-            String prompt = String.format(PromptConstant.REWRITE_PROMPT_TEMPLATE, assignment.getDescription(), engagement.getTextContent());
+            String prompt = String.format(EvaluationPromptConstant.OVERALL_EVALUATION_PROMPT,
+                    assignment.getDescription(), engagement.getTextContent());
             AIRequestService.AIResponse response = requestAIWithRetry(prompt, 0);
             String retContent = response.getChoices().get(0).getMessage().getContent();
             String role = response.getChoices().get(0).getMessage().getRole();
 
-            // 保存评估结果
+            // 保存Markdown格式的评估结果
             saveOverallEvaluationResult(assignmentId, studentId, engagement, retContent);
 
+            log.info("【评分完成】作文长度: {}, 评价长度: {}", 
+                    engagement.getTextContent().length(), retContent.length());
             log.info("evaluation cost: {}", sw.formatTime());
             return new AIEntry(role, retContent);
 
@@ -223,14 +232,32 @@ public class AIEvaluationService {
     }
 
     private AIRequestService.AIResponse requestAIWithRetry(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 requestAIWithRetry(prompt, retryTime + 1);
+        List<DeepSeekMessage> messages = new ArrayList<>();
+        messages.add(DeepSeekMessage.user(prompt));
+        try {
+            DeepSeekResponse response = deepSeekService.chatCompletion(messages);
+            if (response == null && retryTime < 3) {
+                log.info("DeepSeek request failed, retryTime: {}", retryTime + 1);
+                return requestAIWithRetry(prompt, retryTime + 1);
+            }
+            if (response != null && response.getChoices() != null && !response.getChoices().isEmpty()) {
+                AIRequestService.Choice choice = new AIRequestService.Choice();
+                AIRequestService.ResponseMessage msg = new AIRequestService.ResponseMessage();
+                msg.setRole(response.getChoices().get(0).getMessage().getRole());
+                msg.setContent(response.getChoices().get(0).getMessage().getContent());
+                choice.setMessage(msg);
+                AIRequestService.AIResponse aiResponse = new AIRequestService.AIResponse();
+                aiResponse.setChoices(List.of(choice));
+                return aiResponse;
+            }
+            return null;
+        } catch (Exception e) {
+            log.error("DeepSeek request error: {}, retryTime: {}/{}", e.getMessage(), retryTime + 1, 3);
+            if (retryTime < 3) {
+                return requestAIWithRetry(prompt, retryTime + 1);
+            }
+            return null;
         }
-        return response;
     }
 
     /**