capradeepgujaran commited on
Commit
a3b6a5f
1 Parent(s): bc2b2dc

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +128 -105
app.py CHANGED
@@ -38,13 +38,20 @@ class QuizApp:
38
  "correct_answer": 0
39
  }}
40
  ]
 
41
  """
42
 
43
  try:
44
  response = client.chat.completions.create(
45
  messages=[
46
- {"role": "system", "content": "You are a quiz generator. Create clear questions with concise answer options."},
47
- {"role": "user", "content": prompt}
 
 
 
 
 
 
48
  ],
49
  model="llama-3.2-3b-preview",
50
  temperature=0.3,
@@ -53,11 +60,17 @@ class QuizApp:
53
 
54
  response_text = response.choices[0].message.content.strip()
55
  response_text = response_text.replace("```json", "").replace("```", "").strip()
56
- response_text = response_text[response_text.find("["):response_text.rfind("]")+1]
57
 
 
 
 
 
 
 
 
58
  questions = json.loads(response_text)
59
- validated_questions = []
60
 
 
61
  for q in questions:
62
  if not all(key in q for key in ["question", "options", "correct_answer"]):
63
  continue
@@ -71,6 +84,9 @@ class QuizApp:
71
  }
72
  validated_questions.append(clean_q)
73
 
 
 
 
74
  self.current_questions = validated_questions[:num_questions]
75
  return True, self.current_questions
76
 
@@ -80,11 +96,11 @@ class QuizApp:
80
 
81
  def calculate_score(self, answers):
82
  if not answers or not self.current_questions:
83
- return 0, []
84
 
85
  total = len(self.current_questions)
86
  correct = 0
87
- results = []
88
 
89
  for i, (q, a) in enumerate(zip(self.current_questions, answers)):
90
  try:
@@ -93,28 +109,38 @@ class QuizApp:
93
  is_correct = selected_index == q["correct_answer"]
94
  if is_correct:
95
  correct += 1
96
- results.append({
97
  "is_correct": is_correct,
 
98
  "correct_answer": q["options"][q["correct_answer"]]
99
  })
100
  else:
101
- results.append({
102
  "is_correct": False,
 
103
  "correct_answer": q["options"][q["correct_answer"]]
104
  })
105
  except (ValueError, TypeError) as e:
106
  print(f"Error processing answer {i}: {e}")
107
- results.append({
108
  "is_correct": False,
 
109
  "correct_answer": q["options"][q["correct_answer"]]
110
  })
111
 
112
- return (correct / total) * 100, results
 
 
 
 
113
 
 
114
  def create_quiz_interface():
115
  quiz_app = QuizApp()
116
 
117
  with gr.Blocks(title="CertifyMe AI", theme=gr.themes.Soft()) as demo:
 
 
118
  # Header
119
  gr.Markdown("""
120
  # 🎓 CertifyMe AI
@@ -151,130 +177,135 @@ def create_quiz_interface():
151
 
152
  # Step 2: Take Assessment
153
  with gr.Tab("📝 Step 2: Take Assessment") as tab2:
 
154
  question_box = gr.Markdown("")
155
  answers = []
156
- feedback = []
157
-
158
  for i in range(5):
159
- radio = gr.Radio(
160
- choices=[],
161
- label=f"Question {i+1}",
162
- visible=False
163
- )
164
- answers.append(radio)
165
- fb = gr.Markdown(visible=False)
166
- feedback.append(fb)
167
 
168
  submit_btn = gr.Button("Submit Assessment", variant="primary", size="lg")
169
- result_message = gr.Markdown("")
170
 
171
  # Step 3: Get Certified
172
  with gr.Tab("🎓 Step 3: Get Certified") as tab3:
173
  score_display = gr.Number(label="Your Score")
174
- completion_message = gr.Markdown("")
175
  course_name = gr.Textbox(
176
  label="Certification Title",
177
  value="Professional Assessment Certification"
178
  )
179
  certificate_display = gr.Image(label="Your Certificate")
180
 
181
- # Store questions state
182
- questions_state = gr.State([])
183
-
184
  def update_questions(text, num_questions):
185
  if not text.strip():
186
  return (
187
- gr.update(value="Please enter content to generate questions."),
188
- *[gr.update(visible=False) for _ in range(5)], # Radio buttons
189
- *[gr.update(visible=False) for _ in range(5)], # Feedback
190
- [], # questions state
191
- 1, # tab index
192
- "Please enter content to generate questions." # result message
193
  )
