lov2 / app /api /v2 /knowledge_graph.py
work-sejal
Add knowledge graph and adaptive learning path features to HF Space
c045254
Raw
History Blame Contribute Delete
5.19 kB
"""Knowledge graph API endpoints."""
import logging
from fastapi import APIRouter, Depends, HTTPException, Query
from fastapi.responses import JSONResponse
from app.core.exceptions import EntityNotFoundError, DatasetError
from app.schemas.knowledge_graph import KnowledgeGraphResponse
from app.services.knowledge_graph_service import KnowledgeGraphService
from app.api.v2.dependencies import get_knowledge_graph_service
logger = logging.getLogger(__name__)
router = APIRouter(prefix="/ai/v2/knowledge-graph", tags=["knowledge-graph"])
# NOTE: Static-segment routes MUST be declared before dynamic /{lo_id} routes
# so FastAPI doesn't swallow "path" as a lo_id value.
@router.get(
"/path/{start_lo}/{target_lo}",
summary="Get shortest path between two learning outcomes",
description="Find the shortest dependency path between two learning outcomes in the knowledge graph"
)
async def get_learning_path_between_los(
start_lo: str,
target_lo: str,
knowledge_graph_service: KnowledgeGraphService = Depends(get_knowledge_graph_service)
) -> JSONResponse:
"""Get learning path between two learning outcomes."""
try:
path = knowledge_graph_service.get_learning_path(start_lo, target_lo)
return JSONResponse(content={
"start_lo": start_lo,
"target_lo": target_lo,
"path": path,
"steps": len(path)
})
except EntityNotFoundError as exc:
logger.warning("Learning path query failed - entity not found: %s", exc)
raise HTTPException(status_code=404, detail=str(exc)) from exc
except Exception as exc:
logger.error("Learning path query failed: %s", exc)
raise HTTPException(status_code=500, detail="Internal server error") from exc
@router.get(
"/{lo_id}/prerequisites",
summary="Get prerequisites for a learning outcome",
description="Get all prerequisite learning outcomes for a given LO"
)
async def get_prerequisites(
lo_id: str,
max_depth: int = Query(default=None, ge=1, le=10, description="Maximum depth to traverse"),
knowledge_graph_service: KnowledgeGraphService = Depends(get_knowledge_graph_service)
) -> JSONResponse:
"""Get prerequisites for a learning outcome."""
try:
prerequisites = knowledge_graph_service.get_prerequisites(lo_id, max_depth)
return JSONResponse(content={
"lo_id": lo_id,
"prerequisites": prerequisites,
"count": len(prerequisites)
})
except EntityNotFoundError as exc:
logger.warning("Prerequisites query failed - entity not found: %s", exc)
raise HTTPException(status_code=404, detail=str(exc)) from exc
except Exception as exc:
logger.error("Prerequisites query failed: %s", exc)
raise HTTPException(status_code=500, detail="Internal server error") from exc
@router.get(
"/{lo_id}/successors",
summary="Get successors for a learning outcome",
description="Get all successor learning outcomes for a given LO"
)
async def get_successors(
lo_id: str,
max_depth: int = Query(default=None, ge=1, le=10, description="Maximum depth to traverse"),
knowledge_graph_service: KnowledgeGraphService = Depends(get_knowledge_graph_service)
) -> JSONResponse:
"""Get successors for a learning outcome."""
try:
successors = knowledge_graph_service.get_successors(lo_id, max_depth)
return JSONResponse(content={
"lo_id": lo_id,
"successors": successors,
"count": len(successors)
})
except EntityNotFoundError as exc:
logger.warning("Successors query failed - entity not found: %s", exc)
raise HTTPException(status_code=404, detail=str(exc)) from exc
except Exception as exc:
logger.error("Successors query failed: %s", exc)
raise HTTPException(status_code=500, detail="Internal server error") from exc
@router.get(
"/{lo_id}",
response_model=KnowledgeGraphResponse,
summary="Get knowledge graph for a learning outcome",
description="Retrieve full knowledge graph info including prerequisites and successors for a learning outcome"
)
async def get_knowledge_graph(
lo_id: str,
max_depth: int = Query(default=2, ge=1, le=5, description="Maximum depth to traverse"),
knowledge_graph_service: KnowledgeGraphService = Depends(get_knowledge_graph_service)
) -> KnowledgeGraphResponse:
"""Get knowledge graph information for a learning outcome."""
try:
return knowledge_graph_service.get_knowledge_graph(lo_id, max_depth)
except EntityNotFoundError as exc:
logger.warning("Knowledge graph query failed - entity not found: %s", exc)
raise HTTPException(status_code=404, detail=str(exc)) from exc
except DatasetError as exc:
logger.error("Knowledge graph query failed - dataset error: %s", exc)
raise HTTPException(status_code=503, detail="Knowledge graph service unavailable") from exc
except Exception as exc:
logger.error("Knowledge graph query failed - unexpected error: %s", exc)
raise HTTPException(status_code=500, detail="Internal server error") from exc