如何为机器人上的特定 QnA 响应添加英雄卡?

How to add a Hero Card for a particular QnA response on a Bot?

我正在尝试在我的机器人(C#、SDK-v4)中添加英雄卡,它应该显示来自 QnA Maker 服务的某些特定响应的英雄卡。 我试着这样实现 -

using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Azure.CognitiveServices.Language.LUIS.Runtime.Models;
using Microsoft.Bot.Builder;
using Microsoft.Bot.Schema;
using Microsoft.Extensions.Logging;

namespace Microsoft.BotBuilderSamples
{
    public class DispatchBot : ActivityHandler
    {
        private ILogger<DispatchBot> _logger;
        private IBotServices _botServices;

        public DispatchBot(IBotServices botServices, ILogger<DispatchBot> logger)
        {
            _logger = logger;
            _botServices = botServices;
        }

        protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
        {
            // First, we use the dispatch model to determine which cognitive service (LUIS or QnA) to use.
            var recognizerResult = await _botServices.Dispatch.RecognizeAsync(turnContext, cancellationToken);

            // Top intent tell us which cognitive service to use.
            var topIntent = recognizerResult.GetTopScoringIntent();

            // Next, we call the dispatcher with the top intent.
            await DispatchToTopIntentAsync(turnContext, topIntent.intent, recognizerResult, cancellationToken);
        }

        protected override async Task OnMembersAddedAsync(IList<ChannelAccount> membersAdded, ITurnContext<IConversationUpdateActivity> turnContext, CancellationToken cancellationToken)
        {
            const string WelcomeText = "How can I help you today?";

            foreach (var member in membersAdded)
            {
                if (member.Id != turnContext.Activity.Recipient.Id)
                {
                    await turnContext.SendActivityAsync(MessageFactory.Text($"Welcome {member.Name}. {WelcomeText}"), cancellationToken);
                }
            }
        }

        private async Task DispatchToTopIntentAsync(ITurnContext<IMessageActivity> turnContext, string intent, RecognizerResult recognizerResult, CancellationToken cancellationToken)
        {
            switch (intent)
            {
                case "l_luis":
                    await ProcessluisAsync(turnContext, recognizerResult.Properties["luisResult"] as LuisResult, cancellationToken);
                    break;

                case "q_sample-qna":
                    await ProcessSampleQnAAsync(turnContext, cancellationToken);
                    break;
                default:
                    _logger.LogInformation($"Dispatch unrecognized intent: {intent}.");
                    await turnContext.SendActivityAsync(MessageFactory.Text($"Dispatch unrecognized intent: {intent}."), cancellationToken);
                    break;
            }
        }

        private async Task ProcessluisAsync(ITurnContext<IMessageActivity> turnContext, LuisResult luisResult, CancellationToken cancellationToken)
        {
            _logger.LogInformation("ProcessluisAsync");

            // Retrieve LUIS result for Process Automation.
            var result = luisResult.ConnectedServiceResult;
            var topIntent = result.TopScoringIntent.Intent; 

            await turnContext.SendActivityAsync(MessageFactory.Text($"Luis top intent {topIntent}."), cancellationToken);
            //await turnContext.SendActivityAsync(MessageFactory.Text($"Luis intents detected:\n\n{string.Join("\n\n", result.Intents.Select(i => i.Intent))}"), cancellationToken);
            if (luisResult.Entities.Count > 0)
            {
                await turnContext.SendActivityAsync(MessageFactory.Text($"Luis entities were found in the message:\n\n{string.Join("\n\n", result.Entities.Select(i => i.Entity))}"), cancellationToken);
            }
        }

        private async Task ProcessSampleQnAAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
        {
            _logger.LogInformation("ProcessSampleQnAAsync");

            var results = await _botServices.SampleQnA.GetAnswersAsync(turnContext);
            if (results.Any())
            {
                var answer = MessageFactory.Text(results.First().Answer);
                //await turnContext.SendActivityAsync(MessageFactory.Text(results.First().Answer), cancellationToken);
                var ans = answer.ToString();
                //var attachment = GetHeroCard(ans);
                //var reply = MessageFactory.Attachment(attachment);
                string[] qnaAnswerData = ans.Split(';');
                int dataSize = qnaAnswerData.Length;
                if (dataSize > 1 && dataSize <= 6)
                {
                    var attachment = GetHeroCard(ans);
                    var reply = MessageFactory.Attachment(attachment);
                    await turnContext.SendActivityAsync(reply, cancellationToken);

                }
                else
                {
                    await turnContext.SendActivityAsync(answer, cancellationToken);
                }


            }
            else
            {
                await turnContext.SendActivityAsync(MessageFactory.Text("Sorry, could not find an answer in the Q and A system."), cancellationToken);
            }
        }

        private static Attachment GetHeroCard(string ans)
        {
            string[] qnaAnswerData = ans.Split(';');
            string title = qnaAnswerData[0];
            string description = qnaAnswerData[1];
            string url = qnaAnswerData[2];
            string imageURL = qnaAnswerData[3];
            HeroCard card = new HeroCard
            {
                Title = title,
                Subtitle = description,
            };
            card.Buttons = new List<CardAction>
            {
                new CardAction(ActionTypes.OpenUrl, "Learn More", value: url)
            };

            card.Images = new List<CardImage>
            {
                new CardImage(url = imageURL)
            };
            return card.ToAttachment();

        }
    }
}

但是这个机器人仍然以简单的文本回复,即使答案有四个用分号分隔的参数。对代码的任何建议或修改都会有所帮助?

在我的机器人代码中,我使用了代码 -

var answer = MessageFactory.Text(results.First().Answer);

var ans = answer.ToString();
string[] qnaAnswerData = ans.Split(';');

而不是这个,我尝试了这个 -

var ans = results.First().Answer;

string[] qnaAnswerData = ans.Split(';');

这解决了我的问题,现在英雄卡在机器人中可以正常工作了。