Documentation

Powered by Algolia

Dynamic entities

Typically, when you use slots in patterns, the conversation model is static. Patterns in the voice script remain the same for the whole duration of conversation with the user, and you cannot customize them even if new data comes during the dialog session. To make the dialog more flexible, you can use dynamic entities.

Dynamic entities are basically slots capturing different kinds of user input. However, unlike regular slots, they can be updated or redefined in runtime, without restarting the dialog session. When a dynamic entity is updated, Alan rebuilds the conversation model. As a result, the dialog can be adjusted to new circumstances, and the user experience becomes more personalized.

Consider the following intent:

let favoritesList = "flannel shirt|fleece jacket|softshell pants";

intent(`Open $(FAVORITE ${favoritesList})?`, p => {
    p.play(`Opening ${p.FAVORITE.value}...`);
});

Without dynamic entities, the favorites list in the pattern is fixed while the dialog session lasts. With dynamic entities, the list can be altered in runtime. For example, the user can add items to the favorites list with voice and access these items immediately.

onCreateUser(p => {
    p.userData.favorites = "flannel shirt|fleece jacket|softshell pants";
});

intent(`Add $(ITEM* .*) to favorites`, p => {
    p.userData.favorites = p.userData.favorites + '|' + p.ITEM.value;
    p.play(`${p.ITEM.value} is added`);
});

intent(`Open $(FAVORITE u:favorites)?`, p => {
    p.play(`Opening ${p.FAVORITE.value}`);
});

Thanks to dynamic entities, you can create ‘adaptive’ patterns that can be updated after the dialog has started. You can use dynamic entities in the following cases:

  • You want to update patterns with frequently changing information like data retrieved from your database, through API calls and so on
  • You want to customize patterns with information obtained from the user input
  • You want to provide different data depending on the user logged in to the system

Defining dynamic entities

You can define dynamic entities in different ways:

  • With the project global object: use this method if dynamic entities must be accessible globally at the project level.
  • With the userData object: use this method if dynamic entities must be accessible within the user dialog session.
  • With visualState: use this method if values of dynamic entities are passed from the client app.

Defining dynamic entities at the project level

A dynamic entity defined at the project level can be accessed by all users interacting with the voice assistant. You can use this type of dynamic entities to work with generic data that must be available to all app users.

To define a dynamic entity at the project level, save the values of the dynamic entity to the project global object. To refer to such a dynamic entity in patterns, add the $ sign followed by brackets (). In brackets, specify the dynamic entity name followed by p:variablename.

In the example below, values of a dynamic entity are saved to the project.movies variable; to refer to this dynamic entity, $(MOVIE p:movies) is added to the pattern.

onCreateProject(() => {
    project.movies = "Sergio|Valley Girl|All Day and a Night|The Half of It";
});

intent(`When is $(MOVIE p:movies) on?`, p => {
    p.play(`Let me check`);
});

To define dynamic entities at the project level, you can use the onCreateProject callback function.

Defining dynamic entities at the dialog session level

A dynamic entity defined at the dialog session level can be accessed only by the current user interacting with the voice assistant during the dialog session. You can use this type of dynamic entities to work with user-specific and user-sensitive information, for example, when handling data that differs depending on the user logged in to the system.

Values of such dynamic entities exist only while the dialog session is running. After the session ends or the user reconnects to the app in another session, all data stored in such dynamic entities is removed.

To define a dynamic entity at the dialog session level, save the values of the dynamic entity to the userData object. To refer to such a dynamic entity in patterns, add the $ sign followed by brackets (). In brackets, specify the dynamic entity name followed by u:variablename.

In the example below, values of a dynamic entity are saved to the p.userData.contacts variable; to refer to this dynamic entity, $(CONTACT u:contacts) is added to the pattern.

onCreateUser(p => {
    p.userData.contacts = "Anna|Emma|John|Mark";
});

intent(`What is $(CONTACT u:contacts)'s phone number?`, p => {
    p.play(`Opening ${p.CONTACT.value}'s record...`);
}); 

To define dynamic entities at the dialog session level, you can use the onCreateUser and onCleanupUser callback functions.

Passing dynamic entity values from the app

You can define dynamic entities with the help of the visual object. This type of dynamic entities can be helpful if you need to handle data sent from the app to the voice script. In this case, you can pass the necessary data in the visual object, access this data through the keys of the passed object and save it to a dynamic entity.

To refer to such a dynamic entity in patterns, add the $ sign followed by brackets (). In brackets, specify the dynamic entity name followed by v:variablename.

In the example below, we are retrieving the values passed in the visual object and saving them to the p.visual.menu variable. To refer to this dynamic entity, $(ITEM v:menu) is then added to the pattern.

// Set visual state
{
    values: ["pasta", "burger", "quesadilla"]
}

onVisualState((p, s) => {
    if (s.values) {
        p.visual.menu = s.values.join('|');
    }
});

intent(`Is $(ITEM v:menu) on the menu today?`, p => {
    p.play(`Yes, do you want to order ${p.ITEM}?`);
});

For dynamic entities passed with the visual object, you can use the onVisualState callback function.

Changing dynamic entities values with voice commands

You can not only update dynamic entities with values from external sources, but also alter them with voice commands. In the example below, the shopping list is extended when the user gives a command to add a specific item. The resulting string of dynamic entity values is then logged to the console.

onCreateUser(p => {
    p.userData.shopping = "coffee|sugar|honey";
});

intent(`Do I need $(SHOP u:shopping)?`, p => {
    p.play(`${p.SHOP} is in the shopping list`);
});

intent(`Add $(ITEM* .*)`, p => {
    p.userData.shopping = p.userData.shopping + '|' + p.ITEM.value;
    p.play(`${p.ITEM} is added`);
    console.log(p.userData.shopping);
});

Capturing several values with dynamic entities

You can add the same dynamic entity to the pattern several times, just like in case of regular slots. When such an intent is matched, all pieces of data captured with this dynamic entity are collected to an array of values.

To access the list of all values in the array, use the dynamic entity name followed by an underscore character, for example: ITEM_. To access a specific element in the array, refer to the element index, for example: ITEM_[0].

Let’s say you want the user to filter the list of products by brand. You can add the following voice command to the script:

onCreateProject(() => {
    project.BRANDS = "Apple|Asus|Microsoft|Samsung";
});

intent(`Show me $(B p:BRANDS) (and|or|) $(B p:BRANDS|) (and|or|) $(B p:BRANDS|)`, p => {
    p.play(`Getting the products...`);
});

As in regular slots, in dynamic entities each element in the array has its own .value and .label:

  • value fields are populated with values obtained from the user input. To access the value field, refer to it in the following way: p.ENTITYNAME_[index].value. In the example above, to access the value of the first element in the brands array, you need to refer to p.B_[0].value.
  • label fields can contain custom values and can be used to give more accurate responses to the user. To access the label field, refer to it in the following way: p.ENTITYNAME_[index].label. In the example below, to access the label of the first element in the brands array, you need to refer to p.B_[0].label.
onCreateProject(() => {
    project.BRANDS = "Apple~ios|Asus~android|Microsoft~win|Samsung~android";
});

intent(`Show me $(B p:BRANDS) (and|or|) $(B p:BRANDS|) (and|or|) $(B p:BRANDS|)`, p => {
    p.play(`Getting the products`);
    console.log(p.B_[0].label);
    console.log(p.B_[0].value)
});

See also

Using dynamic entities in voice commands tutorial