Vai al contenuto

Documentazione Tecnica — Seldon Core v2

🧠 Introduzione

Questa guida tecnica descrive come servire modelli di machine learning utilizzando Seldon Core v2, compatibile con KServe e MLServer, seguendo lo standard Open Inference Protocol v2.

Il "serving" di un modello consiste nel rendere disponibile un modello di machine learning come servizio accessibile tramite API REST. Questo consente di effettuare inferenze (predizioni) in tempo reale, integrando il modello in applicazioni o pipeline di produzione. Seldon Core v2 gestisce il deployment, la scalabilità, il monitoraggio e la versione dei modelli, facilitando l'integrazione con Kubernetes.


🔗 Endpoint Principali

Scopo Metodo Endpoint
Inferenza POST /v2/models/<MODEL>/infer
Metadata modello GET /v2/models/<MODEL>
Health check GET /v2/health/ready, /v2/models/<MODEL>/ready

📦 Schema della Richiesta

{
  "id": "req-1",
  "inputs": [
    {
      "name": "input-0",
      "shape": [1, 4],
      "datatype": "FP32",
      "data": [0.1, 0.2, 0.3, 0.4]
    }
  ]
}
✅ Regole:

-shape: dimensione del tensore (prodotto = numero di elementi)

-datatype: tipo di dato (vedi sotto)

-data: array flat in ordine row-major

📚 Tipi di Dato Supportati

Tipo Descrizione
InFP32/FP64 Float
INT32/64 Interi
BOOL Booleani
BYTES Stringhe o immagini (con parameters.content_type)

⚙️ Esempi di Richieste

🔢 Numerico

curl -X POST "https://<host>/v2/models/my-sklearn/infer" \
  -H "Content-Type: application/json" \
  -d '{"inputs":[
    {"name":"input-0",
    "shape":[1,4],
    "datatype":"FP32",
    "data":[5.1,3.5,1.4,0.2]
    }
   ]
  }

📝 Testo (BYTES)

curl -X POST "https://<host>/v2/models/my-nlp/infer" \
  -H "Content-Type: application/json" \
  -d '{"inputs":[{"name":"text","shape":[1],"datatype":"BYTES","parameters":{"content_type":"str"},"data":["hello world"]}]}'

🖼️ Immagine (base64)

curl -X POST "https://<host>/v2/models/cifar10/infer" \
  -H "Content-Type: application/json" \
  -d '{"inputs":[
    {
      "name":"image",
      "shape":[1,3,32,32],
      "datatype":"BYTES",
      "parameters":{"content_type":"base64"},
      "data":["$B64"]
      }
    ]
  }
  ```

📤 Output Esempio


```json
{
  "model_name": "my-sklearn",
  "id": "req-1",
  "outputs": [
    {
      "name": "probabilities",
      "shape": [1, 3],
      "datatype": "FP32",
      "data": [0.1, 0.7, 0.2]
    }
  ]
}

✅ Checklist Rapida

  • shape coerente con i dati
  • datatype corretto (BYTES per testo/immagini)
  • parameters.content_type per stringhe/base64
  • dimensione batch → prima dimensione ([N, …])

📘 Tip

Puoi recuperare gli inputs attesi con:

curl https://<host>/v2/models/<MODEL>

e usare i relativi name, shape, datatype per costruire il body corretto.

LATO SVILUPPO SERVIZI

Se il servizio fa uso del tracking e del salvataggio con MlFlow basta avere alcune accortezze:

• Impostare sempre la signature con mlflow.models.infer_signature( X_train, y_train)

• Far uso di pandas dataframe in fase di addestramento così da avere l'informazione sui nomi delle feature

• Se il modello include una pipeline di trasformazione ricordarsi in fase di inferenza che la trasformazione verrà applicata direttamente, quindi non occorre trasformare i dati

📘FORMAT SKLEARN

(mlflow supporta i modelli sklearn, quindi potrebbe essere conveniente farne uso così da non aver bisogno dei seguenti passaggi)

Obiettivo: Permettere a MLServer (runtime mlserver_sklearn.SKLearnModel) di caricare il modello joblib o pkl, e pubblicare lo schema I/O su /v2/models/{name} (vecchio Model Metadata).

📁 Posizionamento

Il file model-settings.json deve essere salvato nella stessa cartella del file modello (model.joblib) e caricato su MinIO.

Quando Seldon la scarica nel Pod, MLServer trova entrambi i file nello stesso percorso.

📄 Esempio Campi fondamentali:

{
  "name": "model-<MODEL_ID>",
  "implementation": "mlserver_sklearn.SKLearnModel",
  "parameters": {
    "uri": "./model.joblib",
    "content_type": "np",
    "task_type": "classification",
    "feature_names": ["feature1", "feature2"]
  },
  "inputs": [
    {
      "name": "features",
      "datatype": "FP32",
      "shape": [-1, 27]
    }
  ],
  "outputs": [
    {
      "name": "label",
      "datatype": "INT64",
      "shape": [-1, 1]
    }
  ]
}

📘 Descrizione dei Campi Principali

Campo Target Descrizione
name nome del modello deve corrispondere a quello usato da Seldon (es. model-123)
implementation runtime MLServer da usare per modelli sklearn → mlserver_sklearn.SKLearnModel
parameters.uri percorso locale del file modello es. ./model.joblib
parameters.content_type tipo iput accettato np: tensore numerico (JSON) o pd: formato colonnare (stringhe o misti) o str: lista di stringhe
parameters.task_type tipo di task (solo informativo) regression, classification, clustering
parameters.feature_names opzionale utile per modelli con colonne stringa o miste
inputs descrive gli ingressi (nome, tipo e shape)
outputs descrive gli output (nome, tipo e shape)

📘 Esempi di Input Caso A — Tabellare numerico

"parameters": { "uri": "./model.joblib", "content_type": "np" },
"inputs": [
  { "name": "features", "datatype": "FP32", "shape": [-1, 27] }
]
Caso B - Pipeline con colonne stringa o miste
"parameters": {
"uri": "./model.joblib",
"content_type": "pd",
"feature_names": ["city","gender","segment"]
},
"inputs": [
{ "name": "city", "datatype": "BYTES", "shape": [-1] },
{ "name": "gender", "datatype": "BYTES", "shape": [-1] },
{ "name": "segment", "datatype": "BYTES", "shape": [-1] }
]
Caso C - Pipeline che si aspetta testo grezzo (una sola feature stringa)
"parameters": { "uri": "./model.joblib", "content_type": "str" },
"inputs": [
{ "name": "text", "datatype": "BYTES", "shape": [-1] }
]

📘 Linee guida per outputs:

Gli outputs descrivono il formato dei risultati che il modello produce.

Ogni elemento in "outputs" è definito da:

• name: nome logico dell’output (pred, label, proba, scores); non ha alcun effetto sull'inferenza, serve solo a "formattare" la risposta di seldon

• datatype: tipo del dato restituito (FP32, INT64)

• shape: dimensione del tensore, con -1 per il batch

I campi dichiarati nella sezione "outputs" del file servono solo a documentare lo schema, ma non influenzano i valori effettivamente calcolati.

Se si dichiara output che il modello non produce, non compaiono nella risposta di /infer, ma restano visibili nel metadata.

Usare nomi coerenti con il tipo di modello

• (pred, label)

• impostare shape coerente: [-1,1] per valori scalari, [-1,K] per vettori di K classi