xiatian 3 月之前
父節點
當前提交
3c3889b9cb

+ 26 - 0
src/main/java/cn/com/qmth/am/bean/AutoScoreEnRequest.java

@@ -0,0 +1,26 @@
+package cn.com.qmth.am.bean;
+
+import javax.validation.constraints.NotNull;
+
+import org.springframework.validation.annotation.Validated;
+
+import com.qmth.boot.core.ai.model.llm.AutoScoreRequest;
+
+/**
+ * 自动判分请求参数
+ */
+@Validated
+public class AutoScoreEnRequest extends AutoScoreRequest {
+
+    @NotNull(message = "题目名称不能为空")
+    private String questionTitle;
+
+    public String getQuestionTitle() {
+        return questionTitle;
+    }
+
+    public void setQuestionTitle(String questionTitle) {
+        this.questionTitle = questionTitle;
+    }
+
+}

+ 18 - 47
src/main/java/cn/com/qmth/am/service/impl/DsMarkingServiceImpl.java

@@ -1,15 +1,11 @@
 package cn.com.qmth.am.service.impl;
 
-import java.math.BigDecimal;
-import java.math.RoundingMode;
-import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 import org.apache.commons.io.IOUtils;
-import org.apache.commons.lang3.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -84,29 +80,8 @@ public class DsMarkingServiceImpl implements DsMarkingService {
                 .map(choice -> choice.getMessage().getContent()).findFirst().orElse("");
         try {
             AutoScoreResult scoreResult = new AutoScoreResult();
-            // 依据总分与步骤分计算最大精度
-            int scale = Math.max(getDecimalPlaces(request.getIntervalScore()),
-                    getDecimalPlaces(request.getTotalScore()));
-            int stepCount = request.getStandardAnswer().size();
-            String scoreStr = null;
-            if (stepCount > 1) {
-                scoreStr = fomatStrByRex(text);
-            } else {
-                scoreStr = fomatStr(text);
-            }
-            String[] scores = StringUtils.split(scoreStr, ",");
-            double[] scoreArray = new double[stepCount];
-            for (int i = 0; i < stepCount; i++) {
-                // 根据得分率与步骤总分计算实际得分,按最大精度保留小数位数
-                double score = BigDecimal
-                        .valueOf(Math.min(Integer.parseInt(scores[i].trim()), 100)
-                                * request.getStandardAnswer().get(i).getScore())
-                        .divide(BigDecimal.valueOf(100), scale, RoundingMode.HALF_UP).doubleValue();
-                scoreArray[i] = score;
-            }
-            scoreResult.setStepScore(scoreArray);
-            scoreResult.setTotalScore(Arrays.stream(scoreArray).mapToObj(BigDecimal::new)
-                    .reduce(BigDecimal.ZERO, BigDecimal::add).doubleValue());
+            String scoreStr = fomatStr(text);
+            scoreResult.setTotalScore(Double.valueOf(scoreStr));
             return scoreResult;
         } catch (Exception e) {
             log.error(e.getMessage() + " | " + res);
@@ -115,30 +90,26 @@ public class DsMarkingServiceImpl implements DsMarkingService {
     }
 
     private String fomatStr(String scoreStr) {
-        scoreStr = scoreStr.substring(scoreStr.lastIndexOf("\n") + 1).trim();
-        String ret = scoreStr.replaceAll(",", ",").replaceAll("。", "").replaceAll(":", ":").replaceAll("[0-9]\\.", "");
+        String ret = scoreStr.replaceAll(",", ",").replaceAll("。", "").replaceAll(":", ":");
         ret = ret.substring(ret.lastIndexOf(":") + 1).trim();
         return ret;
     }
 
-    private String fomatStrByRex(String scoreStr) {
-        int tag = scoreStr.lastIndexOf("</think>");
-        if (tag != -1) {
-            scoreStr = scoreStr.substring(tag).trim();
-        }
-        String ret = scoreStr.replaceAll(",", ",").replaceAll("。", "").replaceAll("[0-9]\\.", "");
-        Pattern pattern = Pattern.compile("(\\d{1,3}\\s*,\\s*)+\\d{1,3}");
-        Matcher matcher = pattern.matcher(ret);
-        if (matcher.find()) {
-            return matcher.group();
-        } else {
-            throw new RuntimeException("返回格式错误");
-        }
-    }
-
-    private int getDecimalPlaces(double value) {
-        return Math.max(0, BigDecimal.valueOf(value).stripTrailingZeros().scale());
-    }
+    // private String fomatStrByRex(String scoreStr) {
+    // int tag = scoreStr.lastIndexOf("</think>");
+    // if (tag != -1) {
+    // scoreStr = scoreStr.substring(tag).trim();
+    // }
+    // String ret = scoreStr.replaceAll(",", ",").replaceAll("。",
+    // "").replaceAll("[0-9]\\.", "");
+    // Pattern pattern = Pattern.compile("(\\d{1,3}\\s*,\\s*)+\\d{1,3}");
+    // Matcher matcher = pattern.matcher(ret);
+    // if (matcher.find()) {
+    // return matcher.group();
+    // } else {
+    // throw new RuntimeException("返回格式错误");
+    // }
+    // }
 
     public static void main(String[] args) {
         String scoreStr = "</think>。\\n\\n\\n70,70,60\\n\\n评分结果2个3,29,110 \\n\\n考生的回答完全覆盖了所有的关键内容,逻辑清晰,术语使用准确";

+ 9 - 17
src/main/java/cn/com/qmth/am/service/impl/StudentScoreServiceImpl.java

@@ -5,7 +5,6 @@ import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
-import java.math.BigDecimal;
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -25,14 +24,12 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
-import com.alibaba.fastjson.JSONArray;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.qmth.boot.core.ai.client.OcrApiClient;
-import com.qmth.boot.core.ai.model.llm.AutoScoreRequest;
 import com.qmth.boot.core.ai.model.llm.AutoScoreResult;
 import com.qmth.boot.core.ai.model.ocr.OcrType;
 import com.qmth.boot.core.ai.service.AiService;
@@ -49,6 +46,7 @@ import com.qmth.boot.tools.models.ByteArray;
 
 import cn.com.qmth.am.bean.AiMarkingDto;
 import cn.com.qmth.am.bean.AnswerImageDto;
+import cn.com.qmth.am.bean.AutoScoreEnRequest;
 import cn.com.qmth.am.bean.ImageSlice;
 import cn.com.qmth.am.bean.ImportResult;
 import cn.com.qmth.am.bean.StudentInfo;
@@ -573,8 +571,8 @@ public class StudentScoreServiceImpl extends ServiceImpl<StudentScoreDao, Studen
         // System.out.println(score+d.substring(start,d.length()));
         // }
         // String[] items = d.split("\\[\\[[0-9](.[0-9]+){0,1}分\\]\\]");
-        String code = "2021113801";
-        String s = "https://file.markingcloud.com/" + getMarkingCloudPath(1379, getSuffix(code), code, 1, "jpg");
+        String code = "23635174";
+        String s = "https://file.markingcloud.com/" + getMarkingCloudPath(725, getSuffix(code), code, 2, "jpg");
         System.out.println(s);
     }
 
@@ -699,22 +697,17 @@ public class StudentScoreServiceImpl extends ServiceImpl<StudentScoreDao, Studen
             if (CollectionUtils.isEmpty(q.getAnswer())) {
                 return;
             }
-            AutoScoreRequest req = new AutoScoreRequest();
+            AutoScoreEnRequest req = new AutoScoreEnRequest();
             req.setQuestionBody(q.getContent());
             req.setStandardAnswer(q.getAnswer());
             req.setStudentAnswer(score.getAnswer());
             req.setSubjectName(q.getSubjectName());
             req.setTotalScore(q.getFullScore());
-            req.setIntervalScore(0.5);
+            req.setIntervalScore(0.1);
+            req.setQuestionTitle(q.getTitle());
             AutoScoreResult ret = aiMarkingDispose(dto, org, req);
             if (ret != null) {
-                List<Double> stepScore = new ArrayList<>();
-                for (Double d : ret.getStepScore()) {
-                    stepScore.add(d);
-                }
-                double total = Arrays.stream(ret.getStepScore()).mapToObj(BigDecimal::valueOf)
-                        .reduce(BigDecimal.ZERO, BigDecimal::add).doubleValue();
-                updateScore(score.getId(), total, stepScore);
+                updateScore(score.getId(), ret.getTotalScore());
             } else {
                 updateScoreNone(score.getId(), 0.0);
             }
@@ -723,7 +716,7 @@ public class StudentScoreServiceImpl extends ServiceImpl<StudentScoreDao, Studen
         }
     }
 
