After spending hours on conversation design, training, and testing your Rasa chatbot, you are finally ready to deploy it as a backend API. You start looking at the deployment documentation, and there is no easy step-by-step guide to deploy your beloved chatbot. I know because I have been there! That’s why I am sharing how I deployed my chatbot here.
First, I built a custom connector to interact with my chatbot through a webhook. Next, I deployed my chatbot to a cloud virtual machine (VM). I used the Google Cloud Platform (GCP) compute instance. However, the steps outlined here are applicable to other cloud providers. Below you can find the details of the step-by-step guide on how I deployed my Rasa chatbot on GCP.
Step 1: Create a Custom Connector
A custom connector is an interface between the chatbot users and Rasa chatbot. Rasa has prebuilt integrations with many channel connectors such as Slack, Telegram, Facebook Messenger, etc. However, to make a custom connector we need to implement a class that subclasses rasa.core.channels.channel.InputChannel
and implements name
and blueprint
methods. More details on this can be found here.
In my chatbot repo, I created a folder called addons
that contains my custom connector class, custom_channel.py
:
import asyncio
import inspect
from sanic import Sanic, Blueprint, response
from sanic.request import Request
from sanic.response import HTTPResponse
from typing import Text, Dict, Any, Optional, Callable, Awaitable, NoReturn
import rasa.utils.endpoints
from rasa.core.channels.channel import (
InputChannel,
CollectingOutputChannel,
UserMessage,
)
class MyIO(InputChannel):
def name(name) -> Text:
return "myio"
def blueprint(
self, on_new_message: Callable[[UserMessage], Awaitable[None]]
) -> Blueprint:
custom_webhook = Blueprint(
"custom_webhook_{}".format(type(self).__name__),
inspect.getmodule(self).__name__,
)
@custom_webhook.route("/", methods=["GET"])
async def health(request: Request) -> HTTPResponse:
return response.json({"status": "ok"})
@custom_webhook.route("/webhook", methods=["POST"])
async def receive(request: Request) -> HTTPResponse:
sender_id = request.json.get("sender")
text = request.json.get("text")
input_channel = self.name()
metadata = self.get_metadata(request)
collector = CollectingOutputChannel()
await on_new_message(
UserMessage(
text,
collector,
sender_id,
input_channel=input_channel,
metadata=metadata,
)
)
return response.json(collector.messages)
return custom_webhook
Additionally, I appended my credentials.yml
file with:
addons.custom_channel.MyIO:
username: "user_name"
another_parameter: "some value"
Also, in the domain.yml
file, I included the channel name myio
after the first response, i.e, utter_greet
:
responses:
utter_greet:
- text: Hello!
channel: myio
And that is all we need to do on the chatbot side to enable the custom connection. To run the chatbot, we will need to specify the path to credentials.yml
:
rasa run --credentials ./credentials.yml
Now that we have the Rasa chatbot server running on port 5005 locally, multiple users can communicate with it simultaneously, each within their own session using the http://localhost:5005/webhooks/myio/webhook
webhook and a payload similar to the following:
{
"sender": "test_user_1",
"text": "Hi there!",
"metadata": {}
}
Vola! We have our custom webhook working. Let’s now move on to deploying our VM.
Step 2: Deploy on a VM
I used a private GitHub repository to store my Rasa chatbot. To enable access to this private repository from within the VM, I set up a GitHub repository SSH deploy key by following the steps below:
- Created a pair of private and public ssh keys using
ssh-keygen
command - Copied the public key (found in the file with the .pub extension) to deploy keys of the repository. If you have never done this before, navigate to the repo > click on “Settings” on the top right > “Deploy keys” on the left menu > “Add deploy key”
- Copied the private key to Google Secret Manager. To accomplish this, navigate to the secret manager > click on “+ CREATE SECRET” > simply assign a name to the secret and upload or copy the key to the secret value. To access the secret from within the VM,
- the scope needs to authenticate with cloud-platform (see below), and
- the service account needs to have the
Secret Manager Secret Accessor
permissions.
To avoid retraining the chatbot on the VM, I stored my trained model weights in cloud storage. I also created a requirements.txt
configuration file for my Python packages including rasa
, google-cloud-core
, google-cloud-storage
, etc.
Finally, I used a startup bash script to deploy the Rasa chatbot remotely. The script
- downloads the Rasa chatbot from a private GitHub repository
- sets up the Python environment
- downloads the trained model weights from the cloud storage
- starts the Rasa server (and action server if exists)
Below is my startup_script.sh
:
sudo apt-get update
sudo apt -y install jq
curl "https://secretmanager.googleapis.com/v1/projects/<PROJECT-NAME>/secrets/<SECRET-NAME>/versions/<SECRET-VERSION>:access" \
--request "GET" \
--header "authorization: Bearer $(gcloud auth print-access-token)" \
--header "content-type: application/json" | jq -r '.payload.data' | base64 --decode > ~/.ssh/id_rsa
echo -e '\n' >> ~/.ssh/id_rsa
chmod 400 ~/.ssh/id_rsa
echo -e 'Host github.com\n\tHostname github.com\n\tIdentityFile ~/.ssh/id_rsa' >> ~/.ssh/config
eval `ssh-agent -s`
ssh-add ~/.ssh/id_rsa
ssh-keyscan -t rsa github.com > known_hosts.github
cp known_hosts.github ~/.ssh/known_hosts
git clone git@github.com:<GITHUB-USERNAME>/<REPOSITORY-NAME>.git ~/app
cd ~/app
yes | sudo apt install python3.8-venv
yes | sudo apt install pip
pip install --upgrade pip
python3 -m pip install --user virtualenv
python3 -m venv venv
source ./venv/bin/activate
yes | pip install -r requirements.txt
mkdir ./models
gsutil cp gs://<PATH-TO-MODEL>/<MODEL-NAME>.tar.gz ./models
rasa run --credentials ./credentials.yml & rasa run actions -p 5055
Running the script below, I spun the VMs and opened port 5005 for the Rasa chatbot:
MY_INSTANCE_NAME=<RASA-CHATBOT-NAME>
ZONE=<ZONE>
gcloud compute instances create $MY_INSTANCE_NAME \
--image-family=ubuntu-2004-lts \
--image-project=ubuntu-os-cloud \
--machine-type=<MACHINE-TYPE> \
--scopes="https://www.googleapis.com/auth/cloud-platform" \
--service-account <SERVICE-ACCOUNT> \
--metadata-from-file startup-script=startup_script.sh \
--zone $ZONE \
--tags rasa
gcloud compute firewall-rules create port-5005 \
--allow tcp:5005 \
--source-ranges 0.0.0.0/0 \
--target-tags rasa \
--description "Allow port 5005 access to server"
If you made it this far with me, you now have your Rasa chatbot accessible on the http://<VM-IP-ADDRESS>:5005/webhooks/myio/webhook
. Enjoy chatting away with your in-cloud bot!