feat(generation): add exercise instructions, grouped display, and wizard improvements

- Add per-section instructions field to exercise wizard with sensible defaults
- Group exercises by type with section headers showing instructions
- Pass type_instructions to backend AI prompt for context-aware generation
- Add instructions editing in exercise edit dialog
- Update Exercise interface to include instructions field

Made-with: Cursor
This commit is contained in:
Yamen Ahmad
2026-04-13 00:54:19 +04:00
parent ca91544acd
commit 01cce7662d

View File

@@ -409,14 +409,41 @@ class AIController(http.Controller):
def _generate_exercises(self, ai, module, body): def _generate_exercises(self, ai, module, body):
passage_text = body.get("passage_text", "") passage_text = body.get("passage_text", "")
exercise_types = body.get("exercise_types", []) exercise_types = body.get("exercise_types", [])
count = body.get("count_per_type", 5) type_counts = body.get("type_counts", {})
types_str = ", ".join(exercise_types) if exercise_types else "multiple choice" type_instructions = body.get("type_instructions", {})
default_count = body.get("count_per_type", 5)
difficulty = body.get("difficulty", "B2")
type_specs = []
total = 0
for et in exercise_types:
c = int(type_counts.get(et, default_count))
instr = type_instructions.get(et, "")
spec_line = f"- EXACTLY {c} questions of type \"{et}\""
if instr:
spec_line += f"\n Student instructions: \"{instr}\""
type_specs.append(spec_line)
total += c
spec_str = "\n".join(type_specs) if type_specs else f"- {default_count} multiple choice questions"
messages = [ messages = [
{"role": "system", "content": ( {"role": "system", "content": (
f"Based on the following text, generate {count} exercises of these types: {types_str}. " f"You are an exam question generator. Generate EXACTLY {total} exercises "
"Return JSON: " f"at CEFR {difficulty} level based on the passage below.\n\n"
'{"questions": [{"type": string, "prompt": string, "options": [string], ' f"REQUIRED question breakdown (you MUST follow these counts exactly):\n"
'"correct_answer": string, "explanation": string, "marks": number}]}' f"{spec_str}\n\n"
"CRITICAL RULES:\n"
f"1. The total number of questions in your response MUST be exactly {total}.\n"
"2. Each question MUST have a 'type' field set to one of the requested types.\n"
"3. Each question MUST include an 'instructions' field with the student-facing instructions "
"for that section (use the provided instructions, or write appropriate ones).\n"
"4. For mcq/true_false types: include 'options' array and 'correct_answer'.\n"
"5. For fill_blanks/write_blanks types: use '___' in the prompt for blanks, "
"set correct_answer to the missing word(s), options can be empty.\n"
"6. For paragraph_match: prompt describes what to match, options are paragraph labels.\n\n"
"Return JSON:\n"
'{"questions": [{"type": string, "instructions": string, "prompt": string, '
'"options": [string], "correct_answer": string, "explanation": string, "marks": number}]}'
)}, )},
{"role": "user", "content": passage_text[:3000]}, {"role": "user", "content": passage_text[:3000]},
] ]