194
 
195
  success, questions = quiz_app.generate_questions(text, num_questions)
196
- if not success:
 
197
  return (
198
- gr.update(value="Failed to generate questions. Please try again."),
199
- *[gr.update(visible=False) for _ in range(5)],
200
- *[gr.update(visible=False) for _ in range(5)],
201
  [],
202
- 1,
203
- "Failed to generate questions. Please try again."
204
  )
205
 
206
- # Create question display with embedded radio buttons
207
- questions_md = "# 📝 Assessment Questions\n\n"
208
-
209
- # Update radio buttons and create question display
210
- radio_updates = []
211
- feedback_updates = []
212
 
 
 
213
  for i, q in enumerate(questions):
214
- questions_md += f"### Question {i+1}\n{q['question']}\n\n"
215
- radio_updates.append(gr.update(
216
- choices=q["options"],
217
- label=f"Select your answer for Question {i+1}:",
218
  visible=True,
219
- value=None
 
 
220
  ))
221
- feedback_updates.append(gr.update(visible=False, value=""))
222
 
223
  # Hide unused radio buttons
224
  for i in range(len(questions), 5):
225
- radio_updates.append(gr.update(visible=False))
226
- feedback_updates.append(gr.update(visible=False))
227
 
228
  return (
229
- gr.update(value=questions_md),
230
- *radio_updates,
231
- *feedback_updates,
232
  questions,
233
- 1,
234
- ""
235
  )
236
-
237
- def submit_answers(q1, q2, q3, q4, q5, questions):
238
  answers = [q1, q2, q3, q4, q5][:len(questions)]
239
 
240
  if not all(a is not None for a in answers):
241
- return [gr.update() for _ in range(5)], 0, "Please answer all questions before submitting."
242
-
243
- score, results = quiz_app.calculate_score(answers)
 
 
 
 
244
 
245
- # Create feedback for each answer
246
- feedback_updates = []
247
- for i, result in enumerate(results):
248
- if result["is_correct"]:
249
- feedback_updates.append(gr.update(
250
- visible=True,
251
- value='<div style="color: green; margin-top: 10px;">✅ Correct!</div>'
252
- ))
253
- else:
254
- feedback_updates.append(gr.update(
255
- visible=True,
256
- value=f'<div style="color: red; margin-top: 10px;">❌ Incorrect. Correct answer: {result["correct_answer"]}</div>'
257
- ))
258
 
259
- # Add empty updates for unused feedback slots
260
- for _ in range(len(results), 5):
261
- feedback_updates.append(gr.update(visible=False))
 
 
 
 
 
 
 
 
 
 
 
262
 
263
- # Create result message
264
- if score >= 80:
265
- message = f"""
266
- ### 🎉 Congratulations!
267
- You passed the assessment with a score of {score:.1f}%
268
- Your certificate has been generated.
 
 
269
  """
 
270
  else:
271
- message = f"""
272
- ### Please Try Again
273
- Your score: {score:.1f}%
274
- You need 80% or higher to pass and receive a certificate.
 
 
275
  """
 
276
 
277
- return feedback_updates, score, message
 
 
 
 
 
 
278
 
279
  # Event handlers
280
  generate_btn.click(
@@ -282,33 +313,25 @@ def create_quiz_interface():
282
  inputs=[text_input, num_questions],
283
  outputs=[
284
  question_box,
 
285
  *answers,
286
- *feedback,
287
- questions_state,
288
- gr.State(1),
289
- result_message
290
  ]
291
- ).then(
292
- fn=lambda x: gr.update(selected=x),
293
- inputs=gr.State(1),
294
- outputs=tabs
295
  )
296
 
297
  submit_btn.click(
298
- fn=submit_answers,
299
- inputs=[*answers, questions_state],
300
  outputs=[
301
- *feedback,
 
302
  score_display,
303
- result_message
 
304
  ]
305
- ).then(
306
- fn=lambda x: gr.update(selected=x),
307
- inputs=gr.State(2),
308
- outputs=tabs
309
  )
310
 
311
-
312
 
313
  def generate_certificate(score, name, course_name, company_logo=None, participant_photo=None):
314
  """
 
38
  "correct_answer": 0
39
  }}
40
  ]
41
+ Keep all options concise (10 words or less each).
42
  """
43
 
44
  try:
