Runway Module

The Runway module exposes three simple functions that can be combined to expose your models to the Runway app using a simple interface.

  • @runway.setup(): A Python decorator used to initialize and configure your model.

  • @runway.command(): A Python decorator used to define the interface to your model. Each command creates an HTTP route which can process user input and return outputs from the model.

  • runway.run(): The entrypoint function that starts the SDK’s HTTP interface. It fires the function decorated by @runway.setup() and listens for commands on the network, forwarding them along to the appropriate functions decorated with @runway.command().

Reference

runway.setup(decorated_fn=None, options=None)

This decorator is used to wrap your own setup() (or equivalent) function to run whatever initialization code you’d like. Your wrapped function should configure and return a model. Your function should also be made resilient to being called multiple times, as this is possible depending on the behavior of the client application.

This endpoint exposes a /setup HTTP route and calls the wrapped (decorated) function once on runway.run() and whenever a new POST request is made to the /setup route.

import runway
from runway.data_types import category
from your_code import model

# Descriptions are used to document each data type; Their values appear in the app as
# tooltips. Writing detailed descriptions for each model option goes a long way towards
# helping users learn how to interact with your model. Write descriptions as full sentences.
network_size_description = "The size of the network. A larger number will result in better accuracy at the expense of increased latency."
options = { "network_size": category(choices=[64, 128, 256, 512], default=256, description=network_size_description) }
@runway.setup(options=options)
def setup(opts):
    print("Setup ran, and the network size is {}".format(opts["network_size"]))
    return model(network_size=opts["network_size"])

Note

This is example code for demonstration purposes only. It will not run, as the your_code import is not a real python module.

Parameters
  • decorated_fn (function, optional) – A function to be decorated. This argument is automatically assigned the value of the wrapped function if the decorator syntax is used without a function call (e.g. @runway.setup instead of @runway.setup()).

  • options (dict, optional) – A dictionary of setup options, mapping string names to runway.data_types. These options define the schema of the object that is passed as the single argument to the wrapped function.

Returns

A decorated function

Return type

function or NoneType

runway.command(name, inputs={}, outputs={})

This decorator function is used to define the interface for your model. All functions that are wrapped by this decorator become exposed via HTTP requests to /<command_name>. Each command that you define can be used to get data into or out of your runway model, or trigger an action.

import runway
from runway.data_types import category, vector, image
from your_code import model

@runway.setup
def setup():
    return model()

sample_inputs= {
    "z": vector(length=512, description="The seed used to generate an output image."),
    "category": category(choices=["day", "night"])
}

sample_outputs = {
    "image": image(width=1024, height=1024)
}

# Descriptions are used to document each data type and `@runway.command()`; Their values appear
# in the app as tooltips. Writing detailed descriptions for each model option goes a long way
# towards helping users learn how to interact with your model. Write descriptions as full
# sentences.
sample_description = "Generate a new image based on a z-vector and an output style: Day or night."
@runway.command("sample",
                inputs=sample_inputs,
                outputs=sample_outputs,
                description=sample_description)
def sample(model, inputs):
    # The parameters passed to a function decorated by @runway.command() are:
    #   1. The return value of a function wrapped by @runway.setup(), usually a model.
    #   2. The inputs sent with the HTTP request to the /<command_name> endpoint,
    #      as defined by the inputs keyword argument delivered to @runway.command().
    img = model.sample(z=inputs["z"], category=inputs["category"])
    # `img` can be a PIL or numpy image. It will be encoded as a base64 URI string
    # automatically by @runway.command().
    return { "image": img }

Note

All @runway.command() decorators accept a description keyword argument that can be used to describe what the command does. Descriptions appear as tooltips in the app and help users learn what the command does. It’s best practice to write full-sentence descriptions for each of your input variables and commands.

Parameters
  • name (string) – The name of the command. This name is used to create the HTTP route associated with the command (i.e. a name of “generate_text” will generate a /generate_text route).

  • inputs (dict) – A dictionary mapping input names to runway.data_types. This dictionary defines the interface used to send input data to this command. At least one key value pair is required.

  • outputs (dict) – A dictionary defining the output data returned from the wrapped function as runway.data_types. At least one key value pair is required.

  • description (string, optional) – A text description of what this command does. If this parameter is present its value will be rendered as a tooltip in Runway. Defaults to None.

Raises

Exception – An exception if there isn’t at least one key value pair for both inputs and outputs dictionaries

Returns

A decorated function

Return type

function

runway.run(host='0.0.0.0', port=9000, model_options={}, debug=False, meta=False)

Run the model and start listening for HTTP requests on the network. By default, the server will run on port 9000 and listen on all network interfaces (0.0.0.0).

import runway

# ... setup an initialization function with @runway.setup()
# ... define a command or two with @runway.command()

# now it's time to run the model server which actually sets up the
# routes and handles the HTTP requests.
if __name__ == "__main__":
    runway.run()

runway.run() acts as the entrypoint to the runway module. You should call it as the last thing in your runway_model.py, once you’ve defined a @runway.setup() function and one or more @runway.command() functions.

Parameters
  • host (string, optional) – The IP address to bind the HTTP server to, defaults to "0.0.0.0" (all interfaces). This value will be overwritten by the RW_HOST environment variable if it is present.

  • port (int, optional) – The port to bind the HTTP server to, defaults to 9000. This value will be overwritten by the RW_PORT environment variable if it is present.

  • model_options (dict, optional) – The model options that are passed to @runway.setup() during initialization, defaults to {}. This value will be overwritten by the RW_MODEL_OPTIONS environment variable if it is present.

  • debug (boolean, optional) – Whether to run the Flask HTTP server in debug mode, which enables live reloading, defaults to False. This value will be overwritten by the RW_DEBUG environment variable if it is present.

  • meta (boolean, optional) – Print the model’s options and commands as JSON and exit, defaults to False. This functionality is used in a production environment to dynamically discover the interface presented by the Runway model at runtime. This value will be overwritten by the RW_META environment variable if it is present.

  • no_serve – Don’t start the Flask server, defaults to False (i.e. the Flask server is started by default when the runway.run() function is called without setting this argument set to True). This functionality is used during automated testing to mock HTTP requests using Flask’s app.test_client() (see Flask’s testing docs for more details).

Warning

All keyword arguments to the runway.run() function will be overwritten by environment variables when your model is run by the Runway app. Using the default values for these arguments, or supplying your own in python code, is fine so long as you are aware of the fact that their values will be overwritten by the following environment variables at runtime in a production environment:

  • RW_HOST: Defines the IP address to bind the HTTP server to. This environment variable overwrites any value passed as the host keyword argument.

  • RW_PORT: Defines the port to bind the HTTP server to. This environment variable overwrites any value passed as the port keyword argument.

  • RW_MODEL_OPTIONS: Defines the model options that are passed to @runway.setup() during initialization. This environment variable overwrites any value passed as the model_options keyword argument.

  • RW_DEBUG: Defines whether to run the Flask HTTP server in debug mode, which enables live reloading. This environment variable overwrites any value passed as the debug keyword argument. RW_DEBUG=1 enables debug mode.

  • RW_META: Defines the behavior of the runway.run() function. If RW_META=1 the function prints the model’s options and commands as JSON and then exits. This environment variable overwrites any value passed as the meta keyword argument.

  • RW_NO_SERVE: Forces runway.run() to not start its Flask server. This environment variable overwrites any value passed as the no_serve keyword argument.