Respuestas de selección visual (Dialogflow)

Explorar en Dialogflow

Haz clic en Continuar para importar nuestra muestra de respuestas en Dialogflow. Luego, sigue los pasos que se indican a continuación para implementar y probar la muestra:

  1. Ingresa un nombre de agente y crea un agente de Dialogflow nuevo para la muestra.
  2. Una vez que el agente termine de importar, haz clic en Ir al agente (Go to agent).
  3. En el menú de navegación principal, ve a Entrega.
  4. Habilita el Editor intercalado y, luego, haz clic en Implementar. El editor contiene el código de muestra.
  5. En el menú de navegación principal, ve a Integraciones y, luego, haz clic en Asistente de Google.
  6. En la ventana modal que aparece, habilita Auto-preview changes y haz clic en Test para abrir el simulador de Actions.
  7. En el simulador, ingresa Talk to my test app para probar la muestra.
Continuar

Usa una respuesta de selección visual si quieres que el usuario elija entre varias opciones para continuar con tu Acción.

Las respuestas de selección visual pueden aparecer en experiencias solo de pantalla o en experiencias que incorporen componentes de audio y pantalla.

Las respuestas de selección visual pueden contener los siguientes componentes:

También puedes revisar nuestros lineamientos de diseño de conversación para aprender a incorporar estos elementos visuales en tu acción.

Propiedades

Las respuestas de selección visual tienen los siguientes requisitos y propiedades opcionales que puedes configurar:

  • Compatible con plataformas con la capacidad actions.capability.SCREEN_OUTPUT.
  • El primer elemento de una respuesta de selección visual debe ser una respuesta simple.
  • Como máximo, una respuesta simple.
  • Como máximo, una tarjeta básica, una interfaz de opciones (list o carrusel) o StructuredResponse (No puedes tener una tarjeta básica y una interfaz de opciones al mismo tiempo).
  • Máximo 8 chips de sugerencias.
  • No se permiten chips de sugerencias en un FinalResponse.

En las siguientes secciones, se muestra cómo compilar varios tipos de respuestas de selección visual.

Ir a la lista

Figura 1: Ejemplo de lista (smartphone)

La lista de selección única presenta al usuario una lista vertical de varios elementos y le permite seleccionar uno solo. Cuando se selecciona un elemento de la lista, se genera una consulta del usuario (burbuja de chat) que contiene el título del elemento de la lista.

El tipo de respuesta de lista es compatible con plataformas con la función actions.capability.SCREEN_OUTPUT.

Propiedades

Las listas deben contener un mínimo de 2 y un máximo de 30 elementos. Las listas tienen las siguientes propiedades:

  • Título de la lista (opcional)
    • Fuente y tamaño de fuente fijos
    • Restringido a una sola línea. (Los caracteres excesivos aparecen truncados).
    • Texto sin formato; Markdown no es compatible.
    • Si no se especifica un título, la altura de la tarjeta se contrae.
  • Elemento de la lista
    • Título
      • Fuente y tamaño de fuente fijos
      • Longitud máxima: 1 línea (truncada con puntos suspensivos...)
      • Debe ser único (para admitir la selección de voz)
    • Descripción (opcional)
      • Fuente y tamaño de fuente fijos
      • Longitud máxima: 2 líneas (truncadas con puntos suspensivos...)
    • Imagen (opcional)
      • Tamaño: 48 x 48 px
  • Interacción
    • Voz/texto
      • El usuario siempre puede decir o escribir el título de un elemento en lugar de presionarlo.
      • Debe tener un intent para la entrada táctil que controle el evento actions_intent_OPTION.

Orientación

Las listas son útiles cuando es importante desambiguar opciones o cuando el usuario debe elegir entre opciones que deben analizarse de un vistazo. Por ejemplo, ¿con qué “Peter” necesitas hablar, Peter Jons o Peter Hans?

Recomendamos agregar chips de sugerencias debajo de una lista para permitir que el usuario gire o expanda la conversación. Nunca repitas las opciones presentadas en la lista como chips de sugerencias. En este contexto, los chips se usan para reorientar la conversación (no para la selección de opciones).

Ten en cuenta que, en el ejemplo adjunto, la burbuja de chat que acompaña a la tarjeta de lista es un subconjunto del audio (TTS/SSML). La salida de audio incluye solo el primer elemento de la lista. No recomendamos leer todos los elementos de la lista.

Asegúrate de que tu Acción muestre lo que es más importante para tus usuarios en la parte superior de la lista (por ejemplo, la más popular, la que la compraron recientemente o la que más se habló). Inicialmente, la lista muestra hasta 10 elementos, pero los usuarios pueden expandirla para mostrar más elementos. La cantidad de elementos que muestra la lista antes de la expansión también puede cambiar según la superficie y el tiempo.

