4

I started learn the Microsoft Bot Framework recently, so I started make a Chatbot and I guess I making it wrong

I making the chatbot this way:

--> I get the message's user
--> send to LUIS
--> get the intent and the entities
--> select my answer and send it.

it's ok, but get the following situation:

USER: I wanna change my email. --> intent : ChangeInfo entities: email/value:email

CHATBOT: Tell me your new Email please. --> intent: noIntent entities: noEntities

USER: email@email.com --> intent: IDon'tKnow entities: email/value:email@email.com

I take this situation, when the USER send his email, I send to LUIs, but a email dont have a intent, just have a entity, but a email can be used in a lot Different situations, My question is, How My bot know the context of conversation to understand this email is for change email and not send a email, or update this email or another thing.

my code on gitHub here, its a ugly code, i know, but i make this just to understand the bot framework, after I will let this code more beautiful

Italo José
  • 1,558
  • 1
  • 17
  • 50
  • 1
    Any reason you are not using a LuisDialog? You shouldn't send the email back to Luis in that scenario, you should fire a PromptDialog.Text to ask the email and do whatever you want after the user input that. – Ezequiel Jadib Dec 26 '16 at 14:42

2 Answers2

3

In my bot flow, I'm using a step variable that I change from the front-end. And another step variable that I change from the bot. This helps me identify which step I am in the conversation. You can do the same to identify what your bot is asking the user.

var data = {step: "asked_email"};
var msg = builder.Message(session).addEntity(data).text("Your message.");
session.send(msg);

If you don't want to send a specific step to LUIS for recognition, you can handle that in the onBeginDialog handler:

intents.onBegin(function (session, args, next) {
  if (session.message.step !== "email") {
    next();
  } else {
    //Do something else and not go to LUIS.
    session.endDialog();
  }
});

You can find the reference to LUIS onBeginDialog here: https://docs.botframework.com/en-us/node/builder/chat/IntentDialog/#onbegin--ondefault-handlers

Details about message data can be found here: https://docs.botframework.com/en-us/node/builder/chat-reference/classes/_botbuilder_d_.message.html#entities

owaisafaq
  • 523
  • 4
  • 7
  • it have in c#? i see the documentation is in nodeJs but im developing in c#] – Italo José Dec 27 '16 at 11:26
  • In C# it is even easier to handle it. You can add a condition above your `var responseLuis = Luis.GetResponse(activity.Text);` to check the message step. If the message step is not email, don't execute this command and send a response directly without LUIS. The `step` data is key here, you can manage what you want to do with a message if you know which step your bot is on. – owaisafaq Dec 27 '16 at 11:42
  • I already try this, but the problem here is when e need change the email in two situations different. example: (1) > **User:** i wanna change my email > **chatbot:** you new email? > **User**: email@email.com > **chatbot**: email changed (2) - > **User**: i wanna get my payment in my email > **chatbot:** it your email: emai222@email.com ? > **User** : no > **chatbot**: whats your current email? > **User:** email@email.com > **chatbot**: I update your email and send your paymen – Italo José Dec 27 '16 at 12:41
  • Those are just 2 different intents, I think that you are getting confusing because of the way you are using Luis and because of having everything in the controller. If you reorder the project using dialogs it will become more clear how you should use this.You don't need to manage steps, etc. – Ezequiel Jadib Dec 27 '16 at 14:35
3

This should be as simple as using a LuisDialog and a set of Prompts to manage the users flow. Below you will find some quick code I put together to show you how this could be done. You don't need extra steps or adding extra entities, or going to Luis with the email provided by the user.

I would recommend you to read a bit more about LuisDialog and Dialogs in general as the way you are using Luis in your controller I don't think is the way to go.

Here is a good Luis Sample and here a good one around multi-dialogs.

Sample Code

