MrSimple01 commited on
Commit
33b3cd8
·
verified ·
1 Parent(s): 4550cfd

Update src/quiz_processing.py

Browse files
Files changed (1) hide show
  1. src/quiz_processing.py +130 -9
src/quiz_processing.py CHANGED
@@ -7,7 +7,60 @@ from typing import Dict, Any, List, Optional
7
  from transformers import AutoTokenizer
8
  from sentence_transformers import SentenceTransformer
9
  from huggingface_hub import login
10
- from src.prompts import SUMMARY_PROMPT_TEMPLATE, SYSTEM_PROMPT, QUIZ_PROMPT_TEMPLATE
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
 
12
  GEMINI_MODEL = "gemini-2.0-flash"
13
  DEFAULT_TEMPERATURE = 0.7
@@ -79,22 +132,60 @@ def generate_with_gemini(text, api_key, language, content_type="summary"):
79
 
80
  try:
81
  content = response.content
82
- json_match = re.search(r'```json\s*([\s\S]*?)\s*```', content)
 
83
 
84
  if json_match:
85
  json_str = json_match.group(1)
86
  else:
 
87
  json_match = re.search(r'(\{[\s\S]*\})', content)
88
  if json_match:
89
  json_str = json_match.group(1)
90
  else:
 
91
  json_str = content
92
 
93
- # Parse the JSON
94
- function_call = json.loads(json_str)
95
- return function_call
96
- except json.JSONDecodeError:
97
- raise Exception("Could not parse JSON from LLM response")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
98
  except Exception as e:
99
  raise Exception(f"Error calling API: {str(e)}")
100
 
@@ -115,6 +206,9 @@ def format_summary_for_display(results, language="English"):
115
  summary_header = "SUMMARY"
116
 
117
  segments = results.get("segments", [])
 
 
 
118
  for i, segment in enumerate(segments):
119
  topic = segment["topic_name"]
120
  segment_num = i + 1
@@ -144,6 +238,9 @@ def format_quiz_for_display(results, language="English"):
144
  output.append(f"{'='*40}\n")
145
 
146
  quiz_questions = results.get("quiz_questions", [])
 
 
 
147
  for i, q in enumerate(quiz_questions):
148
  output.append(f"\n{i+1}. {q['question']}")
149
  for j, option in enumerate(q['options']):
@@ -155,6 +252,9 @@ def format_quiz_for_display(results, language="English"):
155
 
156
  def analyze_document(text, gemini_api_key, language, content_type="summary"):
157
  try:
 
 
 
158
  start_time = time.time()
159
  text_parts = split_text_by_tokens(text)
160
 
@@ -172,11 +272,20 @@ def analyze_document(text, gemini_api_key, language, content_type="summary"):
172
 
173
  analysis = generate_with_gemini(part, gemini_api_key, language, "summary")
174
 
175
- if "segments" in analysis:
176
  for segment in analysis["segments"]:
177
  segment["segment_number"] = segment_counter
178
  all_results["segments"].append(segment)
179
  segment_counter += 1
 
 
 
 
 
 
 
 
 
180
 
181
  formatted_output = format_summary_for_display(all_results, language)
182
 
@@ -190,11 +299,23 @@ def analyze_document(text, gemini_api_key, language, content_type="summary"):
190
 
191
  analysis = generate_with_gemini(part, gemini_api_key, language, "quiz")
192
 
193
- if "quiz_questions" in analysis:
194
  remaining_slots = 10 - len(all_results["quiz_questions"])
195
  if remaining_slots > 0:
196
  questions_to_add = analysis["quiz_questions"][:remaining_slots]
197
  all_results["quiz_questions"].extend(questions_to_add)
 
 
 
 
 
 
 
 
 
 
 
 
198
 
199
  formatted_output = format_quiz_for_display(all_results, language)
200
 
 
7
  from transformers import AutoTokenizer
8
  from sentence_transformers import SentenceTransformer
9
  from huggingface_hub import login
