cryogenic22 commited on
Commit
edfedcd
·
verified ·
1 Parent(s): 8182147

Update learning_platform.py

Browse files
Files changed (1) hide show
  1. learning_platform.py +84 -103
learning_platform.py CHANGED
@@ -1,14 +1,20 @@
1
- import asyncio
2
- import json
3
  from dataclasses import dataclass, field
4
  from datetime import datetime
5
- from typing import List, Dict, Any, Literal
 
 
 
 
 
 
 
6
 
7
- import faiss # Example for vector store
8
- from langchain.chat_models import ChatOpenAI
9
- from langchain.embeddings import OpenAIEmbeddings # Example for embeddings
10
- from langgraph.graph import StateGraph, END
11
 
 
 
 
12
 
13
  @dataclass
14
  class Section:
@@ -18,7 +24,6 @@ class Section:
18
  quiz_questions: List[Dict[str, Any]] = field(default_factory=list)
19
  is_complete: bool = False
20
 
21
-
22
  @dataclass
23
  class LearningModule:
24
  title: str
@@ -29,7 +34,6 @@ class LearningModule:
29
  learning_objectives: List[str] = field(default_factory=list)
30
  is_complete: bool = False
31
 
32
-
33
  @dataclass
34
  class LearningPath:
35
  topic: str
@@ -39,7 +43,6 @@ class LearningPath:
39
  difficulty_level: str
40
  is_generating: bool = True
41
 
42
-
43
  @dataclass
44
  class CourseState:
45
  topic: str
@@ -49,25 +52,31 @@ class CourseState:
49
  sections: List[Dict] = field(default_factory=list)
50
  error: str = ""
51
 
52
-
53
  class Config:
54
  def __init__(self):
55
  self.llm_config = {
56
  "temperature": 0.7,
57
- "model": "gpt-4o", # Or another model if you don't have access to gpt-4o
58
  "max_tokens": 2000
59
  }
60
-
61
  self.graph_config = {
62
  "recursion_limit": 25,
63
  "max_retries": 3,
64
  "timeout": 300
65
  }
 
 
 
 
 
 
66
  self.course_defaults = {
67
- "max_modules": 5
 
 
68
  }
69
 
70
-
71
  class CoursePrompts:
72
  @staticmethod
73
  def planning_prompt() -> str:
@@ -77,102 +86,84 @@ Structure:
77
  - Clear learning objectives
78
  - Practical applications
79
  Return JSON array of:
80
- {{
81
  "title": "module title",
82
  "objectives": ["objective1", "objective2"],
83
  "prerequisites": ["prereq1", "prereq2"]
84
- }}"""
85
 
86
  @staticmethod
87
  def content_prompt() -> str:
88
  return """Create engaging content for {module_title}:
89
- - Start with a hook
90
  - Include code examples
91
  - Real-world applications
92
  - Best practices
93
  Return JSON:
94
- {{
95
  "content": "main content",
96
  "key_points": ["point1", "point2"],
97
- "details": {{
98
  "section1": "detailed content",
99
  "section2": "detailed content"
100
- }}
101
- }}"""
102
 
103
  @staticmethod
104
  def assessment_prompt() -> str:
105
- return """Create an assessment for {module_title}.
106
  Include:
107
  - Practical scenarios
108
  - Code challenges
109
  - Concept validation
