ML-001: Feature Store und erste ML-Tests hinzufügen

This commit is contained in:
2026-06-11 00:21:02 +02:00
parent 2fb086b1a1
commit 627ee03230
3 changed files with 78 additions and 0 deletions

5
app/ml/__init__.py Normal file
View File

@@ -0,0 +1,5 @@
"""Machine-Learning-Grundbausteine für SillyHome Next."""
from app.ml.feature_store import FeatureStore, FeatureVector
__all__ = ["FeatureStore", "FeatureVector"]

31
app/ml/feature_store.py Normal file
View File

@@ -0,0 +1,31 @@
from __future__ import annotations
from collections import defaultdict
from dataclasses import dataclass, field
from typing import Iterable
@dataclass(frozen=True)
class FeatureVector:
sensor_id: str
values: dict[str, float]
label: str | None = None
class FeatureStore:
def __init__(self) -> None:
self._vectors: dict[str, list[FeatureVector]] = defaultdict(list)
def add(self, vector: FeatureVector) -> None:
self._vectors[vector.sensor_id].append(vector)
def add_batch(self, vectors: Iterable[FeatureVector]) -> None:
for vector in vectors:
self.add(vector)
def latest(self, sensor_id: str) -> FeatureVector | None:
series = self._vectors.get(sensor_id)
return series[-1] if series else None
def all(self) -> list[FeatureVector]:
return [vector for vectors in self._vectors.values() for vector in vectors]

View File

@@ -0,0 +1,42 @@
from __future__ import annotations
import pytest
from app.ml.feature_store import FeatureStore, FeatureVector
def _vector(sensor_id: str, temperature: float, label: str | None = None) -> FeatureVector:
return FeatureVector(sensor_id=sensor_id, values={"temperature": temperature}, label=label)
def test_append_and_latest_returns_last_vector() -> None:
store = FeatureStore()
vectors = [_vector("sensor.living_room", 20.0), _vector("sensor.living_room", 21.5)]
for item in vectors:
store.add(item)
assert store.latest("sensor.living_room") == vectors[-1]
def test_latest_returns_none_when_empty() -> None:
store = FeatureStore()
assert store.latest("sensor.living_room") is None
def test_add_batch_appends_all_vectors() -> None:
store = FeatureStore()
vectors = [
_vector("sensor.kitchen", 19.0),
_vector("sensor.kitchen", 20.0),
_vector("sensor.bathroom", 23.5),
]
store.add_batch(vectors)
assert len(store.all()) == 3
assert store.latest("sensor.kitchen").values["temperature"] == 20.0
def test_different_sensors_are_stored_independently() -> None:
store = FeatureStore()
store.add(_vector("sensor.living_room", 21.0))
store.add(_vector("sensor.bedroom", 18.5))
assert store.latest("sensor.living_room").values["temperature"] == 21.0
assert store.latest("sensor.bedroom").values["temperature"] == 18.5