NodeJS alternative to Rasa SDK Action Server
- Allow people to write their own action server in JavaScript with NodeJS
- Does not require the use of Rasa-SDK
- Simple and not verbose action definition
$ npm install rasa-node-action-server
To start a simple Action Server you can use the following quick start example.
// index.js
const { RasaNodeActionServer, RasaActionEvent } = require("./rasa-node-action-server");
const rnas = new RasaNodeActionServer();
rnas.define("action_hello_world", (action, res) => {
res
.addEvent(RasaActionEvent.bot("Hello world, from your action server"))
.send();
});
rnas.start();
and run
node index.js
The RasaNodeActionServer
by default will start an express server on localhost:5055
. For more examples, check out the examples
folder on Github.
If you want to pass additional parameters to your rasa action inside your request, you should use the metadata
field as suggested in the rasa documentation.
For a quick start, you can use the following custom connector which allows the metadata
parameter to be forwarded to the server.
# custom_connector.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,
)
import logging
logger = logging.getLogger(__name__)
class RasaNodeChannel(InputChannel):
"""A simple web bot that listens on a url and responds."""
@classmethod
def name(self) -> Text:
return "rnc"
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") # method to get sender_id
text = request.json.get("message") # method to fetch text
input_channel = self.name() # method to fetch input channel
metadata = self.get_metadata(request) # method to get metadata
collector = CollectingOutputChannel()
# include exception handling
await on_new_message(
UserMessage(
text,
collector,
sender_id,
input_channel=input_channel,
metadata=metadata,
)
)
return response.json(collector.messages)
return custom_webhook
def get_metadata(self, req) -> Text:
return req.json.get("metadata") or self.name()
and define it inside the credentials.yml
file like this:
rest:
custom_channel.RasaNodeChannel:
rasa:
url: "http://localhost:5002/api"
You can then test your server by running:
curl -XPOST http://localhost:5005/webhooks/rnc/webhook \
-H "Content-type: application/json" \
-d '{"sender": "lykos94", "message": "Hello bot", "metadata":{}}'
response:
[{"recipient_id":"lykos94","text":"Hello world, from your action server"}]
Parameter | Type | Description | Default |
---|---|---|---|
port |
number |
Optional.The port on which the Action Server will start | 5055 |
port |
string |
Optional. The host on which the Action Server will start | "localhost" |
Parameter | Type | Description | Default |
---|---|---|---|
action_name |
string |
Required. The name of the action to trigger | none |
action_function |
function |
Required. The function to trigger. This function received 2 parameters: action and response | none |
Function that registers all the action handlers and run the action server
Function to retrieve the sender of the action request
Function to retrieve the metadata of the action request
Function to retrieve the domain of the action request
Parameter | Type | Description | Default |
---|---|---|---|
event |
RasaActionEvent |
Required. A RasaActionEvent with the event type called as function | none |
// example
res.addEvent(RasaActionEvent.bot("Hello from bot"))
Parameter | Type | Description | Default |
---|---|---|---|
response |
object |
Required. The object to add to a response | none |
// example
res.addResponse({ test:"Text of the response" })
Function to send the response back to the Rasa server