YashJD's picture
Initial Commit
e107ee4
raw
history blame
7.54 kB
import ast
from pymongo import MongoClient
from datetime import datetime
import openai
import google.generativeai as genai
from google.generativeai import GenerativeModel
from dotenv import load_dotenv
import os
from file_upload_vectorize import resources_collection, vectors_collection, courses_collection2, faculty_collection
# Load environment variables
load_dotenv()
MONGO_URI = os.getenv('MONGO_URI')
OPENAI_KEY = os.getenv('OPENAI_KEY')
GEMINI_KEY = os.getenv('GEMINI_KEY')
# Configure APIs
openai.api_key = OPENAI_KEY
genai.configure(api_key=GEMINI_KEY)
model = genai.GenerativeModel('gemini-pro')
# Connect to MongoDB
client = MongoClient(MONGO_URI)
db = client['novascholar_db']
quizzes_collection = db["quizzes"]
def strip_code_markers(response_text):
"""Strip off the markers ``` and python from a LLM model's response"""
if response_text.startswith("```python"):
response_text = response_text[len("```python"):].strip()
if response_text.startswith("```"):
response_text = response_text[len("```"):].strip()
if response_text.endswith("```"):
response_text = response_text[:-len("```")].strip()
return response_text
# New function to generate MCQs using Gemini
def generate_mcqs(context, num_questions, session_title, session_description):
"""Generate MCQs either from context or session details"""
try:
# Initialize Gemini model
if context:
prompt = f"""
Based on the following content, generate {num_questions} multiple choice questions.
Format each question as a Python dictionary with the following structure:
{{
"question": "Question text here",
"options": ["A) option1", "B) option2", "C) option3", "D) option4"],
"correct_option": "A) option1" or "B) option2" or "C) option3" or "D) option4"
}}
Content:
{context}
Generate challenging but clear questions that test understanding of key concepts.
Return only the Python list of dictionaries.
"""
else:
prompt = f"""
Generate {num_questions} multiple choice questions about the topic:
Title: {session_title}
Description: {session_description}
Format each question as a Python dictionary with the following structure:
{{
"question": "Question text here",
"options": ["A) option1", "B) option2", "C) option3", "D) option4"],
"correct_option": "A" or "B" or "C" or "D"
}}
Generate challenging but clear questions.
Return only the Python list of dictionaries without any additional formatting or markers
Do not write any other text, do not start the response with (```python), do not end the response with backticks(```)
A Sample response should look like this: Response Text: [
{
"question": "Which of the following is NOT a valid data type in C++?",
"options": ["int", "double", "boolean", "char"],
"correct_option": "C"
}
] (Notice that there are no backticks(```) around the response and no (```python))
.
"""
response = model.generate_content(prompt)
response_text = response.text.strip()
print("Response Text:", response_text)
modified_response_text = strip_code_markers(response_text)
print("Response Text Modified to:", modified_response_text)
# Extract and parse the response to get the list of MCQs
mcqs = ast.literal_eval(modified_response_text) # Be careful with eval, consider using ast.literal_eval for production
print(mcqs)
if not mcqs:
raise ValueError("No questions generated")
return mcqs
except Exception as e:
print(f"Error generating MCQs: , error: {e}")
return None
# New function to save quiz to database
def save_quiz(course_id, session_id, title, questions, user_id):
"""Save quiz to database"""
try:
quiz_data = {
"user_id": user_id,
"course_id": course_id,
"session_id": session_id,
"title": title,
"questions": questions,
"created_at": datetime.utcnow(),
"status": "active",
"submissions": []
}
result = quizzes_collection.insert_one(quiz_data)
return result.inserted_id
except Exception as e:
print(f"Error saving quiz: {e}")
return None
def get_student_quiz_score(quiz_id, student_id):
"""Get student's score for a specific quiz"""
quiz = quizzes_collection.find_one(
{
"_id": quiz_id,
"submissions.student_id": student_id
},
{"submissions.$": 1}
)
if quiz and quiz.get('submissions'):
return quiz['submissions'][0].get('score')
return None
# def submit_quiz_answers(quiz_id, student_id, student_answers):
# """Submit and score student's quiz answers"""
# quiz = quizzes_collection.find_one({"_id": quiz_id})
# if not quiz:
# return None
# # Calculate score
# correct_answers = 0
# total_questions = len(quiz['questions'])
# for q_idx, question in enumerate(quiz['questions']):
# if student_answers.get(str(q_idx)) == question['correct_option']:
# correct_answers += 1
# score = (correct_answers / total_questions) * 100
# # Store submission
# submission_data = {
# "student_id": student_id,
# "answers": student_answers,
# "score": score,
# "submitted_at": datetime.utcnow()
# }
# # Update quiz with submission
# quizzes_collection.update_one(
# {"_id": quiz_id},
# {
# "$push": {"submissions": submission_data}
# }
# )
# return score
def submit_quiz_answers(quiz_id, student_id, student_answers):
"""Submit and score student's quiz answers"""
try:
quiz = quizzes_collection.find_one({"_id": quiz_id})
if not quiz:
return None
# Calculate score
correct_answers = 0
total_questions = len(quiz['questions'])
for q_idx, question in enumerate(quiz['questions']):
student_answer = student_answers.get(str(q_idx))
if student_answer: # Only check if answer was provided
# Extract the option letter (A, B, C, D) from the full answer string
answer_letter = student_answer.split(')')[0].strip()
if answer_letter == question['correct_option']:
correct_answers += 1
score = (correct_answers / total_questions) * 100
# Store submission
submission_data = {
"student_id": student_id,
"answers": student_answers,
"score": score,
"submitted_at": datetime.utcnow()
}
# Update quiz with submission
result = quizzes_collection.update_one(
{"_id": quiz_id},
{"$push": {"submissions": submission_data}}
)
return score if result.modified_count > 0 else None
except Exception as e:
print(f"Error submitting quiz: {e}")
return None