如何在网络聊天中添加多轮提示?

How can I add the multi-turn prompt in the webchat?

我在我的 qna 中添加了多轮提示,它们在 qna 网站上工作,但是在网络聊天中尝试时,提示没有出现。

他们在网络聊天中工作吗?

如果您想像 QnA 测试门户那样将结果显示为卡片,则需要将结果转换为自适应卡片。请参阅下面的代码片段。

截图

机器人代码 - 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();
});
}

希望对您有所帮助!

我已经回答了这个here

基本上,您需要构建自己的对 QnA Maker 知识库的 HTTP 调用,而不是按照 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);

注意: 以上 "acting accordingly" 的代码仅适用于单级提示,根据我在顶部链接的回答。如果您想支持多级提示,那么您必须按照 this sample 实施状态系统 - 请参阅我的其他答案 here 了解更多详情。

注意 2: 正如下面评论中提到的,如果文本太长,使用上述方法 (HeroCard) 可能会导致标题被截断。为避免这种情况,您可以使用 Adaptive Dialogs or Adaptive Cards.

编辑

基于this sample

你应该可以通过这样的方式实现单级提示:

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 包是: