Register a Model
A model enters the registry in one of four ways:
| Way | Where | What it brings |
|---|---|---|
| Publish an AutoML job's model | Publish to Registry on a completed job | Its task, metric, classes, inputs, results, leaderboard and feature importance, and a drift baseline built automatically (see Results and publishing) |
| Register an experiment run's model | Register model on a run that logged a model | The run's params, metrics, machine and the task log_model recorded (see Register a run's model) |
| Upload a model file | Upload Model | One trained model file the platform serves for you |
| Upload a model bundle | Upload Model | Your 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:
| File | Framework |
|---|---|
.joblib, .pkl, .pickle | scikit-learn, XGBoost, LightGBM, or another Python model (pickle) |
.pt, .pth | PyTorch, saved as TorchScript (torch.jit.save) |
.onnx | ONNX |
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
.joblibor.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:
GETon the health path (default/health) with a 200 once the model is loaded.POSTonml.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;predictionfor a single value also works). A model whose answer has another shape declares which field is its prediction and which its score underml.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.