Исследуйте в Dialogflow
Нажмите «Продолжить» , чтобы импортировать образец ответов в Dialogflow. Затем выполните следующие действия, чтобы развернуть и протестировать образец:
- Введите имя агента и создайте новый агент Dialogflow для образца.
- После завершения импорта агента нажмите Перейти к агенту .
- В главном навигационном меню перейдите к Выполнение .
- Включите встроенный редактор , затем нажмите «Развернуть» . Редактор содержит пример кода.
- В главном меню навигации выберите «Интеграции» и нажмите «Google Ассистент» .
- В появившемся модальном окне включите автоматический предварительный просмотр изменений и нажмите «Тест» , чтобы открыть симулятор действий.
- В симуляторе введите
Talk to my test app
, чтобы протестировать образец!
Используйте визуальный ответ выбора, если вы хотите, чтобы пользователь выбрал один из нескольких вариантов, чтобы продолжить ваше действие.
Ответы на визуальный выбор могут появляться только на экране или в приложениях, включающих как звуковые, так и экранные компоненты.
Ответы визуального выбора могут содержать следующие компоненты:
- Один или два простых ответа (пузыри чата).
- Необязательная базовая карта .
- Дополнительные фишки предложений .
- Дополнительный выходной чип.
- Интерфейс опций, такой как список или карусель .
Вы также можете ознакомиться с нашими рекомендациями по дизайну бесед , чтобы узнать, как использовать эти визуальные элементы в своем действии.
Характеристики
Ответы визуального выбора имеют следующие требования и дополнительные свойства, которые можно настроить:
- Поддерживается на поверхностях с возможностью
actions.capability.SCREEN_OUTPUT
. - Первым элементом ответа визуального выбора должен быть простой ответ .
- Максимум один простой ответ.
- Не более одной базовой карточки, опционального интерфейса ( список или карусель ) или
StructuredResponse
. (Вы не можете иметь одновременно и базовую карту, и дополнительный интерфейс). - Не более 8 фишек предложений .
- Чипы предложений не допускаются в
FinalResponse
.
В следующих разделах показано, как создавать различные типы ответов визуального выбора.
Список

Список с одним выбором представляет пользователю вертикальный список из нескольких элементов и позволяет пользователю выбрать один из них. При выборе элемента из списка генерируется пользовательский запрос (пузырь чата), содержащий заголовок элемента списка.
Тип ответа списка поддерживается на поверхностях с возможностью actions.capability.SCREEN_OUTPUT
.
Характеристики
Списки должны содержать не менее 2 и не более 30 элементов списка. Списки обладают следующими свойствами:
- Название списка (необязательно)
- Фиксированный шрифт и размер шрифта
- Ограничено одной строкой. (Лишние символы обрезаются.)
- Обычный текст, Markdown не поддерживается.
- Высота карточки сворачивается, если заголовок не указан.
- Пункт списка
- Заголовок
- Фиксированный шрифт и размер шрифта
- Максимальная длина: 1 строка (усеченная многоточием…)
- Требуется уникальность (для поддержки голосового выбора)
- Описание (необязательно)
- Фиксированный шрифт и размер шрифта
- Максимальная длина: 2 строки (обрезанные многоточием…)
- Изображение (необязательно)
- Размер: 48x48 пикселей
- Заголовок
- Взаимодействие
- Голос/текст
- Пользователь всегда может произнести или ввести название элемента, а не касаться его.
- Должен иметь намерение для сенсорного ввода, которое обрабатывает событие
actions_intent_OPTION
.
- Голос/текст
Руководство
Списки хороши, когда важно устранить неоднозначность параметров или когда пользователю нужно выбрать между вариантами, которые необходимо просмотреть с первого взгляда. Например, с каким «Питером» вам нужно поговорить, с Питером Джонсом или с Питером Хансом?
Мы рекомендуем добавлять чипы предложений под списком, чтобы пользователь мог разворачивать или расширять беседу. Никогда не повторяйте варианты, представленные в списке в виде фишек-предложений. Фишки в этом контексте используются для поворота разговора (а не для выбора выбора).
Обратите внимание, что в прилагаемом примере всплывающее окно чата, которое сопровождает карточку со списком, является подмножеством аудио (TTS/SSML). Аудиовыход включает только первый элемент списка. Мы не рекомендуем читать все элементы из списка.
Убедитесь, что ваше действие показывает то, что наиболее важно для ваших пользователей, вверху списка (например, самое популярное, недавно купленное или самое обсуждаемое). Первоначально в списке отображается до 10 элементов, но пользователи могут расширить список, чтобы отобразить больше элементов. Количество элементов, отображаемых в списке до расширения, также может меняться в зависимости от поверхности и времени.

