cryogenic22 commited on
Commit
f9bf840
Β·
verified Β·
1 Parent(s): 11e29db

Update learning_platform.py

Browse files
Files changed (1) hide show
  1. learning_platform.py +65 -58
learning_platform.py CHANGED
@@ -9,10 +9,11 @@ from langchain_core.messages import BaseMessage, HumanMessage, AIMessage
9
  from langchain.embeddings import OpenAIEmbeddings
10
  from langchain_community.vectorstores import FAISS
11
  from langchain.tools import Tool
12
- from langgraph.graph import StateGraph,START,END
13
  from langgraph.graph.message import add_messages
14
  import streamlit as st
15
 
 
16
  @dataclass
17
  class Section:
18
  title: str
@@ -22,6 +23,7 @@ class Section:
22
  quiz_questions: List[Dict[str, Any]] = field(default_factory=list)
23
  is_complete: bool = False
24
 
 
25
  @dataclass
26
  class CourseModule:
27
  title: str
@@ -30,6 +32,7 @@ class CourseModule:
30
  sections: List[Section] = field(default_factory=list)
31
  is_complete: bool = False
32
 
 
33
  @dataclass
34
  class LearningPath:
35
  topic: str
@@ -39,6 +42,7 @@ class LearningPath:
39
  created_at: datetime
40
  is_generating: bool = True
41
 
 
42
  class CourseState(TypedDict):
43
  messages: Annotated[Sequence[BaseMessage], add_messages]
44
  topic: str
@@ -47,6 +51,7 @@ class CourseState(TypedDict):
47
  modules: List[Dict]
48
  status: str
49
 
 
50
  class CoursePrompts:
51
  @staticmethod
52
  def course_planning_prompt() -> str:
@@ -116,6 +121,7 @@ Return JSON:
116
  "feedback": ["improvement notes"]
