feat(etl): ordonnance la détection d'alertes et les recommandations par un DAG Airflow
Le DAG `alertes` enchaîne `app.detection.internal_alerts` puis `app.cli generate-recommendations`, à la quinzième minute de chaque heure. Le décalage laisse finir `ml_score`, qui écrit à l'heure pile les prédictions dont la règle `anomaly` a besoin, sans créer de dépendance entre les deux DAGs : quatre règles de détection sur cinq ne touchent pas au modèle, et un modèle jamais entraîné ne doit pas priver le parc de ses alertes. L'image Airflow porte un second environnement uv, `/opt/backend/.venv`, puisque la logique vit dans le backend (ADR 0006) et qu'aucune route HTTP ne l'expose. Le `UV_PROJECT_ENVIRONMENT` global hérité de l'issue #115 disparaît : il vaut pour tous les projets, donc `uv run` depuis `/opt/ml` résolvait le venv du backend. uv prend `<projet>/.venv` par défaut, se placer dans le dossier suffit. La CI vérifie maintenant que les deux environnements s'importent sans réseau. Le conteneur reçoit `DATABASE_URL` en asyncpg et une `APP_SECRET_KEY` distincte de celle de l'API, alimentée par `AIRFLOW_APP_SECRET_KEY` : la détection ne signe aucun jeton, et Airflow permet d'exécuter du code depuis son interface.
This commit is contained in:
+19
-7
@@ -1,7 +1,8 @@
|
||||
# Image Airflow EnerVision : ajoute le projet ml/ dans son propre environnement Python 3.14,
|
||||
# distinct du Python 3.12 qui fait tourner Airflow lui-meme (apache-airflow 2.10 ne supporte pas
|
||||
# 3.14), pour que les DAGs puissent lancer `uv run python -m enervision_ml.train`/`.score` en
|
||||
# sous-processus. Airflow ne devient jamais un consommateur direct de LightGBM/MLflow.
|
||||
# Image Airflow EnerVision : ajoute ml/ et apps/backend/ dans leurs propres environnements Python
|
||||
# 3.14, distincts du Python 3.12 qui fait tourner Airflow lui-meme (apache-airflow 2.10 ne supporte
|
||||
# pas 3.14), pour que les DAGs puissent lancer `uv run python -m enervision_ml.train`/`.score`,
|
||||
# `app.detection.internal_alerts` et `app.cli` en sous-processus. Airflow ne devient jamais un
|
||||
# consommateur direct de LightGBM, de MLflow ou du SQLAlchemy du backend. Cf. ADR 0008.
|
||||
FROM apache/airflow:2.10.4-python3.12
|
||||
|
||||
# LightGBM est compile contre libgomp (OpenMP), absent de l'image de base (minimale, sans
|
||||
@@ -16,7 +17,8 @@ RUN apt-get update \
|
||||
# `ml_train` et `ml_score` (le modele ecrit par l'un, lu par l'autre). Un volume nomme herite des
|
||||
# permissions du repertoire qu'il recouvre a son premier montage ; sans ce chown prealable, il
|
||||
# serait cree root:root et illisible par le conteneur, qui tourne en `airflow` (uid 50000).
|
||||
RUN mkdir -p /opt/ml/state && chown -R airflow:root /opt/ml
|
||||
# `/opt/backend` ne porte aucun volume, mais `WORKDIR` le creerait root meme sous `USER airflow`.
|
||||
RUN mkdir -p /opt/ml/state /opt/backend && chown -R airflow:root /opt/ml /opt/backend
|
||||
USER airflow
|
||||
|
||||
# L'image de base embarque deja un `uv`, mais trop ancien (0.4.29) pour le format de verrou de
|
||||
@@ -24,9 +26,10 @@ USER airflow
|
||||
# (apps/backend/Dockerfile).
|
||||
COPY --from=ghcr.io/astral-sh/uv:0.11.26 /uv /home/airflow/.local/bin/uv
|
||||
|
||||
# Piege : pas de `UV_PROJECT_ENVIRONMENT` global. Il vaudrait pour les deux projets, et `uv run`
|
||||
# dans l'un resoudrait le venv de l'autre. Par defaut, uv prend `<projet>/.venv`, donc le bon.
|
||||
ENV UV_COMPILE_BYTECODE=1 \
|
||||
UV_LINK_MODE=copy \
|
||||
UV_PROJECT_ENVIRONMENT=/opt/ml/.venv
|
||||
UV_LINK_MODE=copy
|
||||
|
||||
WORKDIR /opt/ml
|
||||
|
||||
@@ -36,4 +39,13 @@ RUN uv sync --locked --no-install-project --no-dev
|
||||
COPY --chown=airflow:root ml/enervision_ml ./enervision_ml
|
||||
RUN uv sync --locked --no-dev
|
||||
|
||||
WORKDIR /opt/backend
|
||||
|
||||
# `packages = ["app"]` : le reste de apps/backend (alembic, tests) n'a rien a faire dans l'image.
|
||||
COPY --chown=airflow:root apps/backend/pyproject.toml apps/backend/uv.lock ./
|
||||
RUN uv sync --locked --no-install-project --no-dev
|
||||
|
||||
COPY --chown=airflow:root apps/backend/app ./app
|
||||
RUN uv sync --locked --no-dev
|
||||
|
||||
WORKDIR /opt/airflow
|
||||
|
||||
Reference in New Issue
Block a user