-1

I'm developing a chatbot using Microsoft Azure Web App Service. Among them, I'd like to insert a hero card in the greeting, and then click Info Dynamics365 among the corresponding hero buttons to start calling the card list source I've created, and if I press FAQ, I'd like to connect with QnAMaker for questioning. If you use ActionType now, both will call up a list of cards, one of which type should be used to connect to QnAMaker, or how to specify a path.

Bpts/QnABot.cs

namespace Microsoft.BotBuilderSamples
 {
public class QnABot<T> : ActivityHandler 
{

    private BotState _conversationState;
    private BotState _userState;

    //QnAMaker
    //protected readonly BotState ConversationState;
    //protected readonly Microsoft.Bot.Builder.Dialogs.Dialog Dialog;
    //protected readonly BotState UserState;
    private string KBID = "fcd905a3-7269-4ea5-9a58-7b02c888ddb6";
    private string ENDPOINT_KEY = "7b9a938a-e7ac-46f6-ab69-97d4e2e04f66";
    private string HOST = "myfirstqa.azurewebsites.net";

    //Azure 첫 세팅 소스 
    public QnABot(ConversationState conversationState, UserState userState)
    {
        _conversationState = conversationState;
        _userState = userState;

    }

    public override async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken))
    {
        await base.OnTurnAsync(turnContext, cancellationToken);

        // Save any state changes that might have occured during the turn.
        await _conversationState.SaveChangesAsync(turnContext, false, cancellationToken);
        await _userState.SaveChangesAsync(turnContext, false, cancellationToken);
    }

    protected override async Task OnMembersAddedAsync(IList<ChannelAccount> membersAdded, ITurnContext<IConversationUpdateActivity> turnContext, CancellationToken cancellationToken)
    {
        foreach (var member in membersAdded)
        {
            if (member.Id != turnContext.Activity.Recipient.Id)
            {
                var card = new HeroCard();
                card.Title = "";
                card.Text = @"Welcome to Welcome Users bot sample! This Introduction card";
                card.Images = new List<CardImage>() { new CardImage("https://www.google.com/url?sa=i&source=images&cd=&ved=2ahUKEwjQjeeS4obmAhUIfnAKHQGgCB0QjRx6BAgBEAQ&url=https%3A%2F%2Fdougame.tistory.com%2F98&psig=AOvVaw11Y-BZJtsxh1pTp0Qxzedb&ust=1574819546545481") };
                card.Buttons = new List<CardAction>()
            {

                    new CardAction(ActionTypes.PostBack, "테스트 FAQ연결", null,"Connect QnA-Makeshfrjflrk todrur","Connect QnA-Maker", "Connection QnAMaker"),
                    new CardAction(ActionTypes.PostBack, "YOUTUBE LINK", null,"Connect YouTube","Connect YouTube", "Connection YouTube"),
                    new CardAction(ActionTypes.PostBack, "테스트 F연결", null,"Connect QnA-Maker","Connect QnA-Maker", "Connection A")
            };

                var response = MessageFactory.Attachment(card.ToAttachment());
                await turnContext.SendActivityAsync(response, cancellationToken);

            }

        }

    }


    protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
    {

        //QnA Maker연결
        var qnaMaker = new QnAMaker(new QnAMakerEndpoint
        {
            KnowledgeBaseId = "fcd905a3-7269-4ea5-9a58-7b02c888ddb6",
            EndpointKey = "7b9a938a-e7ac-46f6-ab69-97d4e2e04f66",
            Host = "myfirstqa.azurewebsites.net"
        },
                 null,
                 new System.Net.Http.HttpClient());

        var conversationStateAccessors = _conversationState.CreateProperty<ConversationService>(nameof(ConversationService));
        var conversationService = await conversationStateAccessors.GetAsync(turnContext, () => new ConversationService());

        var input = turnContext.Activity.Text;
        if (String.IsNullOrEmpty(conversationService.currentService) && (input.Equals("Connection QnAMaker")))
        {

            conversationService.currentService = input;
            await turnContext.SendActivityAsync(MessageFactory.Text("선택 : " + input + " service ,\n 입력할 내용 " + input + " question"), cancellationToken);

        }
       else if (String.IsNullOrEmpty(conversationService.currentService))
        {
            await turnContext.SendActivityAsync(MessageFactory.Text("select a service from hero card first"), cancellationToken);
        }
        else if (conversationService.currentService.Equals("Connection QnAMaker"))
        {
            //call your dy QNA service here 

            var result = qnaMaker.GetAnswersAsync(turnContext).GetAwaiter().GetResult();
            if (result.Length == 0)
            {
                await turnContext.SendActivityAsync(MessageFactory.Text("Sorry , I can't find any answer for it"), cancellationToken);
            }
            else
            {
                await turnContext.SendActivityAsync(MessageFactory.Text(result[0].Answer), cancellationToken);
            }
            ////await turnContext.SendActivityAsync(MessageFactory.Text(result[0].Answer), cancellationToken);

        }
        else if (conversationService.currentService.Equals("dy365"))
        {
            //call your dy 365 service here 
           await turnContext.SendActivityAsync(MessageFactory.Text("dy365 response"), cancellationToken);

        }
        else
        {
            await turnContext.SendActivityAsync(MessageFactory.Text("error"), cancellationToken);
        };

    } 

}
public class ConversationService
{
    public string currentService { get; set; }

}

}

