EdBoy2202 commited on
Commit
ff40b9b
·
verified ·
1 Parent(s): 7f395a3

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +149 -22
app.py CHANGED
@@ -1,23 +1,147 @@
1
  import streamlit as st
2
  import google.generativeai as genai
3
  import os
 
4
 
5
  # Set up Streamlit page
6
- st.title("Multiple Choice Quiz Generator")
7
  st.markdown("Powered by Gemini API")
8
 
9
- # **API Key Input from User**
10
  gemini_api_key = st.text_input("Enter your Gemini API Key:", type="password")
11
 
12
  if not gemini_api_key:
13
  st.warning("Please enter your Gemini API key to generate a quiz.")
14
- st.stop() # Stop execution if API key is missing
15
  else:
16
  genai.configure(api_key=gemini_api_key)
17
- model = genai.GenerativeModel('gemini-pro') # Or 'gemini-pro-vision' if you need image input later
18
 
19
- # **Security Warning**
20
- st.markdown("<font color='red'>**Warning:** Directly entering your API key in the app is less secure than using Streamlit Secrets or environment variables, especially if this app is shared or deployed publicly. For production or sensitive use, consider using Streamlit Secrets instead.</font>", unsafe_allow_html=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
 
22
 
23
  # User input for topic
@@ -27,7 +151,6 @@ if topic:
27
  if st.button("Generate Quiz"):
28
  with st.spinner(f"Generating quiz on '{topic}'..."):
29
  try:
30
- # Construct the prompt for Gemini
31
  prompt = f"""
32
  Generate a multiple-choice quiz on the topic of "{topic}".
33
  The quiz should have 5 questions.
@@ -35,29 +158,33 @@ if topic:
35
  Clearly indicate the correct answer for each question at the end in a separate section called "Answer Key".
36
  Format the quiz clearly for easy reading.
37
  """
38
-
39
  response = model.generate_content(prompt)
40
  quiz_content = response.text
41
 
42
  if quiz_content:
43
- st.markdown("### Quiz:")
44
- st.markdown(quiz_content)
45
-
46
- # Basic parsing to try and separate quiz and answer key (very basic, might need improvement)
47
- if "Answer Key" in quiz_content:
48
- parts = quiz_content.split("Answer Key")
49
- quiz_questions = parts[0]
50
- answer_key = "Answer Key" + parts[1] # Re-add "Answer Key" to the answer section
51
- st.markdown("### Answer Key:")
52
- st.markdown(answer_key)
53
  else:
54
- st.warning("Could not clearly separate answer key. Answers may be embedded in the quiz text.")
55
-
56
  else:
57
  st.error("Failed to generate quiz content. Please try again or check your API key.")
58
 
59
  except Exception as e:
60
  st.error(f"An error occurred: {e}")
61
  st.error("Please check your API key and network connection. If the problem persists, try a different topic or try again later.")
62
- else:
63
- st.info("Please enter a topic to generate a quiz.")
 
 
 
 
 
 
 
 
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 = []
39
+ answer_key_dict = {}
40
+
41
+ quiz_parts = quiz_content.split("Answer Key")
42
+ if len(quiz_parts) != 2:
43
+ st.warning("Could not reliably separate quiz questions and answer key. Parsing might be imperfect.")
44
+ return None, None
45
+
46
+ question_section = quiz_parts[0]
47
+ answer_key_section = quiz_parts[1]
48
+
49
+ # Parse questions and options using regex (more robust)
50
+ question_blocks = re.split(r'\n(?=\d+\.)', question_section.strip()) # Split by newline followed by number and dot
51
+ for block in question_blocks:
52
+ if not block.strip():
53
+ continue # Skip empty blocks
54
+ lines = block.strip().split('\n')
55
+ question_text = lines[0].strip()
56
+ options = {}
57
+ for line in lines[1:]:
58
+ line = line.strip()
59
+ if line.startswith('A.') or line.startswith('B.') or line.startswith('C.') or line.startswith('D.'):
60
+ option_letter = line[0]
61
+ option_text = line[2:].strip()
62
+ options[option_letter] = option_text
63
+ questions.append({'question': question_text, 'options': options})
64
+
65
+ # Parse answer key (assuming format like 1. A, 2. B, etc.)
66
+ answer_lines = answer_key_section.strip().split('\n')
67
+ for line in answer_lines:
68
+ line = line.strip()
69
+ match = re.match(r'(\d+)\.\s*([A-D])', line) # Regex to find question number and answer letter
70
+ if match:
71
+ question_num = int(match.group(1)) - 1 # Adjust to 0-based index
72
+ correct_answer = match.group(2)
73
+ answer_key_dict[question_num] = correct_answer
74
+
75
+ # Basic validation: Check if we parsed questions and answers and if counts match
76
+ if not questions or not answer_key_dict:
77
+ st.error("Error parsing quiz content. Please try again or check the generated format.")
78
+ return None, None
79
+ if len(questions) != len(answer_key_dict):
80
+ st.warning("Number of questions and answers in answer key do not match. Parsing might be incomplete.")
81
+
82
+
83
+ # Combine parsed questions and answer key into quiz_data
84
+ quiz_data_list = []
85
+ for i, q_data in enumerate(questions):
86
+ correct_answer = answer_key_dict.get(i)
87
+ if correct_answer:
88
+ quiz_data_list.append({
89
+ 'question': q_data['question'],
90
+ 'options': q_data['options'],
91
+ 'correct_answer': correct_answer
92
+ })
93
+ else:
94
+ st.warning(f"Could not find correct answer for question {i+1} in the answer key.")
95
+ return None, None # Inconsistent data, better to stop
96
+
97
+ return quiz_data_list, answer_key_dict
98
+
99
+
100
+ def display_question():
101
+ """Displays the current question and options for interactive quiz."""
102
+ if st.session_state.quiz_data is None:
103
+ st.error("Quiz data not loaded yet. Generate a quiz first.")
104
+ return
105
+
106
+ if st.session_state.current_question_index < len(st.session_state.quiz_data):
107
+ question_data = st.session_state.quiz_data[st.session_state.current_question_index]
108
+ question_number = st.session_state.current_question_index + 1
109
+ st.markdown(f"**Question {question_number}:** {question_data['question']}")
110
+
111
+ options_list = [f"{key}. {value}" for key, value in question_data['options'].items()]
112
+ user_choice = st.radio("Choose an answer:", options_list, key=f"q_{question_number}") # Unique key for radio buttons
113
+
114
+ if st.button("Submit Answer", key=f"submit_q_{question_number}"): # Unique key for submit button
115
+ selected_option_letter = user_choice.split('.')[0] # Extract A, B, C, or D
116
+ st.session_state.user_answers.append(selected_option_letter)
117
+
118
+ if st.session_state.current_question_index < len(st.session_state.quiz_data) - 1:
119
+ st.session_state.current_question_index += 1
120
+ else:
121
+ st.session_state.quiz_completed = True # Mark quiz as completed after last question
122
+ st.experimental_rerun() # Rerun to update UI
123
+
124
+
125
+ def display_results():
126
+ """Displays the quiz results after completion."""
127
+ if st.session_state.quiz_completed:
128
+ st.markdown("### Quiz Results")
129
+ correct_count = 0
130
+ for i in range(len(st.session_state.quiz_data)):
131
+ 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
132
+ correct_answer = st.session_state.quiz_data[i]['correct_answer']
133
+ if user_answer == correct_answer:
134
+ correct_count += 1
135
+ result_text = f"**Question {i+1}:** ✅ Correct! (Your answer: {user_answer}, Correct answer: {correct_answer})"
136
+ color = "green"
137
+ else:
138
+ result_text = f"**Question {i+1}:** ❌ Incorrect. (Your answer: {user_answer if user_answer else 'Not answered'}, Correct answer: {correct_answer})"
139
+ color = "red"
140
+ st.markdown(f"<font color='{color}'>{result_text}</font>", unsafe_allow_html=True)
141
+
142
+ percentage_correct = (correct_count / len(st.session_state.quiz_data)) * 100
143
+ st.markdown(f"### Final Score: {correct_count} out of {len(st.session_state.quiz_data)} correct ({percentage_correct:.2f}%)")
144
+ st.session_state.score = correct_count # Store score in session state
145
 
146
 
147
  # User input for topic
 
151
  if st.button("Generate Quiz"):
152
  with st.spinner(f"Generating quiz on '{topic}'..."):
153
  try:
 
154
  prompt = f"""
155
  Generate a multiple-choice quiz on the topic of "{topic}".
156
  The quiz should have 5 questions.
 
158
  Clearly indicate the correct answer for each question at the end in a separate section called "Answer Key".
159
  Format the quiz clearly for easy reading.
160
  """
 
161
  response = model.generate_content(prompt)
162
  quiz_content = response.text
163
 
164
  if quiz_content:
165
+ parsed_quiz_data, answer_key = parse_quiz_content(quiz_content)
166
+ if parsed_quiz_data:
167
+ st.session_state.quiz_data = parsed_quiz_data
168
+ st.session_state.current_question_index = 0 # Reset to first question
169
+ st.session_state.user_answers = [] # Clear previous answers
170
+ st.session_state.quiz_completed = False # Reset completion status
171
+ st.session_state.score = 0 # Reset score
172
+ st.success(f"Quiz on '{topic}' generated successfully! Let's begin.")
 
 
173
  else:
174
+ st.error("Failed to parse quiz content. Please try generating again.")
175
+ st.session_state.quiz_data = None # Ensure quiz_data is reset in case of parsing failure
176
  else:
177
  st.error("Failed to generate quiz content. Please try again or check your API key.")
178
 
179
  except Exception as e:
180
  st.error(f"An error occurred: {e}")
181
  st.error("Please check your API key and network connection. If the problem persists, try a different topic or try again later.")
182
+
183
+ # Quiz Display Logic
184
+ if st.session_state.quiz_data:
185
+ if not st.session_state.quiz_completed:
186
+ display_question()
187
+ else:
188
+ display_results()
189
+ 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
190
+ st.info("Click 'Generate Quiz' to start the quiz.")