XState Core Chatbot
Overview
Goal: To onboard developers onto the XState-Chatbot code base so that they can modify existing flows or create new ones.
This document sticks to explaining the chatbot's core features and does not dive into the use cases implemented by the chatbot.
Chatbot Fundamentals
This chatbot solves the basic form-filling aspect of a chat flow. By collecting the information from the user, an API call is made to the rainmaker backend services to fulfil the user requirements. It uses the concept of StateCharts (similar to State Machines) to maintain the state of the user in a chat flow and store the information provided by the user. XState is a JavaScript implementation of StateCharts. All chat flows are coded inside the XState framework.
This chatbot does not have any Natural Language Processing component. In the future, we can extend the chatbot to add such features.
Basic Introduction to XState
XState is a JavaScript implementation of StateCharts. There is detailed documentation available to study XState. Some concepts of XState used in the Chatbot are listed below. Basic knowledge of these concepts is necessary. It can also be learned while going through the chat flow implementation of pilot use cases in PGR and Bills.
Actions
onEntry
Few tips about using XState. These have been followed throughout the pilot chat flows.
To move to any state which is not at the same hierarchical level, assign a unique ID value. If it has an ID value, address it using the # qualifier in the target attribute.
Since the ID should be unique, make sure there are no multiple states having the same ID value. If there is a duplicate, the application will not function as expected.
Any actions (like onEntry) should be surrounded by assign.
This includes almost all functions except the guard condition code snippets.
Pre-requisites
NodeJS
PostgreSQL
Kafka_(optional)_
Key Functionalities
Build a chat flow to facilitate a user to interact with rainmaker modules
Link a chat flow with backend services
Deployment Details
Deploy the latest version of xstate-chatbot
Configure /xstate-chatbot to be a whitelisted open endpoint in zuul
Add indexer-config to the egov-indexer to index all the telemetry messages
WHATSAPP_PROVIDER
The provider through which WhatsApp messages are sent & received. An adapter for ValueFirst is written. If there is any new provider a separate adapter will have to be implemented.
A default console
adapter is provided for developers to test the chatbot locally.
REPO_PROVIDER
The database used to store the chat state. Currently, an adapter for PostgreSQL is provided.
An InMemory
adapter is provided to test the chatbot locally
SERVICE_PROVIDER
If it’s value is configured to be eGov, it will call the backend rainmaker services. If the value is configured as Dummy, dummy data would be used rather than fetching data from APIs.
Dummy option is provided for initial dialog development, and is only to be used locally.
SUPPORTED_LOCALES
A list of comma-separated locales supported by the chatbot.
Other configuration details are mentioned in the XState-Chatbot Integration Document.
Chat Flow
All the interactions with the user - sending a message to the user and processing an incoming message from the user are coded as a state in the State Machine. It would be a nice start to test any chat flow with the supplementary react-app provided for the developers to execute the state machine locally. (Please follow the guidelines in the README of the react-app.)
We have applied some standard patterns to code any chat interaction. Please try to follow these patterns to code any new chat flow. These patterns are explained below. You can also study those by browsing through the code of the pilot use cases of PGR and Bills.
The chat states would only include dialogue-specific code. Any code related to the backend service should be written as a part of a separate …-service.js file.
Any code that does not include any asynchronous API call can be written as a part of the onEntry function or action.
If the function needs to make an API call, that would have to be written with the invoke-on Done pattern. The asynchronous function should be written as a part of the service file. The consolidated data returned by it can be processed in the state of the dialogue file.
Helper functions are written in
dialog.js
file. It is advised to use those functions as much as possible rather than writing any custom logic in dialogue files.
Scaffolding
Apart from the chat flow and its backend service API calls, a few other components are present in the project. These components do NOT need to be modified to code any new chat flow or changed for an existing chat flow. These components with a short description for each are listed below:
Session Manager: It manages the sessions of all the users on a server. It will store the user’s state in a datastore, update it, and read it when any new message is received on the server. Based on the state of the user, it creates a state machine and sends the incoming message event to the state machine. It sanctifies the state (any sensitive data like the name and mobile number of a user are removed) before storing the state in the datastore.
Repository: It is the datastore where the states of the users get stored. To reduce dependency, an in-memory repository is also provided, which can be used by configuring an environment variable. So to run the chatbot service, PostgreSQL isn’t a hard dependency, but it is advisable to use the PostgreSQL repo provider.
Channel Provider: There can be many different WhatsApp Providers. Any one of the providers will be configured to be used. A separate
console
WhatsApp Provider is present for the developer to test the chatbot server locally. Postman collection to mimic receiving messages from a user to the server is present in the project directory.Localization: Every message to be sent to the user is stored within the chatbot. Localization service is not being used. These messages are present near the bottom of the dialogue files. A separate localization-service.js is provided to get the messages for the localization codes for the messages that are not owned by the chatbot. For example, the PGR complaint types data is under the ownership of the PGR module, and the messages for such can be fetched from the egov-localization-service using the functions provided in the localization-service.js.
Service Provider: To ease the initial dialogue development, instead of coding API calls to the backend services, we can configure the chat flow to use a dummy service. This can be configured using an environment variable and modifying the
service-loader.js
file.Telemetry: Chatbot logs telemetry events to a Kafka topic. (Any sensitive data will get masked before indexing the events onto ElasticSearch by egov-indexer.) The following events get logged:
Incoming message
Outgoing message
Transition of state
Last updated