Interact with the deployed bot (on k3s using quick install script) using custom connectors

I built a custom connector (by adding a channel.py file) and tested it locally (by interacting with it using postman) via the custom channel.

While deploying the bot, I used the following command to set the environment variable to connect with the custom channel:

export ADDITIONAL_CHANNEL_CREDENTIALS="rest='channel.RestInput1'"

I am able to interact with the deployed bot using by sending post requests (using postman) via rest channel. But, on trying to interact via custom channel, I get the following response:

<!DOCTYPE html>
<meta charset=UTF-8>
<title>404 — Not Found</title>
<style>
	html {
		font-family: sans-serif
    }
</style>
<h1>⚠️ 404 — Not Found</h1>
<p>Requested URL /webhooks/custom_channel/webhook not found

My channel.py file is stored in the repository connected to Rasa X.

Is there an additional step I am missing?

Hi @gaushh, When deploying on kubernetes, this is how I always do it for deploying custom channels & components.

I create a custom docker image of rasa that includes my custom channel as an installed python package, using these steps:

Create this folder structure with files whose content is described below:

|-custom_channels
| |channel.py
| |__init__.py
|
|setup.py
|Dockerfile

The folder custom_channels is just your code, with folder structure of a python package.

The file setup.py , is a minimalistic setup file to install the package.

Content of setup.py is something like this:

"""A setuptools based setup module.

See:
https://packaging.python.org/guides/distributing-packages-using-setuptools/
https://github.com/pypa/sampleproject
"""
from setuptools import setup, find_packages

setup(
    name='custom-channels',
    version='0.0.1',
    url='',
    author='',
    author_email='',
    description='Custom Channels for Rasa',
    packages=find_packages(),
    install_requires=[],
)

During development of your channel, it is useful to just install it inside your python environment, like a conda environment, in editable mode, using this command:

pip install -e .

And then in your bot, use a credentials.yml as defined below.

Once ready to deploy, the file Dockerfile is used to build the custom docker image of Rasa with your custom channel included:

#
# Notes:
# (-) See https://github.com/RasaHQ/rasa/blob/master/docker/Dockerfile_full
#
FROM rasa/rasa:1.10.16-full

##################################################
# Install the custom channel as a python package #
##################################################

USER root

# change working directory
WORKDIR /build-custom

# copy files
COPY custom_channels /build-custom/custom_channels
COPY setup.py /build-custom

# install custom channels
RUN pip install --upgrade pip
RUN python -m pip install .

# cleanup
RUN rm -rf /build-custom

##################################  
# change user to not run as root #
##################################
WORKDIR /app
USER 1001

Once you have this in place, you Build the docker image with:

sudo docker build . --no-cache --file Dockerfile -t custom-rasa:0.0.1

You then push this custom rasa image to your docker registry, and use it to deploy in your k3s cluster.

Note that an alternative to k3s is microk8s, which has a build in container registry. If you use microk8s, your workflow will become a bit easier, because you can just build the docker image on your computer or VM and push it directly into the cluster, without going through an external docker registry.

To deploy this custom rasa container in the cluster, I prefer to deploy using a helm-chart, as described here.

For the Rasa Open Source Version, you add this in the values.yml:

# rasa: Settings common for all Rasa containers
rasa:
    # https://rasa.com/docs/rasa/user-guide/connectors/custom-connectors/#id1
    # name of the Custom Rasa image to use
    # Prefix it with the docker-registry you use
    name: "<DOCKER-REGISTRY>/custom-rasa"
    # tag refers to the Custom Rasa image tag
    tag: "0.0.1"
    # additionalChannelCredentials which should be used by Rasa to connect to various
    # input channels
    additionalChannelCredentials:
      # Custom Connector
      # (-) use `custom_channels`, because the package directory name is `custom_channels`
      # (-) use `channel`, because the python module is called `channel.py`
      # (-) use `RestInput1`, because your class is called `RestInput1`
      rest:
      custom_channels.channel.RestInput1:
        # you don't need to provide anything here - this channel doesn't
        # require any credentials

You Talk to your bot with:

# replace `my_custom_rest_channel` with the name you return from the name() method of your class `RestInput1` in your python file `channel.py`
curl http://HOST:PORT/webhooks/my_custom_rest_channel/

I think that summarizes it. I hope this information helps you get it going.

The nice thing about this approach is that you can de-couple the custom channel development from your bots. You develop & maintain your custom channel code in one repository, and just install it or deploy it with your Rasa X as a custom Rasa container.

Then, you can use it with every bot you create, without having to copy a duplicate of the channel.py into every bot repository.

2 Likes

Can you please elaborate further on this.

Also, Thanks a lot, @Arjaan for your highly detailed response. Will mark it as the solution as soon as I get this to work. :slightly_smiling_face:

@Arjaan I was able to build the channel image and pull it to VM (thanks to your elaborate post.)

This is the description of rasa-worker pod:

Now, the docker image size turned out to be huge (around 1 Gb). Is that normal?

Also, I still am unable to send post requests. When I try sending a message on the following URL:

http://alex.com/webhooks/alex_channel/webhook

Error: Requested URL /webhooks/alex_channel/webhook not found

It works just fine on replacing alex_channel with rest in the URL. What might I be doing wrong?

@arjaan I deployed the pod following your guidelines. Now I pod doesn’t reem to be running. I can see the following error but am unable to resolve it. Kindly take a look into it.

@Juste @akelad
@Arjaan arjaan seems a bit occupied. I’d be really grateful if you can help in resolving the issue or redirect it to someone relevant.

@gaushh, did you follow the exact steps that Arjaan gave, or did you modify them slightly? e.g. Arjaan said to refer to the channel as custom_channels.channel.RestInput1 in the values.yml, but your error message seems to indicate you referred to it as channel.RestInput1

1 Like

Hi @gaushh,

The first error in the log is:

ModuleNotFoundError: No module named 'channel'

I suspect there is a mismatch in some of the names for the folder structure, the class name, the setup.py & values.yml.

To help find the issue, could you post here:

  • Your directory structure and file names for your custom channel code
  • The class name of your custom channel
  • your setup.py
  • The content of the additionalChannelCredentials section of your values.yaml
1 Like

Great!! This particular issue got resolved. @akelads’ input helped big time. I was (rather foolishly) using channel.RestInput1 instead of custom_channels.channel.RestInput1.

Just one last thing, now the POST request gets sent but to the server but I get a blank output ([]) back on postman. Also the sent messages are not reaching rasa X (as I can’t find them in the UI)

Change rasa version to the one being installed in deployment inside Dockerfile… and it is good to go.

Again, Thanks Arjaan and @akelad for your responses. It is because of you, I was able to get it working.

1 Like

@gaushh Hey, I am trying to do the same for my bot, my custom Socket channel is this - socketChannel.py (7.1 KB) After reading this thread, I realized that I need to make a Dockerfile with a custom rasa image and the python packages of my sockerChannel.py file need to be installed using a setup.py file. Now, if you take a look inside my socketChannel.py file, it is importing libraries from both rasa open source and rasa sdk modules and also some other libraries apart from rasa. So, how would my setup.py be written in such a case? Also, if you could attach your own setup.py here then it would be a great help.

@akelad if you could help me out here then would be a huge help! Thanks.