capradeepgujaran commited on
Commit
51fcc77
1 Parent(s): 7f84089

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +119 -94
app.py CHANGED
@@ -38,7 +38,6 @@ class QuizApp:
38
  "correct_answer": 0
39
  }}
40
  ]
41
- Keep all options concise (10 words or less each).
42
  """
43
 
44
  try:
@@ -58,48 +57,28 @@ class QuizApp:
58
  max_tokens=2048
59
  )
60
 
61
- # Clean and parse response
62
  response_text = response.choices[0].message.content.strip()
63
  response_text = response_text.replace("```json", "").replace("```", "").strip()
 
64
 
65
- # Extract JSON array
66
- start_idx = response_text.find("[")
67
- end_idx = response_text.rfind("]")
68
-
69
- if start_idx == -1 or end_idx == -1:
70
- raise ValueError("No valid JSON array found in response")
71
-
72
- response_text = response_text[start_idx:end_idx + 1]
73
  questions = json.loads(response_text)
74
-
75
- # Validate and clean up questions
76
  validated_questions = []
 
77
  for q in questions:
78
  if not all(key in q for key in ["question", "options", "correct_answer"]):
79
  continue
80
-
81
- # Ensure options are strings and reasonably sized
82
- clean_options = []
83
- for opt in q["options"]:
84
- if isinstance(opt, str):
85
- # Limit option length and clean up formatting
86
- clean_opt = opt.strip()[:100] # Limit length
87
- clean_options.append(clean_opt)
88
 
 
89
  if len(clean_options) != 4:
90
  continue
91
-
92
- # Create clean question
93
  clean_q = {
94
  "question": q["question"].strip(),
95
  "options": clean_options,
96
- "correct_answer": int(q["correct_answer"]) % 4 # Ensure valid index
97
  }
98
  validated_questions.append(clean_q)
99
 
100
- if not validated_questions:
101
- raise ValueError("No valid questions after validation")
102
-
103
  self.current_questions = validated_questions[:num_questions]
104
  return True, self.current_questions
105
 
@@ -109,29 +88,47 @@ class QuizApp:
109
 
110
  def calculate_score(self, answers):
111
  if not answers or not self.current_questions:
112
- return 0
113
 
114
  total = len(self.current_questions)
115
  correct = 0
 
 
116
  for i, (q, a) in enumerate(zip(self.current_questions, answers)):
117
  try:
118
  if a is not None:
119
- # Find the index of the selected answer in the options list
120
  selected_index = q["options"].index(a)
121
- if selected_index == q["correct_answer"]:
 
122
  correct += 1
 
 
 
 
 
 
 
 
 
 
 
 
 
123
  except (ValueError, TypeError) as e:
124
  print(f"Error processing answer {i}: {e}")
125
- continue
 
 
 
 
 
126
 
127
- return (correct / total) * 100
128
-
129
 
130
  def create_quiz_interface():
131
  quiz_app = QuizApp()
132
 
133
  with gr.Blocks(title="CertifyMe AI", theme=gr.themes.Soft()) as demo:
134
- # State variables
135
  current_questions = gr.State([])
136
 
137
  # Header
@@ -142,7 +139,7 @@ def create_quiz_interface():
142
 
143
  # Tabs
144
  with gr.Tabs() as tabs:
145
- # Step 1: Profile Setup
146
  with gr.Tab("📋 Step 1: Profile Setup") as tab1:
147
  with gr.Row():
148
  name = gr.Textbox(label="Full Name", placeholder="Enter your full name")
@@ -170,36 +167,28 @@ def create_quiz_interface():
170
 
171
  # Step 2: Take Assessment
172
  with gr.Tab("📝 Step 2: Take Assessment") as tab2:
173
- questions_markdown = gr.Markdown("")
174
- answers = []
175
- for i in range(5):
176
- with gr.Group():
177
- radio = gr.Radio(
178
- choices=[],
179
- label=f"Question {i+1}",
180
- visible=False,
181
- interactive=True
182
- )
183
- answers.append(radio)
184
-
185
- submit_btn = gr.Button(
186
- "Submit Assessment",
187
- variant="primary",
188
- size="lg"
189
- )
190
 
191
- gr.Markdown("""
192
- ### Instructions:
193
- - Read each question carefully
194
- - Select one answer for each question
195
- - Click Submit Assessment when you're done
196
- - You need 80% or higher to earn your certificate
197
- """)
198
-
199
 
200
  # Step 3: Get Certified
201
  with gr.Tab("🎓 Step 3: Get Certified") as tab3:
202
  score_display = gr.Number(label="Your Score")
 
203
  course_name = gr.Textbox(
204
  label="Certification Title",
205
  value="Professional Assessment Certification"
@@ -208,57 +197,85 @@ def create_quiz_interface():
208
 
209
  def update_questions(text, num_questions):
210
  if not text.strip():
211
- return (
212
- gr.update(value="⚠️ Please enter some text content to generate questions."),
213
- *[gr.update(visible=False, choices=[]) for _ in range(5)],
214
- [],
215
- 0
216
- )
217
 
218
- success, questions = quiz_app.generate_questions(text, num_questions)
 
 
 
219
 
220
- if not success or not questions:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
221
  return (
222
- gr.update(value=" Failed to generate questions. Please try again with different content."),
223
- *[gr.update(visible=False, choices=[]) for _ in range(5)],
224
- [],
225
  0
226
  )
227
 
228
- # Update question display with answers immediately following each question
229
- questions_html = "# 📝 Assessment Questions\n\n"
230
- questions_html += "> Please select one answer for each question below.\n\n"
231
 
232
- # Update radio buttons
233
  updates = []
234
- for i, q in enumerate(questions):
235
- questions_html += f"### Question {i+1}\n{q['question']}\n\n"
236
- # Create radio button update for this question
 
 
 
 
 
237
  updates.append(gr.update(
238
  visible=True,
239
- choices=q["options"],
240
- value=None,
241
- label=f"Select your answer:"
242
  ))
243
- questions_html += "\n\n" # Add space between questions
244
 
245
- # Fill remaining radio buttons with hidden updates
246
- for i in range(len(questions), 5):
247
- updates.append(gr.update(visible=False, choices=[]))
 
 
 
 
 
 
 
 
 
 
248
 
249
- return (gr.update(value=questions_html), *updates, questions, 1)
250
-
251
-
252
- def submit_quiz(q1, q2, q3, q4, q5, questions):
253
- answers = [q1, q2, q3, q4, q5][:len(questions)]
254
- score = quiz_app.calculate_score(answers)
255
- return score, 2
256
 
257
  # Event handlers
258
  generate_btn.click(
259
  fn=update_questions,
260
  inputs=[text_input, num_questions],
261
- outputs=[questions_markdown, *answers, current_questions, gr.State(1)]
 
 
 
 
 
262
  ).then(
263
  fn=lambda x: gr.update(selected=x),
264
  inputs=[gr.State(1)],
@@ -267,8 +284,16 @@ def create_quiz_interface():
267
 
268
  submit_btn.click(
269
  fn=submit_quiz,
270
- inputs=[*answers, current_questions],
271
- outputs=[score_display, gr.State(2)]
 
 
 
 
 
 
 
 
272
  ).then(
273
  fn=lambda x: gr.update(selected=x),
274
  inputs=[gr.State(2)],
 
38
  "correct_answer": 0
39
  }}
40
  ]
 
41
  """