45
  response = client.chat.completions.create(
46
  messages=[
47
+ {
48
+ "role": "system",
49
+ "content": "You are a quiz generator. Create clear questions with concise answer options."
50
+ },
51
+ {
52
+ "role": "user",
53
+ "content": prompt
54
+ }
55
  ],
56
  model="llama-3.2-3b-preview",
57
  temperature=0.3,
 
60
 
61
  response_text = response.choices[0].message.content.strip()
62
  response_text = response_text.replace("```json", "").replace("```", "").strip()
 
63
 
64
+ start_idx = response_text.find("[")
65
+ end_idx = response_text.rfind("]")
66
+
67
+ if start_idx == -1 or end_idx == -1:
68
+ raise ValueError("No valid JSON array found in response")
69
+
70
+ response_text = response_text[start_idx:end_idx + 1]
71
  questions = json.loads(response_text)
 
72
 
73
+ validated_questions = []
74
  for q in questions:
75
  if not all(key in q for key in ["question", "options", "correct_answer"]):
76
  continue
 
84
  }
85
  validated_questions.append(clean_q)
86
 
87
+ if not validated_questions:
88
+ raise ValueError("No valid questions after validation")
89
+
90
  self.current_questions = validated_questions[:num_questions]
91
  return True, self.current_questions
92
 
 
96
 
97
  def calculate_score(self, answers):
98
  if not answers or not self.current_questions:
99
+ return 0, None, []
100
 
101
  total = len(self.current_questions)
102
  correct = 0
103
+ feedback = []
104
 
105
  for i, (q, a) in enumerate(zip(self.current_questions, answers)):
106
  try:
 
109
  is_correct = selected_index == q["correct_answer"]
110
  if is_correct:
111
  correct += 1
112
+ feedback.append({
113
  "is_correct": is_correct,
114
+ "selected": a,
115
  "correct_answer": q["options"][q["correct_answer"]]
116
  })
117
  else:
118
+ feedback.append({
119
  "is_correct": False,
120
+ "selected": None,
121
  "correct_answer": q["options"][q["correct_answer"]]
122
  })
123
  except (ValueError, TypeError) as e:
124
  print(f"Error processing answer {i}: {e}")
125
+ feedback.append({
126
  "is_correct": False,
127
+ "selected": None,
128
  "correct_answer": q["options"][q["correct_answer"]]
129
  })
130
 
131
+ score = (correct / total) * 100
132
+ passed = score >= 80
133
+
134
+ return score, passed, feedback
135
+
136
 
137
+ # Update the interface functions
138
  def create_quiz_interface():
139
  quiz_app = QuizApp()
140
 
141
  with gr.Blocks(title="CertifyMe AI", theme=gr.themes.Soft()) as demo:
142
+ current_questions = gr.State([])
143
+
144
  # Header