namespace MyNamespace
{
    using System;
    using System.Threading.Tasks;
    using Microsoft.Bot.Builder.Dialogs;
    using Microsoft.Bot.Builder.Internals.Fibers;
    using Microsoft.Bot.Builder.Luis;
    using Microsoft.Bot.Builder.Luis.Models;
    using Microsoft.Bot.Connector;

    [Serializable]
    [LuisModel("YourModelId", "YourSubscriptionKey")]
    public class MyLuisDialog : LuisDialog<object>
    {
        [LuisIntent("")]
        [LuisIntent("None")]
        public async Task None(IDialogContext context, LuisResult result)
        {
            string message = "Não entendi, me diga com outras palavras!";

            await context.PostAsync(message);
            context.Wait(this.MessageReceived);
        }

        [LuisIntent("ChangeInfo")]
        public async Task ChangeInfo(IDialogContext context, IAwaitable<IMessageActivity> activity, LuisResult result)
        {
            // no need to go to luis again..
            PromptDialog.Text(context, AfterEmailProvided, "Tell me your new email please?");
        }

        private async Task AfterEmailProvided(IDialogContext context, IAwaitable<string> result)
        {
            try
            {
                var email = await result;

                // logic to store your email...
            }
            catch
            {
                // here handle your errors in case the user doesn't not provide an email
            }

          context.Wait(this.MessageReceived);
        }

        [LuisIntent("PaymentInfo")]
        public async Task Payment(IDialogContext context, IAwaitable<IMessageActivity> activity, LuisResult result)
        {
            // logic to retrieve the current payment info..
            var email = "test@email.com";

            PromptDialog.Confirm(context, AfterEmailConfirmation, $"Is it {email} your current email?");
        }

        private async Task AfterEmailConfirmation(IDialogContext context, IAwaitable<bool> result)
        {
            try
            {
                var response = await result;

                // if the way to store the payment email is the same as the one used to store the email when going through the ChangeInfo intent, then you can use the same After... method; otherwise create a new one
                PromptDialog.Text(context, AfterEmailProvided, "What's your current email?");
            }
            catch
            {
                // here handle your errors in case the user doesn't not provide an email
            }

            context.Wait(this.MessageReceived);
        }
    }
}
Ezequiel Jadib
  • 14,767
  • 2
  • 38
  • 43
  • Thank you very much, its the best answer. But know I have a new question, its a simple question. In method **AfterEmailProvided** i will need send the user's answer to LIUS or it isnt necessary? because the user can answer "true" or "false" in many diferent form., I know, I can use options too, but my chatbot is for SMS, so I cant send two buttons with "yes or no" in a SMS and my boss wanna this chatbot looks a really person, and really person dont quention for yes or no, know?! – Italo José Dec 28 '16 at 11:30
  • 1
    You don't need to send the email back to Luis. The flow should be: user request to change his email, bot asks for the new email, user provides the email (and here is when the AfterEmailProvided is called), your bot just received the email, and store it somewhere. No need to ask anything else to the user. In the case of the Payment, the confirmation of the email is a yes/no question. Of course, users can answer anything but it's a yes/no question; worst case, they will get the retry message of the PromptDialog.Confirm which can be changed as well. – Ezequiel Jadib Dec 28 '16 at 11:48
  • I found a way to do yes/no questions, just use PromptDialog.Confirm(context, yourMethod, $"your message"); and your "IAwaitable" will be a Boolean, so the user can response yes(1) or no(0). here is the documentation. (https://docs.botframework.com/en-us/csharp/builder/sdkreference/dd/d7e/class_microsoft_1_1_bot_1_1_builder_1_1_dialogs_1_1_prompt_dialog_1_1_prompt_confirm.html) – Italo José Dec 28 '16 at 20:29
  • That's exactly what I'm doing in the code (see the payment method) and what I said in my previous comment... Am I missing something? – Ezequiel Jadib Dec 29 '16 at 00:25
  • sorry, you are correct, I did not notice this in your code – Italo José Dec 29 '16 at 13:40