Задание вопросов с помощью адаптивных карточек

Note

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

Адаптивные карточки позволяют интегрировать в агенты Copilot Studio фрагменты контента, которыми можно свободно обмениваться с другими облачными приложениями и службами. Чтобы предоставить вашему агенту богатые возможности общения, вы можете включить текст, графические элементы и кнопки. Поскольку они не зависят от платформы, вы можете легко адаптировать адаптивные карточки к своим потребностям.

С помощью узла Адаптивная карточка агент может отображать адаптивную карточку, содержащую одну или несколько кнопок отправки и, при необходимости, одно или несколько полей ввода формы. Агент сохраняет данные, введенные пользователем, в переменных для дальнейшего использования в разговоре.

Note

Copilot Studio поддерживает схему Adaptive Cards версий 1.6 и более ранних версий. Однако подходящая версия схемы зависит от целевого ведущего приложения:

  • Компонент веб-чата Bot Framework (то есть стандартная схема интеграции с веб-сайтом) поддерживает версию 1.6, но не Action.Execute
  • Мини-приложение чата (используемое в многоканальном взаимодействии для Customer Service) ограничено версией 1.5.
  • Teams также ограничен версией 1.5

Кроме того, Copilot Studio рендерит карточки версии 1.6 только в тестовом чате, а не на холсте.

Подробнее см. в разделе Адаптивные карточки.

Copilot Studio включает встроенный конструктор адаптивных карточек, который предлагает самые полезные функции из конструктора адаптивных карточек.

В качестве альтернативы, вы можете:

  • Используйте JSON-представление карточки, которую хотите показать пользователю.
  • Используйте формулу Power Fx для включения динамической информации в карточку.

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

Узел Адаптивная карточка предназначен для интерактивных карточек, на которых пользователь должен отправить ответ. Используйте узлы Сообщение и Вопрос, чтобы показать пользователю неинтерактивную карточку с информацией.

Tip

Переименуйте узлы, чтобы их было легче идентифицировать. Выберите поле имени узла, чтобы изменить имя напрямую, или выберите три точки () узла и выберите Переименовать в меню. Можно также переименовывать узлы в редакторе кода.

Невозможно переименовать узлы Триггер и Перейти на шаг.

Имена узлов могут иметь длину до 500 символов.

Добавление узла адаптивной карточки

  1. Нажмите значок Добавить узел под тем узлом, после которого вы хотите добавить узел адаптивной карточки, затем выберите Задать вопрос с помощью адаптивной карточки.

  2. Нажмите значок с тремя точками (), затем выберите Свойства.

  3. На панели Свойства узла адаптивной карточки выберите Редактировать адаптивную карточку. Откроется панель Конструктор адаптивных карточек.

  4. Добавьте необходимые элементы для вашей карточки и настройте их свойства. Кроме того, в области Редактор полезной нагрузки карточки замените полезные данные по умолчанию литералом JSON для карточки.

    Tip

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

  5. Когда вы закончите с первоначальным дизайном, выберите Сохранить и закройте панель конструктора. На узле отображается предварительный просмотр адаптивной карточки. Copilot Studio автоматически создаёт выходные переменные на основе входных данных, указанных в коде.

    Снимок экрана узла адаптивной карточки с предварительным просмотром содержимого карточки.

    Tip

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

    Ваша интерактивная адаптивная карточка готова. Когда пользователь вашего агента выбирает кнопку отправки на адаптивной карточке, выводные переменные заполняются информацией, которую пользователь предоставил при взаимодействии с карточкой.

Другие свойства

Для управления поведением узла адаптивной карточки можно использовать и другие свойства, например:

  • Реакция агента на недопустимый ответ
  • Если его можно прервать

