@@ -87,12 +87,16 @@ def test_retrain_creates_and_replaces_persisted_model(tmp_path: Path) -> None:
|
||||
assert created.json() == {
|
||||
"model_id": "home-model",
|
||||
"supported_sensors": ["sensor.kitchen"],
|
||||
"trained_features": 1,
|
||||
"model_type": "statistical_baseline",
|
||||
"replaced": False,
|
||||
}
|
||||
assert replaced.status_code == 200
|
||||
assert replaced.json() == {
|
||||
"model_id": "home-model",
|
||||
"supported_sensors": ["sensor.bedroom"],
|
||||
"trained_features": 1,
|
||||
"model_type": "statistical_baseline",
|
||||
"replaced": True,
|
||||
}
|
||||
restarted = ModelRegistry(tmp_path)
|
||||
@@ -107,3 +111,70 @@ def test_retrain_rejects_empty_samples() -> None:
|
||||
)
|
||||
|
||||
assert response.status_code == 422
|
||||
|
||||
|
||||
def test_predict_returns_numeric_forecast_and_confidence(tmp_path: Path) -> None:
|
||||
from app.ml.feature_store import FeatureStore, FeatureVector
|
||||
from app.ml.registry.model_registry import ModelRegistry
|
||||
from app.ml.training import TrainingPipeline
|
||||
|
||||
store = FeatureStore()
|
||||
store.add_batch(
|
||||
[
|
||||
FeatureVector("sensor.kitchen", {"temperature": 19.0}),
|
||||
FeatureVector("sensor.kitchen", {"temperature": 20.0}),
|
||||
]
|
||||
)
|
||||
registry = ModelRegistry(tmp_path)
|
||||
registry.register(TrainingPipeline(store).run("home-model"))
|
||||
|
||||
with TestClient(app) as client:
|
||||
app.state.registry = registry
|
||||
response = client.post(
|
||||
"/ml/predict",
|
||||
json={
|
||||
"modelId": "home-model",
|
||||
"sensor_id": "sensor.kitchen",
|
||||
"values": {"temperature": 21.0},
|
||||
},
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
assert response.json()["predictions"] == {"temperature": 22.0}
|
||||
assert 0.0 < response.json()["confidence"] <= 1.0
|
||||
assert response.json()["model_type"] == "statistical_baseline"
|
||||
|
||||
|
||||
def test_evaluate_returns_real_error_metrics(tmp_path: Path) -> None:
|
||||
from app.ml.feature_store import FeatureStore, FeatureVector
|
||||
from app.ml.registry.model_registry import ModelRegistry
|
||||
from app.ml.training import TrainingPipeline
|
||||
|
||||
store = FeatureStore()
|
||||
store.add_batch(
|
||||
[
|
||||
FeatureVector("sensor.kitchen", {"temperature": 19.0}),
|
||||
FeatureVector("sensor.kitchen", {"temperature": 20.0}),
|
||||
]
|
||||
)
|
||||
registry = ModelRegistry(tmp_path)
|
||||
registry.register(TrainingPipeline(store).run("home-model"))
|
||||
|
||||
with TestClient(app) as client:
|
||||
app.state.registry = registry
|
||||
response = client.post(
|
||||
"/ml/evaluate",
|
||||
json={
|
||||
"modelId": "home-model",
|
||||
"samples": [
|
||||
{
|
||||
"sensor_id": "sensor.kitchen",
|
||||
"values": {"temperature": 21.0},
|
||||
}
|
||||
],
|
||||
},
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
metrics = {metric["name"]: metric["value"] for metric in response.json()["metrics"]}
|
||||
assert metrics == {"mae": 1.0, "rmse": 1.0, "coverage": 1.0}
|
||||
|
||||
Reference in New Issue
Block a user