Bot Framework: многошаговый водопад

Я бы хотел послать боту что-то похожее на это

"[Person] wants to meet at [Place] at [Date]"

однако, если человек упускает какую-то информацию, я хочу, чтобы бот запрашивал ее по частям.

Так, например, если человек пишет:

"Let's meet!"

Бот задавал серию вопросов, чтобы выполнить все требования к данным. Что-то вроде:

  1. С кем я встречусь?
  2. Где им встретиться?
  3. Какая дата и время?

Если человек спросит что-то вроде:

"Alex would like to meet tomorrow"

Тогда бот будет только спрашивать

"Where should they meet?"

После того, как все необходимые данные будут заполнены, он отправит ответ, например:

"Great, I will meet [Person] in [Location] at [DateTime]"

Я пробовал такие подходы с небольшой удачей и получал ошибку «Слишком много вызовов session.EndDialog ()»:

dialog.on('Meeting', [
    function (session, results, next) {
        var person = builder.EntityRecognizer.findEntity(results.entities, 'Person');
        if(!person){
            builder.Prompts.text(session, prompts.meetingPersonMissing); 
        } else {
            next({ response: {
                    person: person.entity
                }
            });
        }
    },
    function (session, results, next) {
        var location = builder.EntityRecognizer.findEntity(results.entities, 'location');
        if(!location){
            builder.Prompts.text(session, prompts.meetingLocationMissing); 
        } else {
            // Pass title to next step.
            next({ response: {
                    person: results.person,
                    location: location.entity
                }
            });
        }
    },
    function (session, results, next) {
        var time = builder.EntityRecognizer.findEntity(results.entities, 'builtin.datetime.date');
        if(!time){
            builder.Prompts.text(session, prompts.meetingTimeMissing); 
        } else {
            next({ response: {
                    person: results.person,
                    location: results.location,
                    time: time.entity
                }
            });
        }
    },
    function (session, results) {
        if (results.response) {
           session.send(prompts.meetingSubmited);
        } else {
            session.send(prompts.canceled);
        }
    }
]);

Неудачная попытка №2 (данные из next () больше не передаются). Это приводит к той же ошибке EndDialog

dialog.on('Meeting', [
    function (session, results, next) {
        var person = builder.EntityRecognizer.findEntity(results.entities, 'Person');
        var location = builder.EntityRecognizer.findEntity(results.entities, 'location');
        var time = builder.EntityRecognizer.findEntity(results.entities, 'builtin.datetime');

        session.messageData = {
            person: person || null,
            location: location || null,
            time: time || null
        }

        if(!session.messageData.person){
            builder.Prompts.text(session.messageData.person, prompts.meetingPersonMissing); 
        } else {
            next();
        }
    },
    function (session, results, next) {    
        if(!session.messageData.location){
            builder.Prompts.text(session.messageData.location, prompts.meetingLocationMissing); 
        } else {
            next();
        }
    },
    function (session, results, next) {
        if(!session.messageData.time){
            builder.Prompts.text(session.messageData.time, prompts.meetingTimeMissing); 
        } else {
            next();
        }
    },
    function (session, results) {
        debugger;
        if (results.response) {
           session.send('Meeting scheduled');
        } else {
            session.send(prompts.canceled);
        }
    }
]);

Обновление №3: в этой версии он хорошо работает, если высказывание не содержит каких-либо значимых сущностей. Например, «Могли бы мы встретиться?» работает отлично.

Проблема с этой версией заключается в том, что я пытаюсь "мы можем встретиться завтра?". Завтра успешно идентифицируется как объект datetime, однако как только он попадает в next() в этом блоке:

 function getDate(session, results){
    session.dialogData.topic = results.response;

    if(session.dialogData.date){
        next();   
     }else{
        builder.Prompts.time(session, "What date would you like to meet?");   
     }

}

Он терпит неудачу и дает мне те же Too many calls to to session.EndDialog() проблемы

dialog.on('Meeting', [meetingQuery, getDate, getTime, respondMeeting]);

function meetingQuery(session, results){

    if (results.response) {
        session.dialogData.date = builder.EntityRecognizer.resolveTime([results.response]);
    }


    session.userData = {
        person: session.message.from.name
    }

    builder.Prompts.text(session, "Hi "+ session.userData.person +"!\n\n What is the meeting in reference too?");

}

function getDate(session, results){
    session.dialogData.topic = results.response;

    if(session.dialogData.date){
        next();   
     }else{
        builder.Prompts.time(session, "What date would you like to meet?");   
     }

}

function getTime(session, results){
    if (results.response) {
        session.dialogData.date = builder.EntityRecognizer.resolveTime([results.response]);
    }


     if(session.dialogData.time){
        next();   
     }else{
        builder.Prompts.choice(session, "Your professor has the follow times availeble?", ["1pm", "2pm", "3pm"]);   
     }
}

function respondMeeting(session, results){
    var time = results.response;
    session.send("Your meeting has been schedueld for " + session.dialogData.date + " at " + time.entity + ". Check your email for the invite.");
}

person abritez    schedule 09.05.2016    source источник


Ответы (3)


Попробуйте вместо этого, это работает на моем боте.

dialog.on('QuieroQueMeLlamen', [
    function (session, args) {
    	var Telefono = builder.EntityRecognizer.findEntity(args.entities, 'Usuario::Telefono');
        
        if(!Telefono){
        	builder.Prompts.number(session, "Dame un número telefónico donde pueda llamarte una de nuestras enfermeras (sin espacios ni caracteres: ej: 3206907529)");
        }      
        
    },
    function (session, results) {
        if (results.response) {
        	//IF STRLEN es un celular entonces:
            session.send("Te estamos llamando al número %s, por favor contesta", results.response);
        } 
    }
]);

person Camilo Duque Velásquez    schedule 14.05.2016

Вы не должны передавать параметр в функцию next (), а должны использовать session.YOUVARIABLES для хранения данных через водопад.

Что-то вроде :

function (session, results, next) {
    var person = builder.EntityRecognizer.findEntity(results.entities, 'Person');
    if(!person){
        builder.Prompts.text(session, prompts.meetingPersonMissing); 
    } else {
        session.person = person.entity
        next();
    }
}
person Etienne Margraff    schedule 10.05.2016
comment
Спасибо, к сожалению, не сработало. Я думаю, что происходит следующее: next () в какой-то момент вызывает EndDialog, поэтому мне нужно было бы BeginDialog или каким-то образом полностью удалить next (). Это всего лишь предположение, что я обновил свой вопрос тем, что я пробовал, на основе ваших отзывов. - person abritez; 10.05.2016

Я думаю, тебе стоит получить доступ

results.response.person 

вместо того

results.person 

то же самое относится и к другим перекрытиям для этого водопада.

person krazy    schedule 29.05.2016