Если агент ожидает отправки от адаптивной карточки, а пользователь вместо этого отправляет текстовое сообщение, этот ответ считается недействительным, кроме случая, когда это сообщение вызывает прерывание. В этом случае поведение определяют следующие свойства.

  • Количество повторных запросов: количество раз, когда ваш агент пытается получить правильную отправку с карточки. Значение по умолчанию — Повторить до 2 раз. Вы также можете выбрать Повторить один раз или Не повторять. При каждой повторной попытке карточка повторно отправляется пользователю.

  • Сообщение для повторной попытки: используйте этот параметр, чтобы определить сообщение, которое отправляется пользователю при повторной попытке вместе с повторной отправкой карточки. Чтобы задать сообщение повторной попытки, выберите Настроить, а затем введите новый запрос.

  • Разрешить переключение на другую тему: если эта опция выбрана (по умолчанию), входящее сообщение от пользователя, когда агент ожидает отправки карточки, вызывает прерывание и переключение на другую тему. Если происходит переключение темы, карточка повторно отправляется пользователю после завершения другой темы.

Поведение кнопки отправки для агентов с последовательными карточками

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

Чтобы действие отправки на одной карточке не мешало другой карточке:

  • Изолируйте действия отправки: убедитесь, что у каждой адаптивной карточки есть свой уникальный идентификатор и обработчики действий.

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

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

  • Отладка и ведение журнала: добавьте подробный журнал в код обработки событий вашего агента, чтобы фиксировать последовательность действий и определить, где происходит непреднамеренная отправка данных.

Использование идентификатора отправки в данных Action.Submit

Если ваш агент отправляет несколько адаптивных карточек в разговоре (например, последовательные карточки, повторные попытки или прерывания), пользователи могут выбрать Отправить на более ранней карточке. Чтобы ваш агент или пользовательский клиент мог определить, от какой карточки и действия поступил ответ, добавьте уникальный идентификатор в полезную нагрузку каждого действия отправки и проверяйте его при обработке ответа.

Пример:

{
  "type": "Action.Submit",
  "title": "Confirm",
  "data": {
    "actionSubmitId": "booking_confirm_card_v3_confirm"
  }
}

Совет по UX для веб-чата: как избежать устаревших кликов

Некоторые чат-клиенты, включая веб-версии, могут оставлять ранее отображенные карточки доступными для нажатия после того, как пользователь отправил более позднюю карточку. Если вы создаете собственный веб-чат, подумайте о том, чтобы отключить кнопки отправки после первого клика или обновить предыдущее сообщение карточки, чтобы уменьшить количество случайных дублирующих или устаревших отправок.

Следующий пример показывает один из способов отключить кнопки Action.Submit после первого клика в пользовательском веб-чате:

  1. Выполняйте отрисовку адаптивных карточек, используя пакет SDK для адаптивных карт или другой отрисовщик, генерирующий реальные HTML-кнопки и элементы ввода.

  2. Когда вы получаете действие Action.Submit, немедленно отметьте текущую карточку как отправленную в пользовательском интерфейсе. Например, установите отметку submitted на сообщении.

  3. Заново выполните отрисовку или измените объектную модель документа (DOM) карточки, чтобы все интерактивные элементы были отключены, а затем отправьте данные отправки вашему боту или сервису.

  4. Если ваш чат поддерживает несколько карточек в одной беседе, повторяйте этот подход для каждого сообщения с карточкой, чтобы предотвратить устаревшие отправки с предыдущих карточек.

Пример:

// Example: disable Adaptive Card submit interactions after the first click.
// This is UI-side logic for custom web chat experiences.

// When you render a card, keep a reference to its container element.
// For example, each chat message could render into its own <div>.
function disableCardInteractivity(cardContainer) {
    // Disable buttons (including Action.Submit rendered as <button>).
    for (const el of cardContainer.querySelectorAll('button, input, select, textarea')) {
        el.disabled = true;
        el.setAttribute('aria-disabled', 'true');
    }

    // Optional: prevent click handlers from firing (defense-in-depth).
    cardContainer.addEventListener(
        'click',
        (evt) => {
            const target = /** @type {HTMLElement} */ (evt.target);
            if (target && target.closest && target.closest('button, input, select, textarea')) {
                evt.preventDefault();
                evt.stopPropagation();
            }
        },
        true
    );
}