Образец кода
Node.js
app.intent('List', (conv) => { if (!conv.screen) { conv.ask('Sorry, try this on a screen device or select the ' + 'phone surface in the simulator.'); return; } conv.ask('This is a list example.'); // Create a list conv.ask(new List({ title: 'List Title', items: { // Add the first item to the list 'SELECTION_KEY_ONE': { synonyms: [ 'synonym 1', 'synonym 2', 'synonym 3', ], title: 'Title of First List Item', description: 'This is a description of a list item.', image: new Image({ url: 'https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png', alt: 'Image alternate text', }), }, // Add the second item to the list 'SELECTION_KEY_GOOGLE_HOME': { synonyms: [ 'Google Home Assistant', 'Assistant on the Google Home', ], title: 'Google Home', description: 'Google Home is a voice-activated speaker powered by ' + 'the Google Assistant.', image: new Image({ url: 'https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png', alt: 'Google Home', }), }, // Add the third item to the list 'SELECTION_KEY_GOOGLE_PIXEL': { synonyms: [ 'Google Pixel XL', 'Pixel', 'Pixel XL', ], title: 'Google Pixel', description: 'Pixel. Phone by Google.', image: new Image({ url: 'https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png', alt: 'Google Pixel', }), }, }, })); });
Джава
@ForIntent("List") public ActionResponse list(ActionRequest request) { ResponseBuilder responseBuilder = getResponseBuilder(request); if (!request.hasCapability(Capability.SCREEN_OUTPUT.getValue())) { return responseBuilder .add("Sorry, try ths on a screen device or select the phone surface in the simulator.") .add("Which response would you like to see next?") .build(); } responseBuilder .add("This is a list example.") .add( new SelectionList() .setTitle("List Title") .setItems( Arrays.asList( new ListSelectListItem() .setTitle("Title of First List Item") .setDescription("This is a description of a list item.") .setImage( new Image() .setUrl( "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png") .setAccessibilityText("Image alternate text")) .setOptionInfo( new OptionInfo() .setSynonyms( Arrays.asList("synonym 1", "synonym 2", "synonym 3")) .setKey("SELECTION_KEY_ONE")), new ListSelectListItem() .setTitle("Google Home") .setDescription( "Google Home is a voice-activated speaker powered by the Google Assistant.") .setImage( new Image() .setUrl( "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png") .setAccessibilityText("Google Home")) .setOptionInfo( new OptionInfo() .setSynonyms( Arrays.asList( "Google Home Assistant", "Assistant on the Google Home")) .setKey("SELECTION_KEY_GOOGLE_HOME")), new ListSelectListItem() .setTitle("Google Pixel") .setDescription("Pixel. Phone by Google.") .setImage( new Image() .setUrl( "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png") .setAccessibilityText("Google Pixel")) .setOptionInfo( new OptionInfo() .setSynonyms( Arrays.asList("Google Pixel XL", "Pixel", "Pixel XL")) .setKey("SELECTION_KEY_GOOGLE_PIXEL"))))); return responseBuilder.build(); }
Node.js
if (!conv.screen) { conv.ask('Sorry, try this on a screen device or select the ' + 'phone surface in the simulator.'); return; } conv.ask('This is a list example.'); // Create a list conv.ask(new List({ title: 'List Title', items: { // Add the first item to the list 'SELECTION_KEY_ONE': { synonyms: [ 'synonym 1', 'synonym 2', 'synonym 3', ], title: 'Title of First List Item', description: 'This is a description of a list item.', image: new Image({ url: 'https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png', alt: 'Image alternate text', }), }, // Add the second item to the list 'SELECTION_KEY_GOOGLE_HOME': { synonyms: [ 'Google Home Assistant', 'Assistant on the Google Home', ], title: 'Google Home', description: 'Google Home is a voice-activated speaker powered by ' + 'the Google Assistant.', image: new Image({ url: 'https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png', alt: 'Google Home', }), }, // Add the third item to the list 'SELECTION_KEY_GOOGLE_PIXEL': { synonyms: [ 'Google Pixel XL', 'Pixel', 'Pixel XL', ], title: 'Google Pixel', description: 'Pixel. Phone by Google.', image: new Image({ url: 'https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png', alt: 'Google Pixel', }), }, }, }));
Джава
ResponseBuilder responseBuilder = getResponseBuilder(request); if (!request.hasCapability(Capability.SCREEN_OUTPUT.getValue())) { return responseBuilder .add("Sorry, try ths on a screen device or select the phone surface in the simulator.") .add("Which response would you like to see next?") .build(); } responseBuilder .add("This is a list example.") .add( new SelectionList() .setTitle("List Title") .setItems( Arrays.asList( new ListSelectListItem() .setTitle("Title of First List Item") .setDescription("This is a description of a list item.") .setImage( new Image() .setUrl( "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png") .setAccessibilityText("Image alternate text")) .setOptionInfo( new OptionInfo() .setSynonyms( Arrays.asList("synonym 1", "synonym 2", "synonym 3")) .setKey("SELECTION_KEY_ONE")), new ListSelectListItem() .setTitle("Google Home") .setDescription( "Google Home is a voice-activated speaker powered by the Google Assistant.") .setImage( new Image() .setUrl( "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png") .setAccessibilityText("Google Home")) .setOptionInfo( new OptionInfo() .setSynonyms( Arrays.asList( "Google Home Assistant", "Assistant on the Google Home")) .setKey("SELECTION_KEY_GOOGLE_HOME")), new ListSelectListItem() .setTitle("Google Pixel") .setDescription("Pixel. Phone by Google.") .setImage( new Image() .setUrl( "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png") .setAccessibilityText("Google Pixel")) .setOptionInfo( new OptionInfo() .setSynonyms( Arrays.asList("Google Pixel XL", "Pixel", "Pixel XL")) .setKey("SELECTION_KEY_GOOGLE_PIXEL"))))); return responseBuilder.build();
JSON
Обратите внимание, что приведенный ниже JSON описывает ответ веб-перехватчика.
{ "payload": { "google": { "expectUserResponse": true, "systemIntent": { "intent": "actions.intent.OPTION", "data": { "@type": "type.googleapis.com/google.actions.v2.OptionValueSpec", "listSelect": { "title": "List Title", "items": [ { "optionInfo": { "key": "SELECTION_KEY_ONE", "synonyms": [ "synonym 1", "synonym 2", "synonym 3" ] }, "description": "This is a description of a list item.", "image": { "url": "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png", "accessibilityText": "Image alternate text" }, "title": "Title of First List Item" }, { "optionInfo": { "key": "SELECTION_KEY_GOOGLE_HOME", "synonyms": [ "Google Home Assistant", "Assistant on the Google Home" ] }, "description": "Google Home is a voice-activated speaker powered by the Google Assistant.", "image": { "url": "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png", "accessibilityText": "Google Home" }, "title": "Google Home" }, { "optionInfo": { "key": "SELECTION_KEY_GOOGLE_PIXEL", "synonyms": [ "Google Pixel XL", "Pixel", "Pixel XL" ] }, "description": "Pixel. Phone by Google.", "image": { "url": "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png", "accessibilityText": "Google Pixel" }, "title": "Google Pixel" } ] } } }, "richResponse": { "items": [ { "simpleResponse": { "textToSpeech": "This is a list example." } } ] } } } }
JSON
Обратите внимание, что приведенный ниже JSON описывает ответ веб-перехватчика.
{ "expectUserResponse": true, "expectedInputs": [ { "possibleIntents": [ { "intent": "actions.intent.OPTION", "inputValueData": { "@type": "type.googleapis.com/google.actions.v2.OptionValueSpec", "listSelect": { "title": "List Title", "items": [ { "optionInfo": { "key": "SELECTION_KEY_ONE", "synonyms": [ "synonym 1", "synonym 2", "synonym 3" ] }, "description": "This is a description of a list item.", "image": { "url": "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png", "accessibilityText": "Image alternate text" }, "title": "Title of First List Item" }, { "optionInfo": { "key": "SELECTION_KEY_GOOGLE_HOME", "synonyms": [ "Google Home Assistant", "Assistant on the Google Home" ] }, "description": "Google Home is a voice-activated speaker powered by the Google Assistant.", "image": { "url": "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png", "accessibilityText": "Google Home" }, "title": "Google Home" }, { "optionInfo": { "key": "SELECTION_KEY_GOOGLE_PIXEL", "synonyms": [ "Google Pixel XL", "Pixel", "Pixel XL" ] }, "description": "Pixel. Phone by Google.", "image": { "url": "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png", "accessibilityText": "Google Pixel" }, "title": "Google Pixel" } ] } } } ], "inputPrompt": { "richInitialPrompt": { "items": [ { "simpleResponse": { "textToSpeech": "This is a list example." } } ] } } } ] }
Обработка выбранного элемента
Когда пользователи выбирают элемент, значение выбранного элемента передается вам в качестве аргумента. В значении аргумента вы получите идентификатор key
для выбранного элемента:
Node.js
app.intent('List - OPTION', (conv, params, option) => { const SELECTED_ITEM_RESPONSES = { 'SELECTION_KEY_ONE': 'You selected the first item', 'SELECTION_KEY_GOOGLE_HOME': 'You selected the Google Home!', 'SELECTION_KEY_GOOGLE_PIXEL': 'You selected the Google Pixel!', }; conv.ask(SELECTED_ITEM_RESPONSES[option]); conv.ask('Which response would you like to see next?'); });
Джава
@ForIntent("List - OPTION") public ActionResponse listSelected(ActionRequest request) { ResponseBuilder responseBuilder = getResponseBuilder(request); String selectedItem = request.getSelectedOption(); String response; if (selectedItem.equals("SELECTION_KEY_ONE")) { response = "You selected the first item"; } else if (selectedItem.equals("SELECTION_KEY_GOOGLE_HOME")) { response = "You selected the Google Home!"; } else if (selectedItem.equals("SELECTION_KEY_GOOGLE_PIXEL")) { response = "You selected the Google Pixel!"; } else { response = "You did not select a valid item"; } return responseBuilder.add(response).add("Which response would you like to see next?").build(); }
Node.js
app.intent('actions.intent.OPTION', (conv, params, option) => { const SELECTED_ITEM_RESPONSES = { 'SELECTION_KEY_ONE': 'You selected the first item', 'SELECTION_KEY_GOOGLE_HOME': 'You selected the Google Home!', 'SELECTION_KEY_GOOGLE_PIXEL': 'You selected the Google Pixel!', }; conv.ask(SELECTED_ITEM_RESPONSES[option]); conv.ask('Which response would you like to see next?'); });
Джава
@ForIntent("actions.intent.OPTION") public ActionResponse listSelected(ActionRequest request) { ResponseBuilder responseBuilder = getResponseBuilder(request); String selectedItem = request.getSelectedOption(); String response; if (selectedItem.equals("SELECTION_KEY_ONE")) { response = "You selected the first item"; } else if (selectedItem.equals("SELECTION_KEY_GOOGLE_HOME")) { response = "You selected the Google Home!"; } else if (selectedItem.equals("SELECTION_KEY_GOOGLE_PIXEL")) { response = "You selected the Google Pixel!"; } else { response = "You did not select a valid item"; } return responseBuilder.add(response).add("Which response would you like to see next?").build(); } public ActionResponse carousel(ActionRequest request) { ResponseBuilder responseBuilder = getResponseBuilder(request); if (!request.hasCapability(Capability.SCREEN_OUTPUT.getValue())) { return responseBuilder .add("Sorry, try ths on a screen device or select the phone surface in the simulator.") .add("Which response would you like to see next?") .build(); } responseBuilder .add("This is a carousel example.") .add( new SelectionCarousel() .setItems( Arrays.asList( new CarouselSelectCarouselItem() .setTitle("Title of First List Item") .setDescription("This is a description of a list item.") .setImage( new Image() .setUrl( "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png") .setAccessibilityText("Image alternate text")) .setOptionInfo( new OptionInfo() .setSynonyms( Arrays.asList("synonym 1", "synonym 2", "synonym 3")) .setKey("SELECTION_KEY_ONE")), new CarouselSelectCarouselItem() .setTitle("Google Home") .setDescription( "Google Home is a voice-activated speaker powered by the Google Assistant.") .setImage( new Image() .setUrl( "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png") .setAccessibilityText("Google Home")) .setOptionInfo( new OptionInfo() .setSynonyms( Arrays.asList( "Google Home Assistant", "Assistant on the Google Home")) .setKey("SELECTION_KEY_GOOGLE_HOME")), new CarouselSelectCarouselItem() .setTitle("Google Pixel") .setDescription("Pixel. Phone by Google.") .setImage( new Image() .setUrl( "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png") .setAccessibilityText("Google Pixel")) .setOptionInfo( new OptionInfo() .setSynonyms( Arrays.asList("Google Pixel XL", "Pixel", "Pixel XL")) .setKey("SELECTION_KEY_GOOGLE_PIXEL"))))); return responseBuilder.build(); } }
JSON
Обратите внимание, что приведенный ниже JSON описывает запрос веб-перехватчика.
{ "responseId": "5d7732d1-d22d-4a0e-ad34-8bc0a7fde20c-21947381", "queryResult": { "queryText": "actions_intent_OPTION", "action": "List.List-custom", "parameters": {}, "allRequiredParamsPresent": true, "fulfillmentText": "Webhook failed for intent: List - OPTION", "fulfillmentMessages": [ { "text": { "text": [ "Webhook failed for intent: List - OPTION" ] } } ], "outputContexts": [ { "name": "projects/df-responses-kohler/agent/sessions/ABwppHHsebncupHK11oKhsCTgyH96GRNYH-xpeeMTqb-cvOxbd67QenbRlZM4bGAIB8_KXdTfI7-7lYVKN1ovAhCaA/contexts/actions_capability_screen_output" }, { "name": "projects/df-responses-kohler/agent/sessions/ABwppHHsebncupHK11oKhsCTgyH96GRNYH-xpeeMTqb-cvOxbd67QenbRlZM4bGAIB8_KXdTfI7-7lYVKN1ovAhCaA/contexts/actions_capability_account_linking" }, { "name": "projects/df-responses-kohler/agent/sessions/ABwppHHsebncupHK11oKhsCTgyH96GRNYH-xpeeMTqb-cvOxbd67QenbRlZM4bGAIB8_KXdTfI7-7lYVKN1ovAhCaA/contexts/actions_capability_media_response_audio" }, { "name": "projects/df-responses-kohler/agent/sessions/ABwppHHsebncupHK11oKhsCTgyH96GRNYH-xpeeMTqb-cvOxbd67QenbRlZM4bGAIB8_KXdTfI7-7lYVKN1ovAhCaA/contexts/actions_capability_audio_output" }, { "name": "projects/df-responses-kohler/agent/sessions/ABwppHHsebncupHK11oKhsCTgyH96GRNYH-xpeeMTqb-cvOxbd67QenbRlZM4bGAIB8_KXdTfI7-7lYVKN1ovAhCaA/contexts/actions_capability_web_browser" }, { "name": "projects/df-responses-kohler/agent/sessions/ABwppHHsebncupHK11oKhsCTgyH96GRNYH-xpeeMTqb-cvOxbd67QenbRlZM4bGAIB8_KXdTfI7-7lYVKN1ovAhCaA/contexts/google_assistant_input_type_touch" }, { "name": "projects/df-responses-kohler/agent/sessions/ABwppHHsebncupHK11oKhsCTgyH96GRNYH-xpeeMTqb-cvOxbd67QenbRlZM4bGAIB8_KXdTfI7-7lYVKN1ovAhCaA/contexts/list-followup", "lifespanCount": 1 }, { "name": "projects/df-responses-kohler/agent/sessions/ABwppHHsebncupHK11oKhsCTgyH96GRNYH-xpeeMTqb-cvOxbd67QenbRlZM4bGAIB8_KXdTfI7-7lYVKN1ovAhCaA/contexts/actions_intent_option", "parameters": { "OPTION": "SELECTION_KEY_GOOGLE_PIXEL", "text": "Google Pixel" } } ], "intent": { "name": "projects/df-responses-kohler/agent/intents/88904350-193e-4472-a2de-977eb5d9e26e", "displayName": "List - OPTION" }, "intentDetectionConfidence": 1, "languageCode": "en" }, "originalDetectIntentRequest": { "source": "google", "version": "2", "payload": { "user": { "locale": "en-US", "lastSeen": "2019-08-04T23:56:32Z", "userVerificationStatus": "VERIFIED" }, "conversation": { "conversationId": "ABwppHHsebncupHK11oKhsCTgyH96GRNYH-xpeeMTqb-cvOxbd67QenbRlZM4bGAIB8_KXdTfI7-7lYVKN1ovAhCaA", "type": "ACTIVE", "conversationToken": "[\"list-followup\"]" }, "inputs": [ { "intent": "actions.intent.OPTION", "rawInputs": [ { "inputType": "TOUCH", "query": "Google Pixel" } ], "arguments": [ { "name": "OPTION", "textValue": "SELECTION_KEY_GOOGLE_PIXEL" }, { "name": "text", "rawText": "Google Pixel", "textValue": "Google Pixel" } ] } ], "surface": { "capabilities": [ { "name": "actions.capability.SCREEN_OUTPUT" }, { "name": "actions.capability.ACCOUNT_LINKING" }, { "name": "actions.capability.MEDIA_RESPONSE_AUDIO" }, { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.WEB_BROWSER" } ] }, "isInSandbox": true, "availableSurfaces": [ { "capabilities": [ { "name": "actions.capability.WEB_BROWSER" }, { "name": "actions.capability.SCREEN_OUTPUT" }, { "name": "actions.capability.AUDIO_OUTPUT" } ] } ], "requestType": "SIMULATOR" } }, "session": "projects/df-responses-kohler/agent/sessions/ABwppHHsebncupHK11oKhsCTgyH96GRNYH-xpeeMTqb-cvOxbd67QenbRlZM4bGAIB8_KXdTfI7-7lYVKN1ovAhCaA" }
JSON
Обратите внимание, что приведенный ниже JSON описывает запрос веб-перехватчика.
{ "user": { "locale": "en-US", "lastSeen": "2019-08-06T07:37:53Z", "userVerificationStatus": "VERIFIED" }, "conversation": { "conversationId": "ABwppHGcqunXh1M6IE0lu2sVqXdpJfdpC5FWMkMSXQskK1nzb4IkSUSRqQzoEr0Ly0z_G3mwyZlk5rFtd1w", "type": "NEW" }, "inputs": [ { "intent": "actions.intent.OPTION", "rawInputs": [ { "inputType": "TOUCH", "query": "Google Home" } ], "arguments": [ { "name": "OPTION", "textValue": "SELECTION_KEY_GOOGLE_HOME" }, { "name": "text", "rawText": "Google Home", "textValue": "Google Home" } ] } ], "surface": { "capabilities": [ { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.MEDIA_RESPONSE_AUDIO" }, { "name": "actions.capability.ACCOUNT_LINKING" }, { "name": "actions.capability.SCREEN_OUTPUT" }, { "name": "actions.capability.WEB_BROWSER" } ] }, "isInSandbox": true, "availableSurfaces": [ { "capabilities": [ { "name": "actions.capability.WEB_BROWSER" }, { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.SCREEN_OUTPUT" } ] } ], "requestType": "SIMULATOR" }
Карусель

Карусель прокручивается горизонтально и позволяет выбрать один элемент. По сравнению с селектором списка, он имеет большие плитки, что позволяет отображать более богатый контент. Тайлы, из которых состоит карусель, аналогичны базовой карточке с изображением. Выбор элемента из карусели генерирует всплывающее окно чата в качестве ответа, как и при выборе списка.
Характеристики
Тип ответа карусели имеет следующие требования и дополнительные свойства, которые вы можете настроить:
- Поддерживается на поверхностях с возможностью
actions.capability.SCREEN_OUTPUT
. - Карусель
- Максимум десять плиток.
- Минимум две плитки.
- Обычный текст, Markdown не поддерживается.
- Карусельная плитка
- Изображение (необязательно)
- Изображение принудительно должно быть 128 dp в высоту x 232 dp в ширину
- Если соотношение сторон изображения не соответствует ограничивающей рамке изображения, изображение центрируется с полосами по обеим сторонам.
- Если ссылка на изображение не работает, вместо нее используется изображение-заполнитель.
- Название (обязательно)
- То же, что и основная текстовая карточка
- Названия должны быть уникальными (для поддержки голосового выбора)
- Описание (необязательно)
- Те же параметры форматирования, что и для основной текстовой карты.
- Макс. 4 линии
- Обычный текст, Markdown не поддерживается.
- Изображение (необязательно)
- Взаимодействие
- Проведите пальцем влево/вправо: сдвиньте карусель, чтобы открыть разные карточки.
- Нажмите на карточку: при нажатии на элемент просто создается всплывающее окно чата с тем же текстом, что и заголовок элемента.
- Должен иметь намерение для сенсорного ввода, которое обрабатывает событие
actions_intent_OPTION
.
- Должен иметь намерение для сенсорного ввода, которое обрабатывает событие
- Голос/Клавиатура: Ответ с названием карты (если указано) работает так же, как и выбор этого элемента.
Руководство
Карусели хороши, когда пользователю представлены различные варианты, но между ними не требуется прямого сравнения (со списками). В общем, предпочитайте списки каруселям, потому что списки легче визуально просматривать и взаимодействовать с помощью голоса.
Если вы хотите создать карусель с элементами, которые ссылаются на веб-страницы, вы можете вместо этого создать карусель просмотра .
Мы рекомендуем добавить фишки предложений под каруселью, если вы хотите продолжить разговор.
Никогда не повторяйте варианты, представленные в списке в виде фишек-предложений. Фишки в этом контексте используются для поворота разговора (а не для выбора выбора).
Как и в случае списков, всплывающее окно чата, сопровождающее карусельную карточку, является подмножеством аудио (TTS/SSML). Аудио (TTS/SSML) здесь интегрирует первую плитку в карусели, и мы также настоятельно не рекомендуем читать все элементы из карусели. Лучше всего упомянуть первый элемент и причину его появления (например, самый популярный, самый последний купленный или самый обсуждаемый).

Образец кода
Node.js
app.intent('Carousel', (conv) => { if (!conv.screen) { conv.ask('Sorry, try this on a screen device or select the ' + 'phone surface in the simulator.'); return; } conv.ask('This is a carousel example.'); // Create a carousel conv.ask(new Carousel({ title: 'Carousel Title', items: { // Add the first item to the carousel 'SELECTION_KEY_ONE': { synonyms: [ 'synonym 1', 'synonym 2', 'synonym 3', ], title: 'Title of First Carousel Item', description: 'This is a description of a carousel item.', image: new Image({ url: 'https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png', alt: 'Image alternate text', }), }, // Add the second item to the carousel 'SELECTION_KEY_GOOGLE_HOME': { synonyms: [ 'Google Home Assistant', 'Assistant on the Google Home', ], title: 'Google Home', description: 'Google Home is a voice-activated speaker powered by ' + 'the Google Assistant.', image: new Image({ url: 'https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png', alt: 'Google Home', }), }, // Add the third item to the carousel 'SELECTION_KEY_GOOGLE_PIXEL': { synonyms: [ 'Google Pixel XL', 'Pixel', 'Pixel XL', ], title: 'Google Pixel', description: 'Pixel. Phone by Google.', image: new Image({ url: 'https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png', alt: 'Google Pixel', }), }, }, })); });
Джава
@ForIntent("Carousel") public ActionResponse carousel(ActionRequest request) { ResponseBuilder responseBuilder = getResponseBuilder(request); if (!request.hasCapability(Capability.SCREEN_OUTPUT.getValue())) { return responseBuilder .add("Sorry, try ths on a screen device or select the phone surface in the simulator.") .add("Which response would you like to see next?") .build(); } responseBuilder .add("This is a carousel example.") .add( new SelectionCarousel() .setItems( Arrays.asList( new CarouselSelectCarouselItem() .setTitle("Title of First List Item") .setDescription("This is a description of a list item.") .setImage( new Image() .setUrl( "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png") .setAccessibilityText("Image alternate text")) .setOptionInfo( new OptionInfo() .setSynonyms( Arrays.asList("synonym 1", "synonym 2", "synonym 3")) .setKey("SELECTION_KEY_ONE")), new CarouselSelectCarouselItem() .setTitle("Google Home") .setDescription( "Google Home is a voice-activated speaker powered by the Google Assistant.") .setImage( new Image() .setUrl( "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png") .setAccessibilityText("Google Home")) .setOptionInfo( new OptionInfo() .setSynonyms( Arrays.asList( "Google Home Assistant", "Assistant on the Google Home")) .setKey("SELECTION_KEY_GOOGLE_HOME")), new CarouselSelectCarouselItem() .setTitle("Google Pixel") .setDescription("Pixel. Phone by Google.") .setImage( new Image() .setUrl( "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png") .setAccessibilityText("Google Pixel")) .setOptionInfo( new OptionInfo() .setSynonyms( Arrays.asList("Google Pixel XL", "Pixel", "Pixel XL")) .setKey("SELECTION_KEY_GOOGLE_PIXEL"))))); return responseBuilder.build(); }
Node.js
if (!conv.screen) { conv.ask('Sorry, try this on a screen device or select the ' + 'phone surface in the simulator.'); return; } conv.ask('This is a carousel example.'); // Create a carousel conv.ask(new Carousel({ title: 'Carousel Title', items: { // Add the first item to the carousel 'SELECTION_KEY_ONE': { synonyms: [ 'synonym 1', 'synonym 2', 'synonym 3', ], title: 'Title of First Carousel Item', description: 'This is a description of a carousel item.', image: new Image({ url: 'https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png', alt: 'Image alternate text', }), }, // Add the second item to the carousel 'SELECTION_KEY_GOOGLE_HOME': { synonyms: [ 'Google Home Assistant', 'Assistant on the Google Home', ], title: 'Google Home', description: 'Google Home is a voice-activated speaker powered by ' + 'the Google Assistant.', image: new Image({ url: 'https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png', alt: 'Google Home', }), }, // Add the third item to the carousel 'SELECTION_KEY_GOOGLE_PIXEL': { synonyms: [ 'Google Pixel XL', 'Pixel', 'Pixel XL', ], title: 'Google Pixel', description: 'Pixel. Phone by Google.', image: new Image({ url: 'https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png', alt: 'Google Pixel', }), }, }, }));
Джава
ResponseBuilder responseBuilder = getResponseBuilder(request); if (!request.hasCapability(Capability.SCREEN_OUTPUT.getValue())) { return responseBuilder .add("Sorry, try ths on a screen device or select the phone surface in the simulator.") .add("Which response would you like to see next?") .build(); } responseBuilder .add("This is a carousel example.") .add( new SelectionCarousel() .setItems( Arrays.asList( new CarouselSelectCarouselItem() .setTitle("Title of First List Item") .setDescription("This is a description of a list item.") .setImage( new Image() .setUrl( "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png") .setAccessibilityText("Image alternate text")) .setOptionInfo( new OptionInfo() .setSynonyms( Arrays.asList("synonym 1", "synonym 2", "synonym 3")) .setKey("SELECTION_KEY_ONE")), new CarouselSelectCarouselItem() .setTitle("Google Home") .setDescription( "Google Home is a voice-activated speaker powered by the Google Assistant.") .setImage( new Image() .setUrl( "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png") .setAccessibilityText("Google Home")) .setOptionInfo( new OptionInfo() .setSynonyms( Arrays.asList( "Google Home Assistant", "Assistant on the Google Home")) .setKey("SELECTION_KEY_GOOGLE_HOME")), new CarouselSelectCarouselItem() .setTitle("Google Pixel") .setDescription("Pixel. Phone by Google.") .setImage( new Image() .setUrl( "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png") .setAccessibilityText("Google Pixel")) .setOptionInfo( new OptionInfo() .setSynonyms( Arrays.asList("Google Pixel XL", "Pixel", "Pixel XL")) .setKey("SELECTION_KEY_GOOGLE_PIXEL"))))); return responseBuilder.build();
JSON
Обратите внимание, что приведенный ниже JSON описывает запрос веб-перехватчика.
{ "payload": { "google": { "expectUserResponse": true, "systemIntent": { "intent": "actions.intent.OPTION", "data": { "@type": "type.googleapis.com/google.actions.v2.OptionValueSpec", "carouselSelect": { "items": [ { "optionInfo": { "key": "SELECTION_KEY_ONE", "synonyms": [ "synonym 1", "synonym 2", "synonym 3" ] }, "description": "This is a description of a carousel item.", "image": { "url": "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png", "accessibilityText": "Image alternate text" }, "title": "Title of First Carousel Item" }, { "optionInfo": { "key": "SELECTION_KEY_GOOGLE_HOME", "synonyms": [ "Google Home Assistant", "Assistant on the Google Home" ] }, "description": "Google Home is a voice-activated speaker powered by the Google Assistant.", "image": { "url": "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png", "accessibilityText": "Google Home" }, "title": "Google Home" }, { "optionInfo": { "key": "SELECTION_KEY_GOOGLE_PIXEL", "synonyms": [ "Google Pixel XL", "Pixel", "Pixel XL" ] }, "description": "Pixel. Phone by Google.", "image": { "url": "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png", "accessibilityText": "Google Pixel" }, "title": "Google Pixel" } ] } } }, "richResponse": { "items": [ { "simpleResponse": { "textToSpeech": "This is a carousel example." } } ] } } } }
JSON
Обратите внимание, что приведенный ниже JSON описывает запрос веб-перехватчика.
{ "expectUserResponse": true, "expectedInputs": [ { "possibleIntents": [ { "intent": "actions.intent.OPTION", "inputValueData": { "@type": "type.googleapis.com/google.actions.v2.OptionValueSpec", "carouselSelect": { "items": [ { "optionInfo": { "key": "SELECTION_KEY_ONE", "synonyms": [ "synonym 1", "synonym 2", "synonym 3" ] }, "description": "This is a description of a carousel item.", "image": { "url": "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png", "accessibilityText": "Image alternate text" }, "title": "Title of First Carousel Item" }, { "optionInfo": { "key": "SELECTION_KEY_GOOGLE_HOME", "synonyms": [ "Google Home Assistant", "Assistant on the Google Home" ] }, "description": "Google Home is a voice-activated speaker powered by the Google Assistant.", "image": { "url": "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png", "accessibilityText": "Google Home" }, "title": "Google Home" }, { "optionInfo": { "key": "SELECTION_KEY_GOOGLE_PIXEL", "synonyms": [ "Google Pixel XL", "Pixel", "Pixel XL" ] }, "description": "Pixel. Phone by Google.", "image": { "url": "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png", "accessibilityText": "Google Pixel" }, "title": "Google Pixel" } ] } } } ], "inputPrompt": { "richInitialPrompt": { "items": [ { "simpleResponse": { "textToSpeech": "This is a carousel example." } } ] } } } ] }
Обработка выбранного элемента
Когда пользователи выбирают элемент, значение выбранного элемента передается вам в качестве аргумента. В значении аргумента вы получите идентификатор key
для выбранного элемента:
Node.js
app.intent('Carousel - OPTION', (conv, params, option) => { const SELECTED_ITEM_RESPONSES = { 'SELECTION_KEY_ONE': 'You selected the first item', 'SELECTION_KEY_GOOGLE_HOME': 'You selected the Google Home!', 'SELECTION_KEY_GOOGLE_PIXEL': 'You selected the Google Pixel!', }; conv.ask(SELECTED_ITEM_RESPONSES[option]); conv.ask('Which response would you like to see next?'); });
Джава
@ForIntent("Carousel - OPTION") public ActionResponse carouselSelected(ActionRequest request) { ResponseBuilder responseBuilder = getResponseBuilder(request); String selectedItem = request.getSelectedOption(); String response; if (selectedItem.equals("SELECTION_KEY_ONE")) { response = "You selected the first item"; } else if (selectedItem.equals("SELECTION_KEY_GOOGLE_HOME")) { response = "You selected the Google Home!"; } else if (selectedItem.equals("SELECTION_KEY_GOOGLE_PIXEL")) { response = "You selected the Google Pixel!"; } else { response = "You did not select a valid item"; } return responseBuilder.add(response).add("Which response would you like to see next?").build(); }
Node.js
app.intent('actions.intent.OPTION', (conv, params, option) => { const SELECTED_ITEM_RESPONSES = { 'SELECTION_KEY_ONE': 'You selected the first item', 'SELECTION_KEY_GOOGLE_HOME': 'You selected the Google Home!', 'SELECTION_KEY_GOOGLE_PIXEL': 'You selected the Google Pixel!', }; conv.ask(SELECTED_ITEM_RESPONSES[option]); conv.ask('Which response would you like to see next?'); });
Джава
@ForIntent("actions.intent.OPTION") public ActionResponse listSelected(ActionRequest request) { ResponseBuilder responseBuilder = getResponseBuilder(request); String selectedItem = request.getSelectedOption(); String response; if (selectedItem.equals("SELECTION_KEY_ONE")) { response = "You selected the first item"; } else if (selectedItem.equals("SELECTION_KEY_GOOGLE_HOME")) { response = "You selected the Google Home!"; } else if (selectedItem.equals("SELECTION_KEY_GOOGLE_PIXEL")) { response = "You selected the Google Pixel!"; } else { response = "You did not select a valid item"; } return responseBuilder.add(response).add("Which response would you like to see next?").build(); } public ActionResponse carousel(ActionRequest request) { ResponseBuilder responseBuilder = getResponseBuilder(request); if (!request.hasCapability(Capability.SCREEN_OUTPUT.getValue())) { return responseBuilder .add("Sorry, try ths on a screen device or select the phone surface in the simulator.") .add("Which response would you like to see next?") .build(); } responseBuilder .add("This is a carousel example.") .add( new SelectionCarousel() .setItems( Arrays.asList( new CarouselSelectCarouselItem() .setTitle("Title of First List Item") .setDescription("This is a description of a list item.") .setImage( new Image() .setUrl( "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png") .setAccessibilityText("Image alternate text")) .setOptionInfo( new OptionInfo() .setSynonyms( Arrays.asList("synonym 1", "synonym 2", "synonym 3")) .setKey("SELECTION_KEY_ONE")), new CarouselSelectCarouselItem() .setTitle("Google Home") .setDescription( "Google Home is a voice-activated speaker powered by the Google Assistant.") .setImage( new Image() .setUrl( "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png") .setAccessibilityText("Google Home")) .setOptionInfo( new OptionInfo() .setSynonyms( Arrays.asList( "Google Home Assistant", "Assistant on the Google Home")) .setKey("SELECTION_KEY_GOOGLE_HOME")), new CarouselSelectCarouselItem() .setTitle("Google Pixel") .setDescription("Pixel. Phone by Google.") .setImage( new Image() .setUrl( "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png") .setAccessibilityText("Google Pixel")) .setOptionInfo( new OptionInfo() .setSynonyms( Arrays.asList("Google Pixel XL", "Pixel", "Pixel XL")) .setKey("SELECTION_KEY_GOOGLE_PIXEL"))))); return responseBuilder.build(); } }
JSON
Обратите внимание, что приведенный ниже JSON описывает запрос веб-перехватчика.
{ "responseId": "fd9c865a-e628-4e89-ae72-14a002361244-21947381", "queryResult": { "queryText": "actions_intent_OPTION", "action": "Carousel.Carousel-custom", "parameters": {}, "allRequiredParamsPresent": true, "fulfillmentText": "Webhook failed for intent: Carousel - OPTION", "fulfillmentMessages": [ { "text": { "text": [ "Webhook failed for intent: Carousel - OPTION" ] } } ], "outputContexts": [ { "name": "projects/df-responses-kohler/agent/sessions/ABwppHHsebncupHK11oKhsCTgyH96GRNYH-xpeeMTqb-cvOxbd67QenbRlZM4bGAIB8_KXdTfI7-7lYVKN1ovAhCaA/contexts/actions_capability_media_response_audio" }, { "name": "projects/df-responses-kohler/agent/sessions/ABwppHHsebncupHK11oKhsCTgyH96GRNYH-xpeeMTqb-cvOxbd67QenbRlZM4bGAIB8_KXdTfI7-7lYVKN1ovAhCaA/contexts/actions_capability_account_linking" }, { "name": "projects/df-responses-kohler/agent/sessions/ABwppHHsebncupHK11oKhsCTgyH96GRNYH-xpeeMTqb-cvOxbd67QenbRlZM4bGAIB8_KXdTfI7-7lYVKN1ovAhCaA/contexts/actions_capability_web_browser" }, { "name": "projects/df-responses-kohler/agent/sessions/ABwppHHsebncupHK11oKhsCTgyH96GRNYH-xpeeMTqb-cvOxbd67QenbRlZM4bGAIB8_KXdTfI7-7lYVKN1ovAhCaA/contexts/actions_capability_screen_output" }, { "name": "projects/df-responses-kohler/agent/sessions/ABwppHHsebncupHK11oKhsCTgyH96GRNYH-xpeeMTqb-cvOxbd67QenbRlZM4bGAIB8_KXdTfI7-7lYVKN1ovAhCaA/contexts/actions_capability_audio_output" }, { "name": "projects/df-responses-kohler/agent/sessions/ABwppHHsebncupHK11oKhsCTgyH96GRNYH-xpeeMTqb-cvOxbd67QenbRlZM4bGAIB8_KXdTfI7-7lYVKN1ovAhCaA/contexts/google_assistant_input_type_touch" }, { "name": "projects/df-responses-kohler/agent/sessions/ABwppHHsebncupHK11oKhsCTgyH96GRNYH-xpeeMTqb-cvOxbd67QenbRlZM4bGAIB8_KXdTfI7-7lYVKN1ovAhCaA/contexts/carousel-followup", "lifespanCount": 1 }, { "name": "projects/df-responses-kohler/agent/sessions/ABwppHHsebncupHK11oKhsCTgyH96GRNYH-xpeeMTqb-cvOxbd67QenbRlZM4bGAIB8_KXdTfI7-7lYVKN1ovAhCaA/contexts/actions_intent_option", "parameters": { "OPTION": "SELECTION_KEY_ONE", "text": "Title of First Carousel Item" } } ], "intent": { "name": "projects/df-responses-kohler/agent/intents/89289810-95e0-4dfd-a26a-b49a2ac51406", "displayName": "Carousel - OPTION" }, "intentDetectionConfidence": 1, "languageCode": "en" }, "originalDetectIntentRequest": { "source": "google", "version": "2", "payload": { "user": { "locale": "en-US", "lastSeen": "2019-08-04T23:59:37Z", "userVerificationStatus": "VERIFIED" }, "conversation": { "conversationId": "ABwppHHsebncupHK11oKhsCTgyH96GRNYH-xpeeMTqb-cvOxbd67QenbRlZM4bGAIB8_KXdTfI7-7lYVKN1ovAhCaA", "type": "ACTIVE", "conversationToken": "[\"carousel-followup\"]" }, "inputs": [ { "intent": "actions.intent.OPTION", "rawInputs": [ { "inputType": "TOUCH", "query": "Title of First Carousel Item" } ], "arguments": [ { "name": "OPTION", "textValue": "SELECTION_KEY_ONE" }, { "name": "text", "rawText": "Title of First Carousel Item", "textValue": "Title of First Carousel Item" } ] } ], "surface": { "capabilities": [ { "name": "actions.capability.MEDIA_RESPONSE_AUDIO" }, { "name": "actions.capability.ACCOUNT_LINKING" }, { "name": "actions.capability.WEB_BROWSER" }, { "name": "actions.capability.SCREEN_OUTPUT" }, { "name": "actions.capability.AUDIO_OUTPUT" } ] }, "isInSandbox": true, "availableSurfaces": [ { "capabilities": [ { "name": "actions.capability.WEB_BROWSER" }, { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.SCREEN_OUTPUT" } ] } ], "requestType": "SIMULATOR" } }, "session": "projects/df-responses-kohler/agent/sessions/ABwppHHsebncupHK11oKhsCTgyH96GRNYH-xpeeMTqb-cvOxbd67QenbRlZM4bGAIB8_KXdTfI7-7lYVKN1ovAhCaA" }
JSON
Обратите внимание, что приведенный ниже JSON описывает запрос веб-перехватчика.
{ "user": { "locale": "en-US", "lastSeen": "2019-08-06T07:37:15Z", "userVerificationStatus": "VERIFIED" }, "conversation": { "conversationId": "ABwppHGcqunXh1M6IE0lu2sVqXdpJfdpC5FWMkMSXQskK1nzb4IkSUSRqQzoEr0Ly0z_G3mwyZlk5rFtd1w", "type": "NEW" }, "inputs": [ { "intent": "actions.intent.OPTION", "rawInputs": [ { "inputType": "TOUCH", "query": "Google Home" } ], "arguments": [ { "name": "OPTION", "textValue": "SELECTION_KEY_GOOGLE_HOME" }, { "name": "text", "rawText": "Google Home", "textValue": "Google Home" } ] } ], "surface": { "capabilities": [ { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.MEDIA_RESPONSE_AUDIO" }, { "name": "actions.capability.WEB_BROWSER" }, { "name": "actions.capability.SCREEN_OUTPUT" }, { "name": "actions.capability.ACCOUNT_LINKING" } ] }, "isInSandbox": true, "availableSurfaces": [ { "capabilities": [ { "name": "actions.capability.WEB_BROWSER" }, { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.SCREEN_OUTPUT" } ] } ], "requestType": "SIMULATOR" }