fix: MC options display, question selection, timeout handling, and grading prompts
This commit is contained in:
@@ -91,6 +91,72 @@ export const graderNode = async (
|
||||
};
|
||||
}
|
||||
|
||||
// ── Rule-based grading: use structured followupMapping if available ──
|
||||
if (currentQuestion.followupHints) {
|
||||
let mapping: any = null;
|
||||
if (typeof currentQuestion.followupHints === 'string') {
|
||||
try { mapping = JSON.parse(currentQuestion.followupHints); } catch {}
|
||||
} else if (typeof currentQuestion.followupHints === 'object') {
|
||||
mapping = currentQuestion.followupHints;
|
||||
}
|
||||
if (mapping && Array.isArray(mapping.branches)) {
|
||||
const userAnswerText = typeof lastUserMessage.content === 'string'
|
||||
? lastUserMessage.content : JSON.stringify(lastUserMessage.content);
|
||||
|
||||
// Score based on keyword coverage
|
||||
let bestScore = mapping.defaultScore ?? 5;
|
||||
let matchedFollowup = mapping.defaultFollowup || '';
|
||||
let matchedAll = true;
|
||||
const maxFollowUps = mapping.maxFollowups ?? 2;
|
||||
|
||||
for (const branch of mapping.branches) {
|
||||
const kws = branch.keywords || [];
|
||||
const matchCount = kws.filter((kw: string) => userAnswerText.toLowerCase().includes(kw.toLowerCase())).length;
|
||||
if (kws.length > 0 && matchCount >= kws.length * 0.5) {
|
||||
const branchScore = branch.score ?? 7;
|
||||
if (branchScore > bestScore) bestScore = branchScore;
|
||||
if (branch.followup) matchedFollowup = branch.followup;
|
||||
} else if (kws.length > 0 && matchCount === 0) {
|
||||
matchedAll = false;
|
||||
}
|
||||
}
|
||||
|
||||
const completionThreshold = mapping.completionThreshold ?? 80;
|
||||
const tooShort = userAnswerText.trim().length < 8;
|
||||
const saysIDontKnow = userAnswerText.trim().length < 10 && (
|
||||
userAnswerText.includes('不知道') || userAnswerText.includes("don't know") || userAnswerText.includes('わかりません')
|
||||
);
|
||||
|
||||
let shouldFollowUp: boolean;
|
||||
if (saysIDontKnow || tooShort) {
|
||||
shouldFollowUp = false;
|
||||
bestScore = Math.min(bestScore, 2);
|
||||
} else if (bestScore >= completionThreshold / 10) {
|
||||
shouldFollowUp = false;
|
||||
} else if (currentFollowUpCount >= maxFollowUps) {
|
||||
shouldFollowUp = false;
|
||||
} else {
|
||||
shouldFollowUp = true;
|
||||
}
|
||||
|
||||
const feedbackMessage = new AIMessage(`Score: ${bestScore}/10\n\nFeedback: ${shouldFollowUp ? matchedFollowup : '回答已覆盖关键点。'}`);
|
||||
|
||||
const feedbackHistoryMessages = shouldFollowUp && matchedFollowup
|
||||
? [feedbackMessage, new AIMessage(matchedFollowup)]
|
||||
: [feedbackMessage];
|
||||
|
||||
console.log('[GraderNode] Rule grading:', { score: bestScore, shouldFollowUp, matchedAll, followup: matchedFollowup?.substring(0, 60) });
|
||||
|
||||
return {
|
||||
feedbackHistory: feedbackHistoryMessages,
|
||||
scores: { [currentQuestion.id || currentQuestionIndex.toString()]: bestScore },
|
||||
shouldFollowUp,
|
||||
followUpCount: shouldFollowUp ? currentFollowUpCount + 1 : 0,
|
||||
currentQuestionIndex: shouldFollowUp ? currentQuestionIndex : currentQuestionIndex + 1,
|
||||
} as any;
|
||||
}
|
||||
}
|
||||
|
||||
const systemPromptZh = `你是一位考官。请评分并给出反馈。
|
||||
|
||||
规则:
|
||||
@@ -100,8 +166,10 @@ export const graderNode = async (
|
||||
问题:${currentQuestion.questionText}
|
||||
关键点:${currentQuestion.keyPoints.join(', ')}
|
||||
|
||||
评分标准:准确性、完整性、深度。
|
||||
部分正确也给分(5-7分),完全不沾边才0-2分。
|
||||
评分标准:不要求深度,不要求使用特定术语,只看用户是否理解了概念。
|
||||
用户理解核心概念就给分。即使没有使用关键点中的原词,只要意思到位就算覆盖。
|
||||
例如关键点是"上下文窗口有限",用户说"信息太多超过AI处理长度"也是覆盖。
|
||||
评分原则:往宽了给分,不确定时就给高分。明显正确就给8-10分,部分正确5-7分,完全不沾边才0-2分。
|
||||
|
||||
返回JSON:
|
||||
- score: 0-10
|
||||
|
||||
Reference in New Issue
Block a user