Upload a trained model
Turn a fitted scikit-learn, Keras or PyTorch model into a registered Kaimei model with one call.
client.models.upload(estimator, name=…) reads the live estimator in your process, extracts its layers and learned weights into a kaimei.structure.v1 spec, registers the model and uploads the spec. Small tensors travel inline as JSON; anything above externalize_above values (default 65,536) streams as a zlib-compressed float32 blob referenced from the spec, so models with millions of parameters upload at about four bytes per weight. The original .h5, .pt or pickle is never sent.
Arguments
A fitted scikit-learn estimator or pipeline, a Keras model, a torch.nn.Module, or a wrapper that stores one on a conventional attribute (model_, estimator_, best_estimator_, module).
Display name. The slug is derived from it unless you pass slug.
Input names, or a full feature schema. Optional when the estimator knows its names (feature_names_in_, a DataFrame).
Inferred from the estimator when omitted. Pass outputs={"labels": [...]} to name the classes.
Reference rows (capped at 5,000) and optional labels, uploaded after the model is created.
{"type": "remote", "url": ...} for models Kaimei cannot execute itself."full" or "summary", which uploads shapes and statistics only: the architecture is drawable, the weights never leave your environment, and explanations need a remote URL.Values per tensor above which it uploads as binary. None keeps everything inline.
progress(stage, done, total), called while tensors upload (stage is "tensors" then "structure").Image models in PyTorch: (channels, height, width). Keras models report their own.
{"mean": [...], "std": [...]} baked into the graph for torchvision-style models that expect Normalize on [0, 1] pixels.[0, 255] when callers send and the model reads 0 to 255 pixels (a Keras Rescaling(1/255) model, for example).As for POST /v1/models.
| Estimator | What is uploaded | Executable |
|---|---|---|
sklearn linear models | Exact coef_ / intercept_ | Yes |
sklearn MLPClassifier / MLPRegressor | Exact layers | Yes |
sklearn tree | Full node list | Yes |
sklearn forest / extra trees | Trees if ≤ 30 estimators and ≤ 4,000 nodes; otherwise feature importances | Only when trees are inlined |
sklearn Pipeline + StandardScaler / MinMaxScaler | Scaler folded or inserted, then the estimator | As the final step |
Keras / TensorFlow | Dense, Conv2D (any stride, padding, dilation, groups), Depthwise/SeparableConv2D, BatchNormalization, pooling, Add, Multiply, Concatenate, ZeroPadding2D, Rescaling, Normalization, Flatten, Dropout, LayerNorm; functional graphs and nested models | Yes, unless a layer is unrecognised |
torch.nn CNNs | Traced with torch.fx: Conv2d, BatchNorm2d, pooling, residual +, torch.cat, squeeze-excitation *, Flatten and the common activations (ResNet, MobileNet, EfficientNet, DenseNet, VGG, SqueezeNet) | Yes, with input_shape |
torch.nn dense nets | Linear, activations, Dropout, LayerNorm, Embedding, BatchNorm1d, in forward-hook order | Yes, unless a layer is unrecognised |
XGBoost / LightGBM / CatBoost | feature_importances_ summary | No: pass inference or attributions |
ONNX, Hugging Face, LLMs | Framework label only | No |
Unknown Keras or PyTorch layers that keep their input's shape are passed through and the spec is marked approximate: it visualises but cannot be queried without a remote URL. Shape-changing operations that cannot be replayed (a channel shuffle, an upsampling decoder) raise StructureError(code="unsupported_layers") naming them. kaimei.extract_structure(estimator, …) returns the spec and tensors without uploading; client.models.upload_structure(model, estimator_or_spec) attaches weights to a model you already registered.
from kaimei import Kaimei
client = Kaimei()
# a scikit-learn model with its validation rows as the reference population
model = client.models.upload(
clf,
name="Churn net",
feature_names=list(X_valid.columns),
X=X_valid, y=y_valid,
outputs={"labels": ["stay", "churn"]},
tags=["lifecycle"],
)
print(model.slug, model.framework) # churn-net sklearn
# a model Kaimei cannot run: draw it, score it through your endpoint
client.models.upload(
xgb_model,
name="Churn forest",
inference={"type": "remote", "url": "https://scoring.example.com/predict"},
)
# a PyTorch CNN: give the input size, bake in the normalization
client.models.upload(
resnet,
name="Defect classifier",
task="multiclass_classification",
outputs={"labels": ["ok", "scratch", "dent"]},
input_shape=(3, 224, 224),
preprocess={"mean": [0.485, 0.456, 0.406], "std": [0.229, 0.224, 0.225]},
X=sample_images, # (n, 3, 224, 224) or (n, 224, 224, 3)
progress=lambda stage, done, total: print(stage, done, "/", total),
)
# weights that must stay private: shapes and statistics only
client.models.upload(net, name="Pricing net", weights="summary",
inference={"type": "remote", "url": "https://..."})