Update app.py
Browse files
app.py
CHANGED
@@ -1,3 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
def parse_quiz_content(quiz_content):
|
2 |
"""Parses the quiz content and answer key into a structured format."""
|
3 |
questions = []
|
@@ -73,4 +108,108 @@ def parse_quiz_content(quiz_content):
|
|
73 |
st.warning(f"Could not find correct answer for question {i+1} in the answer key.")
|
74 |
return None, None # Inconsistent data, better to stop
|
75 |
|
76 |
-
return quiz_data_list, answer_key_dict
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import streamlit as st
|
2 |
+
import google.generativeai as genai
|
3 |
+
import os
|
4 |
+
import re # For improved parsing
|
5 |
+
|
6 |
+
# Set up Streamlit page
|
7 |
+
st.title("Interactive Multiple Choice Quiz Generator")
|
8 |
+
st.markdown("Powered by Gemini API")
|
9 |
+
|
10 |
+
# API Key Input from User
|
11 |
+
gemini_api_key = st.text_input("Enter your Gemini API Key:", type="password")
|
12 |
+
|
13 |
+
if not gemini_api_key:
|
14 |
+
st.warning("Please enter your Gemini API key to generate a quiz.")
|
15 |
+
st.stop()
|
16 |
+
else:
|
17 |
+
genai.configure(api_key=gemini_api_key)
|
18 |
+
model = genai.GenerativeModel('gemini-pro')
|
19 |
+
|
20 |
+
# Security Warning
|
21 |
+
st.markdown("<font color='red'>**Warning:** Directly entering your API key is less secure than using Streamlit Secrets or environment variables. For production, use Secrets.</font>", unsafe_allow_html=True)
|
22 |
+
|
23 |
+
# Initialize session state for quiz data and progress
|
24 |
+
if 'quiz_data' not in st.session_state:
|
25 |
+
st.session_state.quiz_data = None
|
26 |
+
if 'current_question_index' not in st.session_state:
|
27 |
+
st.session_state.current_question_index = 0
|
28 |
+
if 'user_answers' not in st.session_state:
|
29 |
+
st.session_state.user_answers = []
|
30 |
+
if 'quiz_completed' not in st.session_state:
|
31 |
+
st.session_state.quiz_completed = False
|
32 |
+
if 'score' not in st.session_state:
|
33 |
+
st.session_state.score = 0
|
34 |
+
|
35 |
+
|
36 |
def parse_quiz_content(quiz_content):
|
37 |
"""Parses the quiz content and answer key into a structured format."""
|
38 |
questions = []
|
|
|
108 |
st.warning(f"Could not find correct answer for question {i+1} in the answer key.")
|
109 |
return None, None # Inconsistent data, better to stop
|
110 |
|
111 |
+
return quiz_data_list, answer_key_dict
|
112 |
+
|
113 |
+
|
114 |
+
def display_question():
|
115 |
+
"""Displays the current question and options for interactive quiz."""
|
116 |
+
if st.session_state.quiz_data is None:
|
117 |
+
st.error("Quiz data not loaded yet. Generate a quiz first.")
|
118 |
+
return
|
119 |
+
|
120 |
+
if st.session_state.current_question_index < len(st.session_state.quiz_data):
|
121 |
+
question_data = st.session_state.quiz_data[st.session_state.current_question_index]
|
122 |
+
question_number = st.session_state.current_question_index + 1
|
123 |
+
st.markdown(f"**Question {question_number}:** {question_data['question']}")
|
124 |
+
|
125 |
+
options_list = [f"{key}. {value}" for key, value in question_data['options'].items()]
|
126 |
+
user_choice = st.radio("Choose an answer:", options_list, key=f"q_{question_number}") # Unique key for radio buttons
|
127 |
+
|
128 |
+
if st.button("Submit Answer", key=f"submit_q_{question_number}"): # Unique key for submit button
|
129 |
+
selected_option_letter = user_choice.split('.')[0] # Extract A, B, C, or D
|
130 |
+
st.session_state.user_answers.append(selected_option_letter)
|
131 |
+
|
132 |
+
if st.session_state.current_question_index < len(st.session_state.quiz_data) - 1:
|
133 |
+
st.session_state.current_question_index += 1
|
134 |
+
else:
|
135 |
+
st.session_state.quiz_completed = True # Mark quiz as completed after last question
|
136 |
+
st.rerun()
|
137 |
+
|
138 |
+
|
139 |
+
def display_results():
|
140 |
+
"""Displays the quiz results after completion."""
|
141 |
+
if st.session_state.quiz_completed:
|
142 |
+
st.markdown("### Quiz Results")
|
143 |
+
correct_count = 0
|
144 |
+
for i in range(len(st.session_state.quiz_data)):
|
145 |
+
user_answer = st.session_state.user_answers[i] if i < len(st.session_state.user_answers) else None # Handle if user didn't answer all
|
146 |
+
correct_answer = st.session_state.quiz_data[i]['correct_answer']
|
147 |
+
if user_answer == correct_answer:
|
148 |
+
correct_count += 1
|
149 |
+
result_text = f"**Question {i+1}:** ✅ Correct! (Your answer: {user_answer}, Correct answer: {correct_answer})"
|
150 |
+
color = "green"
|
151 |
+
else:
|
152 |
+
result_text = f"**Question {i+1}:** ❌ Incorrect. (Your answer: {user_answer if user_answer else 'Not answered'}, Correct answer: {correct_answer})"
|
153 |
+
color = "red"
|
154 |
+
st.markdown(f"<font color='{color}'>{result_text}</font>", unsafe_allow_html=True)
|
155 |
+
|
156 |
+
percentage_correct = (correct_count / len(st.session_state.quiz_data)) * 100
|
157 |
+
st.markdown(f"### Final Score: {correct_count} out of {len(st.session_state.quiz_data)} correct ({percentage_correct:.2f}%)")
|
158 |
+
st.session_state.score = correct_count # Store score in session state
|
159 |
+
|
160 |
+
|
161 |
+
# User input for topic
|
162 |
+
topic = st.text_input("Enter the topic for your quiz:")
|
163 |
+
|
164 |
+
if topic:
|
165 |
+
if st.button("Generate Quiz"):
|
166 |
+
with st.spinner(f"Generating quiz on '{topic}'..."):
|
167 |
+
try:
|
168 |
+
prompt = f"""
|
169 |
+
Generate a multiple-choice quiz on the topic of "{topic}".
|
170 |
+
The quiz should have 5 questions.
|
171 |
+
For each question, provide four plausible options labeled A, B, C, and D.
|
172 |
+
Clearly indicate the correct answer for each question at the end in a separate section called "Answer Key".
|
173 |
+
Format the quiz clearly for easy reading.
|
174 |
+
"""
|
175 |
+
response = model.generate_content(prompt)
|
176 |
+
quiz_content = response.text
|
177 |
+
|
178 |
+
# --- DEBUGGING PRINTS ---
|
179 |
+
st.write("### Raw Quiz Content from Gemini:")
|
180 |
+
st.code(quiz_content) # Display raw content in a code block for readability
|
181 |
+
|
182 |
+
parsed_quiz_data, answer_key = parse_quiz_content(quiz_content)
|
183 |
+
|
184 |
+
st.write("### Parsed Quiz Data:")
|
185 |
+
st.write(parsed_quiz_data) # Display the parsed data structure
|
186 |
+
|
187 |
+
# --- END DEBUGGING PRINTS ---
|
188 |
+
|
189 |
+
|
190 |
+
if quiz_content: # Check if quiz_content was generated successfully (outer if)
|
191 |
+
if parsed_quiz_data: # Check if parsing was successful (inner if)
|
192 |
+
st.session_state.quiz_data = parsed_quiz_data
|
193 |
+
st.session_state.current_question_index = 0
|
194 |
+
st.session_state.user_answers = []
|
195 |
+
st.session_state.quiz_completed = False
|
196 |
+
st.session_state.score = 0
|
197 |
+
st.success(f"Quiz on '{topic}' generated successfully! Let's begin.")
|
198 |
+
else: # else associated with inner if parsed_quiz_data
|
199 |
+
st.error("Failed to parse quiz content. Please try generating again.")
|
200 |
+
st.session_state.quiz_data = None
|
201 |
+
else: # else associated with outer if quiz_content
|
202 |
+
st.error("Failed to generate quiz content. Please try again or check your API key.")
|
203 |
+
|
204 |
+
except Exception as e:
|
205 |
+
st.error(f"An error occurred: {e}")
|
206 |
+
st.error("Please check your API key and network connection. If the problem persists, try a different topic or try again later.")
|
207 |
+
|
208 |
+
# Quiz Display Logic
|
209 |
+
if st.session_state.quiz_data:
|
210 |
+
if not st.session_state.quiz_completed:
|
211 |
+
display_question()
|
212 |
+
else:
|
213 |
+
display_results()
|
214 |
+
elif topic and not st.session_state.quiz_data and not st.session_state.quiz_completed: # Message if topic entered but quiz not generated yet
|
215 |
+
st.info("Click 'Generate Quiz' to start the quiz.")
|