Как я могу добавить многооборотную подсказку в веб-чате? - PullRequest
1 голос
/ 02 июня 2019

Я добавил многооборотные приглашения в свою qna, и они работают на веб-сайте qna, но при попытке в веб-чате приглашения не отображаются.

Они работают в чате?

Ответы [ 2 ]

2 голосов
/ 02 июня 2019

Если вы хотите отобразить результат в виде карты, как это делает тестовый портал QnA, вам необходимо преобразовать результат в адаптивную карту.Смотрите фрагменты кода ниже.

Снимок экрана

image

Бот-код - onMessage - Узел

this.onMessage(async (context, next) => {

  const qnaResults = await this.qnaMaker.getAnswers(context);

  if (qnaResults[0]) {
      const { answer, context: { prompts }} = qnaResults[0];

      let reply;
      if (prompts.length) {

        const card = {
          "type": "AdaptiveCard",
          "body": [
              {
                  "type": "TextBlock",
                  "text": answer,
                  wrap: true
              }
          ],
          "actions": prompts.map(({ displayText }) => ({ type: "Action.Submit", title: displayText, data: displayText })),
          "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
          "version": "1.1"
        }

        reply = { attachments: [CardFactory.adaptiveCard(card)] };
      } else {
        reply = answer;
      }

      await context.sendActivity(reply);

  // If no answers were returned from QnA Maker, reply with help.
  } else {
      await context.sendActivity('No QnA Maker answers were found.');
  }

  await next();
});
}

Надеждаэто помогает!

0 голосов
/ 02 июня 2019

Я ответил на это здесь .

По сути, вам нужно создать свой собственный HTTP-вызов к вашей QnA Maker KB вместо использования встроенных методов согласно this :

public async Task<QnAResult[]> QueryQnAServiceAsync(string query, QnABotState qnAcontext)
{
    var requestUrl = $"{_endpoint.Host}/knowledgebases/{_endpoint.KnowledgeBaseId}/generateanswer";
    var request = new HttpRequestMessage(HttpMethod.Post, requestUrl);
    var jsonRequest = JsonConvert.SerializeObject(
        new
        {
            question = query,
            top = _options.Top,
            context = qnAcontext,
            strictFilters = _options.StrictFilters,
            metadataBoost = _options.MetadataBoost,
            scoreThreshold = _options.ScoreThreshold,
        }, Formatting.None);

    request.Headers.Add("Authorization", $"EndpointKey {_endpoint.EndpointKey}");
    request.Content = new StringContent(jsonRequest, System.Text.Encoding.UTF8, "application/json");

    var response = await _httpClient.SendAsync(request);
    response.EnsureSuccessStatusCode();


    var contentString = await response.Content.ReadAsStringAsync();

    var result = JsonConvert.DeserializeObject<QnAResultList>(contentString);

    return result.Answers;
}

Затем проверьте результат на наличие любых подсказок и действуйте соответственно:

var query = inputActivity.Text;           
var qnaResult = await _qnaService.QueryQnAServiceAsync(query, new QnABotState());
var qnaAnswer = qnaResult[0].Answer;
var prompts = qnaResult[0].Context?.Prompts;

if (prompts == null || prompts.Length < 1)
{
    outputActivity = MessageFactory.Text(qnaAnswer);
}
else
{
    outputActivity = CardHelper.GetHeroCard(qnaAnswer, prompts);
}

await turnContext.SendActivityAsync(outputActivity);

Примечание: Приведенный выше код для «действия соответственно» будет работать только для одного уровня подсказок, согласно моему ответу, который я связал сверху. Если вы хотите поддерживать несколько уровней запросов, вам придется реализовать их как систему состояний в соответствии с этим примером - см. Мой другой ответ здесь для получения более подробной информации.

Примечание 2: Как упомянуто в комментарии ниже, использование вышеуказанного подхода (HeroCard) может привести к сокращению заголовка, если текст слишком длинный. Чтобы избежать этого, вы можете использовать Adaptive Dialogs или Adaptive Cards .

EDIT

На основании этого образца

Вы должны быть в состоянии достигнуть одного уровня подсказок примерно с таким:

QnAResult.cs

    public class QnAResult
    {
        public string[] Questions { get; set; }

        public string Answer { get; set; }

        public double Score { get; set; }

        public int Id { get; set; }

        public string Source { get; set; }

        public QnAMetadata[] Metadata { get; set; }

        public QnAContext Context { get; set; }
    }

