-
Notifications
You must be signed in to change notification settings - Fork 34
Feature/personalized learning path #76
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,68 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| \# AI-Driven Personalized Learning Path — Design Doc | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| \## Overview | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| This feature dynamically generates a personalized learning path for each user by detecting topic-wise weaknesses based on their performance and activity history. | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| \## Goals | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| \- Detect weak areas using performance analytics. | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| \- Recommend weekly personalized goals. | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| \- Increase engagement and retention. | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| \- Deliver smarter preparation paths via AI. | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| \## Scope (MVP) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| \- Weakness detection using rule-based scoring. | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| \- Weekly roadmap with: | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| - 2–3 weak topics to focus on. | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| - Practice problems \& concept resources. | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| - Progress tracking. | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| \## Data Schema | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| \*\*Events\*\* | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| ```json | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| "user\_id": "string", | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| "activity\_type": "quiz|coding|mock", | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| "topic": "arrays|dp|graphs|system-design", | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| "subtopic": "two-pointer", | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| "timestamp": "ISO8601", | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| "accuracy": 0.85, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| "time\_taken\_seconds": 120, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| "attempts": 1, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| "difficulty": "easy|medium|hard", | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| "exercise\_id": "string" | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+41
to
+65
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix: Close the JSON code fence to avoid broken Markdown rendering The JSON example block is opened (Line 41) but not closed, which will break rendering for everything that follows. Apply this diff to close the code fence: "exercise_id": "string"
}
-
+```📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,69 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| --- | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ## **2. Backend Starter (FastAPI)** — `services/personalization/app.py` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ```python | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+1
to
+4
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Critical: File contains Markdown wrappers (front-matter and code fences) and won’t import There’s Apply this diff to strip Markdown from the Python file: ----
-
-## **2. Backend Starter (FastAPI)** — `services/personalization/app.py`
-```python
+"""
+Personalization Service (FastAPI)
+"""
@@
- return mock_roadmaps[user_id]
-```
+ return mock_roadmaps[user_id]Also applies to: 69-69 🧰 Tools🪛 Ruff (0.12.2)1-2: SyntaxError: Expected an expression 4-4: SyntaxError: Got unexpected token ` 4-4: SyntaxError: Got unexpected token ` 4-4: SyntaxError: Got unexpected token ` 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from fastapi import FastAPI, HTTPException | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from pydantic import BaseModel | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from typing import List | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from datetime import datetime | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+6
to
+9
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Strengthen imports for validation and enums Use Pydantic Field for constraints and Enum for typed fields. -from pydantic import BaseModel
-from typing import List
-from datetime import datetime
+from pydantic import BaseModel, Field
+from typing import List
+from datetime import datetime
+from enum import Enum📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| app = FastAPI(title="Personalization Service") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # ---- Schemas ---- | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| class Event(BaseModel): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| user_id: str | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| activity_type: str | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| topic: str | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| subtopic: str | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| timestamp: datetime | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| accuracy: float | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| time_taken_seconds: int | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| attempts: int | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| difficulty: str | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| exercise_id: str | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+13
to
+24
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Schema hardening: enums and field constraints for Event Constrain inputs to reduce bad data. Also future-proof for Pydantic v2 semantics. -class Event(BaseModel):
- user_id: str
- activity_type: str
- topic: str
- subtopic: str
- timestamp: datetime
- accuracy: float
- time_taken_seconds: int
- attempts: int
- difficulty: str
- exercise_id: str
+class ActivityType(str, Enum):
+ quiz = "quiz"
+ coding = "coding"
+ mock = "mock"
+
+
+class Difficulty(str, Enum):
+ easy = "easy"
+ medium = "medium"
+ hard = "hard"
+
+
+class Event(BaseModel):
+ user_id: str
+ activity_type: ActivityType
+ topic: str
+ subtopic: str
+ timestamp: datetime
+ accuracy: float = Field(ge=0.0, le=1.0)
+ time_taken_seconds: int = Field(ge=0)
+ attempts: int = Field(ge=1)
+ difficulty: Difficulty
+ exercise_id: str📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| class Task(BaseModel): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| description: str | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| completed: bool = False | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| class WeekPlan(BaseModel): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| week_no: int | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| topics: List[str] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| tasks: List[Task] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| goal: str | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| class Roadmap(BaseModel): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| user_id: str | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| weeks: List[WeekPlan] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # ---- Mock Database ---- | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| mock_events = [] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| mock_roadmaps = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "u1": Roadmap( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| user_id="u1", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| weeks=[ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| WeekPlan( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| week_no=1, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| topics=["arrays", "two-pointer"], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| tasks=[ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Task(description="Solve 3 practice problems"), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Task(description="Watch 2 concept videos"), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Task(description="Take revision quiz") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| goal="Reach avg_accuracy ≥ 0.75" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # ---- Endpoints ---- | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @app.post("/events") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def add_event(event: Event): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| mock_events.append(event.dict()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return {"message": "Event recorded", "total_events": len(mock_events)} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+60
to
+63
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion POST /events: return 201 and prefer model_dump() in Pydantic v2 Status 201 is more accurate for creation; model_dump avoids v2 deprecation warnings. If you chose “store models” (Option A above): -@app.post("/events")
-def add_event(event: Event):
- mock_events.append(event.dict())
- return {"message": "Event recorded", "total_events": len(mock_events)}
+@app.post("/events", status_code=201)
+def add_event(event: Event):
+ mock_events.append(event)
+ return {"message": "Event recorded", "total_events": len(mock_events)}If you prefer storing dicts: -@app.post("/events")
-def add_event(event: Event):
- mock_events.append(event.dict())
+@app.post("/events", status_code=201)
+def add_event(event: Event):
+ mock_events.append(event.model_dump())
return {"message": "Event recorded", "total_events": len(mock_events)}📝 Committable suggestion
Suggested change
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @app.get("/user/{user_id}/path", response_model=Roadmap) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def get_roadmap(user_id: str): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if user_id not in mock_roadmaps: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| raise HTTPException(status_code=404, detail="No roadmap found for this user") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return mock_roadmaps[user_id] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+1
to
+69
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Verification agent 🧩 Analysis chainVerify and fix syntax errors flagged by static analysis Confirm that the file no longer contains markdown fences/backticks and parses as Python. Run: 🏁 Script executed: #!/bin/bash
set -euo pipefail
echo "Detecting markdown fences in services/personalization/app.py"
rg -n '^(---|```)' services/personalization/app.py || echo "No markdown fences detected."
echo "AST-parse the file to catch syntax errors"
python - << 'PY'
import ast, sys, pathlib
p = pathlib.Path("services/personalization/app.py")
try:
ast.parse(p.read_text(encoding="utf-8"))
print("AST parse OK: services/personalization/app.py")
except SyntaxError as e:
print("SyntaxError:", e)
sys.exit(1)
PYLength of output: 373 Remove Markdown Fences Causing Syntax Errors The file • services/personalization/app.py:1 After stripping out all backticks/markdown fences, re-run your static analysis or 🧰 Tools🪛 Ruff (0.12.2)1-2: SyntaxError: Expected an expression 4-4: SyntaxError: Got unexpected token ` 4-4: SyntaxError: Got unexpected token ` 4-4: SyntaxError: Got unexpected token ` 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Event schema: add constraints and a few operational fields
To make downstream validation and analytics simpler, specify constraints and add a few commonly used fields.
Recommended refinements:
If you want, I can update the sample JSON here and mirror the same constraints in the FastAPI/Pydantic models.
🤖 Prompt for AI Agents