10
+ from src.prompts import SYSTEM_PROMPT
11
+
12
+ # Define the prompt templates directly in this file since they're referenced but missing
13
+ SUMMARY_PROMPT_TEMPLATE = """You are an expert content analyst specialized in creating professional, actionable summaries of educational content.
14
+
15
+ Please analyze the following text to create a comprehensive yet concise summary that will be valuable to readers. Break down the content into 2-3 meaningful segments, each focused on a key topic or theme.
16
+
17
+ For each segment of the content, provide:
18
+ 1. A descriptive topic name
19
+ 2. 3-5 key concepts or terms that are central to understanding this segment
20
+ 3. A concise summary paragraph (3-5 sentences) that captures the essential information
21
+
22
+ The text to analyze is:
23
+ {text}
24
+
25
+ FORMAT YOUR RESPONSE STRICTLY AS A JSON OBJECT AS FOLLOWS (with no other text, explanation or formatting):
26
+ {
27
+ "segments": [
28
+ {
29
+ "topic_name": "Title for the first segment",
30
+ "key_concepts": ["Key concept 1", "Key concept 2", "Key concept 3"],
31
+ "summary": "Concise summary paragraph for this segment that captures the essential information."
32
+ },
33
+ {
34
+ "topic_name": "Title for the second segment",
35
+ "key_concepts": ["Key concept 1", "Key concept 2", "Key concept 3"],
36
+ "summary": "Concise summary paragraph for this segment that captures the essential information."
37
+ }
38
+ ]
39
+ }"""
40
+
41
+ QUIZ_PROMPT_TEMPLATE = """You are an expert quiz creator specialized in creating educational assessments.
42
+
43
+ Please analyze the following text and create 5 multiple-choice quiz questions that test understanding of the key concepts and information presented in the text. For each question:
44
+ 1. Write a clear, concise question
45
+ 2. Create 4 answer options (A, B, C, D) with exactly one correct answer
46
+
47
+ The text to analyze is:
48
+ {text}
49
+
50
+ FORMAT YOUR RESPONSE STRICTLY AS A JSON OBJECT AS FOLLOWS (with no other text, explanation or formatting):
51
+ {
52
+ "quiz_questions": [
53
+ {
54
+ "question": "The full text of the question?",
55
+ "options": [
56
+ { "text": "First option text", "correct": false },
57
+ { "text": "Second option text", "correct": true },
58
+ { "text": "Third option text", "correct": false },
59
+ { "text": "Fourth option text", "correct": false }
60
+ ]
61
+ }
62
+ ]
63
+ }"""
64
 
65
  GEMINI_MODEL = "gemini-2.0-flash"
66
  DEFAULT_TEMPERATURE = 0.7
 
132
 
133
  try:
134
  content = response.content
135
+ # First try to find JSON within code blocks
136
+ json_match = re.search(r'```(?:json)?\s*([\s\S]*?)\s*```', content)
137
 
138
  if json_match:
139
  json_str = json_match.group(1)
140
  else:
141
+ # Then try to find JSON with curly braces
142
  json_match = re.search(r'(\{[\s\S]*\})', content)
143
  if json_match:
144
  json_str = json_match.group(1)
145
  else:
146
+ # If we still don't have JSON, try to clean and parse the content directly
147
  json_str = content
148
 