117
  }"""
118
 
 
119
  class CourseBuilder:
120
  def __init__(self, api_key: str):
121
  self.api_key = api_key
@@ -135,63 +141,63 @@ class CourseBuilder:
135
  self.setup_graph()
136
 
137
  async def plan_course(self, state: CourseState) -> CourseState:
138
- """Planner agent for course structure"""
139
- st.session_state.agent_logs.append("πŸ“‹ Planning course structure...")
140
 
141
- try:
142
- # Use RAG to find similar course structures
143
- similar_courses = self.vector_store.similarity_search(
144
- f"{state['topic']} {state['difficulty']} course",
145
- k=2
146
- )
147
- context = "\n".join([doc.page_content for doc in similar_courses])
148
 
149
- prompt = self.prompts.course_planning_prompt()
150
- response = await self.llm.apredict(
151
- prompt.format(
152
- topic=state["topic"],
153
- difficulty=state["difficulty"],
154
- context=context
 
155
  )
156
- )
157
 
158
- # Index the course plan for future reference
159
- course_plan = json.loads(response)
160
- self.vector_store.add_texts(
161
- [json.dumps(course_plan)],
162
- metadatas=[{"type": "course_plan", "topic": state["topic"]}]
163
- )
164
 
165
- st.session_state.agent_logs.append("βœ… Course structure planned")
166
- return {
167
- **state,
168
- "messages": [AIMessage(content=response)],
169
- "status": "planning_complete"
170
- }
171
- except Exception as e:
172
- error_message = f"Course creation error: {str(e)}"
173
- st.session_state.agent_logs.append(error_message)
174
- return {
175
- **state,
176
- "messages": [AIMessage(content=error_message)],
177
- "status": "planning_failed"
178
- }
179
 
180
  async def create_content(self, state: CourseState) -> CourseState:
181
  """Content creator agent using RAG"""
182
  st.session_state.agent_logs.append(f"πŸ“ Creating module {state['current_module'] + 1}...")
183
-
184
  messages = state["messages"]
185
  current_plan = json.loads(messages[-1].content)
186
  current_module = current_plan["modules"][state["current_module"]]
187
-
188
  # Use RAG for content enhancement
189
  similar_content = self.vector_store.similarity_search(
190
  current_module["title"],
191
  k=3
192
  )
193
  context = "\n".join([doc.page_content for doc in similar_content])
194
-
195
  prompt = self.prompts.module_content_prompt()
196
  content = await self.llm.apredict(
197
  prompt.format(
@@ -200,7 +206,7 @@ class CourseBuilder:
200
  objectives=", ".join(current_module["objectives"])
201
  )
202
  )
203
-
204
  # Index new content
205
  try:
206
  content_json = json.loads(content)
@@ -214,7 +220,7 @@ class CourseBuilder:
214
  )
215
  except Exception as e:
216
  st.session_state.agent_logs.append(f"⚠️ Warning: Couldn't index content: {str(e)}")
217
-
218
  st.session_state.agent_logs.append("βœ… Module content created")
219
  return {
220
  **state,
@@ -225,17 +231,17 @@ class CourseBuilder:
225
  async def review_content(self, state: CourseState) -> CourseState:
226
  """Content reviewer agent with RAG"""
227
  st.session_state.agent_logs.append("πŸ” Reviewing content quality...")
228
-
229
  messages = state["messages"]
230
  content = messages[-1].content
231
-
232
  # Use RAG for content review
233
  similar_contents = self.vector_store.similarity_search(
234
  content,
235
  k=2
236
  )
237
  context = "\n".join([doc.page_content for doc in similar_contents])
238
-
239
  prompt = self.prompts.review_prompt()
240
  review = await self.llm.apredict(
241
  prompt.format(
@@ -243,9 +249,9 @@ class CourseBuilder:
243
  context=context
244
  )
245
  )
246
-
247
  review_data = json.loads(review)
248
-
249
  if review_data["approved"]:
250
  st.session_state.agent_logs.append("βœ… Content approved")
251
  return {
@@ -270,12 +276,12 @@ class CourseBuilder:
270
  def setup_graph(self):
271
  """Set up the agent workflow graph"""
272
  workflow = StateGraph(CourseState)
273
-
274
  # Add agent nodes
275
  workflow.add_node("planner", self.plan_course)
276
  workflow.add_node("creator", self.create_content)
277
  workflow.add_node("reviewer", self.review_content)
278
-
279
  # Define workflow
280
  workflow.add_edge(START, "planner") # Connect START to planner
281
  workflow.add_edge("planner", "creator")
@@ -288,9 +294,10 @@ class CourseBuilder:
288
  }
289
  )
290
  workflow.add_edge("reviewer", "creator")
291
-
292
  self.graph = workflow.compile()
293
-
 
294
  class LearningPlatform:
295
  def __init__(self, api_key: str = None):
296
  self.api_key = api_key or os.getenv("OPENAI_API_KEY")
@@ -306,13 +313,13 @@ class LearningPlatform:
306
  "modules": [],
307
  "status": "planning"
308
  }
309
-
310
  final_state = None
311
  async for output in self.course_builder.graph.astream(initial_state):
312
  final_state = output
313
-
314
  course_content = json.loads(final_state["messages"][-1].content)
315
-
316
  # Create first module
317
  first_module = CourseModule(
318
  title=course_content["modules"][0]["title"],
@@ -320,7 +327,7 @@ class LearningPlatform:
320
  prerequisites=course_content["modules"][0].get("prerequisites", [])
321
  )
322
  first_module.is_complete = True
323
-
324
  return LearningPath(
325
  topic=topic,
326
  description=course_content["description"],
@@ -335,7 +342,7 @@ class LearningPlatform:
335
  created_at=datetime.now(),
336
  is_generating=True
337
  )
338
-
339
  except Exception as e:
340
  raise Exception(f"Course creation error: {str(e)}")
341
 
@@ -357,11 +364,11 @@ class LearningPlatform:
357
  "modules": [],
358
  "status": "creating"
359
  }
360
-
361
  final_state = None
362
  async for output in self.course_builder.graph.astream(state):
363
  final_state = output
364
-
365
  content = json.loads(final_state["messages"][-1].content)
366
  module.sections = [Section(**s) for s in content["sections"]]
367
  module.is_complete = True
 
9
  from langchain.embeddings import OpenAIEmbeddings
10
  from langchain_community.vectorstores import FAISS
11
  from langchain.tools import Tool
12
+ from langgraph.graph import StateGraph, START, END
13
  from langgraph.graph.message import add_messages
14
  import streamlit as st
15
 
16
+
17
  @dataclass
18
  class Section:
19
  title: str
 
23
  quiz_questions: List[Dict[str, Any]] = field(default_factory=list)
24
  is_complete: bool = False
25
 
26
+
27
  @dataclass
28
  class CourseModule:
29
  title: str
 
32
  sections: List[Section] = field(default_factory=list)
33
  is_complete: bool = False
34
 
35
+
36
  @dataclass
37
  class LearningPath:
38
  topic: str
 
42
  created_at: datetime
43
  is_generating: bool = True
44
 
45
+
46
  class CourseState(TypedDict):
47
  messages: Annotated[Sequence[BaseMessage], add_messages]
48
  topic: str
 
51
  modules: List[Dict]
52
  status: str
53
 
54
+
55
  class CoursePrompts:
56
  @staticmethod
57
  def course_planning_prompt() -> str:
 
121
  "feedback": ["improvement notes"]
122
  }"""
123
 
124
+
125
  class CourseBuilder:
126
  def __init__(self, api_key: str):
127
  self.api_key = api_key
 
141
  self.setup_graph()
142
 
143
  async def plan_course(self, state: CourseState) -> CourseState:
144
+ """Planner agent for course structure"""
145
+ st.session_state.agent_logs.append("πŸ“‹ Planning course structure...")
146
 
147
+ try:
148
+ # Use RAG to find similar course structures
149
+ similar_courses = self.vector_store.similarity_search(
150
+ f"{state['topic']} {state['difficulty']} course",
151
+ k=2
152
+ )
153
+ context = "\n".join([doc.page_content for doc in similar_courses])
154
 
