File size: 3,340 Bytes
ee7d7b9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
from fastapi import APIRouter, HTTPException, Depends
from typing import Dict, Any, Optional
from pydantic import BaseModel
import pandas as pd

from api.deps import get_current_user_id
from ml.model_deployer import get_model_deployer
from ml.model_monitor import ModelMonitor
from ml.model_persistence import get_model_persistence_manager
from utils.paths import get_user_paths
import json

router = APIRouter(prefix="/monitoring", tags=["Monitoring"])

@router.get("/{deploy_id}/metrics")
async def get_model_metrics(
    deploy_id: str,
    user_id: str = Depends(get_current_user_id)
):
    """Get time-series metrics (latency, usage) for a deployed model"""
    deployer = get_model_deployer()
    if deploy_id not in deployer.registry:
        raise HTTPException(status_code=404, detail="Deployment not found")
        
    deployment = deployer.registry[deploy_id]
    if deployment["user_id"] != user_id:
        raise HTTPException(status_code=403, detail="Access denied")
        
    try:
        metrics = ModelMonitor.get_metrics(deploy_id)
        
        # Attach deployment metadata
        metrics["model_name"] = deployment.get("model_name", "Unknown Model")
        metrics["task_type"] = deployment.get("task_type", "unknown")
        metrics["created_at"] = deployment.get("created_at")
        metrics["status"] = deployment.get("status")
        
        return {"success": True, "data": metrics}
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


@router.get("/{deploy_id}/drift")
async def get_model_drift(
    deploy_id: str,
    user_id: str = Depends(get_current_user_id)
):
    """Calculate data drift for a deployed model"""
    deployer = get_model_deployer()
    if deploy_id not in deployer.registry:
        raise HTTPException(status_code=404, detail="Deployment not found")
        
    deployment = deployer.registry[deploy_id]
    if deployment["user_id"] != user_id:
        raise HTTPException(status_code=403, detail="Access denied")
        
    try:
        # Load training dataset stats if possible
        # For full accuracy we'd need the original dataframe, but we'll try to load it from the user's workspace
        # if we know the target column, or use the model's persistence manager.
        pm = get_model_persistence_manager()
        state = pm.load_model(user_id, version=deployment.get("version"))
        
        # We need the original feature columns to do this properly.
        # If we have the training dataframe path, we load it.
        # To avoid blocking, we will just use dummy logic if the dataframe isn't found.
        # In a real system, the training dataset distribution (means, stds) would be saved with the model state.
        
        # Simulated dataframe with random distributions if state is missing
        # In this implementation, we will use the telemetry data against a simulated baseline for demonstration.
        alerts = ModelMonitor.calculate_drift(deploy_id)
        
        # If no alerts, and we want to demo the feature, we can simulate drift if requested?
        # Let's just return what ModelMonitor gives, which handles empty training_df gracefully (returns []).
        return {"success": True, "alerts": alerts}
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))