42
 
43
  try:
 
57
  max_tokens=2048
58
  )
59
 
 
60
  response_text = response.choices[0].message.content.strip()
61
  response_text = response_text.replace("```json", "").replace("```", "").strip()
62
+ response_text = response_text[response_text.find("["):response_text.rfind("]")+1]
63
 
 
 
 
 
 
 
 
 
64
  questions = json.loads(response_text)
 
 
65
  validated_questions = []
66
+
67
  for q in questions:
68
  if not all(key in q for key in ["question", "options", "correct_answer"]):
69
  continue
 
 
 
 
 
 
 
 
70
 
71
+ clean_options = [opt.strip()[:100] for opt in q["options"] if isinstance(opt, str)]
72
  if len(clean_options) != 4:
73
  continue
74
+
 
75
  clean_q = {
76
  "question": q["question"].strip(),
77
  "options": clean_options,
78
+ "correct_answer": int(q["correct_answer"]) % 4
79
  }
80
  validated_questions.append(clean_q)
81
 
 
 
 
82
  self.current_questions = validated_questions[:num_questions]
83
  return True, self.current_questions
84
 
 
88
 
89
  def calculate_score(self, answers):
90
  if not answers or not self.current_questions:
91
+ return 0, []
92
 
93
  total = len(self.current_questions)
94
  correct = 0
95
+ results = [] # Store whether each answer was correct
96
+
97
  for i, (q, a) in enumerate(zip(self.current_questions, answers)):
98
  try:
99
  if a is not None:
 
100
  selected_index = q["options"].index(a)
101
+ is_correct = selected_index == q["correct_answer"]
102
+ if is_correct:
103
  correct += 1
104
+ results.append({
105
+ "question_index": i,
106
+ "selected_index": selected_index,
107
+ "correct_index": q["correct_answer"],
108
+ "is_correct": is_correct
109
+ })
110
+ else:
111
+ results.append({
112
+ "question_index": i,
113
+ "selected_index": None,
114
+ "correct_index": q["correct_answer"],
115
+ "is_correct": False
116
+ })
117
  except (ValueError, TypeError) as e:
118
  print(f"Error processing answer {i}: {e}")
119
+ results.append({
120
+ "question_index": i,
121
+ "selected_index": None,
122
+ "correct_index": q["correct_answer"],
123
+ "is_correct": False
124
+ })
125
 
126
+ return (correct / total) * 100, results
 
127
 
128
  def create_quiz_interface():
129
  quiz_app = QuizApp()
130
 
131
  with gr.Blocks(title="CertifyMe AI", theme=gr.themes.Soft()) as demo:
 
132
  current_questions = gr.State([])
