Skip to main content

Changelog

Deimv2 Detection filter release notes

v0.3.0 - 2026-09-23Direct link to v0.3.0 - 2026-09-23

AddedDirect link to Added

  • A locally buildable image variant that can load a Protege-trained artifact, built with make build-protege and tagged <VERSION>-protege. The code for that path shipped in v0.2.6, but no published image could run it: protege-runtime is not on PyPI, the extra therefore needs the Plainsight index, and the Dockerfile installed the base package only. Pointing a published image at a Protege .zip failed on ModuleNotFoundError: No module named 'protege' inside setup, verified on 0.2.4 and on 0.2.7, which surfaces as a container that starts, logs "Setting up", and then sits at 0% CPU consuming nothing. A --build-arg INSTALL_PROTEGE=true now selects it, and the token reaches pip as a BuildKit secret so it never lands in a layer, the same shape protege-ml uses in docker/Dockerfile.vertex.

    No -protege image is published yet, and this PR does not publish one. The published tags, 0.2.7 included, are default builds that carry no protege-runtime, so pinning .env at any of them does not make a Protege .zip loadable. To run a Protege artifact today, build the variant locally with make build-protege (needs gcloud auth print-access-token for the Plainsight index) and point at <VERSION>-protege. Publishing the variant from CI is tracked separately.

    The default image is unchanged. Without the arg it still resolves entirely from PyPI, needs no credentials, and carries neither protege-runtime nor any new layer, so a site running the reference checkpoint pays nothing for a path it does not use. That was the reason the extra was optional and it still holds. What changes is only that the second path is now reachable by a local build rather than only by a local editable install.

    Worth knowing before deciding which variant to publish: the base image already carries torch 2.13.0, torchvision 0.28.0 and transformers 5.15.1 at 5.88 GB, so the extra's heavy dependencies are already present and the variant costs far less than the size of protege-runtime[transformers] suggests.

ChangedDirect link to Changed

  • The bundle manifest points at gs://protege-artifacts-production/upstream-mirrors/ instead of the asset bucket. Documenting that the asset bucket was the wrong home while leaving source_url pointing at it made the obvious way to turn CI green, uploading the checkpoint to the URL in the file, the exact thing the documentation argued against. The new destination refuses anonymous access, verified without credentials: an unauthenticated list answers 401 and an unauthenticated GET on an existing object answers 403, against 200 for both on the asset bucket. The checkpoint still has to be uploaded there; until it is, the bundle dry run fails on the fetch, which is the correct failure rather than a published public copy of a DINOv3-derived checkpoint. The prefix is upstream-mirrors/ rather than a customer one, because the object is the upstream DEIMv2-L COCO release and not any customer's data: a customer prefix is what the bucket uses to scope ownership, so filing a third-party mirror under one would misstate whose bytes those are.
  • Bump the openfilter dependency to 1.4.0

FixedDirect link to Fixed

  • The RuntimeError raised when the Protege path cannot import protege-runtime named only the pip install line and said the published image "needs an image built with the extra", without saying how to get one. That is the message a container user lands on at the moment of the failure this variant exists to fix, and it dead-ended them: README.md, RELEASE.md, .env.example and pyproject.toml all learned about make build-protege and the <VERSION>-protege tag in this change and the error string did not. It now separates the two cases and names the local build for the container one.

  • docker-compose.yaml still defaulted FILTER_DEIMV2_DETECTION_IMAGE_TAG to 0.2.4 while .env.example had moved off that pin. Largely unreachable, since env_file: .env is required, so this is tidiness rather than a bug: the default now matches VERSION.

  • The README pointed the mirror at gs://plainsight-ml-assets-production, which is world-readable by design: it sits in the asset_buckets map in terraform/gcp/gcs, which grants allUsers roles/storage.objectViewer on purpose, with a comment telling anyone who meets the SCC PUBLIC_BUCKET finding to mute it rather than remove the binding. It is a static-asset bucket doing its job. That makes it the wrong home for the DEIMv2-L checkpoint, whose DINOv3 backbone ships under Meta's source-available licence, so a public copy is redistribution. The remedy is a different, private bucket, which costs no extra credential since the shared fetcher already handles gs:// through workload identity. Two earlier versions of this paragraph were wrong in opposite directions, first calling the bucket private on the strength of a 404 that was only the checkpoint not being uploaded, then calling the public read a misconfiguration to fix.

v0.2.7 - 2026-08-21Direct link to v0.2.7 - 2026-08-21

