NavyDevilDoc commited on
Commit
74a6e3b
·
verified ·
1 Parent(s): ad98c0e

Update src/core/QuizEngine.py

Browse files
Files changed (1) hide show
  1. src/core/QuizEngine.py +51 -39
src/core/QuizEngine.py CHANGED
@@ -25,58 +25,70 @@ class QuizEngine:
25
  }
26
 
27
  # --- MODE 2: DOCUMENTS (NEW) ---
 
 
28
  def get_document_context(self, username):
29
- """
30
- Picks a random file, reads it, and selects a random segment.
31
- Returns the segment to be used as the 'Answer Key'.
32
- """
33
  user_dir = os.path.join(self.source_dir, username)
34
- if not os.path.exists(user_dir):
35
- return None
36
 
37
- # 1. Get list of text/md files
38
  files = [f for f in os.listdir(user_dir) if f.lower().endswith(('.txt', '.md'))]
39
- if not files:
40
- return None
41
 
42
- # 2. Pick a random file
43
- selected_file = random.choice(files)
44
- file_path = os.path.join(user_dir, selected_file)
 
 
 
45
 
46
- try:
47
- with open(file_path, 'r', encoding='utf-8', errors='ignore') as f:
48
- text = f.read()
 
 
 
 
 
 
 
 
 
 
 
49
 
50
- # 3. Split into rough paragraphs (double line break)
51
- # Filter out short/empty paragraphs to avoid bad questions
52
- paragraphs = [p.strip() for p in text.split('\n\n') if len(p.strip()) > 200]
53
-
54
- if not paragraphs:
55
- return None
56
 
57
- # 4. Pick a random paragraph
58
- selected_context = random.choice(paragraphs)
59
-
60
- return {
61
- "type": "document",
62
- "source_file": selected_file,
63
- "context_text": selected_context
64
- }
65
 
66
- except Exception as e:
67
- self.logger.error(f"Error fetching quiz context: {e}")
68
- return None
 
 
69
 
70
- # --- PROMPT CONSTRUCTORS ---
71
  def construct_question_generation_prompt(self, context_text):
72
- """Asks the LLM to write the question for us."""
 
 
73
  return (
74
  f"Act as a US Navy Engineering Duty Officer Board Examiner.\n"
75
- f"Read the following technical excerpt from a Navy reference:\n\n"
76
- f"'{context_text}'\n\n"
77
- f"TASK: Generate a single, tough, short-answer board question based ONLY on this text.\n"
78
- f"The question should test recall of specific details (e.g., 'What are the 3 documents required for...').\n"
79
- f"OUTPUT: Just the question text. No preamble."
 
 
 
 
80
  )
81
 
82
  def construct_grading_prompt(self, question, answer, context_text):
 
25
  }
26
 
27
  # --- MODE 2: DOCUMENTS (NEW) ---
28
+ # ... inside QuizEngine class ...
29
+
30
  def get_document_context(self, username):
 
 
 
 
31
  user_dir = os.path.join(self.source_dir, username)
32
+ if not os.path.exists(user_dir): return None
 
33
 
34
+ # 1. Get files
35
  files = [f for f in os.listdir(user_dir) if f.lower().endswith(('.txt', '.md'))]
36
+ if not files: return None
 
37
 
38
+ # Retry Loop: Try up to 5 times to find a "worthy" chunk
39
+ for attempt in range(5):
40
+ selected_file = random.choice(files)
41
+ try:
42
+ with open(os.path.join(user_dir, selected_file), 'r', encoding='utf-8', errors='ignore') as f:
43
+ text = f.read()
44
 
45
+ # DEFENSE 1: Aggressive Heuristic Filtering
46
+ # Split by double newline (paragraphs)
47
+ paragraphs = text.split('\n\n')
48
+ candidates = []
49
+ for p in paragraphs:
50
+ p = p.strip()
51
+ # A. Too short?
52
+ if len(p) < 250: continue
53
+ # B. Looks like a list item or table row? (starts with number/bullet)
54
+ if p[0].isdigit() or p.startswith(('-', '*', '•')): continue
55
+ # C. Looks like administrative noise?
56
+ if "intentionally left blank" in p.lower(): continue
57
+
58
+ candidates.append(p)
59
 
60
+ if not candidates: continue
 
 
 
 
 
61
 
62
+ # Pick a random survivor
63
+ selected_context = random.choice(candidates)
64
+
65
+ return {
66
+ "type": "document",
67
+ "source_file": selected_file,
68
+ "context_text": selected_context
69
+ }
70
 
71
+ except Exception as e:
72
+ self.logger.error(f"Error fetching context: {e}")
73
+ continue
74
+
75
+ return None # Failed to find good text after 5 tries
76
 
 
77
  def construct_question_generation_prompt(self, context_text):
78
+ """
79
+ DEFENSE 2: Explicit Instructions to Ignore Trivia
80
+ """
81
  return (
82
  f"Act as a US Navy Engineering Duty Officer Board Examiner.\n"
83
+ f"Review the following source text for suitability:\n"
84
+ f"'''{context_text}'''\n\n"
85
+ f"DECISION LOGIC:\n"
86
+ f"1. Does this text contain a specific Engineering Concept, Responsibility, or Procedural Rule?\n"
87
+ f"2. Is it free of pure administrative trivia (dates, page numbers, formatting rules)?\n\n"
88
+ f"IF NO: Output the word 'SKIP'.\n"
89
+ f"IF YES: Generate a difficult, scenario-based question that tests the candidate's understanding of the concept. "
90
+ f"Do not ask 'What does the text say?'. Ask 'How would you apply...?' or 'What are the requirements for...?'\n\n"
91
+ f"OUTPUT: Just the question text."
92
  )
93
 
94
  def construct_grading_prompt(self, question, answer, context_text):