From e5e31f6eba77fb5837ffd2e1b8246811cf922cd4 Mon Sep 17 00:00:00 2001 From: Daniel Date: Wed, 1 Apr 2026 03:22:26 +0200 Subject: [PATCH] Two-phase extraction for end-of-document answer keys (PREP 2013); scroll fix; bug audit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two-phase extraction: - Detects end-of-document answer key format by scanning last 40 pages for "Preferred Response:" (PREP 2013, 2014 etc use this vs PREP 2012 inline "Correct Answer:") - Phase 1: Extract questions with item_number field, allow null correct_answer - Phase 2: Extract answer key (item_number → letter) from last 40% of document - Phase 3: Match questions to answers by item number, resolve letter → full option text - Unmatched questions go to skipped list with reason shown in Jobs page - Standard inline format (PREP 2012) unchanged Updated extraction prompts: - item_number field added to all extractions for cross-referencing - Image content rule: "Item CXXXB" figure references must NOT be treated as new questions - Recognises both "Correct Answer: X" and "Preferred Response: X" - ANSWER_KEY_PROMPT: dedicated prompt for extracting answer key tables Quiz navigation scroll: - Clicking Next, Previous, or question number now scrolls the question card into view (smooth scroll to start of question-card div) Code: extract_questions_no_answers(), extract_answer_key(), _call_model() added to ai_service.py Co-Authored-By: Claude Sonnet 4.6 (1M context) --- backend/app/services/ai_service.py | 165 +++++++++++++++++++++++++---- backend/app/tasks/quiz_tasks.py | 132 +++++++++++++++++------ frontend/src/pages/QuizPage.jsx | 9 +- 3 files changed, 253 insertions(+), 53 deletions(-) diff --git a/backend/app/services/ai_service.py b/backend/app/services/ai_service.py index 3734305..7bed936 100644 --- a/backend/app/services/ai_service.py +++ b/backend/app/services/ai_service.py @@ -16,36 +16,52 @@ def _proxy_model(model_id: str) -> str: EXTRACTION_PROMPT = """You are extracting questions from a PREP (Pediatric Review and Education Program) exam PDF. -These PDFs follow a strict format: -1. A numbered question with a clinical vignette (patient scenario) -2. Five answer options labeled A, B, C, D, E -3. A line "Correct Answer: X" where X is the letter of the correct option -4. An explanation paragraph -5. A "Critique:" section with detailed reasoning -6. A "Content Specifications:" section listing the learning objectives +These PDFs have questions with a clinical vignette, followed by five answer options A-E. +Some PDFs include "Correct Answer: X" or "Preferred Response: X" right after the options. +Some PDFs have the correct answers only at the END of the document — in that case correct_answer will be null. -Your task: extract every question and return ONLY a JSON object in this exact format: +Return ONLY a JSON object: {{"questions": [ {{ - "question_text": "", + "item_number": "", + "question_text": "", "question_type": "mcq", "options": ["