Splitting your Actions in Rasa
Tags: rasa, ai, actions, python
Published: 2020-04-30 15:21:01

Rasa is an amazingly flexible open source system for building conversational chat bots.  You can quite literally have the basic out-of-the-box bot working in less than 15 minutes.  There are a host of tutorials and videos online that explain how to set up, extend and train your bot.

The main reason Rasa is so flexible is that you can build out actions to extend the functionality. If you are familiar with Alexa, you can think of these as added skills. These actions can be as simple as an API call to an external system (ie weather service or joke of the day) or could be setup to walk a user through a set of questions to gather information (think "form"), or you can build actions to interact with an external ERP, other complex system, knowledge base, or really whatever you can think of.

All of these actions are built with python and by default exist as classes in the `actions.py` file.  You can imagine that this file can get quite large and unwieldy as your bot grows in abilities and functionality.  Thankfully  there is a way to split up and organize these actions to make development more streamlined.  This method is not documented anywhere on the RASA site, although it is fully supported out of the box and requires only a little modification to your project's directory structure, which also helps with organization.

**Note**
For this tutorial, we'll reference my main project directory `C3PO`.  I'm on Ubuntu, so I'll also give you the commands to run where necessary, but feel free to perform the necessary steps however you feel comfortable.

From a terminal, lets change to our project's home direcotry:
`cd ~/RASA/C3PO`

### Setting Up Your New Actions Directory
Create a new directory off of the root of your project's directory called `actions`. This is where all of your new action files will live. 

`mkdir actions`

You'll end up with something like this:
`C3PO/actions`

Now we want to make that actions folder a `package` in python. This sounds pretty involved, but really only requires the creating of one file with a special filename.

In the actions directory create an empty file named `__init.py__`  That may be hard to tell, but that is 2 underscores before and after the `init.py`.

From your project's home run
`touch actions/__init.py__`

That's all, you don't have to edit this file at all, it just has to exist.  The actions directory is now considered a package and what that means is that when it is referenced **all** files in there will be loaded.  Perfect.

### Move and package
We can now **move** our `actions.py` file into our package directory. Be sure to not copy it, move it there or else Rasa won't check for the `actions` directory. 

`mv actions.py actions`

GREAT. You can consider your `actions.py` file "packaged" :)  That was pretty easy.

You can stop now and everything will work as it did before, but that's not the point of this article is it.

### The Big Split
The first thing you'll want to do is open `actions.py` in your code editor.
Create a new file in your `actions` directory, the filename is arbitrary. Give it a filename that means something to you.  Here is where the organizational part comes in, and only you can know what makes sense.  

If you're like me, you have a naming convention throughout your bot, and you've split your NLU, Stories and Domain data already.  If you have, you'll probably use that naming style here.  For example, I've prefixed all of my actions with an `a` and an index number that references internal documentation about that particular element whether that is an intent, story, entity, etc.

Here's an example action filename from one of my bots: `a004-ext-api-bmchelix-create-issue.py` I can tell from the text portion that's an external api call to BMC Helix to create an issue (ticket) and I can look up item `004` on my internal documentation and read more about that particular call, if there are other references to entities, etc.  Internal docs are super important, especially if you have other developers working with you on this.  Even if you're a lone-wolf developer, these bots can get pretty complex, so I can't stress enough about taking your time and taking notes about what you've done.

Continuing on.

At the top of this new file, you'll **need** to copy / paste the top section from your main `actions.py` file. This includes all of the code down to the first `Class` statement.  For me it is all of the `import` and `from` lines like this:

```
import logging
from typing import Any, Text, Dict, List, Union, Optional
from rasa_sdk import Action, Tracker
from rasa_sdk.executor import CollectingDispatcher
from rasa_sdk.forms import FormAction
from rasa_sdk.events import SlotSet, AllSlotsReset, Restarted, UserUtteranceReverted, ConversationPaused

logger = logging.getLogger(__name__)
```

That gives your new action file access to all of the RASA related items you'll need for an action.

Then go ahead and **move** (Cut / Paste) the class or classes from your main `actions.py` file that relate to the new file you've created.

Save it.

Repeat that process as necessary as you want.

Now you'll have an `actions` package directory full of `.py` action files.

### Then What?
Then nothing.  You're done.  There's nothing special to do.  You can still launch your bot the same way you always have with `rasa run actions` and it'll load all of your custom action files as if they were in one file like before.

You can try this to be sure you haven't made an error.  Run `rasa run actions` and the server should spin up.  You'll see all of your action class names scroll onto the screen and it'll sit there waiting for the Rasa server to hit it.

### Help Me Help You
I want this to be useful, so if you discover I've made any errors, let me know and I'll correct them asap.

Happy developing