Cómo representar una lista devuelta desde un webhook

Nov 06 2020

Estoy usando Google Actions. Estoy devolviendo JSON de mi webhook y recibo el siguiente error cuando pruebo mi acción en el simulador:

"No se pudo procesar la solicitud de lista o colección debido a que falta la anulación de tipo para un espacio. Nota, la lista y la colección solo deben usarse en el llenado de espacios. Debe haber una anulación de tipo correspondiente que describa cómo renderizar la lista o colección para este tipo. "

El JSON es una muestra ligeramente modificada tomada de documentos en https://developers.google.com/assistant/conversational/prompts-selection.

El nombre de typeOverrides 'elementos' coincide con un nombre de ranura para la escena.

Aquí está la solicitud de webhook y la respuesta JSON.

*** SOLICITUD ***

 {
  "handler": {
    "name": "aa"
  },
  "intent": {
    "name": "searchIntent",
    "params": {
      "searchParm": {
        "original": "milk",
        "resolved": "milk"
      }
    },
    "query": "milk"
  },
  "scene": {
    "name": "Start",
    "slotFillingStatus": "UNSPECIFIED",
    "slots": {},
    "next": {
      "name": "SearchScene"
    }
  },
  "session": {
    "id": "ABwppHGln0UTzfUPqJ1SMr1Cuw2TyPjJQoGUkULazcObus3vUwJCJCpba--5PSRwjqMQelRqMAUnwPvl",
    "params": {},
    "typeOverrides": [],
    "languageCode": ""
  },
  "user": {
    "locale": "en-AU",
    "params": {},
    "accountLinkingStatus": "ACCOUNT_LINKING_STATUS_UNSPECIFIED",
    "verificationStatus": "VERIFIED",
    "packageEntitlements": [],
    "lastSeenTime": "2020-11-05T21:24:16Z"
  },
  "home": {
    "params": {}
  },
  "device": {
    "capabilities": [
      "SPEECH",
      "RICH_RESPONSE",
      "LONG_FORM_AUDIO"
    ]
  }
}

*** RESPUESTA ***

{
  "session": {
    "id": "ABwppHGln0UTzfUPqJ1SMr1Cuw2TyPjJQoGUkULazcObus3vUwJCJCpba--5PSRwjqMQelRqMAUnwPvl",
    "params": {},
    "typeOverrides": [
      {
        "name": "items",
        "synonym": {
          "entries": [
            {
              "name": "ITEM_1",
              "synonyms": [
                "Item 1",
                "First item"
              ],
              "display": {
                "title": "Item #1",
                "description": "Description of Item #1",
                "image": {
                  "alt": "Google Assistant logo",
                  "height": 0,
                  "url": "https://developers.google.com/assistant/assistant_96.png",
                  "width": 0
                }
              }
            },
            {
              "name": "ITEM_2",
              "synonyms": [
                "Item 2",
                "Second item"
              ],
              "display": {
                "title": "Item #2",
                "description": "Description of Item #2",
                "image": {
                  "alt": "Google Assistant logo",
                  "height": 0,
                  "url": "https://developers.google.com/assistant/assistant_96.png",
                  "width": 0
                }
              }
            },
            {
              "name": "ITEM_3",
              "synonyms": [
                "Item 3",
                "Third item"
              ],
              "display": {
                "title": "Item #3",
                "description": "Description of Item #3",
                "image": {
                  "alt": "Google Assistant logo",
                  "height": 0,
                  "url": "https://developers.google.com/assistant/assistant_96.png",
                  "width": 0
                }
              }
            },
            {
              "name": "ITEM_4",
              "synonyms": [
                "Item 4",
                "Fourth item"
              ],
              "display": {
                "title": "Item #4",
                "description": "Description of Item #4",
                "image": {
                  "alt": "Google Assistant logo",
                  "height": 0,
                  "url": "https://developers.google.com/assistant/assistant_96.png",
                  "width": 0
                }
              }
            }
          ]
        },
        "typeOverrideMode": "TYPE_REPLACE"
      }
    ]
  },
  "prompt": {
    "override": false,
    "content": {
      "list": {
        "items": [
          {
            "key": "ITEM_1"
          },
          {
            "key": "ITEM_2"
          },
          {
            "key": "ITEM_3"
          },
          {
            "key": "ITEM_4"
          }
        ],
        "subtitle": "List subtitle",
        "title": "List title"
      }
    },
    "firstSimple": {
      "speech": "This is a list.",
      "text": "This is a list."
    }
  }
}

Respuestas

Prisoner Nov 06 2020 at 18:39

El nombre de TypeOverride debe coincidir con el tipo de la ranura, no con el nombre de la ranura.

CarlosHerrera Nov 27 2020 at 14:39

Comparto con todos ustedes la solución para esto.

Es cierto que la documentación omite ciertas partes para que esto funcione, pero si prestamos atención a leerlo y seguirlo al pie de la letra realmente funciona.

Una vez que tenemos nuestro proyecto Actions Builder, lo primero que hacemos es crear una entidad en la sección de tipos. Solo eso, no necesitamos agregar entradas o valores, solo crear el tipo.

El siguiente paso es preparar el escenario donde mostraremos nuestra colección. En este caso creé uno llamado INTRO.

Aquí es donde tienes el error. Está intentando mostrar la colección en el webhook que se activa cuando ingresa a la escena. No hay que colocar nada allí, debe estar vacío.

El siguiente paso es agregar el tipo de ranura y un nombre. También debemos configurar 2 cosas más, una es hacer obligatoria dicha ranura y la otra es activar la casilla de verificación para que llame a nuestro manejador que se encarga de pintar la colección.

Si se da cuenta, nombré la ranura: type_option y es de tipo prompt_type , es decir, el tipo que declaré en el primer paso. Luego marqué ese espacio como requerido y finalmente lo activé para llamar al controlador llamado LaunchRequest que está en mi webhook.

Ahora veamos el código.

const LaunchRequestHandler = app => {

  app.handle('LaunchRequest', conv => {
    conv.session.typeOverrides = [
      {
        name: 'prompt_option', // We reference the type of slot, not the name
        mode: 'TYPE_REPLACE',
        synonym: {
          entries: [
            {
              name: 'ITEM_1',
              synonyms: ['Item 1', 'First item'],
              display: {
                title: 'Element 1',
                description: 'This is the element 1',
                image: new Image({
                  url: '<YOUR URL>',
                  alt: 'example'
                })
              }
            },
            {
              name: 'ITEM_2',
              synonyms: ['Item 2', 'Second item'],
              display: {
                title: 'Element 2',
                description: 'This is the element 2',
                image: new Image({
                  url: '<YOUR URL>',
                  alt: 'example 2'
                })
              }
            }
          ]
        }
      }
    ];

    const items = [{ key: 'ITEM_1' }, { key: 'ITEM_2' }]

    conv.add(new Collection({ title: '<YOUR TITLE>', subtitle: '<YOUR SUBTITLE>', items }))
  })
}

Este es el fragmento de código que configuramos para que se llame cuando queramos presentar la colección. Si miramos de cerca, nos referimos al tipo, no al nombre de la ranura.

Con esto, todo debería funcionar, si hacemos la prueba desde el simulador. Todo es perfecto.

Espero que mi ayuda te haya servido bien.