Deploy a Worker Node with allora-wkr

Worker nodes are the interfaces between data scientists' models and the Allora Network

A worker node is a machine-intelligent application registered on the Allora chain that provides inference/prediction on a particular topic it's subscribed to and gets rewarded by the Allora chain validators based on the inference quality.

After providing more details about the structure of a worker node, this guide will walk through how to build a worker node and then deploy it to a remote environment. We do so using a tool created for the convenience of data scientists, allora-wkr. However, one can choose to build and deploy a worker node without this tool, which we discuss in the next section here.

Components of a Worker Node

A Worker Node in the Allora Protocol consists of the following components:

1. Allora Inference Base Image (AIB)

This Docker image serves as the base image for your Dockerfile and includes the fundamental node logic. It handles the combination of every part that makes the whole of the worker node and the accommodation for the additional functionality written in the node function.

2. Node Function

This component is the crux of your specific application, enhancing the allora-inference-base docker image. The node function stored on IPFS aims to handle all the custom functionalities needed to provide the inferences. While the AIB handles the communication between the worker node and the Allora chain, the node function provides the actual inference. The structure is such that the AIB downloads the function from IPFS given the attached CID and runs the function, which will then run your custom main.py. This is where the magic comes in: each worker will use a different, custom main.py to provide the inference requested. It is up to the worker to customize main.py. A few examples: the process can be completely run inside that main.py, or it can hit a separate service (e.g. a separate backend with a REST API endpoint), it could query a particular database... the possibilities are endless.

3. Head Node

This independent node publishes the Allora chain request and inference topics to be subscribed to by the worker nodes, which provides inference data in response, thereby channeled to the chain. When a worker node is initialized, it starts with an environment variable called BOOT_NODES, which helps handle the connection and communications between worker nodes and the head node.

With these components, the worker and head node are registered on the Allora chain, which makes requests to the nodes. The inference request is made to the head from the chain, which in turn publishes the request to be subscribed to by the worker, which will call the functions that invoke your custom logic that handles the actual inference. The request-response is a bidirectional flow from the Allora chain to the head node to the worker node to the node function, and then to the model server.

Building a Worker Node with the Allora-wkr CLI

The allora-wkr is a CLI tool that handles worker nodes' seamless creation and deployment. With this tool, you do not need to write the worker node from scratch, the CLI tool will help you bootstrap all the needed components to get worker nodes working. All you have to do is to update the config.yaml file with your custom parameters, update the providedmain.pyto communicate with your inference server, run the deploy command, and your worker should be up and running.

To build a worker node with allora-wkr, you will need to follow the following steps:

1. Install allora-wkr CLI

You will begin with the installing the tool on your machine.

pip install  allora-wkr

you can run allora-wkr --help to get general help or allora-wkr [command]--help to get help relating to a particular command.

2. Initialize the worker

The next step is initializing the CLI to bootstrap all the needed components. The following command will handle the initialization process. It will create all the files in the appropriate directories and generate identities for your node to be used for local development.

allora-wkr init --name <preffered name>

After the bootstrap, you can either move to step 3 or peep into the files to familiarize yourself with the basic/sample worker node generated by the CLI. At the very least, you must edit the provided main.py file to get the worker to talk to your inference server instead of outputting a random value.

3. Run your worker locally.

If you have modified the main.py as suggested above, you just have to execute the run command, and your head and worker node should now run locally, and the head should be ready to accept HTTP as well as broadcast requests to the worker which will call your inference server. If you didn't modify the main.py, the output will be a random value.

allora-wkr run --logs

You can run this without --logs flag to run in detached mode. you can also run allora-wkr terminate to terminate the worker and head nodes.

At this point, you should be seeing the logs from the nodes, and you should be able to make a request to your head node and see it get a response from the worker node. Note that in production, you won't be the one to make the inference request, as the Allora chain will do this at the cadence provided by the topic creator.

You can test your node by running the following curl command:

curl --location 'http://localhost:6000/api/v1/functions/execute' --header 'Accept: application/json, text/plain, */*' --header 'Content-Type: application/json;charset=UTF-8' --data '{
    "function_id": "bafybeigpiwl3o73zvvl6dxdqu7zqcub5mhg65jiky2xqb4rdhfmikswzqm",
    "method": "allora-inference-function.wasm",
    "parameters": null,
    "topic": "<TOPIC_ID>",
    "config": {
        "env_vars": [
            {                              
                "name": "BLS_REQUEST_PATH",
                "value": "/api"
            },
            {                              
                "name": "ALLORA_ARG_PARAMS",
                "value": "<argument>"
            }
        ],
        "number_of_nodes": -1,
        "timeout" : 2
    }
}' | jq

The <TOPIC_ID> needs to be an existing topic on the chain. The <argument> is what the topic is expecting to receive to perform the inference (as an indication to test, you can use the DefaultArg value from the topic on-chain, e.g. for ETH prediction topic, it should be "ETH").

4. Deploy your worker

Your worker node is now ready to be deployed, the main.py has been modified, all env variables passed, and the worker node is running locally. Your next step is to update the config.yaml file with your preferred parameters. You will only need to fill in the empty parameters and leave the already existing ones as they were because they are constants needed to connect to the Allora chain and existing head node. Do not forget that you only need to spin up the head node locally to test your worker. In production, the head node already exists and broadcasts requests. You will only have to deploy your worker to subscribe to those requests and provide inference to the chain.

The following are the requirements to get your workers deployed:

  1. Build and push your docker image to your preferred docker registry. docker login, docker tag image-name:tag username/repository:tag docker push username/repository:tag or similar commands are going to get your image in your registry
  2. Configure Kubernetes on your machine and point your Kubeconfig to your preferred Kubernetes cloud cluster as the current context
  3. Update the config.yaml file

If the above requirements are met, you can then run the command below:

allora-wkr deploy

If all goes as expected, you should now see your stateful set, pods, and containers in your cluster. You can manage your cluster and resources however you prefer. Please note that you can change the generated files as you wish, as this is meant to be a starting guide for your project, not the finished product.