Dialog/RootDialog.cs

namespace Microsoft.BotBuilderSamples.Dialog {

public class RootDialog : ComponentDialog
{

    private const string InitialDialog = "initial-dialog";


    public RootDialog(IBotServices services)
        : base("root")
    {
        AddDialog(new QnAMakerBaseDialog(services));

        AddDialog(new WaterfallDialog(InitialDialog)
           .AddStep(InitialStepAsync));

        // The initial child Dialog to run.
        InitialDialogId = InitialDialog;
    }

    private async Task<DialogTurnResult> InitialStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
    {
        // Set values for generate answer options.
        var qnamakerOptions = new QnAMakerOptions
        {
            ScoreThreshold = QnAMakerBaseDialog.DefaultThreshold,
            Top = QnAMakerBaseDialog.DefaultTopN,
            Context = new QnARequestContext()
        };

        // Set values for dialog responses.
        var qnaDialogResponseOptions = new QnADialogResponseOptions
        {
            NoAnswer = QnAMakerBaseDialog.DefaultNoAnswer,
            ActiveLearningCardTitle = QnAMakerBaseDialog.DefaultCardTitle,
            CardNoMatchText = QnAMakerBaseDialog.DefaultCardNoMatchText,
            CardNoMatchResponse = QnAMakerBaseDialog.DefaultCardNoMatchResponse
        };

        var dialogOptions = new Dictionary<string, object>
        {
            [QnAMakerBaseDialog.QnAOptions] = qnamakerOptions,
            [QnAMakerBaseDialog.QnADialogResponseOptions] = qnaDialogResponseOptions
        };

        return await stepContext.BeginDialogAsync(nameof(QnAMakerBaseDialog), dialogOptions, cancellationToken);
    }
}

}

The above is the part that selects the desired function at the same time as the greeting.

K.natsu
  • 11
  • 4

1 Answers1

1

Try the code below which based on this official demo .Replace the content of Bots/StateManagementBot.cs with the code below :

using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Bot.Builder;
using Microsoft.Bot.Schema;
using Microsoft.Bot.Builder.AI.QnA;

namespace Microsoft.BotBuilderSamples
{
    public class StateManagementBot : ActivityHandler
    {
        private BotState _conversationState;
        private BotState _userState;
        private string KBID = "<KBID>";
        private string ENDPOINT_KEY = "<KEY>";
        private string HOST = "<QnA maker host>";


        public StateManagementBot(ConversationState conversationState, UserState userState)
        {
            _conversationState = conversationState;
            _userState = userState;
        }

