chih.yikuan Claude Opus 4.6 (1M context) commited on
Commit
c99a18b
·
1 Parent(s): 3efc9d0

Fix: Treat '-' and similar markers as correct answers in student data

Browse files

Student answer data often uses '-', 'v', '✓' etc. to mark correct answers.
filter_student_wrong_answers now skips these markers and only includes
actual wrong answer text. Works with or without teacher answers uploaded.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

chatkit/backend/app/report_generator.py CHANGED
@@ -47,15 +47,28 @@ def extract_html(content: str) -> str:
47
  # Per-student report generation (new flow)
48
  # ---------------------------------------------------------------------------
49
 
 
 
 
 
 
 
 
 
 
50
  def filter_student_wrong_answers(
51
  student: dict,
52
  questions_data: dict,
53
  teacher_answers_data: dict,
54
  ) -> tuple[list[dict], list[dict], list[dict], bool]:
55
- """Compare a student's answers with teacher answers, return wrong items.
 
 
 
 
 
56
 
57
  Returns (wrong_questions, wrong_student_answers, relevant_teacher_answers, has_teacher_answers).
58
- When teacher answers are missing, returns ALL student answers & questions instead.
59
  """
60
  teacher_map: dict[int, dict] = {}
61
  for ta in teacher_answers_data.get("answers", []):
@@ -69,11 +82,7 @@ def filter_student_wrong_answers(
69
  if num is not None:
70
  question_map[int(num)] = q
71
 
72
- # No teacher answers → return ALL student answers for LLM to analyze
73
- if not teacher_map:
74
- all_questions = questions_data.get("questions", [])
75
- all_answers = student.get("answers", [])
76
- return all_questions, all_answers, [], False
77
 
78
  wrong_questions: list[dict] = []
79
  wrong_answers: list[dict] = []
@@ -84,21 +93,32 @@ def filter_student_wrong_answers(
84
  if qnum is None:
85
  continue
86
  qnum = int(qnum)
87
- ta = teacher_map.get(qnum)
88
- if ta is None:
 
 
 
89
  continue
90
 
91
- student_ans = str(sa.get("answer", "")).strip()
92
- correct_ans = str(ta.get("correct_answer", "")).strip()
 
93
 
94
- if student_ans.lower() != correct_ans.lower():
95
- wrong_answers.append(sa)
 
 
 
 
96
  relevant_teacher.append(ta)
97
- q = question_map.get(qnum)
98
- if q:
99
- wrong_questions.append(q)
100
 
101
- return wrong_questions, wrong_answers, relevant_teacher, True
 
 
 
 
 
 
102
 
103
 
104
  STUDENT_REPORT_SYSTEM_PROMPT = """You are ClassLens, an AI teaching assistant that creates a focused, personalized exam analysis report for a single student.
 
47
  # Per-student report generation (new flow)
48
  # ---------------------------------------------------------------------------
49
 
50
+ # Markers that mean "correct / no wrong answer" in student answer data
51
+ _CORRECT_MARKERS = {"-", "—", "–", "v", "V", "✓", "✔", "○", "O", "o", "正確"}
52
+
53
+
54
+ def _is_correct_marker(answer: str) -> bool:
55
+ """Check if a student answer value means 'correct' (not a real wrong answer)."""
56
+ return answer.strip() in _CORRECT_MARKERS
57
+
58
+
59
  def filter_student_wrong_answers(
60
  student: dict,
61
  questions_data: dict,
62
  teacher_answers_data: dict,
63
  ) -> tuple[list[dict], list[dict], list[dict], bool]:
64
+ """Find a student's wrong answers.
65
+
66
+ Detection strategy (in priority order):
67
+ 1. If answer is a correct-marker ("-", "v", "✓", etc.) → skip (correct)
68
+ 2. If teacher answers exist → compare against correct_answer
69
+ 3. If no teacher answers and not a marker → treat as wrong
70
 
71
  Returns (wrong_questions, wrong_student_answers, relevant_teacher_answers, has_teacher_answers).
 
72
  """
73
  teacher_map: dict[int, dict] = {}
74
  for ta in teacher_answers_data.get("answers", []):
 
82
  if num is not None:
83
  question_map[int(num)] = q
84
 
85
+ has_teacher = bool(teacher_map)
 
 
 
 
86
 
87
  wrong_questions: list[dict] = []
88
  wrong_answers: list[dict] = []
 
93
  if qnum is None:
94
  continue
95
  qnum = int(qnum)
96
+
97
+ student_ans = str(sa.get("answer") or "").strip()
98
+
99
+ # Skip blank answers
100
+ if not student_ans:
101
  continue
102
 
103
+ # "-" and similar markers mean correct → skip
104
+ if _is_correct_marker(student_ans):
105
+ continue
106
 
107
+ # If we have teacher answers, double-check against correct answer
108
+ ta = teacher_map.get(qnum)
109
+ if ta:
110
+ correct_ans = str(ta.get("correct_answer", "")).strip()
111
+ if student_ans.lower() == correct_ans.lower():
112
+ continue # actually correct
113
  relevant_teacher.append(ta)
 
 
 
114
 
115
+ # This is a wrong answer
116
+ wrong_answers.append(sa)
117
+ q = question_map.get(qnum)
118
+ if q:
119
+ wrong_questions.append(q)
120
+
121
+ return wrong_questions, wrong_answers, relevant_teacher, has_teacher
122
 
123
 
124
  STUDENT_REPORT_SYSTEM_PROMPT = """You are ClassLens, an AI teaching assistant that creates a focused, personalized exam analysis report for a single student.