110
- Return a JSON array of:
111
- {{
112
  "question": "text",
113
  "options": ["A", "B", "C", "D"],
114
  "correct_answer": "A",
115
  "explanation": "detailed explanation"
116
- }}"""
117
-
118
 
119
  class CourseBuilder:
120
- def __init__(self, api_key=None, config: Config = None):
121
- if api_key:
122
- self.api_key = api_key
 
 
123
  else:
124
- self.api_key = os.environ.get('OPENAI_API_KEY')
125
- if not self.api_key:
126
- print("[DEBUG] API key is not set. Please ensure OPENAI_API_KEY is available in the environment.")
127
- else:
128
- print(f"[DEBUG] Using API key: {self.api_key[:4]}... (truncated for security)")
129
  self.config = config or Config()
130
- self.llm = ChatOpenAI(model=self.config.llm_config["model"],
131
- temperature=self.config.llm_config["temperature"],
132
- max_tokens=self.config.llm_config["max_tokens"])
133
-
134
- # Corrected instantiation of OpenAIEmbeddings
135
- self.embeddings = OpenAIEmbeddings(openai_api_key=self.api_key)
136
-
137
- # Example FAISS initialization for vector store (if needed)
138
- self.vector_store = faiss.IndexFlatL2(128)
139
- self.setup_graph()
140
-
141
- def setup_graph(self):
142
- workflow = StateGraph(CourseState)
143
- workflow.add_node("plan_course", self.plan_course)
144
- workflow.add_node("create_module", self.create_module)
145
- workflow.add_node("generate_content", self.generate_content)
146
- workflow.add_node("create_assessment", self.create_assessment)
147
-
148
- workflow.add_edge("plan_course", "create_module")
149
- workflow.add_conditional_edge("create_module", "generate_content", self.has_modules) # Conditional edge
150
- workflow.add_edge("generate_content", "create_assessment")
151
- workflow.add_conditional_edge("create_assessment", "create_module", self.has_modules) # Loop back
152
- workflow.add_edge("create_assessment", END) # Final end
153
-
154
- self.graph = workflow.compile()
155
-
156
- def has_modules(self, state: CourseState) -> Literal["generate_content", "create_module", "__end__"]:
157
- if state.modules:
158
- if state.current_module:
159
- return "create_module" # Go to next module
160
- else:
161
- return "generate_content" # Start first module
162
- else:
163
- return END # No more modules
164
 
165
  async def generate_with_retry(self, prompt: str, variables: Dict) -> Any:
 
166
  print(f"[DEBUG] Generating text with prompt: {prompt.format(**variables)}")
167
  for attempt in range(self.config.graph_config["max_retries"]):
168
  try:
169
- response = await self.llm.agenerate(
170
- [prompt.format(**variables)]
 
 
 
 
 
171
  )
172
- result = response.generations[0][0].text
173
  return json.loads(result)
174
- except json.JSONDecodeError as e:
175
- print(f"[DEBUG] Invalid JSON received, retrying. Error: {e}")
176
  except Exception as e:
177
  print(f"[DEBUG] Error occurred during attempt {attempt + 1}: {e}")
178
  if attempt == self.config.graph_config["max_retries"] - 1:
@@ -222,7 +213,6 @@ class CourseBuilder:
222
  state.error = str(e)
223
  return state
224
 
225
-
226
  class LearningPlatform:
227
  def __init__(self, api_key: str = None, config: Config = None):
228
  self.config = config or Config()
@@ -230,32 +220,17 @@ class LearningPlatform:
230
 
231
  async def create_course(self, topic: str, difficulty: str) -> LearningPath:
232
  try:
233
- state = CourseState(topic=topic, difficulty=difficulty)
234
- result = await self.course_builder.graph.arun(
235
- state,
236
- config={"recursion_limit": self.config.graph_config["recursion_limit"]}
237
- )
238
-
239
- if result.error:
240
- raise Exception(result.error)
241
-
242
- modules = [
243
- LearningModule(
244
- title=section["title"],
245
- content=section["content"]["content"],
246
- sections=[
247
- Section(
248
- title=kp,
249
- content=section["content"].get("details", {}).get(kp, ""),
250
- quiz_questions=section["assessment"]
251
- ) for kp in section["content"]["key_points"]
252
- ],
253
- prerequisites=section.get("prerequisites", []),
254
- learning_objectives=section.get("objectives", []),
255
- is_complete=True
256
- ) for section in result.sections
257
- ]
258
-
259
  return LearningPath(
260
  topic=topic,
261
  description=f"Course on {topic}",
@@ -265,5 +240,11 @@ class LearningPlatform:
265
  is_generating=False
266
  )
267
  except Exception as e:
268
- print(f"Course creation error: {str(e)}") # Print to console for debugging
269
- raise
 
 
 
 
 
 
 
1
+ from typing import List, Dict, Any
 
2
  from dataclasses import dataclass, field
3
  from datetime import datetime
4
+ import os
5
+ import json
6
+ import streamlit as st
7
+ import openai
8
+ import faiss
9
+ from langchain import OpenAI
10
+ from langgraph import Graph
11
+
12
 
13
+ from langchain.prompts import PromptTemplate
 
 
 
14
 
15
+ from langgraph.prebuilt import create_react_agent, ToolNode
16
+ from langgraph.graph import END
17
+ import asyncio
18
 
19
  @dataclass
20
  class Section:
 
24
  quiz_questions: List[Dict[str, Any]] = field(default_factory=list)
25
  is_complete: bool = False
26
 
 
27
  @dataclass
28
  class LearningModule:
29
  title: str
 
34
  learning_objectives: List[str] = field(default_factory=list)
35
  is_complete: bool = False
36
 
 
37
  @dataclass
38
  class LearningPath:
39
  topic: str
 
43
  difficulty_level: str
44
  is_generating: bool = True
45
 
 
46
  @dataclass
47
  class CourseState:
48
  topic: str
 
52
  sections: List[Dict] = field(default_factory=list)
53
  error: str = ""
54
 
 
55
  class Config:
56
  def __init__(self):
57
  self.llm_config = {
58
  "temperature": 0.7,
59
+ "model": "gpt-4",
60
  "max_tokens": 2000
61
  }
62
+
63
  self.graph_config = {
64
  "recursion_limit": 25,
65
  "max_retries": 3,
66
  "timeout": 300
67
  }
68
+ self.rag_config = {
69
+ "chunk_size": 500,
70
+ "chunk_overlap": 50,
71
+ "distance_metric": "cosine",
72
+ "k_similar": 3
73
+ }
74
  self.course_defaults = {
75
+ "max_modules": 5,
76
+ "sections_per_module": 4,
77
+ "questions_per_quiz": 3
78
  }
79
 
 
80
  class CoursePrompts:
81
  @staticmethod
82
  def planning_prompt() -> str:
 
86
  - Clear learning objectives
87
  - Practical applications
88
  Return JSON array of:
89
+ {
90
  "title": "module title",
91
  "objectives": ["objective1", "objective2"],
92
  "prerequisites": ["prereq1", "prereq2"]
93
+ }"""
94
 
