Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ai-ml/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ python-dotenv
groq
yake
pytest
pyjwt
4 changes: 2 additions & 2 deletions ai-ml/weak_topic_detection/app/api/weak_topic_api.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from app.services.weak_topic_service import WeakTopicService
from weak_topic_detection.app.services.weak_topic_service import WeakTopicService


class WeakTopicAPI:
Expand All @@ -9,4 +9,4 @@ def __init__(self):

def get_weak_topics(self):
"""Return the weak topics detected from quiz results."""
return self.service.get_weak_topics()
return self.service.get_weak_topics()
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from collections import defaultdict
from app.models.quiz_result import QuizResult
from weak_topic_detection.app.models.quiz_result import QuizResult


class WeakTopicDetector:
Expand Down Expand Up @@ -54,4 +54,4 @@ def detect(self, results: list[QuizResult]) -> list[dict]:
# Weakest topics first
weak_topics.sort(key=lambda item: item["accuracy"])

return weak_topics
return weak_topics
69 changes: 69 additions & 0 deletions ai-ml/weak_topic_detection/app/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
"""
Team Lambda Weak Topic Detection API — FastAPI service.

Run from ai-ml/ (so weak_topic_detection.* and quiz_generator.*
imports resolve):
uvicorn weak_topic_detection.app.main:app --reload --port <TBD — confirm with captain>

Interactive docs (once running): http://127.0.0.1:<port>/docs
"""

from fastapi import FastAPI, Depends
from fastapi.middleware.cors import CORSMiddleware

# Reusing the JWT auth dependency already built for quiz_generator
# (Contract v1, Section 10) rather than duplicating it — same secret,
# same failure modes, one source of truth for how auth works.
from quiz_generator.app.auth import get_current_user_id

from weak_topic_detection.app.services.weak_topic_service import WeakTopicService

app = FastAPI(title="StudyMind Weak Topic Detection API — Team Lambda")

app.add_middleware(
CORSMiddleware,
allow_origins=["http://localhost:5173"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)

_service: WeakTopicService | None = None


def get_service() -> WeakTopicService:
global _service
if _service is None:
_service = WeakTopicService()
return _service


@app.get("/health")
def health_check():
return {"status": "ok"}


@app.get("/weak-topics")
def get_weak_topics_endpoint(user_id: str = Depends(get_current_user_id)):
"""
Requires "Authorization: Bearer <jwt>". user_id is derived from
the verified token and returned alongside the results so the
caller can confirm whose data this is.

IMPORTANT — current limitation: WeakTopicService reads from a
static demo dataset (data/quiz_results.json), not live per-user
quiz submissions. The detection logic itself works correctly, but
it does not yet filter by user_id — every caller currently sees
the same demo results. Auth is enforced here so the endpoint's
contract (who can call it) is correct now; per-user quiz-result
ingestion is separate follow-up work once real quiz submissions
are wired in from the frontend.
"""
service = get_service()
weak_topics = service.get_weak_topics()

return {
"success": True,
"user_id": user_id,
"weak_topics": weak_topics,
}
10 changes: 5 additions & 5 deletions ai-ml/weak_topic_detection/app/services/weak_topic_service.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from app.detectors.weak_topic_detector import WeakTopicDetector
from app.models.quiz_result import QuizResult
from app.utils.data_loader import load_json_data
from app.config import WEAK_TOPIC_THRESHOLD, MIN_TOPIC_ATTEMPTS
from weak_topic_detection.app.detectors.weak_topic_detector import WeakTopicDetector
from weak_topic_detection.app.models.quiz_result import QuizResult
from weak_topic_detection.app.utils.data_loader import load_json_data
from weak_topic_detection.app.config import WEAK_TOPIC_THRESHOLD, MIN_TOPIC_ATTEMPTS


class WeakTopicService:
Expand Down Expand Up @@ -34,4 +34,4 @@ def get_weak_topics(self) -> list[dict]:

results = self.load_results()

return self.detector.detect(results)
return self.detector.detect(results)
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from app.models.quiz_result import QuizResult
from weak_topic_detection.app.models.quiz_result import QuizResult


class QuizResultValidator:
Expand Down Expand Up @@ -33,4 +33,4 @@ def validate(cls, result: QuizResult) -> bool:
if not result.date_taken:
return False

return True
return True
Loading