155
+ prompt = self.prompts.course_planning_prompt()
156
+ response = await self.llm.apredict(
157
+ prompt.format(
158
+ topic=state["topic"],
159
+ difficulty=state["difficulty"],
160
+ context=context
161
+ )
162
  )
 
163
 
164
+ # Index the course plan for future reference
165
+ course_plan = json.loads(response)
166
+ self.vector_store.add_texts(
167
+ [json.dumps(course_plan)],
168
+ metadatas=[{"type": "course_plan", "topic": state["topic"]}]
169
+ )
170
 
171
+ st.session_state.agent_logs.append("βœ… Course structure planned")
172
+ return {
173
+ **state,
174
+ "messages": [AIMessage(content=response)],
175
+ "status": "planning_complete"
176
+ }
177
+ except Exception as e:
178
+ error_message = f"Course creation error: {str(e)}"
179
+ st.session_state.agent_logs.append(error_message)
180
+ return {
181
+ **state,
182
+ "messages": [AIMessage(content=error_message)],
183
+ "status": "planning_failed"
184
+ }
185
 
186
  async def create_content(self, state: CourseState) -> CourseState:
187
  """Content creator agent using RAG"""
188
  st.session_state.agent_logs.append(f"πŸ“ Creating module {state['current_module'] + 1}...")
189
+
190
  messages = state["messages"]
191
  current_plan = json.loads(messages[-1].content)
192
  current_module = current_plan["modules"][state["current_module"]]
193
+
194
  # Use RAG for content enhancement
195
  similar_content = self.vector_store.similarity_search(
196
  current_module["title"],
197
  k=3
198
  )
199
  context = "\n".join([doc.page_content for doc in similar_content])
200
+
201
  prompt = self.prompts.module_content_prompt()
202
  content = await self.llm.apredict(
203
  prompt.format(
 
206
  objectives=", ".join(current_module["objectives"])
207
  )
208
  )
209
+
210
  # Index new content
211
  try:
212
  content_json = json.loads(content)
 
220
  )
221
  except Exception as e:
222
  st.session_state.agent_logs.append(f"⚠️ Warning: Couldn't index content: {str(e)}")
223
+
224
  st.session_state.agent_logs.append("βœ… Module content created")
225
  return {
226
  **state,
 
231
  async def review_content(self, state: CourseState) -> CourseState:
232
  """Content reviewer agent with RAG"""
233
  st.session_state.agent_logs.append("πŸ” Reviewing content quality...")
234
+
235
  messages = state["messages"]
236
  content = messages[-1].content
237
+
238
  # Use RAG for content review
239
  similar_contents = self.vector_store.similarity_search(
240
  content,
241
  k=2
242
  )
243
  context = "\n".join([doc.page_content for doc in similar_contents])
244
+
245
  prompt = self.prompts.review_prompt()
246
  review = await self.llm.apredict(
247
  prompt.format(
 
249
  context=context
250
  )
251
  )
252
+
253
  review_data = json.loads(review)
254
+
255
  if review_data["approved"]:
256
  st.session_state.agent_logs.append("βœ… Content approved")
257
  return {
 
276
  def setup_graph(self):
277
  """Set up the agent workflow graph"""
278
  workflow = StateGraph(CourseState)
279
+
280
  # Add agent nodes
281
  workflow.add_node("planner", self.plan_course)
282
  workflow.add_node("creator", self.create_content)
283
  workflow.add_node("reviewer", self.review_content)
284
+
285
  # Define workflow
286
  workflow.add_edge(START, "planner") # Connect START to planner
287
  workflow.add_edge("planner", "creator")
 
294
  }
295
  )
296
  workflow.add_edge("reviewer", "creator")
297
+
298
  self.graph = workflow.compile()
299
+
300
+
301
  class LearningPlatform:
302
  def __init__(self, api_key: str = None):
303
  self.api_key = api_key or os.getenv("OPENAI_API_KEY")
 
313
  "modules": [],
314
  "status": "planning"
315
  }
316
+
317
  final_state = None
318
  async for output in self.course_builder.graph.astream(initial_state):
319
  final_state = output
320
+
321
  course_content = json.loads(final_state["messages"][-1].content)
322
+
323
  # Create first module
324
  first_module = CourseModule(
325
  title=course_content["modules"][0]["title"],
 
327
  prerequisites=course_content["modules"][0].get("prerequisites", [])
328
  )
329
  first_module.is_complete = True
330
+
331
  return LearningPath(
332
  topic=topic,
333
  description=course_content["description"],
 
342
  created_at=datetime.now(),
343
  is_generating=True
344
  )
345
+
346
  except Exception as e:
347
  raise Exception(f"Course creation error: {str(e)}")
348
 
 
364
  "modules": [],
365
  "status": "creating"
366
  }
367
+
368
  final_state = None
369
  async for output in self.course_builder.graph.astream(state):
370
  final_state = output
371
+
372
  content = json.loads(final_state["messages"][-1].content)
373
  module.sections = [Section(**s) for s in content["sections"]]
374
  module.is_complete = True