Search code examples
c#.netbotframeworkazure-language-understandingazure-bot-service

Once the message forwarded from LUIS to QnA depending on the intent, not returning to LUIS in c# from the second instance. What to do?


I was trying to connect LUIS and QnA, but from the message controller on the first instance it is going to luis and if required accordingly going to QnA, but once in QnA next messages are not being sent to LUIS only executed by QnA. Someone could Help?

messageControler.cs

public virtual async Task<HttpResponseMessage> Post([FromBody] Activity activity)
        {
            //await Conversation.SendAsync(activity, () => new BasicLuisDialog());
            // check if activity is of type message
            if (activity.GetActivityType() == ActivityTypes.Message)
            {
                //await Conversation.SendAsync(activity, () => new BasicQnAMakerDialog());
                await Conversation.SendAsync(activity, () => new BasicLuisDialog());
            }
            else
            {
                //await Conversation.SendAsync(activity, () => new BasicQnAMakerDialog());
                HandleSystemMessage(activity);
            }
            return new HttpResponseMessage(System.Net.HttpStatusCode.Accepted);
        }
        private Activity HandleSystemMessage(Activity message)
        {
            if (message.Type == ActivityTypes.DeleteUserData)
            {
                // Implement user deletion here
                // If we handle user deletion, return a real message
            }
            else if (message.Type == ActivityTypes.ConversationUpdate)
            {
                // Handle conversation state changes, like members being added and removed
                // Use Activity.MembersAdded and Activity.MembersRemoved and Activity.Action for info
                // Not available in all channels
            }
            else if (message.Type == ActivityTypes.ContactRelationUpdate)
            {
                // Handle add/remove from contact lists
                // Activity.From + Activity.Action represent what happened
            }
            else if (message.Type == ActivityTypes.Typing)
            {
                // Handle knowing tha the user is typing
            }
            else if (message.Type == ActivityTypes.Ping)
            {
            }
            return null;
        }
    }
}

BasicLuisDialog.cs This is the code for basic luisdialog, from here if the intent matches then it is supposed to provide the required reply else if none it will redirected the search to the basic qna. this is performing only for the first instance. from second instance onwards if it is in qna it does not starting from luis.

public class BasicLuisDialog : LuisDialog<object>
    {
        [LuisIntent("")]
        [LuisIntent("None")]
        public async Task None(IDialogContext context, IAwaitable<IMessageActivity> message, LuisResult result)
        {
            var mForward = await message as Activity;
            var username = context.Activity.From.Name;
            string reply = $"Hello {username}! Your query we are taking forward, as we are not aware about what exactly you want to know.";
            //await context.PostAsync(reply);
            await context.Forward(new IDialog(), this.ResumeAfterQnA, mForward, CancellationToken.None);
        }

        private async Task ResumeAfterQnA(IDialogContext context, IAwaitable<object> result)
        {
           context.Wait(MessageReceived);
        }

        [LuisIntent("leave.apply")]
        public async Task ApplyLeave(IDialogContext context, IAwaitable<IMessageActivity> message, LuisResult result)
        {
            var username = context.Activity.From.Name;
            string reply = $"Hello {username}! we are processing it";
            await context.PostAsync(reply);
        }

        [LuisIntent("it")]
        public async Task IT(IDialogContext context, IAwaitable<IMessageActivity> message, LuisResult result)
        {
            var username = context.Activity.From.Name;
            string reply = $"Hello {username}! we would look into your IT problems shortly";
            await context.PostAsync(reply);
        }
    }

BasicQnAMakerDialog Basic QnA code is given below. please help me to find where exactly is the problem.

public class IDialog : IDialog<object>
    {
        public async Task StartAsync(IDialogContext context)
        {
            /* Wait until the first message is received from the conversation and call MessageReceviedAsync 
            *  to process that message. */
            context.Wait(this.MessageReceivedAsync);
        }

        private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<IMessageActivity> result)
        {


            /* When MessageReceivedAsync is called, it's passed an IAwaitable<IMessageActivity>. To get the message,
             *  await the result. */
            var message = await result;
            var activity = await result as Activity;
            var qnaAuthKey = ConfigurationManager.AppSettings["QnAAuthKey"]; 
            var qnaKBId = ConfigurationManager.AppSettings["QnAKnowledgebaseId"];
            var endpointHostName = ConfigurationManager.AppSettings["QnAEndpointHostName"];


            // QnA Subscription Key and KnowledgeBase Id null verification
            if (!string.IsNullOrEmpty(qnaAuthKey) && !string.IsNullOrEmpty(qnaKBId))
            {
                // Forward to the appropriate Dialog based on whether the endpoint hostname is present
                if (string.IsNullOrEmpty(endpointHostName)) { 
                    await context.Forward(new BasicQnAMakerPreviewDialog(), AfterAnswerAsync, message, CancellationToken.None);
                    }
                else
                {
                    await context.Forward(new BasicQnAMakerDialog(), AfterAnswerAsync, message, CancellationToken.None);
                }

                }
            else
            {
                await context.PostAsync("Please set QnAKnowledgebaseId, QnAAuthKey and QnAEndpointHostName (if applicable) in App Settings. Learn how to get them at https://aka.ms/qnaabssetup.");
            }
            //var activity = await result as Activity;
            //await context.Forward(new BasicLuisDialog(), ResumeAfterLuisDialog, activity, CancellationToken.None);
        }

Solution

  • You need to call context.Done(new MyDialogResult()) when the dialog has finished doing what it was supposed to do. The bot framework keeps a stack of dialogs per conversation and whenever you perform a context.Forward it pushes a new dialog to the stack and every message to the bot will always go the dialog who is at the top of the stack and skip the others below, so when you perform context.Done it pops the current dialog from the stack and the conversation returns to the previous dialog.