Search code examples
node.jsdialogbotsazure-language-understanding

Weird instruction flow chatbot with LUIS and nodejs


I can't get what I want with my bot, coded with the help of MS Bot Framework and LUIS for language recognition.

What I'm trying to do is book a plane ticket. So when the user is in the booking dialog, but hasn't given all the informations, the bot asks missing informations (departure date, airline, departure city...)

Here is the function for example where I set the departure city if it's missing (in the previous step of the waterfall, I'm testing if the departure city exists and if not I ask with a prompt).

function (session, results, next) {
        if (results.response) {
            builder.LuisRecognizer.recognize(session.message.text, luisModelUrl,
                function(err, intents, entities) {
                    if(entities) {
                        var departure = builder.EntityRecognizer.findEntity(entities, 'FlightBookingTicket.Departure');
                        console.log(entities);
                        console.log('===== Ticket (2a): =====');
                        console.log(session.privateConversationData.ticket);
                        if (departure)
                            session.privateConversationData.ticket.departure = departure.entity;
                        console.log('===== Ticket (2b): =====');
                        console.log(session.privateConversationData.ticket);
                    }
                }
           );
        }

        console.log('===== Ticket (2c): =====');
        console.log(session.privateConversationData.ticket);

        next();
    },

What I should obtain (according the console.log() calls), is first a log of the entities, the ticket without departure city: 2a, the ticket with the departure: 2b and then the same one with 2c.

But if I run that, here is what I'm getting, and it's really odd:

===== Ticket (2c): =====
{ departure: null,
  destination: 'paris',
  date_time: null,
  airline: null,
  ticket_class: null,
  number_tickets: null }
[ { entity: 'london',
    type: 'FlightBookingTicket.Departure',
    startIndex: 5,
    endIndex: 10,
    score: 0.944474041 } ]
===== Ticket (2a): =====
{ departure: null,
  destination: 'paris',
  date_time: null,
  airline: null,
  ticket_class: null,
  number_tickets: null }
===== Ticket (2b): =====
{ departure: 'london',
  destination: 'paris',
  date_time: null,
  airline: null,
  ticket_class: null,
  number_tickets: null }

I have first the 2c, then the entity 2a and 2b, so in the end, the bot replies with the ticket with only destination (I skipped all the other attributes (airline...) for the post). What am I doing wrong ? Why's the flow of the code like that ?

Alright here is your ticket: ‘{“departure”:null,“destination”:“paris”,“date_time”:null,“airline”:null,“ticket_class”:null,“number_tickets”:null}’

MS Bot Framework and LUIS seem great, but the documentation is really poor and there's not enough help on the Internet yet :(

Thank you


Solution

  • This looks like the expected flow because your code that logs 2c is called before 2a and 2b.

    I think this piece of code is creating the misunderstanding:

                builder.LuisRecognizer.recognize(session.message.text, luisModelUrl,
                function(err, intents, entities) {
                    if(entities) {
                        var departure = builder.EntityRecognizer.findEntity(entities, 'FlightBookingTicket.Departure');
                        console.log(entities);
                        console.log('===== Ticket (2a): =====');
                        console.log(session.privateConversationData.ticket);
                        if (departure)
                            session.privateConversationData.ticket.departure = departure.entity;
                        console.log('===== Ticket (2b): =====');
                        console.log(session.privateConversationData.ticket);
                    }
                }
           );
    

    The function you define, the one that logs 2a and 2b, doesn't get called right away.

    What you are doing is registering the function that logs 2a and 2b as a callback. Then your execution continues to the 2c code. Once LuisRecognizer has completed its recognize function it executes the callback you have registered.

    Does that help?