// Wire the behavior into your Adaptive Cards host.
// The Adaptive Cards SDK surfaces submits via onExecuteAction.
function wireCardSubmitHandling(adaptiveCard, cardContainer, sendToBot) {
    let submitted = false;

    adaptiveCard.onExecuteAction = async (action) => {
        // Only allow the first submit from this card instance.
        if (submitted) {
            return;
        }
        submitted = true;

        // Disable the UI immediately to avoid duplicate/stale clicks.
        disableCardInteractivity(cardContainer);

        // Send the submit payload to your bot/service.
        // If you're using Action.Submit with a unique ID (for example, actionSubmitId),
        // include it in the payload so your bot can de-duplicate safely.
        await sendToBot({
            type: 'adaptiveCard/submit',
            data: action && action.data ? action.data : {},
            verb: action && action.verb ? action.verb : undefined
        });
    };
}

Использование Power Fx, чтобы сделать карточку динамичной

Вы можете использовать формулу Power Fx для включения динамической информации в вашу карточку, ссылаясь на переменные из вашей темы или агента.

  1. Нажмите значок с тремя точками (), затем выберите Свойства.

  2. На панели свойств узла адаптивной карты переключите на опцию Формула. При выборе опции Формула JSON-код вашей карточки автоматически преобразуется в формулу Power Fx.

    Снимок экрана опции переключения на формулу Power Fx вместо JSON на панели свойств узла адаптивной карточки.

    Например, начните со следующего литерала JSON для карточки:

    {
      "$schema": "http://adaptivecards.microsoft.com/schemas/adaptive-card.json",
      "type": "AdaptiveCard",
      "version": "1.5",
      "body": [{
          "type": "ColumnSet",
          "columns": [{
              "type": "Column",
              "width": 2,
              "items": [{
                  "type": "TextBlock",
                  "text": "Tell us about yourself",
                  "weight": "Bolder",
                  "size": "Medium",
                  "wrap": true,
                  "style": "heading"
                }, {
                  "type": "TextBlock",
                  "text": "We just need a few more details to get you booked for the trip of a lifetime!",
                  "isSubtle": true,
                  "wrap": true
                }, {
                  "type": "Input.Text",
                  "id": "myName",
                  "label": "Your name (Last, First)",
                  "isRequired": true,
                  "regex": "^[A-Z][a-z]+, [A-Z][a-z]+$",
                  "errorMessage": "Please enter your name in the specified format"
                }
              ]
            }
          ]
        }
      ],
      "actions": [{
          "type": "Action.Submit",
          "title": "Submit"
        }
      ]
    }
    

    Вот итоговая формула Power Fx, использующая две переменные Topic.Title и Topic.Subtitle вместо жестко закодированного текста из литерала JSON. (В этом примере предполагается, что переменные определены в вашей теме.)

    {
      '$schema': "http://adaptivecards.microsoft.com/schemas/adaptive-card.json",
      type: "AdaptiveCard",
      version: "1.5",
      body: [
        {
          type: "ColumnSet",
          columns: [
            {
              type: "Column",
              width: "2",
              items: [
                {
                  type: "TextBlock",
                  text: Topic.Title,
                  weight: "Bolder",
                  size: "Medium",
                  wrap: true,
                  style: "heading"
                },
                {
                  type: "TextBlock",
                  text: Topic.Subtitle,
                  isSubtle: true,
                  wrap: true
                },
                {
                  type: "Input.Text",
                  id: "myName",
                  label: "Your name (Last, First)",
                  isRequired: true,
                  regex: "^[A-Z][a-z]+, [A-Z][a-z]+$",
                  errorMessage: "Please enter your name in the specified format"
                }
              ]
            }
          ]
        }
      ],
      actions: [
        {
          type: "Action.Submit",
          title: "Submit"
        }
      ]
    }
    

Important

После начала редактирования на панели формул вернуться к исходному коду JSON невозможно. Для итеративного проектирования и внесения изменений сохраните копию исходного JSON в собственных заметках или в виде комментария в узле. Эта мера предосторожности поможет отменить изменения при необходимости.