Как получить представление формы Adaptive Card на следующем этапе водопада - PullRequest
3 голосов
/ 08 марта 2019

Я использую Bot Framework (V4), и у меня есть WaterfallDialog с двумя шагами;первый шаг - захват данных формы, а второй - обработка данных формы.

Первый шаг отправляет ответ:

private async Task<DialogTurnResult> CaptureFormStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
    var reply = await stepContext.Context.Activity.GetReplyFromCardAsync("BusinessyForm");
    await stepContext.Context.SendActivityAsync(reply, cancellationToken);
}

GetReplyFromCardAsync - это метод расширения, который принимаетJSON-представление Activity с адаптивной картой в качестве прикрепленного элемента.Адаптивная карта является формой, подобной этой .Адаптивная карта также имеет действие отправки.

Мой вопрос: как передать эту информацию на следующий шаг?

В предыдущих попытках я вернул подсказку:

return await stepContext.PromptAsync(
    "custom-prompt-id", 
    new PromptOptions { Prompt = MessageFactory.Text("Hello!") }, 
    cancellationToken);

Но в этом контексте я не хочу запрашивать у пользователя дополнительную информацию.В идеале я хотел бы «удерживать» состояние диалога для ответа, и когда он обнаружен, следующий шаг будет обрабатывать результат отправки.

То, что я пробовал:

  • Рассмотренные примеры здесь и здесь .Оба показывают, как карты могут отображаться, но не как обрабатывать ввод на последующих шагах.
  • Рассмотрена документация схемы карт для входных данных здесь .
  • Рассмотрено обсуждение аналогичной проблемы в GitHub.AdaptiveCard repo здесь .

Возможно ли это?Любая помощь будет высоко ценится!

Ответы [ 2 ]

4 голосов
/ 08 марта 2019

Адаптивные карты отправляют свои результаты отправки немного иначе, чем обычный текст пользователя. Когда пользователь печатает в чате и отправляет обычное сообщение, оно заканчивается на Context.Activity.Text. Когда пользователь заполняет ввод на адаптивной карте, он заканчивается на Context.Activity.Value, который является объектом, в котором имена ключей - id на вашей карте, а значения - значения полей в адаптивной карте.

Например, JSON:

{
    "type": "AdaptiveCard",
    "body": [
        {
            "type": "TextBlock",
            "text": "Test Adaptive Card"
        },
        {
            "type": "ColumnSet",
            "columns": [
                {
                    "type": "Column",
                    "items": [
                        {
                            "type": "TextBlock",
                            "text": "Text:"
                        }
                    ],
                    "width": 20
                },
                {
                    "type": "Column",
                    "items": [
                        {
                            "type": "Input.Text",
                            "id": "userText",
                            "placeholder": "Enter Some Text"
                        }
                    ],
                    "width": 80
                }
            ]
        }
    ],
    "actions": [
        {
            "type": "Action.Submit",
            "title": "Submit"
        }
    ],
    "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
    "version": "1.0"
}

.. создает карту, которая выглядит следующим образом:

Test Adaptive Card

Если пользователь вводит «Testing Testing 123» в текстовое поле и нажимает «Отправить», Context.Activity будет выглядеть примерно так:

{ type: 'message',
  value: { userText: 'Testing Testing 123' },
  from: { id: 'xxxxxxxx-05d4-478a-9daa-9b18c79bb66b', name: 'User' },
  locale: '',
  channelData: { postback: true },
  channelId: 'emulator',
  conversation: { id: 'xxxxxxxx-182b-11e9-be61-091ac0e3a4ac|livechat' },
  id: 'xxxxxxxx-182b-11e9-ad8e-63b45e3ebfa7',
  localTimestamp: 2019-01-14T18:39:21.000Z,
  recipient: { id: '1', name: 'Bot', role: 'bot' },
  timestamp: 2019-01-14T18:39:21.773Z,
  serviceUrl: 'http://localhost:58453' }

Представление пользователя можно увидеть в Context.Activity.Value.userText.

Обратите внимание, что отправка адаптивной карты отправляется как postBack, что означает, что данные отправки не отображаются в окне чата как часть разговора - они остаются на адаптивной карте.

Использование адаптивных карт с Диалоги водопада

Собственно, адаптивные карты не работают как подсказки. При появлении приглашения оно будет отображаться и ждать ввода пользователя, прежде чем продолжить. Но с адаптивными картами (даже если они содержат поле ввода и кнопку отправки), в адаптивной карте нет кода, который заставлял бы диалоговое окно «Водопад» ожидать ввода пользователя, прежде чем продолжить диалог.

Итак, если вы используете адаптивную карту, которая принимает пользовательский ввод, вы, как правило, хотите обрабатывать все, что пользователь отправляет, вне контекста диалога водопада.

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

  1. Отображение адаптивной карты
  2. Отображение текстовой подсказки
  3. Преобразовать ввод адаптивной карты пользователя во ввод текстовой подсказки

В вашем классе Waterfall Dialog (шаги 1 и 2):

private async Task<DialogTurnResult> DisplayCardAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
    // Create the Adaptive Card
    var cardPath = Path.Combine(".", "AdaptiveCard.json");
    var cardJson = File.ReadAllText(cardPath);
    var cardAttachment = new Attachment()
    {
        ContentType = "application/vnd.microsoft.card.adaptive",
        Content = JsonConvert.DeserializeObject(cardJson),
    };

    // Create the text prompt
    var opts = new PromptOptions
    {
        Prompt = new Activity
        {
            Attachments = new List<Attachment>() { cardAttachment },
            Type = ActivityTypes.Message,
            Text = "waiting for user input...", // You can comment this out if you don't want to display any text. Still works.
        }
    };

    // Display a Text Prompt and wait for input
    return await stepContext.PromptAsync(nameof(TextPrompt), opts);
}

private async Task<DialogTurnResult> HandleResponseAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
    // Do something with step.result
    // Adaptive Card submissions are objects, so you likely need to JObject.Parse(step.result)
    await stepContext.Context.SendActivityAsync($"INPUT: {stepContext.Result}");
    return await stepContext.NextAsync();
}

В вашем основном классе ботов (<your-bot>.cs), под OnTurnAsync(), рядом с началом метода, где-то до того, как вызывается await dialogContext.ContinueDialogAsync(cancellationToken) (шаг 3):

var activity = turnContext.Activity;

if (string.IsNullOrWhiteSpace(activity.Text) && activity.Value != null)
{
    activity.Text = JsonConvert.SerializeObject(activity.Value);
}
0 голосов
/ 17 мая 2019

Вот версия nodejs:

Ваш файл bot.ts:

 this.onTurn(async (context, next) => {
  if (context.activity.type == ActivityTypes.Message) {
    // Ensure that message is a postBack (like a submission from Adaptive Cards)
    if (context.activity.channelData != null) {
      if (context.activity.channelData.postBack === true) {
        const postbackActivity = context.activity;
        // Convert the user's Adaptive Card input into the input of a Text Prompt
        // Must be sent as a string
        postbackActivity.text = JSON.stringify(postbackActivity.value);
        // context.activity.text = postbackActivity.value
        await context.sendActivity(postbackActivity);
      }
    }
  }
  await next();
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...