From c015ea3697686da2d4f9694bfe3b4521b415c717 Mon Sep 17 00:00:00 2001 From: Developer Date: Thu, 21 May 2026 11:33:17 +0800 Subject: [PATCH] fix: shuffle bank questions + grader LLM error resilience - selectQuestions: shuffle final result for random question order - grader: wrap LLM invoke in try-catch, default score 5 on failure - grader: inner try-catch for JSON parse errors, graceful fallback --- .../src/assessment/graph/nodes/grader.node.ts | 28 +++++++++++++++---- .../services/question-bank.service.ts | 2 +- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/server/src/assessment/graph/nodes/grader.node.ts b/server/src/assessment/graph/nodes/grader.node.ts index 92b4e68..3a07579 100644 --- a/server/src/assessment/graph/nodes/grader.node.ts +++ b/server/src/assessment/graph/nodes/grader.node.ts @@ -201,6 +201,7 @@ Format your response as JSON: console.log('[GraderNode] Question:', currentQuestion?.questionText?.substring(0, 100)); console.log('[GraderNode] Target dimension:', currentQuestion?.dimension); + try { const response = await model.invoke([ new SystemMessage(systemPrompt), new HumanMessage(userContentText), @@ -279,14 +280,29 @@ Format your response as JSON: ? currentQuestionIndex : currentQuestionIndex + 1, } as any; - } catch (error) { - console.error('Failed to parse grade from AI response:', error); + } catch (parseError) { + console.error('[GraderNode] Failed to parse grade:', parseError); + const scoreLabel = isZh ? '得分' : isJa ? 'スコア' : 'Score'; + const fallbackMsg = new AIMessage(`${scoreLabel}: 5/10\n\n评分解析失败,默认给5分。`); return { - feedbackHistory: [ - new AIMessage("I had some trouble grading that, but let's move on."), - ], - currentQuestionIndex: currentQuestionIndex + 1, + feedbackHistory: [fallbackMsg], + scores: { [currentQuestion.id || currentQuestionIndex.toString()]: 5 }, shouldFollowUp: false, + followUpCount: 0, + currentQuestionIndex: currentQuestionIndex + 1, + } as any; + } + } catch (error) { + console.error('[GraderNode] LLM grading failed:', error); + const scoreLabel = isZh ? '得分' : isJa ? 'スコア' : 'Score'; + const feedbackLabel = isZh ? '反馈' : isJa ? 'フィードバック' : 'Feedback'; + const fallbackMsg = new AIMessage(`${scoreLabel}: 5/10\n\n${feedbackLabel}: 评分服务暂时不可用,默认给5分。`); + return { + feedbackHistory: [fallbackMsg], + scores: { [currentQuestion.id || currentQuestionIndex.toString()]: 5 }, + shouldFollowUp: false, + followUpCount: 0, + currentQuestionIndex: currentQuestionIndex + 1, } as any; } }; diff --git a/server/src/assessment/services/question-bank.service.ts b/server/src/assessment/services/question-bank.service.ts index 76c10e3..75f0dc4 100644 --- a/server/src/assessment/services/question-bank.service.ts +++ b/server/src/assessment/services/question-bank.service.ts @@ -588,7 +588,7 @@ export class QuestionBankService { this.logger.log( `[selectQuestions] Selected ${selected.length} questions from bank ${bankId}`, ); - return selected; + return this.shuffleArray(selected); } async batchReviewItems(