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

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +90 -80
app.py CHANGED
@@ -19,19 +19,26 @@ class QuizApp:
19
  prompt = f"""Create exactly {num_questions} multiple choice questions based on this text:
20
  {text}
21
 
 
 
 
 
 
 
22
  Return ONLY a JSON array with this EXACT format - no other text:
23
  [
24
  {{
25
  "question": "Question text here?",
26
  "options": [
27
- "Option 1",
28
- "Option 2",
29
- "Option 3",
30
- "Option 4"
31
  ],
32
  "correct_answer": 0
33
  }}
34
  ]
 
35
  """
36
 
37
  try:
@@ -39,7 +46,7 @@ class QuizApp:
39
  messages=[
40
  {
41
  "role": "system",
42
- "content": "You are a quiz generator. Respond only with a properly formatted JSON array."
43
  },
44
  {
45
  "role": "user",
@@ -47,18 +54,15 @@ class QuizApp:
47
  }
48
  ],
49
  model="llama-3.2-3b-preview",
50
- temperature=0.3, # Reduced temperature for more consistent formatting
51
- max_tokens=2048,
52
- stop=["\n\n", "```"] # Stop generation at these tokens
53
  )
54
 
55
- # Clean up the response
56
  response_text = response.choices[0].message.content.strip()
57
-
58
- # Remove any markdown formatting
59
  response_text = response_text.replace("```json", "").replace("```", "").strip()
60
 
61
- # Find the JSON array
62
  start_idx = response_text.find("[")
63
  end_idx = response_text.rfind("]")
64
 
@@ -66,62 +70,42 @@ class QuizApp:
66
  raise ValueError("No valid JSON array found in response")
67
 
68
  response_text = response_text[start_idx:end_idx + 1]
 
69
 
70
- # Try to parse the JSON
71
- try:
72
- questions = json.loads(response_text)
73
- except json.JSONDecodeError:
74
- # If parsing fails, try to fix common JSON formatting issues
75
- response_text = response_text.replace("'", '"') # Replace single quotes with double quotes
76
- response_text = response_text.replace("},]", "}]") # Fix trailing comma
77
- response_text = response_text.replace(",]", "]") # Fix trailing comma
78
- questions = json.loads(response_text)
79
-
80
- # Validate questions
81
  validated_questions = []
82
  for q in questions:
83
- if not isinstance(q, dict):
84
- continue
85
-
86
- # Ensure all required fields are present
87
  if not all(key in q for key in ["question", "options", "correct_answer"]):
88
  continue
89
 
90
- # Ensure options is a list with exactly 4 items
91
- if not isinstance(q["options"], list) or len(q["options"]) != 4:
92
- # Try to fix by padding with additional options if needed
93
- if isinstance(q["options"], list) and len(q["options"]) < 4:
94
- q["options"].extend([f"Additional option {i+1}" for i in range(4 - len(q["options"]))])
95
- else:
96
- continue
97
-
98
- # Ensure correct_answer is valid
99
- if not isinstance(q["correct_answer"], (int)) or q["correct_answer"] not in range(4):
100
- q["correct_answer"] = 0 # Default to first option if invalid
101
 
102
- validated_questions.append(q)
 
 
 
 
 
 
103
 
104
  if not validated_questions:
105
- return False, []
106
 
107
- self.current_questions = validated_questions[:num_questions] # Limit to requested number
108
  return True, self.current_questions
109
 
110
  except Exception as e:
111
  print(f"Error in question generation: {str(e)}")
112
- # Create a single default question for testing
113
- default_questions = [{
114
- "question": "Default question (Error in generation - please try again)",
115
- "options": [
116
- "Option A",
117
- "Option B",
118
- "Option C",
119
- "Option D"
120
- ],
121
- "correct_answer": 0
122
- }]
123
- self.current_questions = default_questions
124
- return True, default_questions
125
 
126
  def calculate_score(self, answers):
127
  if not answers or not self.current_questions:
@@ -130,11 +114,19 @@ class QuizApp:
130
  total = len(self.current_questions)
131
  correct = 0
132
  for i, (q, a) in enumerate(zip(self.current_questions, answers)):
133
- if a is not None and q['correct_answer'] == int(a):
134
- correct += 1
 
 
 
 
 
 
 
135
 
136
  return (correct / total) * 100
137
 
 
138
  def create_quiz_interface():
139
  quiz_app = QuizApp()
140
 
@@ -180,14 +172,30 @@ def create_quiz_interface():
180
  with gr.Tab("📝 Step 2: Take Assessment") as tab2:
181
  questions_markdown = gr.Markdown("")
182
  answers = []
183
- for i in range(5): # Pre-create radio buttons
184
- radio = gr.Radio(
185
- choices=[],
186
- label=f"Question {i+1}",
187
- visible=False
188
- )
189
- answers.append(radio)
190
- submit_btn = gr.Button("Submit Assessment", variant="primary", size="lg")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
191
 
192
  # Step 3: Get Certified
193
  with gr.Tab("🎓 Step 3: Get Certified") as tab3:
@@ -217,33 +225,35 @@ def create_quiz_interface():
217
  0
218
  )
219
 
220
- # Update question display
221
  questions_html = "# 📝 Assessment Questions\n\n"
222
  questions_html += "> Please select one answer for each question below.\n\n"
223
 
224
- for i, q in enumerate(questions, 1):
225
- questions_html += f"### Question {i}\n{q['question']}\n\n"
226
-
227
  # Update radio buttons
228
  updates = []
229
- for i in range(5):
230
- if i < len(questions):
231
- updates.append(gr.update(
232
- visible=True,
233
- choices=questions[i]["options"],
234
- value=None,
235
- label=f"Select answer for Question {i+1}"
236
- ))
237
- else:
238
- updates.append(gr.update(visible=False, choices=[]))
 
 
 
 
239
 
240
- return (gr.update(value=questions_html), *updates, questions, 1)
241
 
 
242
  def submit_quiz(q1, q2, q3, q4, q5, questions):
243
  answers = [q1, q2, q3, q4, q5][:len(questions)]
244
  score = quiz_app.calculate_score(answers)
245
  return score, 2
246
-
247
  # Event handlers
248
  generate_btn.click(
249
  fn=update_questions,
 
19
  prompt = f"""Create exactly {num_questions} multiple choice questions based on this text:
20
  {text}
21
 
22
+ For each question:
23
+ 1. Create a clear, concise question
24
+ 2. Provide exactly 4 options
25
+ 3. Mark the correct answer with the index (0-3)
26
+ 4. Ensure options are concise and clear
27
+
28
  Return ONLY a JSON array with this EXACT format - no other text:
29
  [
30
  {{
31
  "question": "Question text here?",
32
  "options": [
33
+ "Brief option 1",
34
+ "Brief option 2",
35
+ "Brief option 3",
36
+ "Brief option 4"
37
  ],
38
  "correct_answer": 0
39
  }}
40
  ]
41
+ Keep all options concise (10 words or less each).
42
  """
43
 
44
  try:
 
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",
 
54
  }
55
  ],
56
  model="llama-3.2-3b-preview",
57
+ temperature=0.3,
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
 
 
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
 
106
  except Exception as e:
107
  print(f"Error in question generation: {str(e)}")
108
+ return False, []
 
 
 
 
 
 
 
 
 
 
 
 
109
 
110
  def calculate_score(self, answers):
111
  if not answers or not self.current_questions:
 
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
 
 
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:
 
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,