Blocks
Blocks are the units of work that comprise a worklet.
Blocks are the units of work that comprise a worklet. To create a block, click "Add block" in a worklet graph and select the type of block that you want to add.
Code
Baseten allows you to write your own Python code as part of your worklet. Simply add a Code block to your worklet and select the desired function from a file.
Code blocks require a function with the following signature, selected from the appropriate file.
def func(block_input, env, context):
The three arguments are all optional, but they are positional, so you can't have env
without block_input
or context
without both block_input
and env
. Because the arguments are positional, you can call them whatever you want, but we recommend sticking with the standard parameter names. Valid function signatures:
Let's examine the arguments individually.
block_input
block_input
This is the input to the block. If this block is the first in the worklet, then block_input
is what the worklet was called with. Otherwise block_input
is the return value of the previous block in the worklet.
env
env
Exclusively relying on block input/output for the execution of the worklet would cause headaches. What if the final block needs to access the first block's input? Would you have to ensure that the input is passed along all the way to the end? No.
That's where env
comes in. It's an empty dictionary to which you can add key/value pairs (again, JSON-serializable values only). env
is persisted through the worklet execution, which means that after a block modifies it, all subsequent blocks have access to that data.
context
context
context
provides runtime information as well as variety of ways of invoking many Baseten functionalities:
1. Access to external data connections (e.g. Snowflake, Redis, and PostgreSQL):
Any data connections can be queried with a SQL string via the context
object.
Example:
2. ORM access to user-defined data tables:
Baseten Postgres tables are similarly available to the context
object.
Example:
3. Access to secrets:
Key-value pairs from Baseten's secret store are available via context
for authenticating with third-party services and APIs.
Example:
4. Access to user information like user ID and username:
The context
object contains information on the current user. For workspaces with multiple users, the "current" user is the user who invoked the worklet that runs the code block. If the worklet was invoked via an API endpoint, the "current" user is the account that issued the API key used to invoke the worklet.
Example:
5. Ability to invoke a model:
You can invoke a model from a code block by model ID or model version ID.
Example:
Return value
It's worth repeating that Code blocks must explicitly return a JSON-serializable value to use as input for the next block, unless the Code block in question is the last block in a worklet. Even in this case, we recommend returning JSON in case the worklet is ever called from another worklet.
If your function is only called for its side effects, simply end with return block_input
to pass along the block's input to the next block in the worklet.
Decision
Decision blocks are very similar to Code blocks in that you write custom Python code with access to the same block_input, env, context
args. However, Decision blocks' output must be a boolean, which will determine which of its two child blocks should be called next.
If the decision block returns True
(or a truthy value), the "then" path will be executed. If it returns False
(or equivalent), the "else" path will be executed.
Since a block's output becomes the subsequent block's input, you can imagine that the boolean result of the Decision block will become the input to its subsequent block. That would be somewhat useless, so we made an exception: The input to the Decision block becomes the input to the subsequent block.
While block_input
and env
are available arguments for a Decision block's function, they are considered read-only. Decision blocks should solely return a boolean value, not have any side effects. Any changes made to the input or environment will not be available in subsequent blocks.
Model
A Model block is the heart of any ML-powered worklet. This block invokes a selected model and returns its output.
While the model doesn't have access to env
or context
, the output of the previous block becomes the model's input. As such, make sure to pass along an input of the correct type. For example, if the model expects a list or numpy array, the previous block should return this type.
In your model blocks, you can set a model's version. Like all changes to worklets, changing a model version is environment-specific for users in workspaces with the draft environment feature. Setting the model version to primary will keep your worklet up-to-date as you publish new model versions, but specifying a version lets you roll out new model versions in sync with application changes that support the new version.
Query
A Query block lets you access queries directly in worklets.
The query block, like all other blocks, takes a JSON dictionary as input. For queries that do not require input, this can be an empty dictionary. But in some cases, we need to pass inputs into a query. For example:
In this case, invoking the query block would require passing in:
The query block outputs a dictionary with the key results
and a list of query results. For example, a query that returns the following tabular output:
Would return the following JSON when run as a worklet block:
Worklet
Worklets, like functions, are composable. With a worklet block, you can call another worklet from your current worklet. This does not result in a new API request or worklet invocation, and env
persists in the called worklet. This block returns the result of the called worklet, so be sure to format it as a valid input for the next block.
If you don't enjoy recursion, you can skip this paragraph and still be a fully capable Baseten user. A worklet can call itself, opening the possibility of recursive worklets. Also, worklet A can call worklet B, which in turn calls worklet A. Such complexities are rarely the best way to solve problems, but we have left the capability in the platform to maximize developer freedom and flexibility. The runtime will error out at an unsustainable recursion depth (think hundreds of recursive calls), so don't go too wild.
Slack
To send a Slack message from a worklet:
In Slack, create a webhook.
Paste the webhook into the appropriate field.
Write your message! To include the value of
block_input
in your message, use a single empty pair of curly braces{}
.
When you run the worklet, the Slack message will be sent!
The output of the Slack block will be {'message_sent': 'Your message here'}
, so if you have any blocks set to run after the Slack block make sure that any necessary variables are stored in env
.
Slack is our first of many planned integrations. If there is an API that you would like a similar integration for, please let us know.
Last updated