Skip to main content

Guide Lines

Linee guida di sviluppo e rilascio servizi

1. Scopo

Ogni servizio ML deve essere sviluppato e rilasciato come un normale servizio software containerizzato, mantenendo però separati e tracciabili:

codice applicativo+modello+configurazione\text{codice applicativo} + \text{modello} + \text{configurazione}

Una release deve permettere di identificare senza ambiguità:

Git commit
Docker image + digest
Model name + version + hash
Model format/precision
Runtime
Configuration

Gli ambienti standard sono:

DEV → COLLAUDO → PROD

La stessa immagine Docker e lo stesso model artifact validati in collaudo devono essere promossi in produzione. Non devono essere ricostruiti.


2. Architettura standard

Ogni servizio ML espone una propria API FastAPI ed esegue l'inferenza direttamente nel container.

Client
  ↓
FastAPI
  ↓
Preprocessing
  ↓
Inference Runtime
  ↓
Postprocessing
  ↓
Response

Sulle VM NVIDIA il servizio viene eseguito tramite Docker/Compose con accesso alla GPU.

Non viene introdotto un model server centralizzato salvo esigenze future.

Runtime raccomandati:

Caso Runtime
sviluppo/compatibilità specifica PyTorch
deployment generico ONNX Runtime
NVIDIA ottimizzato ONNX Runtime CUDA / TensorRT
esigenze particolari motivate e documentate

3. Struttura repository

Struttura raccomandata:

project/
├── src/
│   ├── api/
│   ├── inference/
│   │   ├── engine.py
│   │   ├── preprocessing.py
│   │   └── postprocessing.py
│   ├── core/
│   │   └── settings.py
│   └── main.py
│
├── tests/
│   ├── unit/
│   ├── integration/
│   ├── model/
│   └── performance/
│
├── deploy/
│   └── compose.yml
│
├── scripts/
│   ├── fetch_model.py
│   ├── validate_model.py
│   └── benchmark_model.py
│
├── model/
│   └── model-manifest.yaml
│
├── Dockerfile
├── pyproject.toml
├── .gitlab-ci.yml
├── AGENTS.md
└── README.md

I pesi del modello non devono normalmente essere salvati nel repository Git.


4. Gestione del modello

Il modello è un artifact indipendente dall'immagine applicativa.

Default:

GitLab Model Registry / Artifact Registry
             ↓
       model version
             ↓
        deploy job
             ↓
      VM model cache
             ↓
mount read-only nel container

Il deploy deve recuperare una versione esatta, mai latest.

Esempio:

MODEL_NAME=ppe-detector
MODEL_VERSION=2.3.1
MODEL_SHA256=...
MODEL_FORMAT=onnx
MODEL_PRECISION=fp16

Il modello viene scaricato prima dell'avvio del nuovo container, verificato tramite hash e montato read-only.

Se la versione è già presente nella cache della VM e l'hash coincide, può essere riutilizzata.

Incorporare il modello nella Docker image è ammesso solo quando modello e codice hanno un ciclo di rilascio necessariamente indivisibile o per servizi molto semplici. Deve essere una scelta esplicita.


5. Model manifest

Ogni model artifact deve avere metadata associati almeno equivalenti a:

name: ppe-detector
version: 2.3.1

format: onnx
precision: fp16
sha256: ...

base_model: ...

input:
  shape: ...
  dtype: ...
  color_space: RGB

preprocessing_version: "1"
postprocessing_version: "2"

training:
  dataset_version: ...
  git_commit: ...

metrics:
  primary_metric: ...
  value: ...

runtime:
  recommended: onnxruntime-gpu

Preprocessing e postprocessing fanno parte del contratto del modello.

Una modifica incompatibile dell'input/output deve comportare una nuova versione major del model contract.


6. Ottimizzazione del modello

Il modello utilizzato durante il training non è automaticamente il modello da utilizzare in produzione.

Flusso raccomandato:

training artifact
      ↓
baseline benchmark
      ↓
export
      ↓
ONNX
      ↓
equivalence test
      ↓
FP16 / graph optimization
      ↓
benchmark
      ↓
eventuale INT8 / TensorRT
      ↓
quality + performance gate
      ↓
deployment artifact

Ogni ottimizzazione deve essere giustificata da una misura.

Devono essere confrontati almeno:

qualità modello
latenza
throughput
RAM
VRAM
dimensione artifact

FP16 è la prima ottimizzazione da valutare sulle GPU NVIDIA.

INT8 è ammesso solo con calibration dataset rappresentativo e verifica della perdita di qualità.

TensorRT è ammesso quando il miglioramento giustifica la maggiore dipendenza da GPU, CUDA, TensorRT e build environment.

Non è consentito sostituire il deployment artifact senza regression test rispetto al modello di riferimento.


7. API obbligatorie

Ogni servizio deve esporre almeno:

GET /health/live
GET /health/ready
GET /info
GET /metrics

/health/live

Verifica esclusivamente che il processo applicativo sia vivo.

