Models and predictions
This page covers the model registry and how to write predictions back as annotations.
Model types
Section titled “Model types”When creating a registry row, model_type must be one of:
CUSTOMOBJECT_DETECTIONCLASSIFICATIONINSTANCE_SEGMENTATIONACTIVITY_DETECTION
Important activation rule
Section titled “Important activation rule”New models are typically stored with is_active = false.
- You can upload weights and inference packages while inactive.
predictions.create_batchrequires an active model (otherwise the API returns 400).
Activate with handle.activate() or pass is_active=True on create when appropriate.
Option A — Pretrained Ultralytics YOLO
Section titled “Option A — Pretrained Ultralytics YOLO”row = project.models.add_pretrained_yolo( weights_filename="yolov8n.pt", name="yolov8n_coco", version="1.0.0", metadata={ "label_ids": [ "11111111-1111-1111-1111-111111111111", "22222222-2222-2222-2222-222222222222", ], "yolo_conf": 0.25, "yolo_iou": 0.45, }, activate=True,)print(row["id"])What this does: asks the server to attach Ultralytics weights and prepare deployment metadata for YOLO-style detection.
Why label_ids matter: they map model class outputs to your project’s schema UUIDs.
Replace the example UUIDs with real IDs from project.schema.get()["schemas"].
Option B — Custom model + inference package
Section titled “Option B — Custom model + inference package”from pathlib import Path
row = project.models.create( name="my_ensemble", version="1.0.0", model_type="CUSTOM", framework="pytorch", metadata={"label_ids": ["…uuid…"]}, is_active=False,)model_id = row["id"]handle = project.models.model(model_id)
handle.upload( model_path=Path("./weights/main.pt"), config_path=Path("./config.json"), # optional)handle.inference_package.upload_package_dir(Path("./my_inference_package"))handle.activate()What this does:
- Creates a registry row.
- Uploads weight artifacts via presigned upload + confirm.
- Uploads an inference package directory (must include your handler code, typically
inference.py). - Activates the model so predictions are allowed.
Diagram: Custom model path — create → upload weights → upload inference package → activate
Custom handlers implement LabeltyInferenceHandler (load / predict). See the SDK’s ML_CUSTOM_MODEL guide in the repository for package layout details.
List, get, download
Section titled “List, get, download”rows = project.models.list(limit=50, offset=0)detail = project.models.get(model_id)project.models.download(model_id, Path("./downloaded.pt"), artifact="model")Publish and reuse inside an organization
Section titled “Publish and reuse inside an organization”publish_row = project.models.publish( model_id=model_id, title="Dental Ensemble v1", summary="Reusable model for dental detection", tags=["dental", "xray", "object-detection"],)
# Attach an org-store model into a projectadded = client.org_models.add_to_project( org_model_id=publish_row["public_model_id"], # field names may vary — inspect the response project_id="target-project-uuid",)Send batch predictions
Section titled “Send batch predictions”Coordinates are normalized between 0 and 1. Each item creates one annotation. Asset status / assignee are not modified.
result = project.predictions.create_batch( model_id=model_id, predictions=[ { "asset_id": "uuid-of-asset", "label_id": "uuid-of-label-schema", "points": [[0.1, 0.1], [0.5, 0.1], [0.5, 0.4], [0.1, 0.4]], "metadata": {"pipeline": "v1"}, }, ],)# response typically includes model_id, annotation_ids, asset_idsWhy normalized points: they stay correct if images are displayed at different pixel sizes in the labeling UI.
Best practices
Section titled “Best practices”- Activate models only when ready for consumers.
- Keep
label_idsin metadata aligned with the current schema. - Prefer small, idempotent scripts for CI prediction ingest.
- For production HTTP inference to external systems, prefer inference workflows rather than ad-hoc prediction scripts.
Next steps
Section titled “Next steps”- Train on approved labels: Training overview
- Or explore interactively: Notebooks