-    private AutoScoreResult aiMarkingDispose(AiMarkingDto dto, OrgInfo org, AutoScoreRequest req) {
+    private AutoScoreResult aiMarkingDispose(AiMarkingDto dto, OrgInfo org, AutoScoreEnRequest req) {
         SignatureInfo signature = null;
         if (ModelTypeBak.solar.getCode().equals(sysProperty.getMarkingModel())) {
             signature = SignatureInfo.secret(org.getAccessKey(), org.getAccessSecret());
@@ -759,12 +752,11 @@ public class StudentScoreServiceImpl extends ServiceImpl<StudentScoreDao, Studen
         }
     }
 
-    private void updateScore(Long id, Double aiScore, List<Double> scoreStep) {
+    private void updateScore(Long id, Double aiScore) {
         UpdateWrapper<StudentScoreEntity> wrapper = new UpdateWrapper<>();
         LambdaUpdateWrapper<StudentScoreEntity> lw = wrapper.lambda();
         lw.set(StudentScoreEntity::getScoreStatus, DataStatus.SUCCESS);
         lw.set(StudentScoreEntity::getAiScore, aiScore);
-        lw.set(StudentScoreEntity::getStepScore, JSONArray.toJSONString(scoreStep));
         lw.set(StudentScoreEntity::getErrMsg, null);
         lw.set(StudentScoreEntity::getScoreNone, false);
         lw.eq(StudentScoreEntity::getId, id);

+ 1 - 1
src/main/java/cn/com/qmth/am/utils/FreeMarkerUtil.java

@@ -25,7 +25,7 @@ public class FreeMarkerUtil {
         config.setClassForTemplateLoading(FreeMarkerUtil.class, "/templates/");
 
         try {
-            dsMarkingReq = config.getTemplate("ds_marking.ftl", ENCODING);
+            dsMarkingReq = config.getTemplate("ds_marking_translation.ftl", ENCODING);
         } catch (IOException e) {
             throw new RuntimeException(e);
         }

+ 5 - 5
src/main/resources/application.properties

@@ -39,14 +39,14 @@ com.qmth.solar.access-key=7bbdc11570bc474dbf50e0d4a5dff328
 com.qmth.solar.access-secret=IOodRvbp2LspJTHOScgB7Yx8MRloMpyl
 
 am.marking-thread-count=4
-am.ocr-task.enable=false
-am.marking-task.enable=false
+am.ocr-task.enable=true
+am.marking-task.enable=true
 am.data-type=MARKING_CLOUD
 am.image-server=https://file.markingcloud.com
 am.data-dir=./data
-am.marking-ocr-model=Qwen2.5-32B-Instruct-GPTQ-Int4
-am.marking-ocr-server=http://39.174.90.3:31091/spiritx-api/v1/chat/completions
-am.marking-ocr-key=sk-loBBngbg1ymvUo6f647bF35d69684f1280E5D544F1F59f20
+am.marking-ocr-model=solar
+am.marking-ocr-server=
+am.marking-ocr-key=
 am.marking-marking-model=Qwen2.5-32B-Instruct-GPTQ-Int4
 am.marking-marking-server=http://39.174.90.3:31091/spiritx-api/v1/chat/completions
 am.marking-marking-key=sk-loBBngbg1ymvUo6f647bF35d69684f1280E5D544F1F59f20

+ 21 - 24
src/main/resources/templates/ds_marking_translation.ftl

@@ -1,31 +1,28 @@
-作为"${subjectName}"科目的评分教师,您的任务是依据详细的评分指南,对考生关于特定试题的回答进行全面评估。请按照以下结构化流程进行细致评判
+作为${subjectName}科目${questionTitle}试题评分员,请严格按照以下标准为考生作答进行打分
 
-**翻译原文**:
+# 试题内容
 ${questionBody}
 
-**译文**:
-${standardAnswer}
+# 参考答案
+<#list standardAnswer as item> 
+${item.content}
+</#list>
 
-#### 考生回答:
-${studentAnswer}
+# 评分规则
+5个档次和对应的分数范围如下:
+- **优秀**(14~15): 原文的信息全部传达,语气和文体风格与原文一致;断句恰当,句式正确。选词妥帖。段落之间、句子之间互应自然,有一定文采
+- **良好**(12~13): 除个别次要信息有疏漏之外,原文的重要信息全部传达,语气和文体风格与原文一致;选词较正确、得体。句子组织与安排符合汉语规范
+- **中等**(10~11): 有少量理解错误或个别漏译,但主要精神与原文一致;拘泥于英文的句式,行文不够顺大,但没有重大的选词和句式错误
+- **及格**(9~10): 有个别重大错误或遗漏,部分信息含混,但总体上基本达意;语句不够连贯,行文灰色,有个别重大的选词和句式错误
+- **不及格**(0~8): 误译、漏译较多,不能传达原文主要精神;用词不当,行文不通顺,语言不符合汉语规范
 
-#### 评判细则:
-评分分为忠实和通顺2部分
-- **忠实部分**:最高9分。
-原文的信息全部传达,语气和文体风格与原文一致(8.4-9分);
-除个别次要信息有疏漏之外,原文的重要信息全部传达,语气和文体风格与原文一致(7.2-7.8分);
-有少量理解错误或个别漏译,但主要精神与原文一致(6-6.6分);
-有个别重大错误或遗漏,部分信息含混,但总体上基本达意(5.4-6分);
-误译、漏译较多,不能传达原文主要精神(0-4.8分)。
-- **通顺部分**:最高6分。
-断句恰当,句式正确。选词妥帖。段落之间、句子之间互应自然,有一定文采(5.6-6分);
-选词较正确、得体。句子组织与安排符合汉语规范(4.8-5.2分);
-拘泥于英文的句式,行文不够顺大,但没有重大的选词和句式错误(4-4.4分);
-语句不够连贯,行文灰色,有个别重大的选词和句式错误(3.6-4分);
-用词不当,行文不通顺,语言不符合汉语规范(0-3.2分)。
+# 评分流程
+1. 理解试题内容与评分规则,分析考生作答内容,对比参考答案,准确判断考生作答属于哪个档次
+2. 从所属档次的分值范围中选择一个合适的分数作为最终评分结果,能准确反映考生作答的情况
+3. 若考生作答仅包含试题名称或试题内容,没有有效作答,直接判为0分
 
-#### 评分操作指引:
-针对忠实和通顺2部分对考生回答进行细致评判。
+# 考生作答
+${studentAnswer}
 
-#### 最终输出要求:
-直接输出2条关键内容的评分结果,评分结果无需其他文字说明,各分数间以英文逗号分隔,分数项不要加序号且无需其他文字说明。
+# 输出要求:
+直接输出最终评分结果,用数字表示,无需其他文字说明。