-
Notifications
You must be signed in to change notification settings - Fork 635
Initial working version using Pydantic for type annotations #378
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
91e9353
782d2f4
0ffb4ad
0348f48
7f4242b
c4df856
955b455
884aff5
825d881
9c4ca1e
e58e1b9
0bbe391
b212209
1fdff82
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,16 +1,14 @@ | ||
| # Cog: Containers for machine learning | ||
|
|
||
| Use Docker for machine learning, without all the pain. | ||
| Put your machine learning model in a standard, production-ready Docker container without having to know how Docker works. | ||
|
|
||
| Cog gives you a consistent environment to run your model in – for developing on your laptop, training on GPU machines, and for other people working on the model. Then, when the model is trained and you want to share or deploy it, you can bake the model into a Docker image that serves a standard HTTP API. | ||
| Cog does a few things for you: | ||
|
|
||
| Cog does a few handy things beyond normal Docker: | ||
| - **Automatic Docker image.** Define your environment with a simple configuration file, and Cog generates a `Dockerfile` with all the best practices. | ||
| - **Standard, production-ready HTTP and AMQP interface.** Automatically generate APIs for integrating with production systems, battle hardened on Replicate. | ||
| - **No more CUDA hell.** Cog knows which CUDA/cuDNN/PyTorch/Tensorflow/Python combos are compatible and will set it all up correctly for you. | ||
|
|
||
| - **Automatic Docker image.** Define your environment with a simple configuration file, then Cog will generate Dockerfiles with best practices and do all the GPU configuration for you. | ||
| - **Automatic HTTP service.** Cog will generate an HTTP service from the definition of your model, so you don't need to write a Flask server in the right way. | ||
| - **No more CUDA hell.** Cog knows which CUDA/cuDNN/PyTorch/Tensorflow/Python combos are compatible and will pick the right versions for you. | ||
|
|
||
| ## Develop and train in a consistent environment | ||
| ## How it works | ||
|
|
||
| Define the Docker environment your model runs in with `cog.yaml`: | ||
|
|
||
|
|
@@ -23,46 +21,24 @@ build: | |
| python_version: "3.8" | ||
| python_packages: | ||
| - "torch==1.8.1" | ||
| predict: "predict.py:Predictor" | ||
| ``` | ||
|
|
||
| Now, you can run commands inside this environment: | ||
|
|
||
| ``` | ||
| $ cog run python train.py | ||
| ... | ||
| ``` | ||
|
|
||
| This will: | ||
|
|
||
| - Generate a `Dockerfile` with best practices | ||
| - Pick the right CUDA version | ||
| - Build an image | ||
| - Run `python train.py` in the image with the current directory mounted as a volume and GPUs hooked up correctly | ||
|
|
||
| <!-- TODO: this doesn't work yet (needs ports etc) | ||
| Or, spin up a Jupyter notebook: | ||
|
|
||
| ``` | ||
| $ cog run jupyter notebook | ||
| ``` | ||
| --> | ||
|
|
||
| ## Put a trained model in a Docker image | ||
|
|
||
| First, you define how predictions are run on your model: | ||
| And define how predictions are run on your model with `predict.py`: | ||
|
|
||
| ```python | ||
| import cog | ||
| from cog import BasePredictor, Input, Path | ||
| import torch | ||
|
|
||
| class ColorizationPredictor(cog.Predictor): | ||
| class Predictor(BasePredictor): | ||
| def setup(self): | ||
| """Load the model into memory to make running multiple predictions efficient""" | ||
| self.model = torch.load("./weights.pth") | ||
|
|
||
| # The arguments and types the model takes as input | ||
| @cog.input("input", type=cog.Path, help="Grayscale input image") | ||
| def predict(self, input): | ||
| def predict(self, | ||
| input: Path = Input(title="Grayscale input image") | ||
| ) -> Path: | ||
| """Run a single prediction on the model""" | ||
| processed_input = preprocess(input) | ||
| output = self.model(processed_input) | ||
|
|
@@ -87,10 +63,34 @@ $ cog build -t my-colorization-model | |
|
|
||
| $ docker run -d -p 5000:5000 --gpus all my-colorization-model | ||
|
|
||
| $ curl http://localhost:5000/predict -X POST -F [email protected] | ||
| $ curl http://localhost:5000/predictions -X POST \ | ||
| --data '{"input": "https://.../input.jpg"}' | ||
| ``` | ||
|
|
||
| That's it! Your model will now run forever in this reproducible Docker environment. | ||
| <!-- In development, you can also run arbitrary commands inside the Docker environment: | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is this commented out?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just tinkering with this. Perhaps it's more clear what Cog is for (packaging models into Docker containers) when there isn't the diversion into development environments. |
||
|
|
||
| ``` | ||
| $ cog run python train.py | ||
| ... | ||
| ``` --> | ||
|
|
||
| <!-- TODO: this doesn't work yet (needs ports etc) | ||
| Or, spin up a Jupyter notebook: | ||
|
|
||
| ``` | ||
| $ cog run jupyter notebook | ||
| ``` | ||
| --> | ||
|
|
||
| ## Deploying models to production | ||
|
|
||
| Cog does a number of things out of the box to help you deploy models to production: | ||
|
|
||
| - **Standard interface.** Put models inside Cog containers, and they'll run anywhere that runs Docker containers. | ||
| - **HTTP prediction server, based on FastAPI.** | ||
| - **Type checking, based on Pydantic.** Cog models define their input and output with JSON Schema, and the HTTP server is defined with OpenAPI. | ||
| - **AMQP RPC interface.** Long-running deep learning models or batch processing is best architected with a queue. Cog models can do this out of the box. | ||
| - **Read/write files from cloud storage.** Files can be read and written directly on Amazon S3 and Google Cloud Storage for efficiency. | ||
|
|
||
| ## Why are we building this? | ||
|
|
||
|
|
@@ -129,10 +129,10 @@ sudo chmod +x /usr/local/bin/cog | |
| - [Get started with your own model](docs/getting-started-own-model.md) | ||
| - [Take a look at some examples of using Cog](https://github.com/replicate/cog-examples) | ||
| - [`cog.yaml` reference](docs/yaml.md) to learn how to define your model's environment | ||
| - [Prediction interface reference](docs/python.md) to learn how the `cog.Predictor` interface works | ||
| - [Prediction interface reference](docs/python.md) to learn how the `Predictor` interface works | ||
|
|
||
| ## Need help? | ||
|
|
||
| [Join us in #cog on Discord.](https://discord.gg/QmzJApGjyE) | ||
|
|
||
| ## Contributors ✨ | ||
|
|
@@ -166,4 +166,4 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d | |
|
|
||
| <!-- ALL-CONTRIBUTORS-LIST:END --> | ||
|
|
||
| This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome! | ||
| This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome! | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -66,19 +66,18 @@ With `cog.yaml`, you can also install system packages and other things. [Take a | |
| The next step is to update `predict.py` to define the interface for running predictions on your model. The `predict.py` generated by `cog init` looks something like this: | ||
|
|
||
| ```python | ||
| import cog | ||
| from pathlib import Path | ||
| from cog import BasePredictor, Path, Input | ||
| import torch | ||
|
|
||
| class Predictor(cog.Predictor): | ||
| class Predictor(BasePredictor): | ||
| def setup(self): | ||
| """Load the model into memory to make running multiple predictions efficient""" | ||
| self.net = torch.load("weights.pth") | ||
|
|
||
| # Define the input types for a prediction | ||
| @cog.input("input", type=Path, help="Image to enlarge") | ||
| @cog.input("scale", type=float, default=1.5, help="Factor to scale image by") | ||
| def predict(self, input, scale): | ||
| def predict(self, | ||
| image: Path = Input(description="Image to enlarge"), | ||
| scale: float = Input(description="Factor to scale image by", default=1.5) | ||
| ) -> Path: | ||
| """Run a single prediction on the model""" | ||
| # ... pre-processing ... | ||
| output = self.net(input) | ||
|
|
@@ -88,16 +87,26 @@ class Predictor(cog.Predictor): | |
|
|
||
| Edit your `predict.py` file and fill in the functions with your own model's setup and prediction code. You might need to import parts of your model from another file. | ||
|
|
||
| You also need to define the inputs to your model using the `@cog.input()` decorator, as demonstrated above. The first argument maps to the name of the argument in the `predict()` function, and it also takes these other arguments: | ||
| You also need to define the inputs to your model as arguments to the `predict()` function, as demonstrated above. For each argument, you need to annotate with a type. The supported types are: | ||
|
|
||
| - `type`: Either `str`, `int`, `float`, `bool`, or `Path` (be sure to add the import, as in the example above). `Path` is used for files. For more complex inputs, save it to a file and use `Path`. | ||
| - `help`: A description of what to pass to this input for users of the model | ||
| - `str`: a string | ||
| - `int`: an integer | ||
| - `float`: a floating point number | ||
| - `bool`: a boolean | ||
| - `cog.File`: a file-like object representing a file | ||
| - `cog.Path`: a path to a file on disk | ||
|
|
||
| You can provide more information about the input with the `Input()` function, as shown above. It takes these basic arguments: | ||
|
|
||
| - `description`: A description of what to pass to this input for users of the model | ||
| - `default`: A default value to set the input to. If this argument is not passed, the input is required. If it is explicitly set to `None`, the input is optional. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
👍🏼
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There could be an argument for a more explicit, easier to understand design here. #114 Not sure what is best. |
||
| - `min`: A minimum value for `int` or `float` types. | ||
| - `max`: A maximum value for `int` or `float` types. | ||
| - `options`: A list of values to limit the input to. It can be used with `str`, `int`, and `float` inputs. | ||
| - `gt`: For `int` or `float` types, the value should be greater than this number. | ||
| - `ge`: For `int` or `float` types, the value should be greater than or equal to this number. | ||
| - `lt`: For `int` or `float` types, the value should be less than this number. | ||
| - `le`: For `int` or `float` types, the value should be less than or equal to this number. | ||
| - `choices`: A list of possible values for this input. | ||
|
|
||
| For more details about writing your model interface, [take a look at the prediction interface documentation](python.md). | ||
| There are some more advanced options you can pass, too. For more details, [take a look at the prediction interface documentation](python.md). | ||
|
|
||
| Next, add the line `predict: "predict.py:Predictor"` to your `cog.yaml`, so it looks something like this: | ||
|
|
||
|
|
@@ -122,7 +131,7 @@ Written output to output.png | |
| To pass more inputs to the model, you can add more `-i` options: | ||
|
|
||
| ``` | ||
| $ cog predict -i input=@input.jpg -i scale=2.0 | ||
| $ cog predict -i image=@image.jpg -i scale=2.0 | ||
| ``` | ||
|
|
||
| In this case it is just a number, not a file, so you don't need the `@` prefix. | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
❤️