Back to Cog

examples/resnet

examples/resnet/README.md

0.20.04.8 KB
Original Source

examples/resnet

ResNet50 image classifier (microsoft/resnet-50 from HuggingFace) packaged with v1 managed weights. Takes an image, returns top-3 ImageNet classes.

Use this as a starting point for packaging a real model with managed weights.

What are managed weights?

Managed weights separate your model weights from your model image. Instead of baking multi-GB weight files into the Docker image (slow builds, huge layers), cog packs them into dedicated OCI layers that get mounted at runtime.

The key idea: your run.py reads weights from a path like /src/weights/resnet50, but those files don't live inside the Docker image -- they arrive separately and get overlaid at that path when the container starts.

File layout

examples/resnet/
├── cog.yaml              # model config -- declares weights, build settings
├── run.py                # runner -- loads weights from target path
├── requirements.txt      # python deps
├── weights.lock          # generated by `cog weights import` -- don't hand-edit
├── .dockerignore         # keeps local weight dirs out of the Docker build context
├── .gitignore            # keeps local weight dirs and .cog/ out of git
├── hotdog.png            # test image
└── cat.png               # test image

Weight files themselves don't live in the project directory. cog weights import downloads them into a content-addressed store at ~/.cache/cog/weights/ (override with $COG_CACHE_DIR). When you run cog run, cog assembles a temporary directory under .cog/mounts/ using hardlinks from the store and bind-mounts it into the container at the target path. The mount dir is cleaned up when the container stops.

How cog.yaml works

yaml
weights:
  - name: resnet50
    source:
      uri: hf://microsoft/resnet-50 # where to fetch from
      exclude: # files to skip
        - "pytorch_model.bin"
        - "flax_model.msgpack"
        - "tf_model.h5"
        - "README.md"
        - ".gitattributes"
    target: /src/weights/resnet50 # where files appear in the container

name -- an identifier for this weight set. Used in lockfile entries and OCI tags. Pick something short and descriptive.

source.uri -- where the weights come from. Two formats:

  • hf://<org>/<repo> -- pulls from HuggingFace Hub
  • A local directory path (e.g. weights/) -- uses files already on disk

source.exclude -- glob patterns for files to skip. Most HF repos ship weights in multiple formats (PyTorch, TF, Flax, ONNX). Exclude the ones you don't need -- it'll save gigabytes.

target -- the absolute path where weight files land inside the container. Your run.py loads from this path. Must start with /.

Getting started

1. Import weights

This downloads weight files from HuggingFace into the local cache and generates weights.lock:

sh
cd examples/resnet
cog weights import

The lockfile records digests and sizes for every file. It's how cog knows whether weights have changed on subsequent imports. Commit weights.lock to version control.

2. Run a prediction locally

sh
cog run -i [email protected]

Locally, cog assembles the weight files from the cache and bind-mounts them into the container at the target path. You don't need to push anything to test.

3. Build and push

sh
cog push

This builds the model image and pushes it to the registry specified by image: in cog.yaml, alongside the weight layers as an OCI image index. The weights and model image are separate artifacts in the registry -- the image index ties them together.

Important: .dockerignore

The .dockerignore excludes weights/ and .cog/weights-cache/ from the Docker build context. This matters if you're using local directory weight sources -- without it, Docker would send the full weight directory to the build daemon on every cog build.

Adapting this for your own model

  1. Copy this directory as a starting point
  2. Edit cog.yaml:
    • Change source.uri to your HuggingFace repo (or a local path)
    • Adjust exclude patterns for the formats you don't need
    • Set target to wherever your code expects to find the weights
    • Set image to your registry destination (required for cog push)
  3. Edit run.py to load your model from WEIGHTS_DIR
  4. Update requirements.txt with your dependencies
  5. Run cog weights import to fetch weights and generate the lockfile
  6. Test with cog run
  7. Push with cog push

Using local weights instead of HuggingFace

If you already have weights on disk (downloaded separately, trained locally, etc.), point the source at a local directory:

yaml
weights:
  - name: my-model
    source:
      uri: my-weights-dir/
      include:
        - "*.safetensors"
        - "*.json"
    target: /src/weights/my-model

Then run cog weights import as usual -- it'll hash the local files and generate the lockfile.