Spaces:
Sleeping
Sleeping
File size: 8,970 Bytes
7043517 e6ee63c d86cfde edfedcd 77249ba 243e367 123020a 77249ba 1fa4c2c 77249ba 7043517 77249ba f9bf840 123020a 77249ba 123020a 77249ba 123020a 7043517 a38f03b 123020a b0cde20 962359a 1fa4c2c 77249ba 1fa4c2c 77249ba 962359a 1fa4c2c 962359a 77249ba 962359a 1fa4c2c 962359a 77249ba 1fa4c2c 77249ba 962359a 77249ba 962359a 77249ba 962359a b0cde20 962359a 1fa4c2c 962359a f9bf840 7043517 123020a 1fa4c2c 77249ba 1fa4c2c f9bf840 e388377 1fa4c2c 7043517 77249ba 39b312d 7274e3e 1fa4c2c e388377 77249ba 7043517 f9bf840 7043517 adb6a76 f9bf840 1fa4c2c 7043517 d65d305 1fa4c2c 77249ba 1fa4c2c f9bf840 e388377 1fa4c2c 7043517 f9bf840 7043517 f9bf840 d841cf3 43f4955 77249ba a38f03b 43f4955 b0cde20 42706d1 1fa4c2c 7043517 a38f03b d841cf3 1fa4c2c 7043517 72c1126 1fa4c2c 7043517 1fa4c2c 7043517 1fa4c2c 77249ba |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 |
from typing import List, Dict, Any
from dataclasses import dataclass, field
from datetime import datetime
import json
import os
from langchain_community.chat_models import ChatOpenAI
from langchain_community.embeddings import OpenAIEmbeddings
from langchain_community.vectorstores import FAISS
import streamlit as st
import logging
# Set up logging for debugging purposes
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')
@dataclass
class Section:
title: str
content: str = ""
key_points: List[str] = field(default_factory=list)
examples: List[str] = field(default_factory=list)
quiz_questions: List[Dict[str, Any]] = field(default_factory=list)
is_complete: bool = False
@dataclass
class CourseModule:
title: str
objectives: List[str]
prerequisites: List[str] = field(default_factory=list)
sections: List[Section] = field(default_factory=list)
is_complete: bool = False
@dataclass
class LearningPath:
topic: str
description: str
modules: List[CourseModule]
difficulty_level: str
created_at: datetime
is_generating: bool = True
class CoursePrompts:
@staticmethod
def course_planning_prompt() -> str:
return """As a course planning expert, design a structured learning path for {topic} at {difficulty} level.
Requirements:
1. 5-7 progressive modules
2. Clear prerequisites and objectives
3. Practical applications
4. Real-world examples
5. A compelling description that excites the learner about the journey ahead
6. Each module should contain content, quiz questions, and be designed to progressively enhance understanding.
Return a structured JSON with detailed content for each module.
"""
@staticmethod
def module_content_prompt() -> str:
return """Create engaging module content for the module titled '{title}' with the following objectives:
Objectives: {objectives}
Include:
1. Clear explanations with practical examples to deepen understanding
2. Real-world applications relevant to the topic
3. Key points that summarize each section concisely
4. A set of 3-5 quiz questions for each section, with answers and explanations
5. Encourage learners to think critically and ask questions related to '{title}'
Return a structured JSON with detailed content for each section.
"""
@staticmethod
def user_question_prompt() -> str:
return """As an AI assistant, provide a clear and informative answer to the user's question based on the course topic '{topic}', the module '{module_title}', and the related content.
User Question: {question}
Ensure your response is helpful, easy to understand, and relevant to the course content.
"""
class CourseBuilder:
def __init__(self, api_key: str):
self.api_key = api_key
self.llm = ChatOpenAI(
temperature=0.7,
model="gpt-4",
openai_api_key=api_key
)
self.embeddings = OpenAIEmbeddings(openai_api_key=api_key)
self.vector_store = FAISS.from_texts(
["Initial course content"],
embedding=self.embeddings
)
self.prompts = CoursePrompts()
async def plan_course(self, topic: str, difficulty: str) -> LearningPath:
prompt = self.prompts.course_planning_prompt().format(topic=topic, difficulty=difficulty)
logging.debug(f"Sending course planning prompt: {prompt}")
response = await self.llm.apredict(prompt)
logging.debug(f"Received response for course planning: {response}")
# Debug: Log the raw response for troubleshooting
if not response.strip():
logging.error("Empty response from API")
raise ValueError("Empty response from API")
try:
course_plan = json.loads(response)
except json.JSONDecodeError as e:
logging.error(f"Invalid JSON response from API: {str(e)}\nResponse: {response}")
raise ValueError(f"Invalid JSON response from API: {str(e)}\nResponse: {response}")
modules = [
CourseModule(
title=module["title"],
objectives=module.get("objectives", []),
prerequisites=module.get("prerequisites", []),
sections=[
Section(
title=section["title"],
content=section.get("content", ""),
key_points=section.get("key_points", []),
examples=section.get("examples", []),
quiz_questions=section.get("quiz_questions", [])
) for section in module.get("sections", [])
]
) for module in course_plan.get("modules", [])
]
learning_path = LearningPath(
topic=topic,
description=course_plan.get("description", ""),
modules=modules,
difficulty_level=difficulty,
created_at=datetime.now(),
is_generating=False
)
# Store embeddings for course plan for future reference
self.vector_store.add_texts(
[json.dumps(course_plan)],
metadatas=[{"type": "course_plan", "topic": topic}]
)
logging.info(f"Created learning path for topic '{topic}' with difficulty '{difficulty}'")
return learning_path
async def create_module_content(self, module: CourseModule) -> List[Section]:
prompt = self.prompts.module_content_prompt().format(
title=module.title,
objectives=", ".join(module.objectives)
)
logging.debug(f"Sending module content prompt: {prompt}")
response = await self.llm.apredict(prompt)
logging.debug(f"Received response for module content: {response}")
if not response.strip():
logging.error("Empty response from API")
raise ValueError("Empty response from API")
try:
content_json = json.loads(response)
except json.JSONDecodeError as e:
logging.error(f"Invalid JSON response from API: {str(e)}\nResponse: {response}")
raise ValueError(f"Invalid JSON response from API: {str(e)}\nResponse: {response}")
sections = [Section(**section) for section in content_json.get("sections", [])]
# Store embeddings for module content
for section in sections:
self.vector_store.add_texts(
[section.content],
metadatas=[{"type": "module_content", "module": module.title}]
)
logging.info(f"Created {len(sections)} sections for module: {module.title}")
return sections
async def answer_user_question(self, topic: str, module_title: str, question: str) -> str:
prompt = self.prompts.user_question_prompt().format(
topic=topic,
module_title=module_title,
question=question
)
logging.debug(f"Sending user question prompt: {prompt}")
response = await self.llm.apredict(prompt)
logging.debug(f"Received response for user question: {response}")
if not response.strip():
logging.error("Empty response from API")
raise ValueError("Empty response from API")
return response
class LearningPlatform:
def __init__(self, api_key: str = None):
self.api_key = api_key or os.getenv("OPENAI_API_KEY")
self.course_builder = CourseBuilder(self.api_key)
async def create_course(self, topic: str, difficulty: str) -> LearningPath:
try:
learning_path = await self.course_builder.plan_course(topic, difficulty)
return learning_path
except Exception as e:
logging.error(f"Course creation error: {str(e)}")
raise Exception(f"Course creation error: {str(e)}")
async def generate_next_module(self, path: LearningPath, module_index: int):
if module_index < len(path.modules):
module = path.modules[module_index]
if not module.is_complete:
logging.info(f"Generating content for module: {module.title}")
sections = await self.course_builder.create_module_content(module)
module.sections = sections
module.is_complete = True
logging.info(f"Module '{module.title}' is now complete.")
async def handle_user_question(self, path: LearningPath, module_index: int, question: str) -> str:
if module_index < len(path.modules):
module = path.modules[module_index]
logging.info(f"Answering user question for module: {module.title}")
answer = await self.course_builder.answer_user_question(path.topic, module.title, question)
return answer
else:
logging.error(f"Invalid module index: {module_index}")
raise ValueError("Invalid module index")
|