95
  @staticmethod
96
  def content_prompt() -> str:
97
  return """Create engaging content for {module_title}:
98
+ - Start with hook
99
  - Include code examples
100
  - Real-world applications
101
  - Best practices
102
  Return JSON:
103
+ {
104
  "content": "main content",
105
  "key_points": ["point1", "point2"],
106
+ "details": {
107
  "section1": "detailed content",
108
  "section2": "detailed content"
109
+ }
110
+ }"""
111
 
112
  @staticmethod
113
  def assessment_prompt() -> str:
114
+ return """Create assessment for {module_title}.
115
  Include:
116
  - Practical scenarios
117
  - Code challenges
118
  - Concept validation
119
+ Return JSON array of:
120
+ {
121
  "question": "text",
122
  "options": ["A", "B", "C", "D"],
123
  "correct_answer": "A",
124
  "explanation": "detailed explanation"
125
+ }"""
 
126
 
127
  class CourseBuilder:
128
+ def __init__(self, api_key: str = None, config: Config = None):
129
+ # Debugging API Key
130
+ self.api_key = api_key or os.getenv('OPENAI_API_KEY')
131
+ if not self.api_key:
132
+ print("[DEBUG] API key is not set. Please ensure OPENAI_API_KEY is available in the environment.")
133
  else:
134
+ print(f"[DEBUG] Using API key: {self.api_key[:4]}... (truncated for security)")
 
 
 
 
135
  self.config = config or Config()
136
+ self.llm = openai.Completion
137
+ # Debugging OpenAI Client Initialization
138
+ print(f"[DEBUG] Initializing ChatOpenAI with api_key: {self.api_key[:4]}... (truncated for security)")
139
+ self.embeddings = OpenAI.Embeddings(api_key=self.api_key) # Example OpenAI Embeddings usage
140
+ # Debugging Embeddings Initialization
141
+ print(f"[DEBUG] Initializing OpenAIEmbeddings with api_key: {self.api_key[:4]}... (truncated for security)")
142
+ self.vector_store = faiss.IndexFlatL2(128) # Example FAISS initialization for vector store
143
+ self.setup_agent()
144
+
145
+ def setup_agent(self):
146
+ # Define the tools to be used by the agent
147
+ tools = [self.plan_course, self.create_module, self.generate_content, self.create_assessment]
148
+
149
+ # Create a react agent with the specified tools
150
+ self.graph = create_react_agent(self.llm, tools=tools)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
151
 
152
  async def generate_with_retry(self, prompt: str, variables: Dict) -> Any:
153
+ # Debugging prompt generation
154
  print(f"[DEBUG] Generating text with prompt: {prompt.format(**variables)}")
155
  for attempt in range(self.config.graph_config["max_retries"]):
156
  try:
157
+ response = await asyncio.to_thread(
158
+ openai.Completion.create,
159
+ model=self.config.llm_config['model'],
160
+ prompt=prompt.format(**variables),
161
+ max_tokens=self.config.llm_config['max_tokens'],
162
+ temperature=self.config.llm_config['temperature'],
163
+ api_key=self.api_key
164
  )
165
+ result = response['choices'][0]['text']
166
  return json.loads(result)
 
 
167
  except Exception as e:
168
  print(f"[DEBUG] Error occurred during attempt {attempt + 1}: {e}")
169
  if attempt == self.config.graph_config["max_retries"] - 1:
 
213
  state.error = str(e)
214
  return state
215
 
 
216
  class LearningPlatform:
217
  def __init__(self, api_key: str = None, config: Config = None):
218
  self.config = config or Config()
 
220
 
221
  async def create_course(self, topic: str, difficulty: str) -> LearningPath:
222
  try:
223
+ inputs = {"messages": ["user", f"Create a course on {topic} at {difficulty} level"]}
224
+ async for s in self.course_builder.graph.stream(inputs, stream_mode="values"):
225
+ message = s["messages"][-1]
226
+ if isinstance(message, tuple):
227
+ print(message)
228
+ else:
229
+ message.pretty_print()
230
+
231
+ # Use the response to create LearningPath instance
232
+ # Placeholder logic - modify this to fit your needs
233
+ modules = [LearningModule(title="Sample Module", content="Generated content...")]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
234
  return LearningPath(
235
  topic=topic,
236
  description=f"Course on {topic}",
 
240
  is_generating=False
241
  )
242
  except Exception as e:
243
+ st.error(f"Course creation error: {str(e)}")
244
+ raise,
245
+ difficulty_level=difficulty,
246
+ is_generating=False
247
+ )
248
+ except Exception as e:
249
+ st.error(f"Course creation error: {str(e)}")
250
+ raise