QnAResultList.cs

public class QnAResultList
    {
        public QnAResult[] Answers { get; set; }
    }

IQnAService.cs

    public interface IQnAService
    {
        Task<QnAResult[]> QueryQnAServiceAsync(string query, QnABotState qnAcontext, QnAMakerEndpoint qnAMakerEndpoint);
    }

QnAService.cs

public class QnAService : IQnAService
    {
        private readonly HttpClient _httpClient;
        private readonly IConfiguration _configuration;

        public QnAService(HttpClient httpClient, IConfiguration configuration)
        {
            _httpClient = httpClient;
            _configuration = configuration;
        }

        public async Task<QnAResult[]> QueryQnAServiceAsync(string query, QnABotState qnAcontext, QnAMakerEndpoint qnAMakerEndpoint)
        {
            var options = new QnAMakerOptions
            {
                Top = 3
            };

            var hostname = qnAMakerEndpoint.Host;

            var endpoint = new QnAMakerEndpoint
            {
                KnowledgeBaseId = qnAMakerEndpoint.KnowledgeBaseId,
                EndpointKey = qnAMakerEndpoint.EndpointKey,
                Host = hostname
            };

            var requestUrl = $"{endpoint.Host}/knowledgebases/{endpoint.KnowledgeBaseId}/generateanswer";
            var request = new HttpRequestMessage(HttpMethod.Post, requestUrl);
            var jsonRequest = JsonConvert.SerializeObject(
                new
                {
                    question = query,
                    top = options.Top,
                    context = qnAcontext,
                    strictFilters = options.StrictFilters,
                    metadataBoost = options.MetadataBoost,
                    scoreThreshold = options.ScoreThreshold,
                }, Formatting.None);

            request.Headers.Add("Authorization", $"EndpointKey {endpoint.EndpointKey}");
            request.Content = new StringContent(jsonRequest, System.Text.Encoding.UTF8, "application/json");

            var response = await _httpClient.SendAsync(request);
            response.EnsureSuccessStatusCode();


            var contentString = await response.Content.ReadAsStringAsync();

            var result = JsonConvert.DeserializeObject<QnAResultList>(contentString);

            return result.Answers;
        }
    }

CardHelper.cs

    public class CardHelper
    {
        /// <summary>
        /// Get Hero card
        /// </summary>
        /// <param name="cardTitle">Title of the card</param>
        /// <param name="prompts">List of suggested prompts</param>
        /// <returns>Message activity</returns>
        public static Activity GetHeroCardWithPrompts(string cardTitle, QnAPrompts[] prompts)
        {
            var chatActivity = Activity.CreateMessageActivity();
            var buttons = new List<CardAction>();

            var sortedPrompts = prompts.OrderBy(r => r.DisplayOrder);
            foreach (var prompt in sortedPrompts)
            {
                buttons.Add(
                    new CardAction()
                    {
                        Value = prompt.DisplayText,
                        Type = ActionTypes.ImBack,
                        Title = prompt.DisplayText
                    });
            }

            var plCard = new HeroCard()
            {
                Title = cardTitle,
                Subtitle = string.Empty,
                Buttons = buttons
            };

            var attachment = plCard.ToAttachment();

            chatActivity.Attachments.Add(attachment);

            return (Activity)chatActivity;
        }
    }

MyBot.cs HandleQnA ()

QnAResult[] qnaResults =  await _qnAService.QueryQnAServiceAsync(context.Activity.Text, new QnABotState(), _qnAMakerEndpoint);

                if (qnaResults.Any())
                {
                    // Get result by highest confidence
                    QnAResult highestRankedResult = qnaResults.OrderByDescending(x => x.Score).First();
                    string answer = highestRankedResult.Answer;

                    QnAPrompts[] prompts = highestRankedResult.Context?.Prompts;

                    if (prompts == null || prompts.Length < 1)
                    {
                        await context.SendActivityAsync(answer, cancellationToken: cancellationToken);
                    }
                    else
                    {
                        await context.SendActivityAsync(CardHelper.GetHeroCardWithPrompts(answer, prompts), cancellationToken: cancellationToken);
                    }
                }

Используемые мной пакеты NuGet:

packages

...