149
+ # Clean up the JSON string
150
+ json_str = json_str.strip()
151
+
152
+ # Try to parse the JSON
153
+ try:
154
+ function_call = json.loads(json_str)
155
+ return function_call
156
+ except json.JSONDecodeError:
157
+ # If direct parsing fails, try to fix common issues
158
+ # Remove markdown formatting or extra text
159
+ cleaned_json = re.sub(r'^[^{]*', '', json_str)
160
+ cleaned_json = re.sub(r'[^}]*$', '', cleaned_json)
161
+ return json.loads(cleaned_json)
162
+
163
+ except json.JSONDecodeError as e:
164
+ # Fall back to a default structure
165
+ if content_type == "summary":
166
+ return {
167
+ "segments": [
168
+ {
169
+ "topic_name": "Content Analysis",
170
+ "key_concepts": ["AI Processing", "Text Analysis"],
171
+ "summary": "The model was unable to produce a properly formatted JSON response. Please try again with a different text sample."
172
+ }
173
+ ]
174
+ }
175
+ else:
176
+ return {
177
+ "quiz_questions": [
178
+ {
179
+ "question": "Unable to generate quiz questions from the provided text.",
180
+ "options": [
181
+ {"text": "Try again", "correct": true},
182
+ {"text": "Use different text", "correct": false},
183
+ {"text": "Adjust the prompt", "correct": false},
184
+ {"text": "Contact support", "correct": false}
185
+ ]
186
+ }
187
+ ]
188
+ }
189
  except Exception as e:
190
  raise Exception(f"Error calling API: {str(e)}")
191
 
 
206
  summary_header = "SUMMARY"
207
 
208
  segments = results.get("segments", [])
209
+ if not segments:
210
+ return "No segments were generated. Please try again with a different text sample."
211
+
212
  for i, segment in enumerate(segments):
213
  topic = segment["topic_name"]
214
  segment_num = i + 1
 
238
  output.append(f"{'='*40}\n")
239
 
240
  quiz_questions = results.get("quiz_questions", [])
241
+ if not quiz_questions:
242
+ return "No quiz questions were generated. Please try again with a different text sample."
243
+
244
  for i, q in enumerate(quiz_questions):
245
  output.append(f"\n{i+1}. {q['question']}")
246
  for j, option in enumerate(q['options']):
 
252
 
253
  def analyze_document(text, gemini_api_key, language, content_type="summary"):
254
  try:
255
+ if not text or len(text.strip()) < 100:
256
+ return "Error: Text is too short to analyze. Please provide a longer text sample.", None, None
257
+
258
  start_time = time.time()
259
  text_parts = split_text_by_tokens(text)
260
 
 
272
 
273
  analysis = generate_with_gemini(part, gemini_api_key, language, "summary")
274
 
275
+ if "segments" in analysis and analysis["segments"]:
276
  for segment in analysis["segments"]:
277
  segment["segment_number"] = segment_counter
278
  all_results["segments"].append(segment)
279
  segment_counter += 1
280
+ else:
281
+ # Add a default segment if none were returned
282
+ all_results["segments"].append({
283
+ "segment_number": segment_counter,
284
+ "topic_name": "Content Analysis",
285
+ "key_concepts": ["Text Processing", "AI Analysis", "Document Summarization"],
286
+ "summary": "The system was unable to generate detailed segments from this text portion. This may be due to the complexity of the content or formatting issues. Consider breaking the text into smaller, more focused sections."
287
+ })
288
+ segment_counter += 1
289
 
290
  formatted_output = format_summary_for_display(all_results, language)
291
 
 
299
 
300
  analysis = generate_with_gemini(part, gemini_api_key, language, "quiz")
301
 
302
+ if "quiz_questions" in analysis and analysis["quiz_questions"]:
303
  remaining_slots = 10 - len(all_results["quiz_questions"])
304
  if remaining_slots > 0:
305
  questions_to_add = analysis["quiz_questions"][:remaining_slots]
306
  all_results["quiz_questions"].extend(questions_to_add)
307
+ else:
308
+ # Add a default question if none were returned
309
+ if len(all_results["quiz_questions"]) < 10:
310
+ all_results["quiz_questions"].append({
311
+ "question": "What is the main purpose of text analysis in educational contexts?",
312
+ "options": [
313
+ {"text": "To change the original meaning of the text", "correct": False},
314
+ {"text": "To extract key concepts and facilitate understanding", "correct": True},
315
+ {"text": "To reduce text to exactly half its original length", "correct": False},
316
+ {"text": "To eliminate all technical terminology", "correct": False}
317
+ ]
318
+ })
319
 
320
  formatted_output = format_quiz_for_display(all_results, language)
321