Figura 2: Ejemplo de lista (pantalla inteligente)

Código de muestra

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',
        }),
      },
    },
  }));
});

Java

@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',
      }),
    },
  },
}));

Java

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

Ten en cuenta que el siguiente JSON describe una respuesta de webhook.

{
  "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

Ten en cuenta que el siguiente JSON describe una respuesta de webhook.

{
  "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."
              }
            }
          ]
        }
      }
    }
  ]
}

Manejo de un elemento seleccionado

Cuando los usuarios seleccionan un elemento, el valor del elemento seleccionado se te pasa como un argumento. En el valor del argumento, obtendrás el identificador key del elemento seleccionado:

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?');
});

Java

@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?');
});

Java

  @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

Ten en cuenta que el siguiente JSON describe una solicitud de webhook.

{
  "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

Ten en cuenta que el siguiente JSON describe una solicitud de webhook.

{
  "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"
}
Figura 3: Ejemplo de carrusel (smartphone)

El carrusel se desplaza horizontalmente y permite seleccionar un elemento. En comparación con el selector de lista, tiene mosaicos grandes, lo que permite contenido más enriquecido. Las tarjetas que conforman un carrusel son similares a la tarjeta básica con imagen. Cuando se selecciona un elemento del carrusel, se genera una burbuja de chat como respuesta, al igual que con el selector de listas.

Propiedades

El tipo de respuesta de carrusel tiene los siguientes requisitos y propiedades opcionales que puedes configurar:

  • Compatible con plataformas con la capacidad actions.capability.SCREEN_OUTPUT.
  • Carrusel
    • Máximo de diez mosaicos.
    • Dos mosaicos como mínimo.
    • Texto sin formato; Markdown no es compatible.
  • Mosaico de carrusel
    • Imagen (opcional)
      • La imagen debe tener 128 dp de alto x 232 dp de ancho
      • Si la relación de aspecto de la imagen no coincide con el cuadro de límite de la imagen, se centrará con barras a ambos lados.
      • Si el vínculo de una imagen se rompe, se usa una imagen de marcador de posición en su lugar.
    • Título (obligatorio)
      • Igual que la tarjeta de texto básica
      • Los títulos deben ser únicos (para admitir la selección de voz)
    • Descripción (opcional)
      • Tiene las mismas opciones de formato que la tarjeta de texto básica.
      • Máx. 4 líneas
      • Texto sin formato; Markdown no es compatible.
  • Interacción
    • Desliza el dedo hacia la izquierda o la derecha: Desliza el carrusel para ver diferentes tarjetas.
    • Tarjeta de toque: Cuando se presiona un elemento, simplemente se genera una burbuja de chat con el mismo texto que el título del elemento.
      • Debe tener un intent para la entrada táctil que controle el evento actions_intent_OPTION.
    • Voz o teclado: Responder con el título de la tarjeta (si se especifica) funciona de la misma manera que seleccionar ese elemento.

Orientación

Los carruseles funcionan cuando se presentan varias opciones al usuario, pero no se requiere una comparación directa entre ellas (en comparación con las listas). En general, es preferible utilizar las listas antes que los carruseles, ya que es más fácil escanearlas visualmente y, además, interactuar con ellas por voz.

Si deseas crear un carrusel con elementos que vinculan a páginas web, te recomendamos crear un carrusel de navegación en su lugar.

Recomendamos agregar chips de sugerencias debajo del carrusel si deseas continuar la conversación.

Nunca repitas las opciones presentadas en la lista como chips de sugerencias. En este contexto, los chips se usan para reorientar la conversación (no para la selección de opciones).

Al igual que con las listas, la burbuja de chat que acompaña a la tarjeta del carrusel es un subconjunto de audio (TTS/SSML). El audio (TTS/SSML) aquí integra la primera tarjeta en el carrusel, y no recomendamos leer todos los elementos de este. Es mejor mencionar el primer elemento y el motivo por el que está allí (por ejemplo, el más popular, el que se compró más recientemente o el más comentado).

Código de muestra

Controla el elemento seleccionado

Cuando los usuarios seleccionan un elemento, el valor del elemento seleccionado se te pasa como un argumento. En el valor del argumento, obtendrás el identificador key del elemento seleccionado:

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?');
});

Java

@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?');
});

Java

  @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

Ten en cuenta que el siguiente JSON describe una solicitud de webhook.

{
  "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

Ten en cuenta que el siguiente JSON describe una solicitud de webhook.

{
  "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"
}