145
  gr.Markdown("""
146
  # 🎓 CertifyMe AI
 
177
 
178
  # Step 2: Take Assessment
179
  with gr.Tab("📝 Step 2: Take Assessment") as tab2:
180
+ feedback_box = gr.Markdown("")
181
  question_box = gr.Markdown("")
182
  answers = []
 
 
183
  for i in range(5):
184
+ with gr.Group():
185
+ radio = gr.Radio(
186
+ choices=[],
187
+ label=f"Question {i+1}",
188
+ visible=False,
189
+ interactive=True
190
+ )
191
+ answers.append(radio)
192
 
193
  submit_btn = gr.Button("Submit Assessment", variant="primary", size="lg")
 
194
 
195
  # Step 3: Get Certified
196
  with gr.Tab("🎓 Step 3: Get Certified") as tab3:
197
  score_display = gr.Number(label="Your Score")
198
+ result_message = gr.Markdown("")
199
  course_name = gr.Textbox(
200
  label="Certification Title",
201
  value="Professional Assessment Certification"
202
  )
203
  certificate_display = gr.Image(label="Your Certificate")
204
 
 
 
 
205
  def update_questions(text, num_questions):
206
  if not text.strip():
207
  return (
208
+ gr.update(value=""),
209
+ gr.update(value="⚠️ Please enter some text content to generate questions."),
210
+ *[gr.update(visible=False, choices=[]) for _ in range(5)],
211
+ [],
212
+ gr.update(selected=1)
 
213
  )
214
 
215
  success, questions = quiz_app.generate_questions(text, num_questions)
216
+
217
+ if not success or not questions:
218
  return (
219
+ gr.update(value=""),
220
+ gr.update(value="❌ Failed to generate questions. Please try again."),
221
+ *[gr.update(visible=False, choices=[]) for _ in range(5)],
222
  [],
223
+ gr.update(selected=1)
 
224
  )
225
 
226
+ # Create question display
227
+ questions_html = "# 📝 Assessment Questions\n\n"
228
+ questions_html += "> Please select one answer for each question.\n\n"
 
 
 
229
 
230
+ # Update radio buttons
231
+ updates = []
232
  for i, q in enumerate(questions):
233
+ questions_html += f"### Question {i+1}\n{q['question']}\n\n"
234
+ updates.append(gr.update(
 
 
235
  visible=True,
236
+ choices=q["options"],
237
+ value=None,
238
+ label=f"Select your answer:"
239
  ))
 
240
 
241
  # Hide unused radio buttons
242
  for i in range(len(questions), 5):
243
+ updates.append(gr.update(visible=False, choices=[]))
 
244
 
245
  return (
246
+ gr.update(value=questions_html),
247
+ gr.update(value=""),
248
+ *updates,
249
  questions,
250
+ gr.update(selected=1)
 
251
  )
252
+
253
+ def submit_quiz(q1, q2, q3, q4, q5, questions):
254
  answers = [q1, q2, q3, q4, q5][:len(questions)]
255
 
256
  if not all(a is not None for a in answers):
257
+ return (
258
+ gr.update(value="⚠️ Please answer all questions before submitting."),
259
+ *[gr.update() for _ in range(5)],
260
+ 0,
261
+ "",
262
+ gr.update(selected=1)
263
+ )
264
 
265
+ score, passed, feedback = quiz_app.calculate_score(answers)
 
 
 
 
 
 
 
 
 
 
 
 
266
 
267
+ # Create feedback HTML
268
+ feedback_html = "# Assessment Results\n\n"
269
+ for i, (q, f) in enumerate(zip(quiz_app.current_questions, feedback)):
270
+ color = "green" if f["is_correct"] else "red"
271
+ symbol = "✅" if f["is_correct"] else "❌"
272
+ feedback_html += f"""
273
+ ### Question {i+1}
274
+ {q["question"]}
275
+
276
+ <div style="color: {color}; padding: 10px; margin: 5px 0; border-left: 3px solid {color};">
277
+ {symbol} Your answer: {f["selected"]}
278
+ {'' if f["is_correct"] else f'<br>Correct answer: {f["correct_answer"]}'}
279
+ </div>
280
+ """
281
 
282
+ # Add result message
283
+ if passed:
284
+ feedback_html += f"""
285
+ <div style="background-color: #e6ffe6; padding: 20px; margin-top: 20px; border-radius: 10px;">
286
+ <h3 style="color: #008000;">🎉 Congratulations!</h3>
287
+ <p>You passed the assessment with a score of {score:.1f}%</p>
288
+ <p>Your certificate has been generated.</p>
289
+ </div>
290
  """
291
+ result_msg = f"🎉 Congratulations! You passed with {score:.1f}%"
292
  else:
293
+ feedback_html += f"""
294
+ <div style="background-color: #ffe6e6; padding: 20px; margin-top: 20px; border-radius: 10px;">
295
+ <h3 style="color: #cc0000;">Please Try Again</h3>
296
+ <p>Your score: {score:.1f}%</p>
297
+ <p>You need 80% or higher to pass and receive a certificate.</p>
298
+ </div>
299
  """
300
+ result_msg = f"Score: {score:.1f}%. You need 80% to pass."
301
 
302
+ return (
303
+ gr.update(value=feedback_html),
304
+ *[gr.update(visible=False) for _ in range(5)],
305
+ score,
306
+ result_msg,
307
+ gr.update(selected=2)
308
+ )
309
 
310
  # Event handlers
311
  generate_btn.click(
 
313
  inputs=[text_input, num_questions],
314
  outputs=[
315
  question_box,
316
+ feedback_box,
317
  *answers,
318
+ current_questions,
319
+ tabs
 
 
320
  ]
 
 
 
 
321
  )
322
 
323
  submit_btn.click(
324
+ fn=submit_quiz,
325
+ inputs=[*answers, current_questions],
326
  outputs=[
327
+ feedback_box,
328
+ *answers,
329
  score_display,
330
+ result_message,
331
+ tabs
332
  ]
 
 
 
 
333
  )
334
 
 
335
 
336
  def generate_certificate(score, name, course_name, company_logo=None, participant_photo=None):
337
  """