Update app.py
Browse files
app.py
CHANGED
@@ -46,87 +46,43 @@ def parse_quiz_content(quiz_content):
|
|
46 |
question_section = quiz_parts[0].strip()
|
47 |
answer_key_section = quiz_parts[1].strip()
|
48 |
|
49 |
-
# --- Split into blocks by double newline
|
50 |
-
blocks = re.split(r'\n\n+', question_section)
|
51 |
|
52 |
-
# ---
|
53 |
-
st.write("### Debugging: Question Blocks after Splitting:")
|
54 |
-
st.write(blocks)
|
55 |
-
|
56 |
-
# --- Handle Potential Title (First Block) - More robust title check ---
|
57 |
if blocks:
|
58 |
first_block = blocks[0].strip()
|
59 |
-
if not re.
|
60 |
-
|
|
|
|
|
|
|
61 |
|
62 |
|
63 |
# --- Process Question Blocks ---
|
64 |
-
question_number = 1 # Keep track of expected question number for better parsing
|
65 |
-
|
66 |
for block in blocks:
|
67 |
block = block.strip()
|
68 |
-
if not block
|
69 |
-
st.write(f"Debugging: Skipping very short or empty block: '{block}'") # Debugging skip message
|
70 |
continue
|
71 |
|
72 |
lines = block.split('\n')
|
73 |
-
|
74 |
-
|
75 |
-
parsing_question_text = True # Flag to indicate we are parsing question text
|
76 |
-
question_label_found = False # Flag to track if "Question N:" label was found
|
77 |
-
block_has_question_content = False # Flag to check if block has any question content
|
78 |
-
|
79 |
|
80 |
-
|
|
|
81 |
line = line.strip()
|
82 |
-
if
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
if re.match(r'^Question\s+\d+:', line, re.IGNORECASE): # Check for "Question N:"
|
87 |
-
question_label_found = True # Mark label as found
|
88 |
-
# **MODIFIED QUESTION TEXT EXTRACTION:**
|
89 |
-
if len(lines) > line_index + 1: # Check if there's a line AFTER "Question N:"
|
90 |
-
question_text = lines[line_index + 1].strip() # Take the *NEXT* line as question text
|
91 |
-
parsing_question_text = False # Stop parsing question text, move to options
|
92 |
-
block_has_question_content = True # Mark that we found question content
|
93 |
-
else:
|
94 |
-
st.warning(f"Warning: Question label '{line}' found, but no question text followed.")
|
95 |
-
question_text = "" # No question text found after label
|
96 |
-
parsing_question_text = False # Move to options parsing even if question text missing
|
97 |
-
# **MODIFIED - Moved this condition to be ELSE if question_label_found is False**
|
98 |
-
elif not question_label_found and not question_text: # Check if question_label NOT found AND question_text is still empty
|
99 |
-
# If no "Question N:" label found yet in this block, and we are still parsing question text,
|
100 |
-
# consider this line as question text (for the very first line if no label)
|
101 |
-
question_text = line
|
102 |
-
parsing_question_text = False # Move to options parsing
|
103 |
-
block_has_question_content = True # Mark that we found question content
|
104 |
-
|
105 |
-
|
106 |
-
elif re.match(r'^[A-D]\)\s(.+)', line): # Parse options
|
107 |
-
match = re.match(r'^([A-D])\)\s(.+)', line)
|
108 |
-
if match:
|
109 |
-
option_letter = match.group(1)
|
110 |
-
option_text = match.group(2).strip()
|
111 |
-
options[option_letter] = option_text
|
112 |
-
block_has_question_content = True # Mark that we found option content
|
113 |
-
|
114 |
-
# --- DEBUGGING PRINT: Print question text and options for each block ---
|
115 |
-
st.write(f"#### Debugging: Block {question_number} - Parsed Data:")
|
116 |
-
st.write(f"- Question Text: '{question_text}'")
|
117 |
-
st.write(f"- Options: {options}")
|
118 |
-
st.write(f"- Block has question content: {block_has_question_content}") # Debugging flag
|
119 |
-
|
120 |
-
if question_text and block_has_question_content: # Only add question if we successfully extracted question text AND block has content
|
121 |
-
questions.append({'question': question_text, 'options': options})
|
122 |
-
else:
|
123 |
-
st.warning(f"Warning: Could not parse question text OR no question content found for block (potential issue in question {question_number}). Block content:\n{block}")
|
124 |
|
125 |
-
|
|
|
126 |
|
127 |
|
128 |
# --- Answer Key Parsing (No change needed) ---
|
129 |
-
answer_lines = answer_key_section.strip('\n')
|
130 |
for line in answer_lines:
|
131 |
line = line.strip()
|
132 |
match = re.match(r'(\d+)\.\s*([A-D])', line)
|
@@ -169,7 +125,7 @@ def display_question():
|
|
169 |
if st.session_state.current_question_index < len(st.session_state.quiz_data):
|
170 |
question_data = st.session_state.quiz_data[st.session_state.current_question_index]
|
171 |
question_number = st.session_state.current_question_index + 1
|
172 |
-
st.markdown(f"**Question {question_number}:** {question_data['question']}")
|
173 |
|
174 |
options_list = [f"{key}. {value}" for key, value in question_data['options'].items()]
|
175 |
user_choice = st.radio("Choose an answer:", options_list, key=f"q_{question_number}") # Unique key for radio buttons
|
@@ -217,38 +173,37 @@ if topic:
|
|
217 |
prompt = f"""
|
218 |
Generate a multiple-choice quiz on the topic of "{topic}".
|
219 |
The quiz should have 5 questions.
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
Format the quiz for easy reading.
|
224 |
"""
|
225 |
response = model.generate_content(prompt)
|
226 |
quiz_content = response.text
|
227 |
|
228 |
-
# --- DEBUGGING PRINTS
|
229 |
st.write("### Raw Quiz Content from Gemini:")
|
230 |
st.code(quiz_content) # Display raw content in a code block for readability
|
231 |
|
232 |
parsed_quiz_data, answer_key = parse_quiz_content(quiz_content)
|
233 |
|
234 |
-
st.write("### Parsed Quiz Data:")
|
235 |
st.write(parsed_quiz_data) # Display the parsed data structure
|
236 |
|
237 |
-
# --- END DEBUGGING PRINTS
|
238 |
|
239 |
|
240 |
-
if quiz_content: # Check if
|
241 |
-
if parsed_quiz_data: # Check if parsing was successful
|
242 |
st.session_state.quiz_data = parsed_quiz_data
|
243 |
st.session_state.current_question_index = 0
|
244 |
st.session_state.user_answers = []
|
245 |
st.session_state.quiz_completed = False
|
246 |
st.session_state.score = 0
|
247 |
st.success(f"Quiz on '{topic}' generated successfully! Let's begin.")
|
248 |
-
else: #
|
249 |
st.error("Failed to parse quiz content. Please try generating again.")
|
250 |
st.session_state.quiz_data = None
|
251 |
-
else: #
|
252 |
st.error("Failed to generate quiz content. Please try again or check your API key.")
|
253 |
|
254 |
except Exception as e:
|
|
|
46 |
question_section = quiz_parts[0].strip()
|
47 |
answer_key_section = quiz_parts[1].strip()
|
48 |
|
49 |
+
# --- Split into blocks by double newline ---
|
50 |
+
blocks = re.split(r'\n\n+', question_section) # Split by one or more double newlines
|
51 |
|
52 |
+
# --- Handle Potential Title (First Block) ---
|
|
|
|
|
|
|
|
|
53 |
if blocks:
|
54 |
first_block = blocks[0].strip()
|
55 |
+
if not re.match(r'^\d+\.\s', first_block): # Check if the first block DOES NOT start with a question number
|
56 |
+
# Assume the first block is the title and remove it
|
57 |
+
blocks = blocks[1:] # Slice to remove the first block (title)
|
58 |
+
else:
|
59 |
+
st.warning("Unexpected format: First block starts with a question number. Title might not be removed correctly.")
|
60 |
|
61 |
|
62 |
# --- Process Question Blocks ---
|
|
|
|
|
63 |
for block in blocks:
|
64 |
block = block.strip()
|
65 |
+
if not block:
|
|
|
66 |
continue
|
67 |
|
68 |
lines = block.split('\n')
|
69 |
+
# --- First line is question text (after removing bold markdown) ---
|
70 |
+
question_text = re.sub(r'\*\*|\*', '', lines[0]).strip()
|
|
|
|
|
|
|
|
|
71 |
|
72 |
+
options = {}
|
73 |
+
for line in lines[1:]:
|
74 |
line = line.strip()
|
75 |
+
if re.match(r'^[A-D]\.\s', line): # Options are like "A. Elephant"
|
76 |
+
option_letter = line[0]
|
77 |
+
option_text = line[2:].strip()
|
78 |
+
options[option_letter] = option_text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
79 |
|
80 |
+
if question_text: # Only append if we have a question text
|
81 |
+
questions.append({'question': question_text, 'options': options})
|
82 |
|
83 |
|
84 |
# --- Answer Key Parsing (No change needed) ---
|
85 |
+
answer_lines = answer_key_section.strip().split('\n')
|
86 |
for line in answer_lines:
|
87 |
line = line.strip()
|
88 |
match = re.match(r'(\d+)\.\s*([A-D])', line)
|
|
|
125 |
if st.session_state.current_question_index < len(st.session_state.quiz_data):
|
126 |
question_data = st.session_state.quiz_data[st.session_state.current_question_index]
|
127 |
question_number = st.session_state.current_question_index + 1
|
128 |
+
st.markdown(f"**Question {question_number}:** {question_data['question']}")
|
129 |
|
130 |
options_list = [f"{key}. {value}" for key, value in question_data['options'].items()]
|
131 |
user_choice = st.radio("Choose an answer:", options_list, key=f"q_{question_number}") # Unique key for radio buttons
|
|
|
173 |
prompt = f"""
|
174 |
Generate a multiple-choice quiz on the topic of "{topic}".
|
175 |
The quiz should have 5 questions.
|
176 |
+
For each question, provide four plausible options labeled A, B, C, and D.
|
177 |
+
Clearly indicate the correct answer for each question at the end in a separate section called "Answer Key".
|
178 |
+
Format the quiz clearly for easy reading.
|
|
|
179 |
"""
|
180 |
response = model.generate_content(prompt)
|
181 |
quiz_content = response.text
|
182 |
|
183 |
+
# --- DEBUGGING PRINTS ---
|
184 |
st.write("### Raw Quiz Content from Gemini:")
|
185 |
st.code(quiz_content) # Display raw content in a code block for readability
|
186 |
|
187 |
parsed_quiz_data, answer_key = parse_quiz_content(quiz_content)
|
188 |
|
189 |
+
st.write("### Parsed Quiz Data:")
|
190 |
st.write(parsed_quiz_data) # Display the parsed data structure
|
191 |
|
192 |
+
# --- END DEBUGGING PRINTS ---
|
193 |
|
194 |
|
195 |
+
if quiz_content: # Check if quiz_content was generated successfully (outer if)
|
196 |
+
if parsed_quiz_data: # Check if parsing was successful (inner if)
|
197 |
st.session_state.quiz_data = parsed_quiz_data
|
198 |
st.session_state.current_question_index = 0
|
199 |
st.session_state.user_answers = []
|
200 |
st.session_state.quiz_completed = False
|
201 |
st.session_state.score = 0
|
202 |
st.success(f"Quiz on '{topic}' generated successfully! Let's begin.")
|
203 |
+
else: # else associated with inner if parsed_quiz_data
|
204 |
st.error("Failed to parse quiz content. Please try generating again.")
|
205 |
st.session_state.quiz_data = None
|
206 |
+
else: # else associated with outer if quiz_content
|
207 |
st.error("Failed to generate quiz content. Please try again or check your API key.")
|
208 |
|
209 |
except Exception as e:
|