From 245dc497ad8dcc2b186ed6c1faddad751d932e61 Mon Sep 17 00:00:00 2001 From: chenyuan Date: Fri, 16 Oct 2026 20:27:27 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20AI=E8=AF=84=E8=AF=AD=E6=94=B9=E4=B8=BA30?= =?UTF-8?q?-50=E5=AD=97(=E8=BF=87=E7=9F=AD=E8=87=AA=E5=8A=A8=E9=87=8D?= =?UTF-8?q?=E5=86=99=E4=B8=80=E6=AC=A1),AI=E8=AF=84=E5=88=86=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E7=9F=A5=E8=AF=86=E6=A3=80=E7=B4=A2/=E6=A8=A1?= =?UTF-8?q?=E5=9E=8B=E8=B0=83=E7=94=A8=E5=88=86=E6=AE=B5=E8=AE=A1=E6=97=B6?= =?UTF-8?q?=E6=97=A5=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 验收:评语按AI评分数据精简到30-50字默认填入评语框,教师可改 - 排查AI评分过慢:实测知识检索32ms、千问模型调用约12s为主体,接口已异步化 --- .../impl/AiTrainingEvaluationServiceImpl.java | 34 ++++++++++++++++--- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/sztzjy/linkCommerce/service/impl/AiTrainingEvaluationServiceImpl.java b/src/main/java/com/sztzjy/linkCommerce/service/impl/AiTrainingEvaluationServiceImpl.java index c5845d2..7f87931 100644 --- a/src/main/java/com/sztzjy/linkCommerce/service/impl/AiTrainingEvaluationServiceImpl.java +++ b/src/main/java/com/sztzjy/linkCommerce/service/impl/AiTrainingEvaluationServiceImpl.java @@ -216,15 +216,27 @@ public class AiTrainingEvaluationServiceImpl implements AiTrainingEvaluationServ } private AiTrainingEvaluationView runAssessment(EvaluationContext context, JwtUser actor, AiTrainingEvaluation evaluation) { + long startedAt = System.currentTimeMillis(); String answerSnapshot = answerSnapshot(context.answer); String taskSnapshot = taskSnapshot(context.effectiveContent); List criterionPlan = assessmentCriterionPlan(context.effectiveContent.getSteps()); String rawResponse = null; try { + long knowledgeStartedAt = System.currentTimeMillis(); String knowledgeContext = knowledgeContext(context, actor, ""); + long knowledgeCost = System.currentTimeMillis() - knowledgeStartedAt; String choiceQuestionContext = choiceQuestionContext(context.effectiveContent, context.answer); + long modelStartedAt = System.currentTimeMillis(); rawResponse = qwenChatClient.completeJson(assessmentSystemPrompt(criterionPlan), assessmentUserPrompt(taskSnapshot, answerSnapshot, knowledgeContext, choiceQuestionContext)); + long modelCost = System.currentTimeMillis() - modelStartedAt; + // AI 评分过慢排查:分段记录知识检索与模型调用耗时(prompt 长度一并输出) + log.info("AI assessment timing, evaluationId={}, knowledgeContext={} ms, modelCall={} ms, total={} ms, " + + "knowledgeContextChars={}, answerSnapshotChars={}, promptChars={}", + evaluation.getId(), knowledgeCost, modelCost, System.currentTimeMillis() - startedAt, + knowledgeContext.length(), answerSnapshot.length(), + assessmentSystemPrompt(criterionPlan).length() + + assessmentUserPrompt(taskSnapshot, answerSnapshot, knowledgeContext, choiceQuestionContext).length()); JsonNode assessmentReport = object(rawResponse); int score = validateAssessment(assessmentReport, criterionPlan); compactAssessmentRationales(assessmentReport); @@ -302,20 +314,34 @@ public class AiTrainingEvaluationServiceImpl implements AiTrainingEvaluationServ // AI 评分报告是评语的主要依据;助学报告只做补充,没有也能生成 throw new ServiceException(HttpStatus.BAD_REQUEST, "该学生还没有AI评分数据,请先执行AI评分"); } + String comment = normalizeTeacherComment(generateCommentOnce(assessmentReport, helpReport, "")); + if (comment.codePointCount(0, comment.length()) < 30) { + // 验收要求 30-50 字;过短时带纠正指令重写一次,取更长的那条 + String instruction = " 上一次生成的评语只有" + comment.codePointCount(0, comment.length()) + + "个字,太短;重新生成的评语必须不少于30个字、不超过50个字。"; + String retried = normalizeTeacherComment(generateCommentOnce(assessmentReport, helpReport, instruction)); + if (retried.codePointCount(0, retried.length()) > comment.codePointCount(0, comment.length())) { + comment = retried; + } + } + return Collections.singletonMap("comment", comment); + } + + private String generateCommentOnce(String assessmentReport, String helpReport, String extraInstruction) { String rawResponse = qwenChatClient.completeJson(commentSystemPrompt(), - commentUserPrompt(assessmentReport, helpReport)); + commentUserPrompt(assessmentReport, helpReport) + StringUtils.trimToEmpty(extraInstruction)); JsonNode report = object(rawResponse); JsonNode commentNode = report.get("comment"); - if (commentNode == null || !commentNode.isTextual() || StringUtils.isBlank(commentNode.textValue())) { + if (commentNode == null || !commentNode.isTextual()) { throw invalidReport(); } - return Collections.singletonMap("comment", normalizeTeacherComment(commentNode.textValue())); + return commentNode.textValue(); } private String commentSystemPrompt() { return "You are a vocational school teacher writing feedback for one student's training task. " + "Based on the given AI scoring report (and AI tutoring report if present), write ONE Chinese teacher comment. " - + "Requirements: 10 to 50 Chinese characters; a single short paragraph; objective, specific and encouraging; " + + "Requirements: 30 to 50 Chinese characters; a single short paragraph; objective, specific and encouraging; " + "comment on the performance and give one improvement direction; " + "no bullet points, no quotes, no salutation, no prefix or suffix such as 评语. " + "Return only JSON: {\"comment\":\"...\"}";