cog
d6cb965e - OCI bundle format for model weights (#2676)

Commit
37 days ago
OCI bundle format for model weights (#2676) * feat(model): add ModelFormat and Index types for OCI bundle support * feat(model): add WeightsManifest and WeightFile types * feat(model): add WeightsLock file format for weight metadata * feat(tools): add weights-lock-gen for testing OCI bundle format * feat(ociartifact): add weights artifact builder using go-containerregistry Implements WeightsArtifactBuilder for creating OCI artifacts containing model weights. The builder: - Creates OCI-format manifests (application/vnd.oci.image.manifest.v1+json) - Sets artifactType to application/vnd.cog.weights.v1 - Adds layers with custom media types and annotations for weight files - Uses mutate.Addendum to properly attach layer annotations Layer annotations include: - vnd.cog.weights.name: original filename - vnd.cog.weights.dest: container path - vnd.cog.weights.source: origin URL (optional) - vnd.cog.weights.digest.original: uncompressed digest - vnd.cog.weights.size.uncompressed: uncompressed size Test coverage: 93.8% * feat(ociartifact): add AddLayersFromLock for file-based weight loading * feat(model): add OCIIndex and WeightsLockPath build options * feat(model): add OCI index detection helpers in resolver Add helper functions to detect and handle OCI indexes: - isOCIIndex: checks if ManifestResult is an OCI Image Index - findWeightsManifest: finds weights manifest by annotation - findImageManifest: finds model image manifest with platform filtering Also: - Add Annotations field to PlatformManifest struct - Populate annotations when reading OCI index manifests - Add PushImage/PushIndex to registry Client interface for OCI index push support * feat(model): consolidate OCI index builders and wire push flow - Move WeightsArtifactBuilder, IndexBuilder, IndexFactory from pkg/ociartifact to pkg/model/index_factory.go - Delete pkg/ociartifact/ package (code duplication eliminated) - Add OCI index push flow in pkg/cli/push.go (COG_OCI_INDEX=1 env var) - Add index detection helpers in resolver for loading OCI indexes - Simplify BuildOptions: remove WeightsLockPath (hardcoded to weights.lock) - Add Platform.Variant field to pkg/model/image.go - Add push_test.go placeholder for registry push tests * feat(weights-lock-gen): generate random weight files for testing Replace the --files flag with random file generation: - Add --count (-n) flag for number of files (default: 3) - Add --min-size and --max-size flags (default: 25mb-50mb) - Add --output-dir to optionally keep generated files - Files are named weights-001.bin, weights-002.bin, etc. - Generate random data in 1MB chunks for memory efficiency This simplifies testing the OCI bundle format without needing real weight files. * feat(model): refactor OCI index push into Resolver.Push() - Add ModelImageFormat enum (FormatStandalone, FormatBundle) in format.go - Update Model struct: replace Format with ImageFormat field - Update BuildOptions: replace OCIIndex bool with ImageFormat - Create Pusher interface with ImagePusher and BundlePusher implementations - Add Resolver.Push() that delegates to appropriate pusher based on format - Add BuildWeightsArtifactFromManifest to IndexFactory - Simplify pkg/cli/push.go to use resolver.Push() for bundles - Move ImageFormatFromEnv() to model package The push logic is now cleanly separated: - ImagePusher: Simple docker push for standalone images - BundlePusher: Full OCI Index workflow (push image, build weights artifact, build index, push index) Closes cog-cz1 * feat(integration-tests): add mock registry and OCI bundle tests - Add inline mock weights generator to avoid pkg/wheels init panic - Add StartTestRegistryWithCleanup for harness (no *testing.T required) - Add registry-start, registry-inspect, docker-push, mock-weights commands - Add oci_bundle_build.txtar and oci_bundle_push.txtar integration tests - Update push_test.go to use testcontainers instead of TEST_REGISTRY env * chore: add test weight files to gitignore * fix(weights-lock-gen): suppress gosec warning for test data RNG * refactor(weights): remove Source field and use filePaths map for weight resolution - Remove Source field from WeightFile - lockfile maps name→blob, not source - Change Name semantics to identifier/handle (e.g., 'model-v1') not filename - Add filePaths map[string]string parameter to AddLayersFromLock for file location - Add context cancellation support to AddLayersFromLock for long operations - Add AnnotationValueWeights constant for 'weights' annotation value - Improve registry push error messages to include reference - Remove binary test files (~109MB) that were accidentally committed - Update all tests to use new API and identifier-style names * refactor: replace magic strings with constants for platform and weights - Add PlatformUnknown constant for non-platform-specific artifacts - Use AnnotationValueWeights constant instead of "weights" string literal - Update all usages in index_factory.go, resolver.go, and tests
Author
Parents
Loading