Skip to content

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.

Deploying to UbiOps

Deployment package structure

Templates available on GitHub

Template structures are available for both Python and R 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)
deployment_folder.zip
        deployment_package/
                - deployment.R

                - renv.lock or install_packages.R (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. For R you can useinstall_packages.R or renv.lock.

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 or the deployment.R file needs to have the structure as shown below. They both contain an initialization method, which is called when the deployment is activated 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()
        }
# This file (containing the deployment code) is required to be called 'deployment.R' and should contain an 'init'
# and 'request' method.

#' @title Init
#' @description Initialisation method for the deployment.
#'     It can for example be used for loading modules that have to be kept in memory or setting up connections.
#' @param base_directory (str) absolute path to the directory where the deployment.R file is located
#' @param context (named list) details of the deployment that might be useful in your code
init <- function(base_directory, context) {
    print("Initialising My Deployment")
}


#' @title Request
#' @description Method for deployment requests, called separately for each individual request.
#' @param input_data (str or named list) request input data
#'     - In case of structured input: a named list, with as keys the input fields as defined upon deployment creation
#'     - In case of plain input: a string
#' @param base_directory (str) absolute path to the directory where the deployment.R file is located
#' @param context (named list) details of the deployment that might be useful in your code
#' @return output data (str or named list) request result
#'     - In case of structured output: a named list, with as keys the output fields as defined upon deployment creation
#'     - In case of plain output: a string
request <- function(input_data, base_directory, context) {
    print("Processing request for My Deployment")


    # ADD YOUR CODE HERE...


    # Another script can be called using: source(file.path(base_directory, "<script name>.R"))
    # Environment variables can be obtained via: Sys.getenv("ENV_VAR", unset = "")


    # In this example, the input field "input" in multiplied by a random number and returned in output field "output"
    list( output = input_data[["input"]] * runif(1) )
}

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.

Read more ->

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 (or run_deployment.R) 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'