in experimental/adaptive-dialog/javascript_nodejs/08.todo-bot-with-luis-qnamaker/dialogs/getUserProfileDialog/getUserProfileDialog.js [16:143]
constructor() {
super(DIALOG_ID);
const lgFile = Templates.parseFile(path.join(__dirname, `${DIALOG_ID}.lg`));
this.lgGenerator = new TemplateEngineLanguageGenerator(lgFile);
const dialog = new AdaptiveDialog(DIALOG_ID).configure({
generator: this.lgGenerator,
recognizer: this.createCrossTrainedRecognizer(),
triggers: [
// Actions to execute when this dialog begins. This dialog will attempt to fill user profile.
// Each adaptive dialog can have its own recognizer. The LU definition for this dialog is under GetUserProfileDialog.lu
// This dialog supports local intents. When you say things like 'why do you need my name' or 'I will not give you my name'
// it uses its own recognizer to handle those.
// It also demonstrates the consultation capability of adaptive dialog. When the local recognizer does not come back with
// a high-confidence recognition, this dialog will defer to the parent dialog to see if it wants to handle the user input.
new OnBeginDialog([
new SetProperty().configure({
property: new StringExpression("user.profile.name"),
// Whenever an adaptive dialog begins, any options passed in to the dialog via 'BeginDialog' are available through dialog.xxx scope.
// Coalesce is a prebuilt function available as part of Adaptive Expressions. Take the first non-null value.
// @EntityName is a short-hand for turn.recognized.entities.<EntityName>. Other useful short-hands are
// #IntentName is a short-hand for turn.intents.<IntentName>
// $PropertyName is a short-hand for dialog.<PropertyName>
value: new ValueExpression("=coalesce(dialog.userName, @userName, @personName)")
}),
new SetProperty().configure({
property: new StringExpression("user.profile.age"),
value: new ValueExpression("=coalesce(dialog.userAge, @age)")
}),
new TextInput().configure({
property: new StringExpression("user.profile.name"),
prompt: new ActivityTemplate("${AskFirstName()}"),
validations: [
// Name must be 3-50 characters in length.
// Validations are expressed using Adaptive expressions
// You can access the current candidate value for this input via 'this.value'
"count(this.value) >= 3",
"count(this.value) <= 50"
],
invalidPrompt: new ActivityTemplate("${AskFirstName.Invalid()}"),
// Because we have a local recognizer, we can use it to extract entities.
// This enables users to say things like 'my name is vishwac' and we only take 'vishwac' as the name.
value: new ValueExpression("=@personName"),
// We are going to allow any interruption for a high confidence interruption intent classification .or.
// when we do not get a value for the personName entity.
allowInterruptions: new ValueExpression("turn.recognized.score >= 0.9 || !@personName"),
}),
new TextInput().configure({
property: new StringExpression("user.profile.age"),
prompt: new ActivityTemplate("${AskUserAage()}"),
validations: [
// Age must be within 1-150.
"int(this.value) >= 1",
"int(this.value) <= 150"
],
invalidPrompt: new ActivityTemplate("${AskUserAge.Invalid()}"),
unrecognizedPrompt: new ActivityTemplate("${AskUserAge.Unrecognized()}"),
// We have both a number recognizer as well as age prebuilt entity recognizer added. So take either one we get.
// LUIS returns a complex type for prebuilt age entity. Take just the number value.
value: new ValueExpression("=coalesce(@age.number, @number)"),
// Allow interruption if we do not get either an age or a number.
allowInterruptions: new BoolExpression("!@age && !@number")
}),
new SendActivity("${ProfileReadBack()}")
]),
new OnIntent("NoValue", [], [
new IfCondition().configure({
condition: new BoolExpression("user.profile.name == null"),
actions: [
new SetProperty().configure(
{
property: new StringExpression("user.profile.name"),
value: new ValueExpression("Human")
}),
new SendActivity("${NoValueForUserNameReadBack()}")
],
elseActions: [
new SetProperty().configure(
{
property: new StringExpression("user.profile.age"),
value: new ValueExpression("30")
}),
new SendActivity("${NoValueForUserAgeReadBack()}")
]
})
],
// Only do this only on high confidence recognition
"#NoValue.Score >= 0.8"
),
new OnIntent("GetInput", [], [
new SetProperty().configure({
property: new StringExpression("user.profile.name"),
value: new ValueExpression("=@personName")
}),
new SetProperty().configure(
{
property: new StringExpression("user.profile.age"),
value: new ValueExpression("=coalesce(@age, @number)")
})
]),
new OnIntent("Restart", [], [
new DeleteProperty().configure(
{
property: new StringExpression("user.profile")
})
]),
// Help and chitchat is handled by qna
new OnQnAMatch([
// Use code action to render QnA response. This is also a demonstration of how to use code actions to light up custom functionality.
new CodeAction(this.resolveAndSendQnAAnswer.bind(this))
]),
]
});
// Add named dialogs to the DialogSet. These names are saved in the dialog state.
this.addDialog(dialog);
// The initial child Dialog to run.
this.initialDialogId = DIALOG_ID;
}