Deployment package structure¶
Your deployment code needs to be packaged in the structure described below for the UbiOps platform to run it.
The packaged deployment is a zip file containing a number of required files and directories. This page specifies in what structure UbiOps expects your deployment file.
Deployment package structure¶
Templates available on GitHub
Template structures are available on our Github. You can download an example Python deployment package .zip here: Download example deployment package.
Each deployment package should be uploaded to UbiOps as a ZIP archive. This ZIP can have any name. The ZIP must contain a directory, which can have any name, in the root of the ZIP. If your ZIP contains multiple directories, it will look for a directory called deployment_package
. This directory should contain all deployment files.
The structure of the .zip package is independent on which base environment it is deployed, and and needs to include the following:
deployment_folder.zip
deployment_package/
- deployment.py
- requirements.txt (optional)
- libraries/ (optional)
- ubiops.yaml (optional)
- other files & artifacts (optional)
The files in the example deployment package
above can be subdivided into two types of files: deployment files and environment files.
Deployment files¶
The deployment files consist of the deployment.py
, which is the file that contains the code which ubiops will run each time a request is made, and all files containing deployment artifacts and attributes e.g. a model parameter file or a pickle file.
Environment files¶
The environment files consists of the files that specify what dependencies you want to use, e.g, a requirements.txt
for package and library requirements, directory libraries
for including dependencies that your deployment uses, or a ubiops.yaml
for installing OS level packages.
You can find more information and examples about creating, using, and managing environments on our environments page.
Maximum deployment package size
The maximum size for a deployment package is 8 GiB.
The deployment file¶
The deployment.py
file needs to have the structure as shown below. It should contain an initialization method, which is called when the deployment is initialized, and a request
method, which runs when a request to the deployment is received by UbiOps.
From here you can extend the code in any way you like.
"""
The file containing the deployment code is required to be called 'deployment.py' and should contain the 'Deployment'
class and 'request' method.
"""
# Always use absolute imports when importing modules from the deployment package directory. For example
# `import my_module` instead of `import .my_module`
import random
class Deployment:
def __init__(self, base_directory, context):
"""
Initialization method for the deployment. It can for example be used for loading modules that have to be kept in
memory or setting up connections. Load your external deployment files (such as pickles or .h5 files) here.
:param str base_directory: absolute path to the directory where the deployment.py file is located
:param dict context: a dictionary containing details of the deployment (version) that might be useful in your
code.
It contains the following keys:
- project (str): name of the project that hosts the deployment
- project_id (str): unique identifier of the project
- deployment_id (str): unique identifier of the deployment
- deployment (str): name of the deployment
- version_id (str): unique identifier of the deployment version
- version (str): name of the version
- input_type (str): deployment input type, either 'structured' or 'plain'
- output_type (str): deployment output type, either 'structured' or 'plain'
- input_fields (list): list with all input fields of the deployment
- output_fields (list): list with all output fields of the deployment
- language (str) : programming language the deployment is running
- environment_variables (dict/str): the custom environment variables configured for the deployment.
You can also access those as normal environment variables via os.environ
"""
print("Initialising My Deployment")
def request(self, data, context):
"""
Method for deployment requests, called separately for each individual request.
:param dict/str data: request input data. In case of deployments with structured data, a Python dictionary
with as keys the input fields as defined upon deployment creation via the platform. In case of a deployment
with plain input, it is a string.
:param dict context: a dictionary containing details of the request that might be useful in your code.
It contains the following keys:
- id (str): the id of the request
- user_id (str): unique identifier of the (service) user that sent the request
- request_mode (str): mode of the request, either 'express' or 'batch'
For a pipeline request, it contains the additional keys:
- pipeline_request_id (str): unique identifier of the pipeline request
- pipeline_id (str): unique identifier of the pipeline
- pipeline_version_id (str): unique identifier of the pipeline version
- pipeline_object_id (str): unique identifier of the object in the pipeline. Deployments and operators
in pipelines are assigned a unique identifier.
:return dict/str: request output. In case of deployments with structured output data, a Python dictionary
with as keys the output fields as defined upon deployment creation via the platform. In case of a deployment
with plain output, it is a string. In this example, a dictionary with the key: output.
"""
print("Processing request for My Deployment")
# You can run any code to handle the request here.
# For a structured deployment, we return a Python dict with output. In this example, we are assuming this
# deployment receives one input field called 'input' and outputs one field called 'output'
return {
"output": data['input'] * random.random()
}
Raising custom errors
It is also possible to raise custom errors in your deployment file, for more information on how to do that see here.
Input and output of the request
function¶
The request
method has an input variable called data
. This object will contain the data payload for each request. After processing, the request
function will also return an output. By default this is an empty dictionary.
UbiOps supports the following data-types:
Data type | Data format | Reference |
---|---|---|
String | 'string' or "string" | string |
Integer | 9999 | int |
Double precision | 9999.99 | double |
Boolean | True /False | bool |
File | 'ubiops-file://{bucket-name}/{filename}' (a file URI) | file |
Array of strings | ['string', "string", ... ] | array_string |
Array of integers | [88, 99, ... ] | array_int |
Array of doubles | [88.88, 99.99, ... ] | array_double |
Array of files | ['ubiops-file://{bucket-name}/{filename1}', 'ubiops-file://{bucket-name}/{filename2}', ...] | array_file |
Dictionary | dict | dict |
class Deployment:
def request(self, data):
with open("/tmp/file.txt", "w") as f:
f.write("test")
return {
"output_file": {
"file": "/tmp/file.txt",
"bucket": "example-bucket",
"bucket_file": "request-output/file.txt"
}
}
More details on how to handle the input and output of the request
function, can be found in the Deployment In- and output section.
There you can also find examples on how to work with files or how to convert well-known Python data structures like NumPy Arrays
and Pandas DataFrames
to data-types that UbiOps can work with.
Testing your deployment¶
The deployment template in our Github project contains an example script to test whether your deployment is working correctly within our deployment wrapper.
You can edit and execute the file run_deployment.py
according to your deployment to simulate the UbiOps back-end that initializes the deployment and makes a request. Alternatively, UbiOps provides a utils function that you can use to test locally
Context dictionaries¶
UbiOps passes metadata to the initialization and request
functions of a deployment in the form of dictionaries. These dictionaries contain information about the deployment and its environment, and about the the request and its environment. Please note that the dictionaries contain different values for both functions. The context dictionary of the request
function contains additional information if the deployment is called inside a pipeline.
The deployment initialization context dictionary | |
---|---|
Key (type) | Description of the value |
project (str) | The name of the project that hosts the deployment |
project_id (str) | The unique identifier of the project |
deployment (str) | The name of the deployment |
deployment_id (str) | The unique identifier of the deployment |
version (str) | The name of the deployment version |
version_id (str) | The unique identifier of the deployment version |
input_type (str) | The deployment input type, either 'structured' or 'plain' |
output_type (str) | The deployment output type, either 'structured' or 'plain' |
input_fields (list of strings) | The name of the deployment |
output_fields (list of strings) | The unique identifier of the deployment |
language (str) | The programming language the deployment is running |
environment_variables list[dict/str] | The custom environment variables that are configured for the deployment. |
The context dictionary that is passed to the request
function of a deployment, is described below:
The deployment request context dictionary | |
---|---|
Key (type) | Description of the value |
id (str) | The unique identifier of the deployment request |
user_id (str) | The unique identifier of the (service) user that sent the request |
request_mode (str) | Mode of the request, either 'express' or 'batch' |
The context dictionary contains extra keys if the deployment is placed inside a pipeline. In this case the deployment is assigned an object_id
, which is different from its deployment_id
. This way, identical deployment versions inside a pipeline can still be distinguished from eachother.
The pipeline request context dictionary | |
---|---|
Key (type) | Description of the value |
id (str) | The unique identifier of the request that is sent to the deployment inside the pipeline |
user_id (str) | The unique identifier of the (service) user that sent the pipeline request |
pipeline_request_id (str) | The unique identifier of the pipeline request |
pipeline_version_id (str) | The unique identifier of the pipeline version |
pipeline_object_id (str) | The unique identifier of the object in the pipeline. |
request_mode (str) | Mode of the request, either 'express' or 'batch' |