microsoft / BotBuilder-V3

Microsoft Bot Builder V3 SDK for Microsoft Bot Framework
MIT License
51 stars 61 forks source link

Bot not waiting for Prompts.text input and Prompts.choice #118

Closed vishmonne closed 5 years ago

vishmonne commented 5 years ago

Bot info:

• SDK Platform : Node.js • SDK Version : v3 • Deployment Environment : Azure Bot service • 3 Web app bot created in Azure ( dev, demo and prod)

Issue Description:

builder.Prompts.choice and builder.Prompts.text is not waiting for user input ( It sometimes wait for the user input and sometimes doesn’t wait and goes back to the main function and treat it as a separate utterance and goes to Luis ) in the prod environment

We were facing the same issue in the demo environment , where we had followed these steps in solving the issue. • We moved all the packages from dev to demo environment • We moved all the code files again from dev to demo • We restarted the app service

We had followed the same steps in the prod environment but we are not able to resolve the issue . We tried the same prod code in the local in visual studio code and tested it with bot Emulator and it works completely fine.

Behaviour Noticed:

We noticed that whenever the bot URL link is opened , the connectorsetup.js file, which connects with the bot is getting refreshed multiple times in azure.

Code Example:

I am using this way to recognize the Luis in my code

builder.LuisRecognizer.recognize(session.message.text, '<model url>', function (err, intents, entities) {
    if (entities) {
        var entity = builder.EntityRecognizer.findEntity(entities, 'TYPE');
        // do something with entity...
    }
});

Things done from my side

When i searched in git i got this solution in which they told to use on enable and solve the issue Another example can be found here: #2670 (comment)

var recognizer = new builder.LuisRecognizer(LuisModelUrl)
    .onEnabled(function (context, callback) {
        // LUIS is only ON when there are no tasks pending(e.g. Prompt text) 
        var enabled = context.dialogStack().length === 0;
        callback(null, enabled);
    });

But the problem here was my way of calling the Luis is different and i am not sure how we can use onenabled function is builder.LuisRecognizer.recognize

v-kydela commented 5 years ago

You say those prompts aren't waiting for user input. Can you explain what you mean by that? What specific behavior are you experiencing and what specific behavior are you expecting?

Also, the code you shared doesn't include any prompts. It's unclear what that LUIS code has to do with your prompts not waiting.

In any case, if your bot works when running locally but not when it's published then that indicates a state issue. Are you using in-memory state storage?

vishmonne commented 5 years ago

hi @v-kydela ,

Please find the CODE below.

function myIntentHandler(session, msg) {
    session.sendTyping();
    builder.LuisRecognizer.recognize(msg, LuisModelUrl,
        function (err, intents, entities) {
            if (err) {
                console.log("LUI Error: " + err);
                session.send('Something went wrong. Type **Hello** to start over.');
            }

            if (intents[0].intent != null && intents[0].score > (process.env.INTENTSCORETHRLD)) {
                switch (intents[0].intent) {
                    case 'None':
                        session.beginDialog('None', { intent: intents[0].intent, entities: entities });
                        break;
                    default:
                        session.beginDialog('defaultDialog', { "intent": intents[0].intent, "entities": entities });
                        break;
                }
            }
        });
}

bot.dialog('None', [
    function (session, args) {
        builder.Prompts.text(session, "I&apos;m sorry, would you mind asking again differently? I can connect you with a live person if I still don&apos;t understand.");
    },
    function (session, results) {
        var resp = results.response;
        session.sendTyping();
        builder.LuisRecognizer.recognize(resp, LuisModelUrl, function (err, intents, entities) {
            if (intents) {
                var TopIntent = intents[0].intent;

                if (TopIntent != "None") {
                    session.endDialog();
                    myIntentHandler(session, session.message.text);
                }
                else if (TopIntent == "None") {
                    noneSecondResp(session);
                }

                session.endDialog();
            }
        });
    }
]);
vishmonne commented 5 years ago

Hi Team,

Any solution for this issue ?

vishmonne commented 5 years ago

Hi i think i am facing the same issue as https://github.com/Microsoft/BotBuilder/issues/4477

v-kydela commented 5 years ago

The issue you linked to was fixed in BotBuilder 3.15.3. Have you updated your SDK to the latest version of v3?