133
 
134
  # Header
 
139
 
140
  # Tabs
141
  with gr.Tabs() as tabs:
142
+ # Step 1: Profile Setup (remains largely the same)
143
  with gr.Tab("📋 Step 1: Profile Setup") as tab1:
144
  with gr.Row():
145
  name = gr.Textbox(label="Full Name", placeholder="Enter your full name")
 
167
 
168
  # Step 2: Take Assessment
169
  with gr.Tab("📝 Step 2: Take Assessment") as tab2:
170
+ assessment_status = gr.Markdown("")
171
+ with gr.Group() as question_group:
172
+ questions = []
173
+ for i in range(5):
174
+ with gr.Group(visible=False) as qgroup:
175
+ question_md = gr.Markdown("", elem_id=f"question_{i}")
176
+ radio = gr.Radio(
177
+ choices=[],
178
+ label="Select your answer:",
179
+ interactive=True,
180
+ elem_id=f"answer_{i}"
181
+ )
182
+ result_md = gr.Markdown("", elem_id=f"result_{i}")
183
+ questions.append({"group": qgroup, "md": question_md, "radio": radio, "result": result_md})
 
 
 
184
 
185
+ submit_btn = gr.Button("Submit Assessment", variant="primary", size="lg")
186
+ result_modal = gr.Markdown("")
 
 
 
 
 
 
187
 
188
  # Step 3: Get Certified
189
  with gr.Tab("🎓 Step 3: Get Certified") as tab3:
190
  score_display = gr.Number(label="Your Score")
191
+ result_message = gr.Markdown("")
192
  course_name = gr.Textbox(
193
  label="Certification Title",
194
  value="Professional Assessment Certification"
 
197
 
198
  def update_questions(text, num_questions):
199
  if not text.strip():
200
+ return [
201
+ gr.update(visible=False) for _ in range(5)
202
+ ], "⚠️ Please enter some text content to generate questions.", [], 0
203
+
204
+ success, generated_questions = quiz_app.generate_questions(text, num_questions)
 
205
 
206
+ if not success or not generated_questions:
207
+ return [
208
+ gr.update(visible=False) for _ in range(5)
209
+ ], "❌ Failed to generate questions. Please try again.", [], 0
210
 
211
+ updates = []
212
+ for i in range(5):
213
+ if i < len(generated_questions):
214
+ q = generated_questions[i]
215
+ updates.append(gr.update(
216
+ visible=True,
217
+ value={
218
+ "md": f"### Question {i+1}\n{q['question']}",
219
+ "radio": gr.update(choices=q["options"], value=None),
220
+ "result": ""
221
+ }
222
+ ))
223
+ else:
224
+ updates.append(gr.update(visible=False))
225
+
226
+ return updates, "", generated_questions, 1
227
+
228
+ def submit_quiz(answers, questions):
229
+ if not all(a is not None for a in answers[:len(questions)]):
230
  return (
231
+ gr.update(value="⚠️ Please answer all questions before submitting."),
232
+ score_display.value,
 
233
  0
234
  )
235
 
236
+ score, results = quiz_app.calculate_score(answers)
 
 
237
 
238
+ # Update result display for each question
239
  updates = []
240
+ for i, result in enumerate(results):
241
+ if result["is_correct"]:
242
+ status = "✅ Correct!"
243
+ color = "green"
244
+ else:
245
+ status = f"❌ Incorrect. Correct answer: {questions[i]['options'][result['correct_index']]}"
246
+ color = "red"
247
+
248
  updates.append(gr.update(
249
  visible=True,
250
+ value=f'<div style="color: {color};">{status}</div>'
 
 
251
  ))
 
252
 
253
+ # Add result message
254
+ if score >= 80:
255
+ message = f"""
256
+ ## 🎉 Congratulations!
257
+ You passed the assessment with a score of {score:.1f}%
258
+ Your certificate has been generated.
259
+ """
260
+ else:
261
+ message = f"""
262
+ ## Try Again
263
+ Your score: {score:.1f}%
264
+ You need 80% or higher to pass and receive a certificate.
265
+ """
266
 
267
+ return updates, message, score, 2
 
 
 
 
 
 
268
 
269
  # Event handlers
270
  generate_btn.click(
271
  fn=update_questions,
272
  inputs=[text_input, num_questions],
273
+ outputs=[
274
+ *[q["group"] for q in questions],
275
+ assessment_status,
276
+ current_questions,
277
+ gr.State(1)
278
+ ]
279
  ).then(
280
  fn=lambda x: gr.update(selected=x),
281
  inputs=[gr.State(1)],
 
284
 
285
  submit_btn.click(
286
  fn=submit_quiz,
287
+ inputs=[
288
+ *[q["radio"] for q in questions],
289
+ current_questions
290
+ ],
291
+ outputs=[
292
+ *[q["result"] for q in questions],
293
+ result_modal,
294
+ score_display,
295
+ gr.State(2)
296
+ ]
297
  ).then(
298
  fn=lambda x: gr.update(selected=x),
299
  inputs=[gr.State(2)],