github-actions[bot] commited on
Commit
f524bd9
ยท
1 Parent(s): 1959397

๐Ÿš€ Auto-deploy backend from GitHub (af4a835)

Browse files
Files changed (1) hide show
  1. main.py +120 -0
main.py CHANGED
@@ -86,6 +86,7 @@ from rag.curriculum_rag import (
86
  build_analysis_curriculum_context,
87
  build_lesson_prompt,
88
  build_lesson_query,
 
89
  retrieve_curriculum_context,
90
  summarize_retrieval_confidence,
91
  )
@@ -366,6 +367,7 @@ ROLE_POLICIES: Dict[str, Set[str]] = {
366
  "/api/admin/model-config/override": ADMIN_ONLY,
367
  "/api/admin/model-config/reset": ADMIN_ONLY,
368
  "/api/lessons/videos/search": ALL_APP_ROLES,
 
369
  "/api/quiz-battle/generate": ALL_APP_ROLES,
370
  "/api/quiz-battle/ingest-pdf": TEACHER_OR_ADMIN,
371
  "/api/quiz-battle/bank-status": TEACHER_OR_ADMIN,
@@ -13160,6 +13162,124 @@ async def generate_learning_path(request: DiagnosticLearningPathRequest):
13160
  raise HTTPException(status_code=500, detail=f"Learning path error: {str(e)}")
13161
 
13162
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13163
  # โ”€โ”€โ”€ Main โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
13164
 
13165
  if __name__ == "__main__":
 
86
  build_analysis_curriculum_context,
87
  build_lesson_prompt,
88
  build_lesson_query,
89
+ format_retrieved_chunks,
90
  retrieve_curriculum_context,
91
  summarize_retrieval_confidence,
92
  )
 
367
  "/api/admin/model-config/override": ADMIN_ONLY,
368
  "/api/admin/model-config/reset": ADMIN_ONLY,
369
  "/api/lessons/videos/search": ALL_APP_ROLES,
370
+ "/api/lesson/personalized": ALL_APP_ROLES,
371
  "/api/quiz-battle/generate": ALL_APP_ROLES,
372
  "/api/quiz-battle/ingest-pdf": TEACHER_OR_ADMIN,
373
  "/api/quiz-battle/bank-status": TEACHER_OR_ADMIN,
 
13162
  raise HTTPException(status_code=500, detail=f"Learning path error: {str(e)}")
13163
 
13164
 
