feat: judgment-anchored grading and per-question results
- Grader: inject judgment as pass criteria anchor in LLM prompt - Grader: use followupHints for follow-up direction (not generic text) - Grader: follow-up limit from followupHints.length instead of hardcoded 2 - Session: correctAnswer/judgment stored in questions, stripped during assessment - Frontend: per-question results panel with choice ✅/❌ + judgment display
This commit is contained in:
@@ -501,6 +501,8 @@ private async getModel(tenantId: string): Promise<ChatOpenAI> {
|
||||
questionText: item.questionText,
|
||||
questionType: item.questionType,
|
||||
options: item.options,
|
||||
correctAnswer: item.correctAnswer,
|
||||
judgment: item.judgment,
|
||||
keyPoints: item.keyPoints,
|
||||
difficulty: item.difficulty,
|
||||
dimension: item.dimension,
|
||||
@@ -768,7 +770,10 @@ const initialState: Partial<EvaluationState> = {
|
||||
}
|
||||
await this.sessionRepository.save(session);
|
||||
|
||||
const mappedData: any = this.sanitizeStateForClient({ ...finalData });
|
||||
const mappedData: any = this.sanitizeStateForClient(
|
||||
{ ...finalData },
|
||||
session.status !== AssessmentStatus.COMPLETED,
|
||||
);
|
||||
mappedData.messages = this.mapMessages(finalData.messages);
|
||||
mappedData.feedbackHistory = this.mapMessages(
|
||||
finalData.feedbackHistory || [],
|
||||
@@ -1139,7 +1144,10 @@ const initialState: Partial<EvaluationState> = {
|
||||
}
|
||||
await this.sessionRepository.save(session);
|
||||
|
||||
const mappedData: any = this.sanitizeStateForClient({ ...finalData });
|
||||
const mappedData: any = this.sanitizeStateForClient(
|
||||
{ ...finalData },
|
||||
session.status !== AssessmentStatus.COMPLETED,
|
||||
);
|
||||
mappedData.messages = this.mapMessages(finalData.messages);
|
||||
mappedData.feedbackHistory = this.mapMessages(
|
||||
finalData.feedbackHistory || [],
|
||||
@@ -1185,7 +1193,10 @@ const initialState: Partial<EvaluationState> = {
|
||||
values.feedbackHistory = this.mapMessages(values.feedbackHistory);
|
||||
}
|
||||
|
||||
return this.sanitizeStateForClient(values);
|
||||
return this.sanitizeStateForClient(
|
||||
values,
|
||||
session.status !== AssessmentStatus.COMPLETED,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1394,14 +1405,19 @@ const initialState: Partial<EvaluationState> = {
|
||||
/**
|
||||
* Strips sensitive fields before sending state to frontend.
|
||||
*/
|
||||
private sanitizeStateForClient(data: any): any {
|
||||
private sanitizeStateForClient(data: any, stripAnswers = true): any {
|
||||
if (!data) return data;
|
||||
const sanitized = { ...data };
|
||||
delete sanitized.questionAnswerKey;
|
||||
if (stripAnswers) {
|
||||
delete sanitized.questionAnswerKey;
|
||||
}
|
||||
if (Array.isArray(sanitized.questions)) {
|
||||
sanitized.questions = sanitized.questions.map((q: any) => {
|
||||
const { correctAnswer, judgment, followupHints, ...rest } = q;
|
||||
return rest;
|
||||
if (stripAnswers) {
|
||||
const { correctAnswer, judgment, followupHints, ...rest } = q;
|
||||
return rest;
|
||||
}
|
||||
return q;
|
||||
});
|
||||
}
|
||||
return sanitized;
|
||||
|
||||
Reference in New Issue
Block a user