Also, you should not be using in-memory storage for a published bot. Please have a look at the documentation for some help implementing proper storage.

Looking at your code, it is a little strange to me that you're calling session.endDialog() twice:

if (TopIntent != "None") {
    session.endDialog();
    myIntentHandler(session, session.message.text);
}
else if (TopIntent == "None") {
    noneSecondResp(session);
}

session.endDialog();

That's probably not directly related to your problem, though.

vishmonne commented 5 years ago

Hi @v-kydela thanks for replying back.

i was not able to update it to 3.15.3 it showed me this error (PFA THE Screenshot) error package

Can u help me with why this error is coming and i am only able to update it to 3.16.0 , not other than that in SDK V3. And after i update it to 3.16.0 also the same issue exists.

I am using now a Manage state data using CosmosDB , thanks for updating that

Looking forward in hearing from you @v-kydela

v-kydela commented 5 years ago

Hi @vishmonne

You can see that the output is saying that version 3.15.3 is not available. It shows you a list of valid install targets and 3.16.0 and 3.15.0 are there but not 3.15.3. You can also verify this by going here and clicking on versions.

This is fine because you don't need 3.15.3. I just said to update to the latest version, and 3.16.0 is sure to have all the fixes you need. There's no reason to downgrade.

Does using CosmosDB fix your problem?

vishmonne commented 5 years ago

hi @v-kydela , when i implemented the CosmosDB, the prompts.text issue got resolved, but in the prompts.choice function i have a issue ( the same random types)

Please see my code for the Prompts.choice

var test = ""; //assigning a global variable test

function Prompt_With_Choice(session,entity)
{
    test=entity; 
    console.log("the test value is " + test ); // i am getting the value of test 
    session.beginDialog('Prompt_With_Choice', entityType_prompts);
}

bot.dialog('Prompt_With_Choice', [
    function (session) {
        console.log("the test value is " + test ); // i am getting the value of test 
        builder.Prompts.customize(builder.PromptType.choice, new builder.PromptChoice({minScore: 1.0}));
        builder.Prompts.choice(session,content_prompts,buttons_prompts,{listStyle:builder.ListStyle.button,maxRetries: 0});
    },
    function (session, results) {
        console.log("the test value is " + test ); // i am not getting the value of test, its showing empty 
        if(results.response)
        {
            var lowerentity=results.response.entity;
            session.endDialog();
        }
        else
        {
            session.sendTyping();
            session.endDialog();
            a.myIntentHandler(session, session.message.text);
        } 
    }
]);

The problem i am facing here is inside function(session,results) , the value of the global variable test is empty.Its random like sometimes we get the value inside function(session,results) sometimes we wont get the value of test. But inside function(Session) , always we get the value of test

It works randomly. Would be happy if you could see this issue

v-kydela commented 5 years ago

Hi @vishmonne

That is actually expected behavior and it's a good example of why bots need state storage. When deployed, your bot may be running on many different servers. When you send a message to your bot, there's no telling what machine will receive that message. Therefore there's no reason to expect the bot's local variables to have the same locally-stored data that they did on the last turn. The best way to conceptualize how a bot works is to assume your bot has shut down and then restarted between each turn so that each turn is handled by a totally different instance of your bot application. This article from the V4 documentation may help you understand state better. If you want a variable like test to persist between turns, you'll need to store it in your bot's state.

Does this resolve your issue?

vishmonne commented 5 years ago

hi @v-kydela , thanks for the detailed update on this, i read through the link and got to understand better on the bot's state . By doing that , solved my random issue.

But i wanted to know how come the same code with the memory storage as inMemory is working correctly in another web app bot , but not in this ?

v-kydela commented 5 years ago

It's very difficult to answer that without more information. Here are some possibilities:

  1. Maybe it is only working randomly and so you just happened to not have seen it fail yet
  2. Maybe you're using a different version of the BotBuilder SDK that handles state differently
  3. Maybe you're using different code that doesn't depend on state in the same way
  4. Maybe you're uploading the bot to a server that doesn't scale sideways
  5. Maybe you're not uploading it at all and just testing locally

Does this resolve your issue?

v-kydela commented 5 years ago

@vishmonne - Do you still need help?

vishmonne commented 5 years ago

Hi @v-kydela , i am fine with the explanation. Thanks a lot for helping around with the random button issues. Really appreciate the help. We can close this issue.