Non deve eseguire inferenze complete.

/health/ready

Restituisce 200 solamente se:

modello caricato
hash verificato
runtime inizializzato
GPU disponibile se obbligatoria
warmup completato
dipendenze indispensabili disponibili

Se il servizio richiede GPU, il fallback silenzioso su CPU non è consentito salvo configurazione esplicita.

/info

Deve rendere disponibili almeno:

{
  "app_version": "...",
  "git_sha": "...",
  "model_name": "...",
  "model_version": "...",
  "model_format": "...",
  "precision": "...",
  "runtime": "..."
}

Non deve esporre secret.

/metrics

Deve essere compatibile con il sistema di monitoring adottato e separare almeno tempi HTTP e tempi effettivi di inferenza.


8. Warmup

Il modello deve essere caricato prima che il servizio risulti ready.

Quando necessario deve essere effettuato un warmup:

process start
    ↓
load model
    ↓
initialize CUDA/runtime
    ↓
warmup inference
    ↓
READY

Il traffico non deve raggiungere una nuova istanza prima del completamento.


9. Logging

Il logging applicativo deve essere strutturato, preferibilmente JSON, e scritto su stdout/stderr.

Ogni inference deve poter essere correlata tramite un request_id.

Campi raccomandati:

timestamp
level
service
request_id
git_sha
model_name
model_version
latency_ms
preprocess_ms
inference_ms
postprocess_ms
status
error_type

Immagini, video o payload sensibili non vengono loggati automaticamente.

Eventuali log degli output ML devono essere campionati o aggregati per evitare volumi ingestibili.

Non utilizzare request_id, user id o valori ad alta cardinalità come label Prometheus.


10. Monitoring

Ogni servizio deve permettere di monitorare quattro livelli.

Livello Metriche
Container/VM CPU, RAM, restart, disk
GPU utilization, VRAM, temperatura
API request rate, error rate, P50/P95/P99
ML preprocess, inference, postprocess, confidence/output distribution

Quando significativo devono essere aggiunte metriche di dominio.

Esempio CV:

FPS
frames dropped
detections/frame
confidence distribution
invalid frames
blur/brightness
queue length

Lo stato HTTP 200 non è sufficiente per considerare sano un sistema ML.


11. Docker

Le immagini devono essere costruite esclusivamente dalla CI.

In collaudo e produzione il Compose deve utilizzare:

image: registry/...@sha256:...

o una versione immutabile equivalente.

Sulle VM remote non deve essere presente:

build:

La stessa image digest deve attraversare:

COLLAUDO → PROD

Il container deve essere il più possibile minimale, eseguito come utente non root e privo delle dipendenze di training quando non necessarie all'inference.


12. Configurazione

La configurazione varia tra ambienti, gli artifact no.

image = immutabile
model = immutabile
configuration = environment-specific

Secret, token di registry e credenziali devono provenire da GitLab CI/CD Variables o dal sistema di secret adottato.

Non devono essere versionati file .env contenenti credenziali.


13. Pipeline GitLab

Pipeline minima:

quality
   ↓
tests
   ↓
model validation
   ↓
build image
   ↓
push registry
   ↓
deploy COLLAUDO [manual]
   ↓
smoke/integration/performance test
   ↓
deploy PROD [manual]

La CI deve almeno verificare:

lint/type checks
unit tests
API tests
model loading
model contract
representative inference
model equivalence se esportato/ottimizzato
Docker build

Il deployment in collaudo e produzione deve utilizzare la stessa Docker image già costruita.

GitLab raccomanda anch'esso tag immutabili basati sul commit invece di costruire direttamente su latest.


14. Collaudo

Il collaudo deve riprodurre quanto più possibile la configurazione di produzione.

Prima della promozione devono essere verificati:

container health
GPU/runtime
model version
API contract
representative inference
logging
metrics
latency
VRAM
assenza di regressioni note

Il deploy PROD è consentito solamente dopo il superamento del collaudo.


15. Release manifest

Ogni rilascio deve produrre un manifest equivalente a:

service: ppe-service
release: 3.4.0

git_sha: 7e91ac2

image:
  digest: sha256:...

model:
  name: ppe-detector
  version: 2.3.1
  sha256: ...
  format: onnx
  precision: fp16

Questo è il riferimento per deploy, incident analysis e rollback.


16. Rollback

Il rollback non deve richiedere una nuova build.

Deve essere sufficiente ripristinare:

previous IMAGE_DIGEST
previous MODEL_VERSION

Le VM devono mantenere almeno le versioni recenti necessarie a effettuare un rollback rapido.


17. Definition of Done

Un servizio ML non è pronto al rilascio se manca uno di questi elementi:

container riproducibile
modello versionato
model manifest
health/live
health/ready
info endpoint
metrics
structured logging
test inferenza
CI
compose
collaudo
release manifest
rollback definito

La performance ML, la performance software e l'operabilità in produzione sono tutte parte della qualità del servizio.