Update gen_mcqs.py
Browse files- gen_mcqs.py +282 -0
gen_mcqs.py
CHANGED
@@ -1,3 +1,210 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
import ast
|
2 |
from pymongo import MongoClient
|
3 |
from datetime import datetime
|
@@ -23,6 +230,7 @@ model = genai.GenerativeModel('gemini-pro')
|
|
23 |
client = MongoClient(MONGO_URI)
|
24 |
db = client['novascholar_db']
|
25 |
quizzes_collection = db["quizzes"]
|
|
|
26 |
|
27 |
def strip_code_markers(response_text):
|
28 |
"""Strip off the markers ``` and python from a LLM model's response"""
|
@@ -117,6 +325,26 @@ def save_quiz(course_id, session_id, title, questions, user_id):
|
|
117 |
print(f"Error saving quiz: {e}")
|
118 |
return None
|
119 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
120 |
|
121 |
def get_student_quiz_score(quiz_id, student_id):
|
122 |
"""Get student's score for a specific quiz"""
|
@@ -131,6 +359,19 @@ def get_student_quiz_score(quiz_id, student_id):
|
|
131 |
return quiz['submissions'][0].get('score')
|
132 |
return None
|
133 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
134 |
# def submit_quiz_answers(quiz_id, student_id, student_answers):
|
135 |
# """Submit and score student's quiz answers"""
|
136 |
# quiz = quizzes_collection.find_one({"_id": quiz_id})
|
@@ -201,6 +442,47 @@ def submit_quiz_answers(quiz_id, student_id, student_answers):
|
|
201 |
|
202 |
return score if result.modified_count > 0 else None
|
203 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
204 |
except Exception as e:
|
205 |
print(f"Error submitting quiz: {e}")
|
206 |
return None
|
|
|
1 |
+
# import ast
|
2 |
+
# from pymongo import MongoClient
|
3 |
+
# from datetime import datetime
|
4 |
+
# import openai
|
5 |
+
# import google.generativeai as genai
|
6 |
+
# from google.generativeai import GenerativeModel
|
7 |
+
# from dotenv import load_dotenv
|
8 |
+
# import os
|
9 |
+
# from file_upload_vectorize import resources_collection, vectors_collection, courses_collection2, faculty_collection
|
10 |
+
|
11 |
+
# # Load environment variables
|
12 |
+
# load_dotenv()
|
13 |
+
# MONGO_URI = os.getenv('MONGO_URI')
|
14 |
+
# OPENAI_KEY = os.getenv('OPENAI_KEY')
|
15 |
+
# GEMINI_KEY = os.getenv('GEMINI_KEY')
|
16 |
+
|
17 |
+
# # Configure APIs
|
18 |
+
# openai.api_key = OPENAI_KEY
|
19 |
+
# genai.configure(api_key=GEMINI_KEY)
|
20 |
+
# model = genai.GenerativeModel('gemini-pro')
|
21 |
+
|
22 |
+
# # Connect to MongoDB
|
23 |
+
# client = MongoClient(MONGO_URI)
|
24 |
+
# db = client['novascholar_db']
|
25 |
+
# quizzes_collection = db["quizzes"]
|
26 |
+
|
27 |
+
# def strip_code_markers(response_text):
|
28 |
+
# """Strip off the markers ``` and python from a LLM model's response"""
|
29 |
+
# if response_text.startswith("```python"):
|
30 |
+
# response_text = response_text[len("```python"):].strip()
|
31 |
+
# if response_text.startswith("```"):
|
32 |
+
# response_text = response_text[len("```"):].strip()
|
33 |
+
# if response_text.endswith("```"):
|
34 |
+
# response_text = response_text[:-len("```")].strip()
|
35 |
+
# return response_text
|
36 |
+
|
37 |
+
|
38 |
+
# # New function to generate MCQs using Gemini
|
39 |
+
# def generate_mcqs(context, num_questions, session_title, session_description):
|
40 |
+
# """Generate MCQs either from context or session details"""
|
41 |
+
# try:
|
42 |
+
# # Initialize Gemini model
|
43 |
+
# if context:
|
44 |
+
# prompt = f"""
|
45 |
+
# Based on the following content, generate {num_questions} multiple choice questions.
|
46 |
+
# Format each question as a Python dictionary with the following structure:
|
47 |
+
# {{
|
48 |
+
# "question": "Question text here",
|
49 |
+
# "options": ["A) option1", "B) option2", "C) option3", "D) option4"],
|
50 |
+
# "correct_option": "A) option1" or "B) option2" or "C) option3" or "D) option4"
|
51 |
+
# }}
|
52 |
+
|
53 |
+
# Content:
|
54 |
+
# {context}
|
55 |
+
|
56 |
+
# Generate challenging but clear questions that test understanding of key concepts.
|
57 |
+
# Return only the Python list of dictionaries.
|
58 |
+
# """
|
59 |
+
# else:
|
60 |
+
# prompt = f"""
|
61 |
+
# Generate {num_questions} multiple choice questions about the topic:
|
62 |
+
# Title: {session_title}
|
63 |
+
# Description: {session_description}
|
64 |
+
|
65 |
+
# Format each question as a Python dictionary with the following structure:
|
66 |
+
# {{
|
67 |
+
# "question": "Question text here",
|
68 |
+
# "options": ["A) option1", "B) option2", "C) option3", "D) option4"],
|
69 |
+
# "correct_option": "A" or "B" or "C" or "D"
|
70 |
+
# }}
|
71 |
+
|
72 |
+
# Generate challenging but clear questions.
|
73 |
+
# Return only the Python list of dictionaries without any additional formatting or markers
|
74 |
+
# Do not write any other text, do not start the response with (```python), do not end the response with backticks(```)
|
75 |
+
# A Sample response should look like this: Response Text: [
|
76 |
+
# {
|
77 |
+
# "question": "Which of the following is NOT a valid data type in C++?",
|
78 |
+
# "options": ["int", "double", "boolean", "char"],
|
79 |
+
# "correct_option": "C"
|
80 |
+
# }
|
81 |
+
# ] (Notice that there are no backticks(```) around the response and no (```python))
|
82 |
+
# .
|
83 |
+
# """
|
84 |
+
|
85 |
+
# response = model.generate_content(prompt)
|
86 |
+
# response_text = response.text.strip()
|
87 |
+
# print("Response Text:", response_text)
|
88 |
+
# modified_response_text = strip_code_markers(response_text)
|
89 |
+
# print("Response Text Modified to:", modified_response_text)
|
90 |
+
# # Extract and parse the response to get the list of MCQs
|
91 |
+
# mcqs = ast.literal_eval(modified_response_text) # Be careful with eval, consider using ast.literal_eval for production
|
92 |
+
# print(mcqs)
|
93 |
+
# if not mcqs:
|
94 |
+
# raise ValueError("No questions generated")
|
95 |
+
# return mcqs
|
96 |
+
# except Exception as e:
|
97 |
+
# print(f"Error generating MCQs: , error: {e}")
|
98 |
+
# return None
|
99 |
+
|
100 |
+
# # New function to save quiz to database
|
101 |
+
# def save_quiz(course_id, session_id, title, questions, user_id):
|
102 |
+
# """Save quiz to database"""
|
103 |
+
# try:
|
104 |
+
# quiz_data = {
|
105 |
+
# "user_id": user_id,
|
106 |
+
# "course_id": course_id,
|
107 |
+
# "session_id": session_id,
|
108 |
+
# "title": title,
|
109 |
+
# "questions": questions,
|
110 |
+
# "created_at": datetime.utcnow(),
|
111 |
+
# "status": "active",
|
112 |
+
# "submissions": []
|
113 |
+
# }
|
114 |
+
# result = quizzes_collection.insert_one(quiz_data)
|
115 |
+
# return result.inserted_id
|
116 |
+
# except Exception as e:
|
117 |
+
# print(f"Error saving quiz: {e}")
|
118 |
+
# return None
|
119 |
+
|
120 |
+
|
121 |
+
# def get_student_quiz_score(quiz_id, student_id):
|
122 |
+
# """Get student's score for a specific quiz"""
|
123 |
+
# quiz = quizzes_collection.find_one(
|
124 |
+
# {
|
125 |
+
# "_id": quiz_id,
|
126 |
+
# "submissions.student_id": student_id
|
127 |
+
# },
|
128 |
+
# {"submissions.$": 1}
|
129 |
+
# )
|
130 |
+
# if quiz and quiz.get('submissions'):
|
131 |
+
# return quiz['submissions'][0].get('score')
|
132 |
+
# return None
|
133 |
+
|
134 |
+
# # def submit_quiz_answers(quiz_id, student_id, student_answers):
|
135 |
+
# # """Submit and score student's quiz answers"""
|
136 |
+
# # quiz = quizzes_collection.find_one({"_id": quiz_id})
|
137 |
+
# # if not quiz:
|
138 |
+
# # return None
|
139 |
+
|
140 |
+
# # # Calculate score
|
141 |
+
# # correct_answers = 0
|
142 |
+
# # total_questions = len(quiz['questions'])
|
143 |
+
|
144 |
+
# # for q_idx, question in enumerate(quiz['questions']):
|
145 |
+
# # if student_answers.get(str(q_idx)) == question['correct_option']:
|
146 |
+
# # correct_answers += 1
|
147 |
+
|
148 |
+
# # score = (correct_answers / total_questions) * 100
|
149 |
+
|
150 |
+
# # # Store submission
|
151 |
+
# # submission_data = {
|
152 |
+
# # "student_id": student_id,
|
153 |
+
# # "answers": student_answers,
|
154 |
+
# # "score": score,
|
155 |
+
# # "submitted_at": datetime.utcnow()
|
156 |
+
# # }
|
157 |
+
|
158 |
+
# # # Update quiz with submission
|
159 |
+
# # quizzes_collection.update_one(
|
160 |
+
# # {"_id": quiz_id},
|
161 |
+
# # {
|
162 |
+
# # "$push": {"submissions": submission_data}
|
163 |
+
# # }
|
164 |
+
# # )
|
165 |
+
|
166 |
+
# # return score
|
167 |
+
# def submit_quiz_answers(quiz_id, student_id, student_answers):
|
168 |
+
# """Submit and score student's quiz answers"""
|
169 |
+
# try:
|
170 |
+
# quiz = quizzes_collection.find_one({"_id": quiz_id})
|
171 |
+
# if not quiz:
|
172 |
+
# return None
|
173 |
+
|
174 |
+
# # Calculate score
|
175 |
+
# correct_answers = 0
|
176 |
+
# total_questions = len(quiz['questions'])
|
177 |
+
|
178 |
+
# for q_idx, question in enumerate(quiz['questions']):
|
179 |
+
# student_answer = student_answers.get(str(q_idx))
|
180 |
+
# if student_answer: # Only check if answer was provided
|
181 |
+
# # Extract the option letter (A, B, C, D) from the full answer string
|
182 |
+
# answer_letter = student_answer.split(')')[0].strip()
|
183 |
+
# if answer_letter == question['correct_option']:
|
184 |
+
# correct_answers += 1
|
185 |
+
|
186 |
+
# score = (correct_answers / total_questions) * 100
|
187 |
+
|
188 |
+
# # Store submission
|
189 |
+
# submission_data = {
|
190 |
+
# "student_id": student_id,
|
191 |
+
# "answers": student_answers,
|
192 |
+
# "score": score,
|
193 |
+
# "submitted_at": datetime.utcnow()
|
194 |
+
# }
|
195 |
+
|
196 |
+
# # Update quiz with submission
|
197 |
+
# result = quizzes_collection.update_one(
|
198 |
+
# {"_id": quiz_id},
|
199 |
+
# {"$push": {"submissions": submission_data}}
|
200 |
+
# )
|
201 |
+
|
202 |
+
# return score if result.modified_count > 0 else None
|
203 |
+
|
204 |
+
# except Exception as e:
|
205 |
+
# print(f"Error submitting quiz: {e}")
|
206 |
+
# return None
|
207 |
+
|
208 |
import ast
|
209 |
from pymongo import MongoClient
|
210 |
from datetime import datetime
|
|
|
230 |
client = MongoClient(MONGO_URI)
|
231 |
db = client['novascholar_db']
|
232 |
quizzes_collection = db["quizzes"]
|
233 |
+
surprise_quizzes_collection = db["surprise_quizzes"]
|
234 |
|
235 |
def strip_code_markers(response_text):
|
236 |
"""Strip off the markers ``` and python from a LLM model's response"""
|
|
|
325 |
print(f"Error saving quiz: {e}")
|
326 |
return None
|
327 |
|
328 |
+
def save_surprise_quiz(course_id, session_id, title, questions, user_id, no_minutes):
|
329 |
+
"""Save quiz to database"""
|
330 |
+
try:
|
331 |
+
quiz_data = {
|
332 |
+
"user_id": user_id,
|
333 |
+
"course_id": course_id,
|
334 |
+
"session_id": session_id,
|
335 |
+
"title": title,
|
336 |
+
"questions": questions,
|
337 |
+
"created_at": datetime.now(),
|
338 |
+
"status": "active",
|
339 |
+
"submissions": [],
|
340 |
+
"no_minutes": no_minutes
|
341 |
+
}
|
342 |
+
result = surprise_quizzes_collection.insert_one(quiz_data)
|
343 |
+
return result.inserted_id
|
344 |
+
except Exception as e:
|
345 |
+
print(f"Error saving quiz: {e}")
|
346 |
+
return None
|
347 |
+
|
348 |
|
349 |
def get_student_quiz_score(quiz_id, student_id):
|
350 |
"""Get student's score for a specific quiz"""
|
|
|
359 |
return quiz['submissions'][0].get('score')
|
360 |
return None
|
361 |
|
362 |
+
def get_student_surprise_quiz_score(quiz_id, student_id):
|
363 |
+
"""Get student's score for a specific quiz"""
|
364 |
+
quiz = surprise_quizzes_collection.find_one(
|
365 |
+
{
|
366 |
+
"_id": quiz_id,
|
367 |
+
"submissions.student_id": student_id
|
368 |
+
},
|
369 |
+
{"submissions.$": 1}
|
370 |
+
)
|
371 |
+
if quiz and quiz.get('submissions'):
|
372 |
+
return quiz['submissions'][0].get('score')
|
373 |
+
return None
|
374 |
+
|
375 |
# def submit_quiz_answers(quiz_id, student_id, student_answers):
|
376 |
# """Submit and score student's quiz answers"""
|
377 |
# quiz = quizzes_collection.find_one({"_id": quiz_id})
|
|
|
442 |
|
443 |
return score if result.modified_count > 0 else None
|
444 |
|
445 |
+
except Exception as e:
|
446 |
+
print(f"Error submitting quiz: {e}")
|
447 |
+
return None
|
448 |
+
|
449 |
+
def submit_surprise_quiz_answers(quiz_id, student_id, student_answers):
|
450 |
+
"""Submit and score student's quiz answers"""
|
451 |
+
try:
|
452 |
+
quiz = surprise_quizzes_collection.find_one({"_id": quiz_id})
|
453 |
+
if not quiz:
|
454 |
+
return None
|
455 |
+
|
456 |
+
# Calculate score
|
457 |
+
correct_answers = 0
|
458 |
+
total_questions = len(quiz['questions'])
|
459 |
+
|
460 |
+
for q_idx, question in enumerate(quiz['questions']):
|
461 |
+
student_answer = student_answers.get(str(q_idx))
|
462 |
+
if student_answer: # Only check if answer was provided
|
463 |
+
# Extract the option letter (A, B, C, D) from the full answer string
|
464 |
+
answer_letter = student_answer.split(')')[0].strip()
|
465 |
+
if answer_letter == question['correct_option']:
|
466 |
+
correct_answers += 1
|
467 |
+
|
468 |
+
score = (correct_answers / total_questions) * 100
|
469 |
+
|
470 |
+
# Store submission
|
471 |
+
submission_data = {
|
472 |
+
"student_id": student_id,
|
473 |
+
"answers": student_answers,
|
474 |
+
"score": score,
|
475 |
+
"submitted_at": datetime.utcnow()
|
476 |
+
}
|
477 |
+
|
478 |
+
# Update quiz with submission
|
479 |
+
result = surprise_quizzes_collection.update_one(
|
480 |
+
{"_id": quiz_id},
|
481 |
+
{"$push": {"submissions": submission_data}}
|
482 |
+
)
|
483 |
+
|
484 |
+
return score if result.modified_count > 0 else None
|
485 |
+
|
486 |
except Exception as e:
|
487 |
print(f"Error submitting quiz: {e}")
|
488 |
return None
|