ChangedDirect link to Changed

  • Publish the model bundle from CI through the shared filter-model-bundle workflow in gh-actions (PLAT-1581), and drop the repo-local prepublish, build-model-image, check-model-version-exists and publish-model-image targets along with prepare_models.py and Dockerfile.model. The bundle flow here was the first one and was deliberately hand-run, which is what made it the source of the failures it then had to defend against: docker build stamping the publisher's architecture, copy2 carrying a 0600 checkpoint through to a pod that runs as appuser under a read-only mount, and a bare docker push walking past the version guard. Building on a runner removes the first two as a class rather than patching them, and the guard is now a step in the job that runs before staging and on pull requests too, so a bundle version that was not bumped fails on the PR. The bundle is multi-arch as a result; the weights layer is byte-identical across platforms, so the registry stores one copy of it and the second architecture costs only the busybox base, which is what the single-arch decision was protecting against. models.toml now declares a source_url that CI fetches and verifies against the declared sha256, since a path in one person's home directory is not something a runner can pull; path stays as an optional local shortcut and cannot change what is published. make pull-models is unchanged apart from dropping its --platform linux/amd64 pin, which now only forces an Apple Silicon machine to pull an emulated variant of a file-only image. RESOURCE_BUNDLE_VERSION goes to 0.2.0: the contents are the same checkpoint, but 0.1.0 is already published and published bundle versions are immutable.

v0.2.6 - 2026-08-21Direct link to v0.2.6 - 2026-08-21

AddedDirect link to Added

  • Accept a Protege-trained artifact as well as an original DEIMv2 checkpoint (PLAT-1524). This filter loads the original format, a torch file with an ema/model state dict that YAMLConfig builds a model around from a YAML file. A Protege export is a different thing: a zip holding weights.pt with Hugging Face parameter names under a network.model. wrapper prefix, plus .MODELCONFIG.json carrying the architecture, the class map and the HF config. Neither the YAML nor the state-dict shape lines up, so a Protege artifact could not be loaded here at all and a site already running this filter had to switch filters to use a model trained in Protege. Detection is on content rather than extension, since a .zip proves nothing and a checkpoint can be renamed: a Protege artifact always carries .MODELCONFIG.json, and the zip index is read rather than extracted so guessing wrong costs nothing. Loading delegates to protege-runtime, which owns the format, rather than reimplementing the wrapper prefix, class map and postprocessor here where nothing in CI would catch them drifting. It is an optional extra (pip install 'filter-deimv2-detection[protege]'), so sites running the reference checkpoint do not pull in the trainer's runtime.

v0.2.5 - 2026-08-18Direct link to v0.2.5 - 2026-08-18

ChangedDirect link to Changed

  • Update the openfilter dependency to 1.3.0
  • Add Python 3.14 support: raise the requires-python ceiling to <3.15 and add 3.14 to the CI test matrix (3.10–3.13 unchanged).

AddedDirect link to Added

  • Model bundle flow, matching filter-rt-detr and filter-protege-model: models.toml declares the artifacts, prepare_models.py stages them into ./models, and Dockerfile.model bakes that into a bundle image published to premium-filters/filter-deimv2-detection-model under RESOURCE_BUNDLE_VERSION. make pull-models unpacks a published bundle into ./models, so operators no longer place the .pth by hand and the weights reach a node through the registry it already pulls from.

v0.2.4 - 2026-08-14Direct link to v0.2.4 - 2026-08-14

FixedDirect link to Fixed

  • aggregate_results now defaults to false. In a video pipeline one frame is one aggregate() call and the store is only cleared on shutdown, so the append strategy made every emitted frame carry the previous max_aggregated_results (10) frames of detections concatenated. Measured on the CPD evaluation corpus at 640x480 over 2,070 frames: 11.89 boxes per frame with the old default against 1.21 with aggregation off, and frames in which the subject had already walked out of shot still carried person boxes. Downstream stages that run per detection (attribute extraction, captioning, event emission) paid that multiplier. Set FILTER_AGGREGATE_RESULTS=true to restore the sliding window where several calls genuinely describe one frame.

v0.2.3 - 2026-08-13Direct link to v0.2.3 - 2026-08-13

AddedDirect link to Added

  • ByteTrack using supervision library added
  • Always returns tracking id if detected.

v0.2.2 - 2026-08-12Direct link to v0.2.2 - 2026-08-12

ChangedDirect link to Changed

  • Migrate the release pipeline from the private-filter track (filter-release-private.yaml publishing to filter-registry-48eec17d-…/filter-deimv2-detection) to the premium-filter track (filter-release-premium.yaml publishing to premium-filters/filter-deimv2-detection). Auth switches from a long-lived GAR access key to WIF-based federated auth. The Makefile IMAGE variable and the docker-compose.yaml image path are updated to the new location; the compose fallback tag is bumped to 0.2.2.

v0.2.1 - 2026-08-10Direct link to v0.2.1 - 2026-08-10

AddedDirect link to Added

  • NMS options for postprocessing.
  • Options to ignore classes
  • Ability to set num-classes and use default config

v0.2.0 - 2026-08-05Direct link to v0.2.0 - 2026-08-05

AddedDirect link to Added

  • Comprehensive pipeline documentation detailing configuration keys and output metadata signatures
  • Direct input/output compatibility parity verified with existing Protege filters
  • Premium multi-colored class overlays, sleek filled text labels, and dynamic confidence scoring

v0.1.0 - 2025-02-22Direct link to v0.1.0 - 2025-02-22

AddedDirect link to Added

  • Initial Release: new Deimv2 Detection filter