I have been building a Rasa chatbot and the number of custom actions I have written kept on growing and I wanted to change something.
What I do not like about Rasa is that it relies heavily on classes. For example, if you want to write a custom action, you have to follow this pattern:
class ActionHelloWorld(Action):
def name(self) -> Text:
return "action_hello_world"
def run(self, dispatcher: CollectingDispatcher,
tracker: Tracker,
domain: Dict[Text, Any]) -> List[Dict[Text, Any]]:
dispatcher.utter_message(text="Hello World!")
return []
The name
method is required and you have to implement it every time you write a custom action. This style is being followed across the Rasa source code. Being a lazy programmer, I don't want to write more of these. Writing it as an attribute as shown below is a much simpler pattern.
class ActionHelloWorld(Action):
__name__ = "action_hello_world"
def run(self, dispatcher: CollectingDispatcher,
tracker: Tracker,
domain: Dict[Text, Any]) -> List[Dict[Text, Any]]:
dispatcher.utter_message(text="Hello World!")
return []
But I want it even simpler. A decorator? This gave me an idea of implementing it into a rasam
feature.
In the example below, we simply have written a function with the same signature as the run
method in ActionHelloWorld
class and used rasam.action
decorator.
from rasam import action
@action
def action_hello_world(
self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict[Text, Any]
) -> List[Dict[Text, Any]]:
dispatcher.utter_message(text="Hello World!")
return []
The @action
decorator, creates a class derived from Action
, uses the function name as the name of the class and converts the original function into a run
method.
More to go
I am still working on implementing this style on other Rasa classes. If you want to contribute, feel free to create a pull request into the rasam
repository here.