Download backend/api/ml_controller.py from subhan07/hvac-agents: direct link, hf CLI and curl.
- Browser
- Download file 5.47 kB
-
https://huggingface.co/subhan07/hvac-agents/resolve/main/backend/api/ml_controller.py
- Command line
-
hf download hf://subhan07/hvac-agents/backend/api/ml_controller.py
-
curl -L -o ml_controller.py https://huggingface.co/subhan07/hvac-agents/resolve/main/backend/api/ml_controller.py
5.47 kB
| """Shared HVAC ML HTTP API. Training datasets are never LIVE_BMS.""" | |
| from __future__ import annotations | |
| from typing import Any, Dict, Optional | |
| from fastapi import APIRouter | |
| from pydantic import BaseModel, Field | |
| from backend.ml.prediction.service import list_models, model_status, predict | |
| from backend.ml.registry.service import list_datasets, list_maps, opportunity_health, register_datasets | |
| from backend.ml.training.pipeline import train_all | |
| router = APIRouter(prefix="/api/ml", tags=["ml"]) | |
| class PredictBody(BaseModel): | |
| opportunity_id: str | |
| agent_id: Optional[str] = None | |
| building_id: Optional[str] = None | |
| features: Dict[str, Any] = Field(default_factory=dict) | |
| def get_datasets(): | |
| return {"datasets": list_datasets(), "source": "TRAINING_DATASET"} | |
| def post_register(): | |
| return {"datasets": register_datasets(), "source": "TRAINING_DATASET"} | |
| def get_dataset(dataset_id: str): | |
| for row in list_datasets(): | |
| if row["id"] == dataset_id: | |
| return row | |
| return {"status": "NOT_FOUND", "id": dataset_id} | |
| def post_validate(dataset_id: str): | |
| rows = {r["id"]: r for r in list_datasets()} | |
| row = rows.get(dataset_id) | |
| if not row: | |
| return {"status": "NOT_FOUND", "id": dataset_id} | |
| return {"status": row["status"], "source": "TRAINING_DATASET", "dataset": row} | |
| def get_maps(opportunity_id: Optional[str] = None): | |
| return {"maps": list_maps(opportunity_id)} | |
| def get_health(): | |
| try: | |
| return opportunity_health() | |
| except Exception as exc: | |
| from backend.ml.features.maps import AGENT_FOR, OPPORTUNITY_MAPS | |
| maps = {m["opportunity_id"]: m for m in OPPORTUNITY_MAPS} | |
| rows = [] | |
| for i in range(1, 21): | |
| oid = f"O{i}" | |
| primary = maps.get(oid) | |
| trainable = bool(primary and primary.get("training_allowed") and primary.get("target_column")) | |
| rows.append( | |
| { | |
| "opportunity_id": oid, | |
| "agent_id": (primary or {}).get("agent_id") or AGENT_FOR.get(oid), | |
| "dataset_id": (primary or {}).get("dataset_id"), | |
| "dataset_name": None, | |
| "dataset_status": None, | |
| "dataset_quality": None, | |
| "feature_map": (primary or {}).get("feature_map") or {}, | |
| "target": (primary or {}).get("target_column"), | |
| "task_type": (primary or {}).get("task_type"), | |
| "training_allowed": trainable, | |
| "notes": (primary or {}).get("notes") or "No legitimate mapping.", | |
| "missing_dataset": (primary or {}).get("missing_dataset"), | |
| "model_id": None, | |
| "model_version": None, | |
| "status": "MODEL_NOT_TRAINABLE" if oid == "O10" or not trainable else "MODEL_NOT_AVAILABLE", | |
| "validation_status": "N/A", | |
| "metrics": None, | |
| "last_trained": None, | |
| "prediction_availability": "UNAVAILABLE", | |
| "provenance": "TRAINING DATA", | |
| "last_prediction": None, | |
| "training_run": None, | |
| } | |
| ) | |
| return {"opportunities": rows, "source": "TRAINING_DATASET", "datasets": [], "degraded": type(exc).__name__} | |
| def get_models(): | |
| return {"models": list_models(), "source": "TRAINING_DATASET"} | |
| def get_model(opportunity_id: str): | |
| return model_status(opportunity_id) | |
| def post_train(): | |
| from backend.ml.features.maps import trainable_maps | |
| return {"runs": train_all(), "trainable_maps": len(trainable_maps())} | |
| def post_predict(body: PredictBody): | |
| return predict(body.opportunity_id, features=body.features, agent_id=body.agent_id, building_id=body.building_id) | |
| def post_batch(body: Dict[str, Any]): | |
| items = body.get("items") or [] | |
| return {"results": [predict(it.get("opportunity_id"), features=it.get("features") or {}, persist=False) for it in items]} | |
| def get_predictions(opportunity_id: str): | |
| from database.models_ml import MLPredictionDB | |
| from database.session import SessionLocal | |
| db = SessionLocal() | |
| try: | |
| rows = ( | |
| db.query(MLPredictionDB) | |
| .filter_by(opportunity_id=opportunity_id.upper()) | |
| .order_by(MLPredictionDB.created_at.desc()) | |
| .limit(50) | |
| .all() | |
| ) | |
| return { | |
| "predictions": [ | |
| { | |
| "id": r.id, | |
| "status": r.status, | |
| "provenance": r.provenance, | |
| "source": r.source, | |
| "prediction": r.prediction_json, | |
| "confidence": r.confidence, | |
| "created_at": r.created_at.isoformat() if r.created_at else None, | |
| } | |
| for r in rows | |
| ] | |
| } | |
| finally: | |
| db.close() | |