Skip to main content

Register a Model

A model enters the registry in one of four ways:

WayWhereWhat it brings
Publish an AutoML job's modelPublish to Registry on a completed jobIts task, metric, classes, inputs, results, leaderboard and feature importance, and a drift baseline built automatically (see Results and publishing)
Register an experiment run's modelRegister model on a run that logged a modelThe run's params, metrics, machine and the task log_model recorded (see Register a run's model)
Upload a model fileUpload ModelOne trained model file the platform serves for you
Upload a model bundleUpload ModelYour model with its own serving code and Dockerfile

Each is registered as version 1. A published AutoML model is deployed at once (it moves through Building to Running); the others are Ready to Deploy until you select Deploy. Add Version on the model's Versions tab adds the next version the same way (see Versions).

Upload a model file​

Select Upload Model and choose one trained model file. The platform builds its server and serves it with exactly what it was saved with:

FileFramework
.joblib, .pkl, .picklescikit-learn, XGBoost, LightGBM, or another Python model (pickle)
.pt, .pthPyTorch, saved as TorchScript (torch.jit.save)
.onnxONNX

Model File Details asks for what serving the file needs:

  • Framework: one its file type is served as.
  • Library version (scikit-learn, XGBoost, LightGBM, PyTorch): the version the model was saved with, sklearn.__version__ for example. A pickle loads reliably only in the library version that wrote it.
  • Python version (a .joblib or .pkl): the Python the model was saved with. The model is served on that Python, whatever environment you pick for its resources.
  • Task: what the model predicts (classification, regression, ...). Drift and actuals score it by its task.
  • Inputs: each input's name and type, in the order the model takes them. Predictions are fed in this order, and the Test tab and drift use these names.
  • Extra requirements (optional): pip packages the model imports beyond its framework, one per line (category-encoders==2.6.3, for a pipeline's custom transformer).

A file uploaded without one of these is refused, naming what is missing. Environment Variables you add are set on the model's serving pod. Add Version on a model uploads its next file the same way, starting from the model's inputs.

From Python:

import sys, sklearn

model = client.model_registry.create_with_upload(
"model.joblib",
name="churn-rf",
framework="sklearn",
framework_version=sklearn.__version__,
python_version=sys.version.split()[0],
problem_type="classification",
feature_names=["tenure", "monthly_spend"],
input_fields=[{"name": "tenure", "type": "int"}, {"name": "monthly_spend", "type": "float"}],
)
client.model_registry.deploy(model.id)

Upload a model bundle​

Select Upload Model, give the model a Model Name (and optionally a Description and Algorithm), choose the bundle, pick an Environment for its resources and the number of Instances, and select Upload Model. The model is registered as version 1, Ready to Deploy. Deploy builds the bundle's image with its own Dockerfile and starts it.

A bundle is a .zip with these files at its root (or one folder down):

model.joblib              # your trained model, in any format your code loads
app.py # the HTTP server that serves it
requirements.txt
Dockerfile # builds the serving image; the platform uses it as it is
strongly.manifest.yaml # how to run it, and the model's card

The serving contract. The container listens on the port the manifest declares and answers:

  • GET on the health path (default /health) with a 200 once the model is loaded.
  • POST on ml.predict_path (default /predict) with the caller's input as the JSON body: one row as an object, or a list of rows. It answers {"predictions": [...], "probabilities": [[...], ...]} (one prediction per row; prediction for a single value also works). A model whose answer has another shape declares which field is its prediction and which its score under ml.schema.output (prediction, score), so drift and actuals can score it.

A minimal Flask server for a scikit-learn classifier:

import joblib
import pandas as pd
from flask import Flask, jsonify, request

FEATURES = ["sepal_length", "sepal_width", "petal_length", "petal_width"]
model = joblib.load("model.joblib")
app = Flask(__name__)

@app.get("/health")
def health():
return jsonify(status="ok")

@app.post("/predict")
def predict():
body = request.get_json()
rows = body if isinstance(body, list) else [body]
frame = pd.DataFrame(rows)[FEATURES]
return jsonify(predictions=[int(p) for p in model.predict(frame)],
probabilities=model.predict_proba(frame).tolist())

with a Dockerfile such as:

FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "--workers", "2", "app:app"]

The manifest. type and ml.framework are required; everything under ml fills the model's page (Overview, Metrics, Features) and tells drift and actuals the model's task:

version: "1.0"
type: flask # flask, custom, ...: the kind of container
ports:
- port: 8000
health_check:
path: /health
ml:
framework: sklearn # sklearn, xgboost, lightgbm, pytorch, tensorflow, onnx, transformers, custom
problem_type: multiclass # classification, regression, multiclass, multilabel, timeseries, other
predict_path: /predict
features:
feature_names: [sepal_length, sepal_width, petal_length, petal_width]
target_name: species
dataset:
name: iris
num_samples: 150
num_classes: 3
class_labels: ["0", "1", "2"]
training:
predictor_type: LogisticRegression
hyperparameters:
max_iter: 500
metrics:
test_score: 0.974
classification:
accuracy: 0.974
schema:
input:
fields:
- {name: sepal_length, type: float, required: true}
- {name: sepal_width, type: float, required: true}
- {name: petal_length, type: float, required: true}
- {name: petal_width, type: float, required: true}

The model is named and described by what you enter when you upload it; a name or description in the manifest stays with the bundle. A manifest that does not match this shape is refused at upload, naming the field to fix.