Spaces:
Paused
Paused
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 filesStudent 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 |
-
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
-
|
| 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 |
-
|
| 88 |
-
|
|
|
|
|
|
|
|
|
|
| 89 |
continue
|
| 90 |
|
| 91 |
-
|
| 92 |
-
|
|
|
|
| 93 |
|
| 94 |
-
|
| 95 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 96 |
relevant_teacher.append(ta)
|
| 97 |
-
q = question_map.get(qnum)
|
| 98 |
-
if q:
|
| 99 |
-
wrong_questions.append(q)
|
| 100 |
|
| 101 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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.
|