from datetime import datetime, timedelta, date | |
import os | |
from typing import Dict, List, Any | |
from pymongo import MongoClient | |
import requests | |
import uuid | |
import openai | |
from openai import OpenAI | |
import streamlit as st | |
from bson import ObjectId | |
from dotenv import load_dotenv | |
import json | |
load_dotenv() | |
MONGODB_URI = os.getenv("MONGO_URI") | |
PERPLEXITY_API_KEY = os.getenv("PERPLEXITY_KEY") | |
OPENAI_API_KEY = os.getenv("OPENAI_KEY") | |
client = MongoClient(MONGODB_URI) | |
db = client['novascholar_db'] | |
courses_collection = db['courses'] | |
faculty_collection = db['faculty'] | |
def generate_perplexity_response(api_key, course_name): | |
headers = { | |
"accept": "application/json", | |
"content-type": "application/json", | |
"authorization": f"Bearer {api_key}" | |
} | |
prompt = f""" | |
You are an expert educational AI assistant specializing in curriculum design and instructional planning. Your task is to generate comprehensive, academically rigorous course structures for undergraduate level education. | |
Please generate a detailed course structure for the course {course_name} in JSON format following these specifications: | |
1. The course structure should be appropriate for a full semester (14-16 weeks) | |
2. Each module should be designed for 2-4 weeks of instruction | |
3. Follow standard academic practices and nomenclature | |
4. Ensure progressive complexity from foundational to advanced concepts | |
5. The course_title should exactly match the course name provided in the prompt. No additional information should be included in the course_title field. | |
6: Ensure that the property names are enclosed in double quotes (") and followed by a colon (:), and the values are enclosed in double quotes ("). | |
7. **DO NOT INCLUDE THE WORD JSON IN THE OUTPUT STRING, DO NOT INCLUDE BACKTICKS (```) IN THE OUTPUT, AND DO NOT INCLUDE ANY OTHER TEXT, OTHER THAN THE ACTUAL JSON RESPONSE. START THE RESPONSE STRING WITH AN OPEN CURLY BRACE {{ AND END WITH A CLOSING CURLY BRACE }}.** | |
The JSON response should follow this structure: | |
{{ | |
"course_title": "string", | |
"course_description": "string", | |
"modules": [ | |
{{ | |
"module_title": "string", | |
"sub_modules": [ | |
{{ | |
"title": "string", | |
"topics": [string], | |
}} | |
] | |
}} | |
] | |
}} | |
Example response: | |
{{ | |
"course_title": "Advanced Natural Language Processing", | |
"course_descriptio": "An advanced course covering modern approaches to NLP using deep learning, with focus on transformer architectures and their applications.", | |
"modules": [ | |
{{ | |
"module_title": "Foundations of Modern NLP", | |
"sub_modules": [ | |
{{ | |
"title": "Attention Mechanism", | |
"topics": [ | |
"Self-attention", | |
"Multi-head attention", | |
"Positional encoding" | |
] | |
}} | |
] | |
}} | |
] | |
}} | |
""" | |
messages = [ | |
{ | |
"role": "system", | |
"content": ( | |
"You are an expert educational AI assistant specializing in course design and curriculum planning. " | |
"Your task is to generate accurate, detailed, and structured educational content for undergraduate-level and post-graduate-level courses. " | |
"Provide detailed and accurate information tailored to the user's prompt." | |
"Ensure that the responses are logical, follow standard academic practices, and include realistic concepts relevant to the course." | |
), | |
}, | |
{ | |
"role": "user", | |
"content": prompt | |
}, | |
] | |
try: | |
client = OpenAI(api_key=api_key, base_url="https://api.perplexity.ai") | |
response = client.chat.completions.create( | |
model="llama-3.1-sonar-small-128k-online", | |
messages=messages | |
) | |
content = response.choices[0].message.content | |
return content | |
except Exception as e: | |
st.error(f"Failed to fetch data from Perplexity API: {e}") | |
return "" | |
def get_new_course_id(): | |
"""Generate a new course ID by incrementing the last course ID""" | |
last_course = courses_collection.find_one(sort=[("course_id", -1)]) | |
if last_course: | |
last_course_id = int(last_course["course_id"][2:]) | |
new_course_id = f"CS{last_course_id + 1}" | |
else: | |
new_course_id = "CS101" | |
return new_course_id | |
def create_course_perplexity(course_name, start_date, duration_weeks): | |
# Generate course overview | |
# overview_prompt = f"""Generate an overview for the undergraduate course {course_name} | |
# Include all relevant concepts and key topics covered in a typical curriculum. | |
# The response should be concise (300-400 words). Ensure that your response is in a valid JSON format.""" | |
# overview_prompt2 = f"""Generate an overview for the undergraduate course {course_name}. | |
# The overview should include: | |
# The course title, a detailed course description, | |
# a division of all relevant concepts and key topics into 4-6 logical modules, | |
# capturing the flow and structure of a typical curriculum. | |
# Ensure the response adheres to the following JSON format: | |
# {{ | |
# 'overview': 'string', | |
# 'modules': [ | |
# {{ | |
# 'name': 'string', | |
# 'description': 'string' | |
# }} | |
# ] | |
# }} | |
# overview: A detailed description of the course. | |
# modules: An array of 4-6 objects, each representing a logical module with a name and a brief description | |
# **DO NOT INCLUDE THE WORD JSON IN THE OUTPUT STRING, DO NOT INCLUDE BACKTICKS (```) IN THE OUTPUT, AND DO NOT INCLUDE ANY OTHER TEXT, OTHER THAN THE ACTUAL JSON RESPONSE. START THE RESPONSE STRING WITH AN OPEN CURLY BRACE {{ AND END WITH A CLOSING CURLY BRACE }}""" | |
# course_overview = generate_perplexity_response(PERPLEXITY_API_KEY, overview_prompt2) | |
# # print(course_overview) | |
# course_overview_store = course_overview | |
# # print(course_overview_store) | |
# # Generate modules | |
# # modules_prompt = f"Based on this overview: {course_overview}\nCreate 4-6 logical modules for the course, each module should group related concepts and each module may include reference books if applicable" | |
# sub_modules_prompt = f"""Using the provided modules in the overview {course_overview_store}, generate 2-3 submodules for each module. | |
# Each submodule should represent a cohesive subset of the module's topics, logically organized for teaching purposes. | |
# Ensure the response adheres to the following JSON format: | |
# { | |
# 'modules': [ | |
# { | |
# 'name': 'string', | |
# 'sub_modules': [ | |
# { | |
# 'name': 'string', | |
# 'description': 'string' | |
# } | |
# ] | |
# } | |
# ] | |
# } | |
# modules: An array where each object contains the name of the module and its corresponding sub_modules. | |
# sub_modules: An array of 2-3 objects for each module, each having a name and a brief description." | |
# **DO NOT INCLUDE THE WORD JSON IN THE OUTPUT STRING, DO NOT INCLUDE BACKTICKS (```) IN THE OUTPUT, AND DO NOT INCLUDE ANY OTHER TEXT, OTHER THAN THE ACTUAL JSON RESPONSE. START THE RESPONSE STRING WITH AN OPEN CURLY BRACE {{ AND END WITH A CLOSING CURLY BRACE }} | |
# """ | |
# sub_modules = generate_perplexity_response(PERPLEXITY_API_KEY, sub_modules_prompt) | |
# # modules_response = generate_perplexity_response(modules_prompt) | |
# print(sub_modules) | |
# total_sessions = duration_weeks * sessions_per_week | |
course_plan = generate_perplexity_response(PERPLEXITY_API_KEY, course_name) | |
course_plan_json = json.loads(course_plan) | |
# Generate sessions for each module | |
all_sessions = [] | |
for module in course_plan_json['modules']: | |
for sub_module in module['sub_modules']: | |
for topic in sub_module['topics']: | |
session = create_session( | |
title=topic, | |
date=start_date, | |
module_name=module['module_title'] | |
) | |
# print(session) | |
all_sessions.append(session) | |
start_date += timedelta(days=7) # Next session after a week | |
# sample_sessions = [ | |
# {'session_id': ObjectId('6767d0bbad8316ac358def25'), 'title': 'What is Generative AI?', 'date': datetime(2024, 12, 22, 14, 11, 27, 153899), 'status': 'upcoming', 'created_at': datetime(2024, 12, 22, 8, 41, 31, 504599), 'pre_class': {'resources': [], 'completion_required': True}, 'in_class': {'quiz': [], 'polls': []}, 'post_class': {'assignments': []}}, | |
# {'session_id': ObjectId('6767d0bbad8316ac358def26'), 'title': 'History and Evolution of AI', 'date': datetime(2024, 12, 29, 14, 11, 27, 153899), 'status': 'upcoming', 'created_at': datetime(2024, 12, 22, 8, 41, 31, 504599), 'pre_class': {'resources': [], 'completion_required': True}, 'in_class': {'quiz': [], 'polls': []}, 'post_class': {'assignments': []}}, | |
# {'session_id': ObjectId('6767d0bbad8316ac358def27'), 'title': 'Types of Generative AI (e.g., GANs, VAEs, LLMs)', 'date': datetime(2025, 1, 5, 14, 11, 27, 153899), 'status': 'upcoming', 'created_at': datetime(2024, 12, 22, 8, 41, 31, 505626), 'pre_class': {'resources': [], 'completion_required': True}, 'in_class': {'quiz': [], 'polls': []}, 'post_class': {'assignments': []}}, | |
# {'session_id': ObjectId('6767d0bbad8316ac358def28'), 'title': 'Overview of popular GenAI tools (e.g., ChatGPT, Claude, Google Gemini)', 'date': datetime(2025, 1, 12, 14, 11, 27, 153899), 'status': 'upcoming', 'created_at': datetime(2024, 12, 22, 8, 41, 31, 506559), 'pre_class': {'resources': [], 'completion_required': True}, 'in_class': {'quiz': [], 'polls': []}, 'post_class': {'assignments': []}}, | |
# {'session_id': ObjectId('6767d0bbad8316ac358def29'), 'title': 'Frameworks for building GenAI models (e.g., TensorFlow, PyTorch)', 'date': datetime(2025, 1, 19, 14, 11, 27, 153899), 'status': 'upcoming', 'created_at': datetime(2024, 12, 22, 8, 41, 31, 506559), 'pre_class': {'resources': [], 'completion_required': True}, 'in_class': {'quiz': [], 'polls': []}, 'post_class': {'assignments': []}}, | |
# {'session_id': ObjectId('6767d0bbad8316ac358def2a'), 'title': 'Integration with other AI technologies', 'date': datetime(2025, 1, 26, 14, 11, 27, 153899), 'status': 'upcoming', 'created_at': datetime(2024, 12, 22, 8, 41, 31, 507612), 'pre_class': {'resources': [], 'completion_required': True}, 'in_class': {'quiz': [], 'polls': []}, 'post_class': {'assignments': []}}, | |
# {'session_id': ObjectId('6767d0bbad8316ac358def2b'), 'title': 'Text-to-text models (e.g., GPT-3, BERT)', 'date': datetime(2025, 2, 2, 14, 11, 27, 153899), 'status': 'upcoming', 'created_at': datetime(2024, 12, 22, 8, 41, 31, 508512), 'pre_class': {'resources': [], 'completion_required': True}, 'in_class': {'quiz': [], 'polls': []}, 'post_class': {'assignments': []}}, | |
# {'session_id': ObjectId('6767d0bbad8316ac358def2c'), 'title': 'Text generation for content creation and marketing', 'date': datetime(2025, 2, 9, 14, 11, 27, 153899), 'status': 'upcoming', 'created_at': datetime(2024, 12, 22, 8, 41, 31, 508512), 'pre_class': {'resources': [], 'completion_required': True}, 'in_class': {'quiz': [], 'polls': []}, 'post_class': {'assignments': []}}, | |
# {'session_id': ObjectId('6767d0bbad8316ac358def2d'), 'title': 'Chatbots and conversational interfaces', 'date': datetime(2025, 2, 16, 14, 11, 27, 153899), 'status': 'upcoming', 'created_at': datetime(2024, 12, 22, 8, 41, 31, 509612), 'pre_class': {'resources': [], 'completion_required': True}, 'in_class': {'quiz': [], 'polls': []}, 'post_class': {'assignments': []}}, | |
# {'session_id': ObjectId('6767d0bbad8316ac358def2e'), 'title': 'Generative Adversarial Networks (GANs)', 'date': datetime(2025, 2, 23, 14, 11, 27, 153899), 'status': 'upcoming', 'created_at': datetime(2024, 12, 22, 8, 41, 31, 509612), 'pre_class': {'resources': [], 'completion_required': True}, 'in_class': {'quiz': [], 'polls': []}, 'post_class': {'assignments': []}}, | |
# {'session_id': ObjectId('6767d0bbad8316ac358def2f'), 'title': 'Variational Autoencoders (VAEs)', 'date': datetime(2025, 3, 2, 14, 11, 27, 153899), 'status': 'upcoming', 'created_at': datetime(2024, 12, 22, 8, 41, 31, 510612), 'pre_class': {'resources': [], 'completion_required': True}, 'in_class': {'quiz': [], 'polls': []}, 'post_class': {'assignments': []}}, | |
# {'session_id': ObjectId('6767d0bbad8316ac358def30'), 'title': 'Applications in art, design, and media', 'date': datetime(2025, 3, 9, 14, 11, 27, 153899), 'status': 'upcoming', 'created_at': datetime(2024, 12, 22, 8, 41, 31, 511497), 'pre_class': {'resources': [], 'completion_required': True}, 'in_class': {'quiz': [], 'polls': []}, 'post_class': {'assignments': []}}, | |
# {'session_id': ObjectId('6767d0bbad8316ac358def31'), 'title': 'Understanding prompt design principles', 'date': datetime(2025, 3, 16, 14, 11, 27, 153899), 'status': 'upcoming', 'created_at': datetime(2024, 12, 22, 8, 41, 31, 511497), 'pre_class': {'resources': [], 'completion_required': True}, 'in_class': {'quiz': [], 'polls': []}, 'post_class': {'assignments': []}}, | |
# {'session_id': ObjectId('6767d0bbad8316ac358def33'), 'title': 'Advanced techniques for fine-tuning models', 'date': datetime(2025, 3, 30, 14, 11, 27, 153899), 'status': 'upcoming', 'created_at': datetime(2024, 12, 22, 8, 41, 31, 512514), 'pre_class': {'resources': [], 'completion_required': True}, 'in_class': {'quiz': [], 'polls': []}, 'post_class': {'assignments': []}}, | |
# {'session_id': ObjectId('6767d0bbad8316ac358def34'), 'title': 'Ethical implications of AI-generated content', 'date': datetime(2025, 4, 6, 14, 11, 27, 153899), 'status': 'upcoming', 'created_at': datetime(2024, 12, 22, 8, 41, 31, 513613), 'pre_class': {'resources': [], 'completion_required': True}, 'in_class': {'quiz': [], 'polls': []}, 'post_class': {'assignments': []}}, | |
# {'session_id': ObjectId('6767d0bbad8316ac358def35'), 'title': 'Addressing bias in AI models', 'date': datetime(2025, 4, 13, 14, 11, 27, 153899), 'status': 'upcoming', 'created_at': datetime(2024, 12, 22, 8, 41, 31, 514639), 'pre_class': {'resources': [], 'completion_required': True}, 'in_class': {'quiz': [], 'polls': []}, 'post_class': {'assignments': []}}, | |
# {'session_id': ObjectId('6767d0bbad8316ac358def36'), 'title': 'Regulatory frameworks and guidelines', 'date': datetime(2025, 4, 20, 14, 11, 27, 153899), 'status': 'upcoming', 'created_at': datetime(2024, 12, 22, 8, 41, 31, 514639), 'pre_class': {'resources': [], 'completion_required': True}, 'in_class': {'quiz': [], 'polls': []}, 'post_class': {'assignments': []}}, | |
# {'session_id': ObjectId('6767d0bbad8316ac358def37'), 'title': 'Case studies from various industries (e.g., marketing, healthcare, finance)', 'date': datetime(2025, 4, 27, 14, 11, 27, 153899), 'status': 'upcoming', 'created_at': datetime(2024, 12, 22, 8, 41, 31, 515610), 'pre_class': {'resources': [], 'completion_required': True}, 'in_class': {'quiz': [], 'polls': []}, 'post_class': {'assignments': []}}, | |
# {'session_id': ObjectId('6767d0bbad8316ac358def38'), 'title': 'Success stories and challenges faced by companies using GenAI', 'date': datetime(2025, 5, 4, 14, 11, 27, 153899), 'status': 'upcoming', 'created_at': datetime(2024, 12, 22, 8, 41, 31, 515610), 'pre_class': {'resources': [], 'completion_required': True}, 'in_class': {'quiz': [], 'polls': []}, 'post_class': {'assignments': []}}, | |
# {'session_id': ObjectId('6767d0bbad8316ac358def39'), 'title': 'Guidelines for developing a GenAI project', 'date': datetime(2025, 5, 11, 14, 11, 27, 153899), 'status': 'upcoming', 'created_at': datetime(2024, 12, 22, 8, 41, 31, 516614), 'pre_class': {'resources': [], 'completion_required': True}, 'in_class': {'quiz': [], 'polls': []}, 'post_class': {'assignments': []}}, | |
# {'session_id': ObjectId('6767d0bbad8316ac358def3a'), 'title': 'Tools and resources for project implementation', 'date': datetime(2025, 5, 18, 14, 11, 27, 153899), 'status': 'upcoming', 'created_at': datetime(2024, 12, 22, 8, 41, 31, 516614), 'pre_class': {'resources': [], 'completion_required': True}, 'in_class': {'quiz': [], 'polls': []}, 'post_class': {'assignments': []}}, | |
# {'session_id': ObjectId('6767d0bbad8316ac358def3b'), 'title': 'Best practices for testing and deployment', 'date': datetime(2025, 5, 25, 14, 11, 27, 153899), 'status': 'upcoming', 'created_at': datetime(2024, 12, 22, 8, 41, 31, 517563), 'pre_class': {'resources': [], 'completion_required': True}, 'in_class': {'quiz': [], 'polls': []}, 'post_class': {'assignments': []}} | |
# ] | |
# small_sample_sessions = [ | |
# {'session_id': ObjectId('6767d0bbad8316ac358def25'), 'title': 'What is Generative AI?', 'date': datetime(2024, 12, 22, 14, 11, 27, 153899), 'status': 'upcoming', 'created_at': datetime(2024, 12, 22, 8, 41, 31, 504599), 'pre_class': {'resources': [], 'completion_required': True}, 'in_class': {'quiz': [], 'polls': []}, 'post_class': {'assignments': []}}, | |
# {'session_id': ObjectId('6767d0bbad8316ac358def26'), 'title': 'History and Evolution of AI', 'date': datetime(2024, 12, 29, 14, 11, 27, 153899), 'status': 'upcoming', 'created_at': datetime(2024, 12, 22, 8, 41, 31, 504599), 'pre_class': {'resources': [], 'completion_required': True}, 'in_class': {'quiz': [], 'polls': []}, 'post_class': {'assignments': []}}, | |
# ] | |
# print(all_sessions) | |
print("Number of sessions:", len(all_sessions)) | |
# Create course document | |
# course_description = course_plan_json['course_description'] | |
# course_doc = { | |
# "course_id": get_new_course_id(), | |
# "title": course_name, | |
# "description": course_description, | |
# "faculty": faculty_name, | |
# "faculty_id": faculty_id, | |
# "duration": f"{duration_weeks} weeks", | |
# "created_at": datetime.utcnow(), | |
# "sessions": all_sessions | |
# } | |
# try: | |
# courses_collection.insert_one(course_doc) | |
# except Exception as e: | |
# st.error(f"Failed to insert course data into the database: {e}") | |
# print(course_plan) | |
def create_course(course_name, duration_weeks, faculty_name, sessions_per_week, start_date: date, course_description, faculty_id): | |
""" | |
Create a course document in the desired JSON format and insert it into MongoDB. | |
""" | |
try: | |
# Count sessions | |
# st.write("Number of sessions:", len(all_sessions) | |
# Generate a new course ID | |
course_id = get_new_course_id() | |
if isinstance(start_date, date): | |
start_date = datetime.combine(start_date, datetime.min.time()) | |
# Create the course document | |
course_doc = { | |
"_id": ObjectId(), | |
"course_id": course_id, # Assumes there's a helper function in your code | |
"title": course_name, | |
"description": course_description, | |
"faculty": faculty_name, | |
"faculty_id": faculty_id, | |
"duration": f"{duration_weeks} weeks", | |
"sessions_per_week": sessions_per_week, | |
"start_date": start_date, | |
"created_at": datetime.utcnow(), | |
} | |
# Insert into MongoDB | |
courses_collection.insert_one(course_doc) | |
faculty_collection.update_one( | |
{"_id": st.session_state.user_id}, | |
{ | |
"$push": { | |
"courses_taught": { | |
"course_id": course_id, | |
"title": course_name, | |
} | |
} | |
} | |
) | |
st.success("Course created successfully!") | |
# st.json(course_doc) | |
return course_doc | |
except Exception as e: | |
st.error(f"Failed to insert course data into the database: {e}") | |
return None | |
def create_session(title: str, date: datetime, module_name: str): | |
"""Create a session document with pre-class, in-class, and post-class components.""" | |
return { | |
"session_id": ObjectId(), | |
"title": title, | |
"date": date, | |
"status": "upcoming", | |
"created_at": datetime.utcnow(), | |
"pre_class": { | |
"resources": [], | |
"completion_required": True | |
}, | |
"in_class": { | |
"quiz": [], | |
"polls": [] | |
}, | |
"post_class": { | |
"assignments": [] | |
} | |
} | |
# Usage example: | |
if __name__ == "__main__": | |
create_course("Introduction to Data Analytics", datetime.now(), 2) |