Overview

This document introduce dialogs and covers the main related concepts.

As explained in the documents covering the concepts of Bofuel Dialog, a chatbot is a web application implementing the MVC pattern where:

  • Brain is the model, it contains all the information about the bot, the users, the conversations.
  • Dialog is the controller, it updates the brain and calls its view with the required data.
  • View generates the messages to be sent to the user.

A dialog interacts with the brain (reads and writes), performs computations (e.g., by calling external APIs) and calls its view with the required data. Note that a dialog named <name>-dialog has a single view named <name>-view.

Dialog resolution

Given a user message, the DialogManager is responsible for selecting the dialogs to execute. For a selected dialog named <name>-dialog, the DialogManager resolves it by looking for existing dialogs following this order of locations:

[
  '<bot-path>/src/dialogs/<name>-dialog.<adapter>.js',
  '<bot-path>/src/dialogs/<name>-dialog.js',
  '<bot-path>/node_modules/<module_1-name>/src/dialogs/<name>-dialog.<adapter>.js',
  '<bot-path>/node_modules/<module_1-name>/src/dialogs/<name>-dialog.js',
  ...,
  '<bot-path>/node_modules/<module_k-name>/src/dialogs/<name>-dialog.<adapter>.js',
  '<bot-path>/node_modules/<module_k-name>/src/dialogs/<name>-dialog.js',
  '<botuel-dialog-path>/src/dialogs/<name>-dialog.<adapter>.js',
  '<botuel-dialog-path>/src/dialogs/<name>-dialog.js',
];

This allows you to customize the dialog depending on the adapter.

Dialog properties

Dialogs have the property triggeredBy that lets you know how the dialog has been triggered.

It can take one of the following values:

  • nlu: the dialog has been triggered by the classification results
  • dialog-manager: the dialog has been triggered by the dialog manager. This may happen when there is no classification results (i.e., default dialog triggered), when there are several classification results (i.e., classification-disambiguation dialog triggered) or when a confirmation is required to continue a dialog (i.e., confirmation-dialog)
  • postback: the dialog has been triggered by the click on a postback button
  • <DIALOG_NAME>-dialog: the dialog has been triggered by another dialog (using triggerNext or cancelPrevious or startNewConversation when the next dialog's name is provided)

Dialog instructions

Dialogs come with a set of powerful instructions:

  • complete
  • wait
  • triggerNext
  • cancelPrevious
  • startNewConversation

Each instruction returns an action, which is interpreted by the DialogManager.

The complete instruction

The complete instruction indicates that the dialog is complete. The DialogManager can now execute other dialogs if any dialog is due to be executed.

/**
 * Builds an action
 * indicating that the current dialog is completed.
 * @returns {Object} the action object
 */
complete();

The wait instruction

The wait instruction stops the dialog execution and waits for user input.

/**
 * Builds an action
 * indicating that current dialog should wait.
 * @returns {Object} the action object
 */
wait();

The triggerNext instruction

The triggerNext instruction is used for triggering the execution of another dialog.

/**
 * Builds an action
 * indicating that the current dialog is completed and
 * providing the name of the next dialog to execute.
 * @param {String} name - the name of the next dialog to execute
 * @param {Object} data - the data for the next dialog
 * @returns {Object} the action object
 */
triggerNext(name, (data = {}));

The cancelPrevious instruction

The cancelPrevious instruction cancels the previous dialog.

/**
 * Builds an action
 * indicating that the previous dialog is canceled and
 * optionally providing the name of the next dialog.
 * @param {String} [name] - the name of the next dialog (optional)
 * @returns {Object} the action object
 */
cancelPrevious(name);

The startNewConversation instruction

The startNewConversation instruction starts a new conversation.

/**
 * Builds an action
 * indicating that a new conversation should be started and
 * optionally providing the name of the next dialog.
 * @param {String} [name] - the name of the next dialog (optional)
 * @param {Object} [data] - the data for the next dialog
 * @returns {Object} the action object
 */
startNewConversation(name, (data = {}));

Hooks

Hooks are very useful for performing actions before displaying messages or before completing a dialog without overriding other methods of the PromptDialog.

dialogWillDisplay()

The dialogWillDisplay hook is triggered before displaying dialog messages. It allows you to perform API calls and actions in the brain, after which the returned data are passed to the view here.

/**
 * Hook to be overridden before dialog displays.
 * Returns null by default.
 * @async
 * @param {Object} [userMessage] - the user message
 * @param {Object} data - the data
 * @returns {Promise.<*>} - the extra data which will be added to the data passed to the view
 */
async dialogWillDisplay(userMessage, data)

For example, in this GreetingsDialog the dialogWillDisplay hook returns an object containing a single boolean indicating if the user has already been greeted:

async dialogWillDisplay(userMessage) {
  const userId = userMessage.user;
  const { greeted } = (await this.brain.userGet(userId, 'greetings')) || { greeted: false };
  if (!greeted) {
    await this.brain.userSet(userId, 'greetings', { greeted: true });
  }
  return { greeted } ;
}

We could use this data in a view as follows:

render(userMessage, { greeted }) {
  ...
}

Specifically, the corresponding GreetingsView passes the greeted value to the render method that uses it as follows:

render(userMessage, { greeted }) {
  if (greeted) {
    return ['Hello again human!'];
  }
  return ['Hello human!'];
}

dialogWillComplete()

The dialogWillComplete hook is triggered before completing the dialog. It allows you to perform actions in the brain or to branch to a specific dialog. By default, it returns the complete action.

/**
 * Hook to be overridden before dialog completes.
 * @async
 * @param {Object} [userMessage] - the user message
 * @param {Object} data - the data passed to the view
 * @returns {Promise.<*>}
 */
async dialogWillComplete(userMessage, data)

For example, in this ResetDialog the dialogWillComplete hook starts a new conversation by calling the corresponding dialog instruction:

async dialogWillComplete() {
  return this.startNewConversation('greetings');
}

Dialog configuration

If you want to define extra configuration for your dialogs, such as constant values used in many dialogs of your project, you can define this configuration by using the custom key in your config file. This configuration will be accessible in all your dialogs.

See an example of how to use custom configuration here.