v0.21.2
Added
- Benchmark versioning / lineage.
create_benchmark()acceptsparent_benchmark_idto create a new version downstream of an existing benchmark: the child inherits the parent's items, the source arguments add on top, andremoved_item_idsprune inherited items (parent ∪ added ∖ removed). Version defaults to a minor bump; passbump_type="major"or explicitversion_major+version_minor(must exceed the parent's).Benchmarknow exposesparent_benchmark_id,version_major,version_minor, andversion_label. - Draft benchmarks.
create_benchmark(..., draft=True)creates a mutable draft (sources optional). Add items across many calls withBenchmark.add_items()/NucleusClient.add_benchmark_items()(async, same sources as create), remove withBenchmark.remove_items()/NucleusClient.remove_benchmark_items(), then freeze withBenchmark.finalize()/NucleusClient.finalize_benchmark(). A draft cannot be evaluated until finalized; a finalized benchmark is immutable (make a new version instead). NucleusClient.merge_model_runs(). Merges two or more model runs into one new run holding the union of their predictions, leaving the sources untouched. A benchmark evaluation names a single model run and a benchmark's items may span datasets, so a model uploaded as several runs previously had no single run covering the benchmark — every uncovered item scored as a false negative. Merge first, wait for the copy to finish, then pass the new run tocreate_benchmark_evaluation_v2(). All source runs must belong to the same model.
The copy runs asynchronously: the call returns {"model_run_id", "dataset_ids", "job"} immediately, but the new run is empty until the job completes — call job.sleep_until_complete() before evaluating. The merge is a full union: predictions are copied, never deduplicated, and colliding annotation_ids are rewritten rather than dropped. Copy counts (predictions_copied, predictions_ignored, annotation_ids_rewritten) are reported on the job.
Model.create_run(name)+ModelRun.add_predictions(predictions, ...). Create a model run with just a name, then attach predictions — no dataset needed up front:Each prediction identifies its target item byrun = model.create_run(name="my-run") run.add_predictions(predictions)
dataset_item_id(thedi_*id returned on exported items), so predictions can come from anywhere and a single run can cover items across multiple datasets.add_predictionsposts toPOST /nucleus/modelRun/:modelRunId/uploadPredictionsand supportsupdate/batch_size/ file-batching arguments;asynchronous=TrueraisesNotImplementedErrorfor now.create_runstill accepts the olddataset=/predictions=arguments for backwards compatibility (the deprecated dataset-bound path); omit them to use the flow above.
- Per-prediction target. Every prediction type (
box,line,polygon,keypoints,cuboid,category,scene_category,segmentation) emits itsdataset_item_idinto_payload(asitem_id) when set, which is how the dataset-less upload route resolves each item. dataset_item_idon exported items and objects. Batch exports now carry the Nucleus-internal dataset item id (di_*) everywherereference_idalready appeared: onDatasetItem, and on every exported annotation and prediction (box,line,polygon,keypoints,cuboid,category,multicategory,segmentation). Video/scene exports carry it on each track frame. Previously onlyreference_idwas returned, so keying predictions back to items required a second lookup. The field is server-assigned and read-only: it is populated byfrom_json, leftNoneon objects you construct locally, excluded from__eq__, passed keyword-only on constructors, and never sent into_payload. Exports from an older backend that does not return it simply leave itNone.- Multi-dataset model runs.
Dataset.upload_predictions_for_model_run(model_run_id, predictions, ...)uploads predictions for an existing run against this dataset, adding the dataset to the run's set if it isn't there already. This is what lets a single model run be scored against a benchmark whose items span several datasets. Supports the sameupdate/asynchronous/batch_size/ file-batching /trained_slice_idarguments asupload_predictions.- A run's dataset set only ever grows — a later upload never removes a dataset, so it cannot widen who can read the run.
- Access: write on this dataset and on every dataset the run already covers. Runs are visible only to users who can read all of their datasets, so adding one can remove the run from a collaborator's view.
Dataset.upload_predictionsis unchanged and still cannot widen a run: it identifies the run by(dataset, model), so it finds the run already on this dataset or creates a new one.
- Model weights. Attach a raw weights artifact (any binary, no format constraints) to a model and fetch it back:
NucleusClient.upload_model_weights(model, path),download_model_weights(model, path),get_model_weights(model), anddelete_model_weights(model), plusModel.upload_weights()/download_weights()/weights()/delete_weights()and the newModelWeightsmetadata type (present,status,size_bytes,original_filename,content_type,download_url). Artifacts up to 10 GB are supported; uploading requires edit access on the model, downloading is available to anyone who can see it. - Large artifacts are handled without any extra work on the caller's part: transfers stream directly to/from storage, show a
tqdmprogress bar by default (passprogress=Falseto silence it), and automatically retry transient storage failures (network blips, 429s, 5xx) with exponential backoff.
Changed
Benchmark.statuscan now be"draft"(in addition to"building"/"ready"/"failed"). A draft benchmark cannot be evaluated until finalized.reference_idis now optional on predictions. A prediction can be constructed from itsdataset_item_idalone (at least one ofreference_id/dataset_item_idis required). Annotations still requirereference_id. Existing prediction code that passesreference_idis unaffected.- Benchmark evaluations no longer require the run to cover the benchmark's datasets.
create_benchmark_evaluation_v2previously failed when the benchmark contained items outside the model run's dataset. Those members are now scored as false negatives like any other uncovered item, so a partial run ranks comparably instead of being rejected. Docstrings oncreate_benchmark_evaluation_v2andBenchmark.create_evaluation_v2updated accordingly. PredictionUploaderacceptsdataset_idtogether withmodel_run_idto select the new endpoint. Previously that combination was rejected by an assertion. The other two forms —(dataset_id, model_id)andmodel_run_idalone — route exactly as before.
Deprecated
ModelRun.predict()(already deprecated with the rest ofModelRun) infers its target dataset from the run, so it fails for a run spanning several datasets. UseDataset.upload_predictions_for_model_runinstead.