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.
No comments to display
No comments to display