13165
+ # โ”€โ”€โ”€ Personalized Lesson Endpoint โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
13166
+
13167
+ class PersonalizedLessonRequest(BaseModel):
13168
+ topic: str = Field(..., description="Lesson topic")
13169
+ student_uid: str = Field(..., description="Student UID for profile lookup")
13170
+ assessment_context: Optional[Dict[str, Any]] = Field(None, description="Optional assessment context")
13171
+ subject: Optional[str] = Field(None, description="Subject area")
13172
+ quarter: Optional[int] = Field(None, description="Quarter (1-4)")
13173
+
13174
+
13175
+ class PersonalizedLessonResponse(BaseModel):
13176
+ topic: str
13177
+ content: str
13178
+ personalization_notes: str
13179
+ sections: List[Dict[str, str]]
13180
+ suggested_exercises: List[str]
13181
+ difficulty_adjustment: str
13182
+
13183
+
13184
+ @app.post("/api/lesson/personalized", response_model=PersonalizedLessonResponse)
13185
+ async def generate_personalized_lesson(request: PersonalizedLessonRequest):
13186
+ """
13187
+ Generate a personalized lesson based on student's assessment profile.
13188
+ Adapts content to address weaknesses and reinforce strengths.
13189
+ """
13190
+ try:
13191
+ # Load student's competency profile if available
13192
+ weaknesses = []
13193
+ strengths = []
13194
+ if firebase_firestore and request.student_uid:
13195
+ try:
13196
+ db = firebase_firestore.client()
13197
+ profile_doc = db.collection("competencyProfiles").document(request.student_uid).get()
13198
+ if profile_doc.exists:
13199
+ profile_data = profile_doc.to_dict()
13200
+ if profile_data and "competencies" in profile_data:
13201
+ for comp_id, comp_data in profile_data["competencies"].items():
13202
+ if comp_data.get("score", 0) < 50:
13203
+ weaknesses.append(comp_id)
13204
+ elif comp_data.get("score", 0) >= 80:
13205
+ strengths.append(comp_id)
13206
+ except Exception as e:
13207
+ logger.warning(f"Could not load competency profile: {e}")
13208
+
13209
+ # Retrieve curriculum context
13210
+ context_chunks = retrieve_curriculum_context(
13211
+ query=build_lesson_query(request.topic, request.subject or "General Mathematics", request.quarter or 1),
13212
+ subject=request.subject,
13213
+ quarter=request.quarter,
13214
+ top_k=5,
13215
+ )
13216
+ context_text = format_retrieved_chunks(context_chunks)
13217
+
13218
+ # Build personalized prompt
13219
+ prompt = f"""Generate a DepEd-aligned SHS mathematics lesson on: {request.topic}
13220
+
13221
+ Student Assessment Profile:
13222
+ - Weaknesses to address: {', '.join(weaknesses) if weaknesses else 'None identified'}
13223
+ - Strengths to reinforce: {', '.join(strengths) if strengths else 'None identified'}
13224
+
13225
+ Curriculum Context:
13226
+ {context_text}
13227
+
13228
+ Instructions:
13229
+ 1. Structure the lesson with: Introduction, Key Concepts, Examples, Practice Problems, Summary
13230
+ 2. Include extra practice on these weak areas: {', '.join(weaknesses) if weaknesses else 'general topic areas'}
13231
+ 3. Provide advanced challenges on these strong areas: {', '.join(strengths) if strengths else 'related advanced topics'}
13232
+ 4. Use Filipino Senior High School appropriate language and context
13233
+ 5. Reference specific DepEd MELC competencies where applicable
13234
+
13235
+ Return as JSON with fields: topic, sections (array of title/content), suggested_exercises, personalization_notes"""
13236
+
13237
+ req = InferenceRequest(
13238
+ messages=[
13239
+ {"role": "system", "content": "You are a precise DepEd-aligned curriculum assistant."},
13240
+ {"role": "user", "content": prompt},
13241
+ ],
13242
+ task_type="rag_lesson",
13243
+ max_new_tokens=1800,
13244
+ temperature=0.2,
13245
+ top_p=0.9,
13246
+ enable_thinking=True,
13247
+ )
13248
+ response_text = get_inference_client().generate_from_messages(req)
13249
+
13250
+ # Parse JSON response
13251
+ try:
13252
+ # Extract JSON from response
13253
+ json_match = re.search(r'\{.*\}', response_text, re.DOTALL)
13254
+ if json_match:
13255
+ lesson_data = json.loads(json_match.group())
13256
+ else:
13257
+ lesson_data = json.loads(response_text)
13258
+
13259
+ return PersonalizedLessonResponse(
13260
+ topic=request.topic,
13261
+ content=lesson_data.get("content", response_text),
13262
+ personalization_notes=f"Personalized for weaknesses: {', '.join(weaknesses)}" if weaknesses else "General lesson",
13263
+ sections=lesson_data.get("sections", []),
13264
+ suggested_exercises=lesson_data.get("suggested_exercises", []),
13265
+ difficulty_adjustment="supportive" if weaknesses else "standard",
13266
+ )
13267
+ except json.JSONDecodeError:
13268
+ # Return raw text if JSON parsing fails
13269
+ return PersonalizedLessonResponse(
13270
+ topic=request.topic,
13271
+ content=response_text,
13272
+ personalization_notes="Raw response (JSON parsing failed)",
13273
+ sections=[{"title": "Content", "content": response_text}],
13274
+ suggested_exercises=[],
13275
+ difficulty_adjustment="standard",
13276
+ )
13277
+
13278
+ except Exception as e:
13279
+ logger.error(f"Personalized lesson generation error: {e}")
13280
+ raise HTTPException(status_code=500, detail=f"Lesson generation error: {str(e)}")
13281
+
13282
+
13283
  # โ”€โ”€โ”€ Main โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
13284
 
13285
  if __name__ == "__main__":