        public override async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken))
        {
            await base.OnTurnAsync(turnContext, cancellationToken);

            // Save any state changes that might have occured during the turn.
            await _conversationState.SaveChangesAsync(turnContext, false, cancellationToken);
            await _userState.SaveChangesAsync(turnContext, false, cancellationToken);
        }

        protected override async Task OnMembersAddedAsync(IList<ChannelAccount> membersAdded, ITurnContext<IConversationUpdateActivity> turnContext, CancellationToken cancellationToken)
        {
            foreach (var member in membersAdded)
            {
                if (member.Id != turnContext.Activity.Recipient.Id)
                {

                    var card = new HeroCard();
                    card.Title = "";
                    card.Text = @"Welcome to Welcome Users bot sample! This Introduction card";
                    card.Images = new List<CardImage>() { new CardImage("https://www.google.com/url?sa=i&source=images&cd=&ved=2ahUKEwjQjeeS4obmAhUIfnAKHQGgCB0QjRx6BAgBEAQ&url=https%3A%2F%2Fdougame.tistory.com%2F98&psig=AOvVaw11Y-BZJtsxh1pTp0Qxzedb&ust=1574819546545481") };
                    card.Buttons = new List<CardAction>()
                {

                    //new CardAction(ActionTypes.OpenUrl, "FAQ", null, "Get an overview", "Get an overview", "https://learn.microsoft.com/en-us/azure/bot-service/?view=azure-bot-service-4.0"),
                    new CardAction(ActionTypes.PostBack, "Info Dynamics365", null, "Ask a question", "Ask a question", "dy365"),
                    new CardAction(ActionTypes.PostBack, "FAQ",null , "Ask a question", "Ask a question", "FAQ"  ),

                    new CardAction(ActionTypes.OpenUrl, "Connect", null, "Learn how to deploy", "Learn how to deploy", "https://learn.microsoft.com/en-us/azure/bot-service/bot-builder-howto-deploy-azure?view=azure-bot-service-4.0"),
                };

                    var response = MessageFactory.Attachment(card.ToAttachment());
                    await turnContext.SendActivityAsync(response, cancellationToken);
                }
            }

        }

        protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
        {

            var qnaMaker = new QnAMaker(new QnAMakerEndpoint
            {
                KnowledgeBaseId = KBID,
                EndpointKey = ENDPOINT_KEY,
                Host = HOST
            },
                    null,
                    new System.Net.Http.HttpClient());

            var conversationStateAccessors = _conversationState.CreateProperty<ConversationService>(nameof(ConversationService));
            var conversationService = await conversationStateAccessors.GetAsync(turnContext, () => new ConversationService());

            var input = turnContext.Activity.Text;
            if (String.IsNullOrEmpty(conversationService.currentService) && (input.Equals("FAQ") || input.Equals("dy365")))
            {

                conversationService.currentService = input;
                await turnContext.SendActivityAsync(MessageFactory.Text("using "+ input + " service , pls enter your " + input + " question"), cancellationToken);

            } else if (String.IsNullOrEmpty(conversationService.currentService)) {
                await turnContext.SendActivityAsync(MessageFactory.Text("select a service from hero card first"), cancellationToken);
            }
            else if (conversationService.currentService.Equals("FAQ"))
            {

                var result = qnaMaker.GetAnswersAsync(turnContext).GetAwaiter().GetResult();

            if (result.Length == 0)
            {
                await turnContext.SendActivityAsync(MessageFactory.Text("Sorry , I can't find any answer for it"), cancellationToken);
            }
            else {
                await turnContext.SendActivityAsync(MessageFactory.Text(result[0].Answer), cancellationToken);
            }
            }
            else if (conversationService.currentService.Equals("dy365"))
            {
                //call your dy 365 service here 
                await turnContext.SendActivityAsync(MessageFactory.Text("dy365 response"), cancellationToken);
            }
            else {
                await turnContext.SendActivityAsync(MessageFactory.Text("error"), cancellationToken);
            };

        }
    }

    public class ConversationService{
        public string currentService { get; set; } 
}


}

You can find all QnA related params on QnA portal after you publish it : enter image description here

Result : enter image description here

In brief , let user select a service first and save the service type into conversation state so that users' requests will be redirected to corresponding service .

Hope it helps .

Stanley Gong
  • 11,522
  • 1
  • 8
  • 16
  • Hi @K.natsu, how's going ? Has your issue been solved ? – Stanley Gong Nov 28 '19 at 01:31
  • Hello. I'm sorry for the late answer. I did as you told me, but I don't know how to connect the 파일을 and Bots/.cs files. The part of the QnAMaker that answers is in the Rootdialog.cs section, so can you tell me how to connect? – K.natsu Nov 29 '19 at 07:52
  • Hi @K.natsu , if you want to know how to connect to QnA maker service , I have updated my answer with results . Pls click on the check mark beside the answer to toggle it from greyed out to filled in to mark it as an answer if it is helpful for you and I am glad to answer your further questions . Thanks ! – Stanley Gong Nov 29 '19 at 08:42
  • Hi @Stanley Gong. It's weekend, so I'll check and answer. If you change it that way, the starts.cs. file currently fails.How do you know how to change this part? I looked at the samples on the chatbot and tried to copy them, but they were not connected. I will correct the source of the above text. I'll also add the Dialog/RootDialog.cs file this time. – K.natsu Dec 02 '19 at 05:13