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 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 similar for every language 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)
- A
deployment
file that contains the code which UbiOps will run each time a request is made. - (optional) Files containing package and library requirements that are installed and managed by UbiOps. For example,
requirements.txt
for Python andinstall_packages.R
orrenv.lock
for R. - (optional) Files containing deployment artifacts and attributes. For instance, a model parameter file or pickle file.
- (optional) A directory
libraries
where you can include dependencies that your deployment uses. This directory is added to the system$PATH
variable, such that its contents can be easily imported. - (optional) A
ubiops.yaml
for installing anything on the Docker level. For more information see installing OS level packages.
Using the CLI to create the zip for you
You can also make use of the UbiOps command line interface to create the zip for you and upload it to reduce manual work.
Maximum deployment package size
The maximum size for a deployment package is 8 GiB.
Installing packages¶
-
requirements.txt
- A list of Python packages required for the deployment. UbiOps will install the packages defined in this file for you using a freshpip
virtual environment once you upload your deployment. After this build step the dependencies are fixed and won't change. Read more about therequirements.txt
file format and possibilities here. -
libraries/
- directory where packages and system libraries are installed. This directory is added to the system$PATH
variable. -
A
ubiops.yaml
file for installing OS level packages in the container.
-
renv.lock
- A lockfile containing packages required for the deployment. UbiOps will install the packages defined in this file for you usingrenv::restore()
once you upload your deployment. For more information, take a look at renv documentation. -
install_packages.R
- An R file containing instructions to install packages, like,install.packages("randomForest")
. After this build step the dependencies are fixed and won't change. -
ubiops.yaml
- A yaml file to install OS level packages in the container.
Preinstalled packages
To speed up the package installation process, some standard R packages are preinstalled:
- tidyverse
- here
- remotes
- renv
askpass, assertthat, backports, base64enc, BH, blob, broom, callr, cellranger, cli, clipr, colorspace, cpp11, crayon, curl, DBI, dbplyr, digest, dplyr, ellipsis, evaluate, fansi, farver, forcats, fs, generics, ggplot2, glue, gtable, haven, here, highr, hms, htmltools, httr, isoband, jsonlite, knitr, labeling, lifecycle, lubridate, magrittr, markdown, mime, modelr, munsell, openssl, pillar, pkgconfig, prettyunits, processx, progress, ps, purrr, R6, RColorBrewer, Rcpp, readr, readxl, rematch, remotes, renv, reprex, rlang, rmarkdown, rprojroot, rstudioapi, rvest, scales, selectr, stringi, stringr, sys, tibble, tidyr, tidyselect, tidyverse, tinytex, utf8, vctrs, viridisLite, withr, xfun, xml2, yaml All preinstalled packages
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):
"""
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. 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 that might be useful in your code.
It contains the following keys:
- deployment (str): name of the deployment
- 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'
- language (str): programming language the deployment is running
- environment_variables (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):
"""
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.
: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.
More details on how to handle the input and output of the request
function and what data types can be used, 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.
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.