Views

This document will describe views in Botfuel Dialog. Because chatbots are very similar to web applications, bots developed with Botfuel Dialog follow the MVC pattern. Views in Botfuel Dialog are the V of this pattern. They generate messages based on the data computed in dialogs. Botfuel Dialog offers the following message formats, so you can tailor bot messages according to your use cases and the messaging platforms you are using:

  • Text messages and quick replies
  • Images and image uploads
  • Links
  • Buttons and clicks on buttons (aka postbacks)
  • Complex messages, such as carousels

Linking views to dialogs

Views are linked to dialogs by file name, if you need a view for a dialog greetings-dialog.js, the view file has to be named greetings-view.js.

The views are resolved by the ViewResolver that looks for existing views following this order of locations:

[
  '<bot-path>/src/views/<name>-view.<locale>.js',
  '<bot-path>/src/views/<name>-view.js',
  '<bot-path>/node_modules/<module_1-name>/src/views/<name>-view.<locale>.js',
  '<bot-path>/node_modules/<module_1-name>/src/views/<name>-view.js',
  ...,
  '<bot-path>/node_modules/<module_k-name>/src/views/<name>-view.<locale>.js',
  '<bot-path>/node_modules/<module_k-name>/src/views/<name>-view.js',
  '<botuel-dialog-path>/src/views/<name>-view.<locale>.js',
  '<botuel-dialog-path>/src/views/<name>-view.js',
]

This allows to customize views rendering depending on the language of your bot.

View

The View is the generic class subclassed by all the others views.

Concrete subclasses of View must implement the render() method that takes as parameters the userMessage object and the data object passed from the corresponding dialog, and return an array of bot messages.

/**
* Renders a view as an array of bot messages.
* @param {Object} userMessage - the user message
* @param {Object} [data] - data used at display time
* @returns {Object[]} an array of bot messages
*/
render(userMessage, data = {}) {
  ...
}

Botfuel Dialog comes with several predefined views and also allows you to write custom views.

Predefined views

Botfuel Dialog offers several built-in views tailored to specific needs.

CatchView

The CatchView displays messages when an error occurs in the bot. It is likely that you want to customize these messages by redefining this view in your bot.

ClassificationDisambiguationView

The ClassificationDisambiguationView displays several alternatives. It prompts the user to confirm which intent or QnA the user had in mind.

ConfirmationView

The ConfirmationView prompts the user for a boolean confirmation which is required to unblock the blocked dialog.

To implement this view you need to define the following three parameters:

  • dialogQuestion is the question asked when the dialog is triggered
  • dialogConfirmed is the sentence displayed when the dialog is confirmed
  • dialogDiscarded is the sentence displayed when the dialog is discarded

These parameters are passed to the constructor of the ConfirmationView directly.

See an example in the test-complexdialogs bot: CarConfirmationView.

ComplexInputView

The ComplexInputView is a view used to display an error when a input is too complex. We consider a input is complex when he has more than 255 characters.

DefaultView

The default views DefaultView (en) and DefaultView (fr) are used by Botfuel Dialog to get answers when the bot does not understand user input.

You can implement your own default views by defining a view class file named default-view.locale.txt (locale can be en, fr, es ...) in the bot views directory, otherwise the bot will use those defined in the SDK.

PromptView

The PromptView is useful when you need to extract entities in your dialog. This view implements the render() method to confirm defined entities and ask for the missing ones:

// matchedEntities, missingEntities and messageEntities are computed by PromptDialog
render(userMessage, { matchedEntities, missingEntities, messageEntities }) {
  ...
}

We provide a default implementation of this method, which you can override according to your needs.

You can easily pass additional parameters to your view. There is an example in the reference documentation of the dialogWillDisplay.

See examples of implementation in test-complexentities bot: CitiesView or GuessView.

Entities

In addition to the userMessage, the PromptDialog lifecycle methods (dialogWillDisplay and dialogWillComplete) as well as the PromptView render method are all provided with the following data:

matchedEntities

An Object containing entities that have matched an entity extracted from a user message. For example, if a dialog expects a city entity named myTown and the user says I live in Paris, matchedEntities will be equal to:

{
  myTown: {
    dim: 'city',
    body: 'Paris',
    values: [
      {
        value: 'Paris',
        type: 'string',
        direction: null
      },
    ],
    start: 10,
    end: 15,
  }
}

matchedEntities can be used in PromptDialog in bot logic (dialogWillDisplay and dialogWillComplete) to call APIs or adapt bot answers according to user input, e.g.

class TravelView extends PromptView {
  render(userMessage, { matchedEntities, missingEntities }) {
    if (matchedEntities.myTown) {
      return [
        new BotTextMessage(
          `Okay so you want to travel to ${
            matchedEntities.myTown.values[0].value
          }!`
        ),
      ];
    }

    return [new BotTextMessage('Where do you want to go to?')];
  }
}
missingEntities

A Map containing all entities that are expected by the PromptDialog, but are still missing. The Map type is used to retain order. For example, let's take the following PromptDialog:

const { PromptDialog } = require('botfuel-dialog');

class TravelDialog extends PromptDialog {}

TravelDialog.params = {
  namespace: 'travel',
  entities: {
    city: {
      dim: 'city',
    },
    date: {
      dim: 'time',
      isFulfilled: date => date && date > Date.now(),
    },
  },
};

missingEntities will be a Map with entity names as keys and Objects with the dimension dim and other optional parameters, such as isFulfilled as values:

Map { 'city' => { dim: 'city' }, 'date' => { dim: 'time', isFulfilled: [Function] } }

missingEntities can be used in PromptDialog and PromptView to adapt the bot logic or messages according to missing information:

class TravelView extends PromptView {
  render(userMessage, { matchedEntities, missingEntities }) {
    if (missingEntities.size === 0) {
      return [new BotTextMessage('Great, I got all I need!')];
    }

    return [new BotTextMessage('I need more information!')];
  }
}
messageEntities

An Array of all possible entities extracted from the last user message. These entities have not been matched with the PromptDialog entities parameters.

For example, the user sentence: I live in France will result in the following messageEntities because France can be either a country or a forename:

[
  {
    dim: 'country',
    body: 'France',
    values: [
      {
        value: 'France',
        type: 'string',
        direction: null,
      },
    ],
    start: 0,
    end: 6,
  },
  {
    dim: 'forename',
    body: 'France',
    values: [
      {
        value: 'france',
        sex: 'female',
      },
    ],
    start: 0,
    end: 6,
  },
];

For most use cases, messageEntities should not be used because the extracted entities have not been matched yet with the PromptDialog parameters. You should use matchedEntities instead. When you need to know if an entity has just been extracted from the last user message, you can use messageEntities.

QnasView

The QnasView is a view to render QnA answers received from the Botfuel Classification service.

Custom views

Custom views are useful when your specific use case requirements (e.g., business logic) are not covered by the pre-defined Botfuel Dialog views described above. They are also used to associate a View with a BaseDialog.

To implement a custom view, you simply need to create a class that extends the View class and implement the render() method. The only restriction is that the render method must return an array of Botfuel Bot Message.

For example:

const { View, BotTextMessage } = require('botfuel-dialog');

class CustomView extends View {
  render(userMessage, data) {
    return [new BotTextMessage('Hello world!')];
  }
}

The optional parameter data provides the extra data computed by the associated dialog. This is useful when you need to adapt the text of your message.

See examples of implementation in test-complexdialogs bot: GreetingsView, ThanksView or OnboardingView.