feat(ml,backend): implemente le service de scoring et GET /predictions (#37)

This commit is contained in:
Dorian
2026-09-18 11:06:04 +02:00
parent 3cf9194d4c
commit e9376a98bf
21 changed files with 1369 additions and 19 deletions
+197
View File
@@ -1632,6 +1632,62 @@
}
]
}
},
"/api/v1/predictions": {
"get": {
"tags": [
"predictions"
],
"summary": "Dernière prédiction de consommation par site",
"operationId": "get_predictions_api_v1_predictions_get",
"responses": {
"200": {
"description": "Successful Response",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/PredictionSummaryResponse"
}
}
}
},
"500": {
"description": "Erreur interne. `correlation` identifie la trace côté serveur, qui n'est pas renvoyée au client.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/InternalErrorResponse"
}
}
}
},
"401": {
"description": "Jeton absent, illisible, périmé, ou rendu caduc par un changement de rôle ou une désactivation. L'en-tête `WWW-Authenticate` porte la cause dans `error=`.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
},
"403": {
"description": "Mot de passe provisoire à changer (`detail` vaut `password_change_required`).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
}
},
"security": [
{
"Jeton d'accès": []
}
]
}
}
},
"components": {
@@ -1885,6 +1941,45 @@
],
"title": "PasswordChangeRequest"
},
"PredictionStatus": {
"type": "string",
"enum": [
"available",
"insufficient_data",
"error"
],
"title": "PredictionStatus"
},
"PredictionSummaryResponse": {
"properties": {
"timestamp": {
"type": "string",
"format": "date-time",
"title": "Timestamp"
},
"sites": {
"items": {
"$ref": "#/components/schemas/SitePredictionSummaryResponse"
},
"type": "array",
"title": "Sites"
}
},
"type": "object",
"required": [
"timestamp",
"sites"
],
"title": "PredictionSummaryResponse"
},
"PredictionTargetMetric": {
"type": "string",
"enum": [
"consumption_kwh",
"consumption_kw"
],
"title": "PredictionTargetMetric"
},
"PrincipalResponse": {
"properties": {
"id": {
@@ -2297,6 +2392,104 @@
],
"title": "SensorStatusResponse"
},
"SitePredictionResponse": {
"properties": {
"target_at": {
"type": "string",
"format": "date-time",
"title": "Target At"
},
"target_metric": {
"$ref": "#/components/schemas/PredictionTargetMetric"
},
"period_minutes": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"title": "Period Minutes"
},
"predicted_value": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"title": "Predicted Value"
},
"status": {
"$ref": "#/components/schemas/PredictionStatus"
},
"failure_reason": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Failure Reason"
},
"model_reference": {
"type": "string",
"title": "Model Reference"
},
"created_at": {
"type": "string",
"format": "date-time",
"title": "Created At"
}
},
"type": "object",
"required": [
"target_at",
"target_metric",
"period_minutes",
"predicted_value",
"status",
"failure_reason",
"model_reference",
"created_at"
],
"title": "SitePredictionResponse"
},
"SitePredictionSummaryResponse": {
"properties": {
"site_id": {
"type": "string",
"title": "Site Id"
},
"site_name": {
"type": "string",
"title": "Site Name"
},
"prediction": {
"anyOf": [
{
"$ref": "#/components/schemas/SitePredictionResponse"
},
{
"type": "null"
}
]
}
},
"type": "object",
"required": [
"site_id",
"site_name",
"prediction"
],
"title": "SitePredictionSummaryResponse"
},
"SiteResponse": {
"properties": {
"site_id": {
@@ -2752,6 +2945,10 @@
{
"name": "sensors",
"description": "État de santé des capteurs par site. Réservé au rôle `admin`."
},
{
"name": "predictions",
"description": "Dernière prévision de consommation par site, calculée hors ligne par le pipeline de scoring (`ml/`) et simplement lue ici. Accessible à partir du rôle `lecteur`."
}
]
}