Вебхуки

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

  • Создание динамического запроса на основе информации, предоставленной пользователем.
  • Размещение заказа во внешней системе и подтверждение успешного выполнения.
  • Проверка слотов с использованием данных из бэкэнда.
Рисунок 1. Интенты и сценарии вызова могут запускать веб-хуки.

Триггеры и обработчики веб-хуков

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

  • После совпадения намерений вызова
  • Во время сцены на входе на сцену
  • После того, как условие на этапе определения условий сцены становится истинным,
  • На этапе заполнения слотов в сцене
  • После того, как совпадение намерений происходит на этапе ввода сцены

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

Полезная нагрузка

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

Пример запроса

{
  "handler": {
    "name": "handler_name"
  },
  "intent": {
    "name": "actions.intent.MAIN",
    "params": {},
    "query": ""
  },
  "scene": {
    "name": "SceneName",
    "slotFillingStatus": "UNSPECIFIED",
    "slots": {}
  },
  "session": {
    "id": "example_session_id",
    "params": {},
    "typeOverrides": []
  },
  "user": {
    "locale": "en-US",
    "params": {
      "verificationStatus": "VERIFIED"
    }
  },
  "home": {
    "params": {}
  },
  "device": {
    "capabilities": [
      "SPEECH",
      "RICH_RESPONSE",
      "LONG_FORM_AUDIO"
    ]
  }
}

Пример ответа

{
  "session": {
    "id": "example_session_id",
    "params": {}
  },
  "prompt": {
    "override": false,
    "firstSimple": {
      "speech": "Hello World.",
      "text": ""
    }
  },
  "scene": {
    "name": "SceneName",
    "slots": {},
    "next": {
      "name": "actions.scene.END_CONVERSATION"
    }
  }
}

Взаимодействие во время выполнения

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

Отправляйте подсказки

С помощью Interactive Canvas вы можете создавать подсказки с простым текстом, форматированным текстом, карточками и даже полноценными HTML-подсказками, поддерживаемыми веб-приложением. В документации по подсказкам содержится полная информация о том, как создать подсказку при обработке события веб-перехватчика. Следующие фрагменты кода демонстрируют подсказку в виде карточки:

Node.js

app.handle('rich_response', conv => {
  conv.add('This is a card rich response.');
  conv.add(new Card({
    title: 'Card Title',
    subtitle: 'Card Subtitle',
    text: 'Card Content',
    image: new Image({
      url: 'https://developers.google.com/assistant/assistant_96.png',
      alt: 'Google Assistant logo'
    })
  }));
});

Ответ в формате JSON

{
  "session": {
    "id": "example_session_id",
    "params": {}
  },
  "prompt": {
    "override": false,
    "content": {
      "card": {
        "title": "Card Title",
        "subtitle": "Card Subtitle",
        "text": "Card Content",
        "image": {
          "alt": "Google Assistant logo",
          "height": 0,
          "url": "https://developers.google.com/assistant/assistant_96.png",
          "width": 0
        }
      }
    },
    "firstSimple": {
      "speech": "This is a card rich response.",
      "text": ""
    }
  }
}

Прочтение параметров намерения

Когда среда выполнения Assistant находит совпадение с намерением, она извлекает все определенные параметры. Исходное свойство — это то, что пользователь предоставил в качестве входных данных, а разрешенное свойство — это то, во что NLU преобразовал входные данные на основе спецификации типа.

Node.js

conv.intent.params['param_name'].original
conv.intent.params['param_name'].resolved

Запрос в формате JSON

{
  "handler": {
    "name": "handler_name"
  },
  "intent": {
    "name": "intent_name",
    "params": {
      "slot_name": {
        "original": "1",
        "resolved": 1
      }
    },
    "query": ""
  },
  "scene": {
    "name": "SceneName",
    "slotFillingStatus": "UNSPECIFIED",
    "slots": {},
    "next": {
      "name": "actions.scene.END_CONVERSATION"
    }
  },
  "session": {
    "id": "session_id",
    "params": {},
    "typeOverrides": []
  },
  "user": {
    "locale": "en-US",
    "params": {
      "verificationStatus": "VERIFIED"
    }
  },
  "home": {
    "params": {}
  },
  "device": {
    "capabilities": [
      "SPEECH",
      "RICH_RESPONSE",
      "LONG_FORM_AUDIO"
    ]
  }
}

Прочитать локаль пользователя

Это значение соответствует языковым настройкам пользователя для Google Ассистента.

Node.js

conv.user.locale

JSON

{
  "handler": {
    "name": "handler_name"
  },
  "intent": {
    "name": "actions.intent.MAIN",
    "params": {},
    "query": ""
  },
  "scene": {
    "name": "SceneName",
    "slotFillingStatus": "UNSPECIFIED",
    "slots": {}
  },
  "session": {
    "id": "session_id",
    "params": {},
    "typeOverrides": []
  },
  "user": {
    "locale": "en-US",
    "params": {
      "verificationStatus": "VERIFIED"
    }
  },
  "home": {
    "params": {}
  },
  "device": {
    "capabilities": [
      "SPEECH",
      "RICH_RESPONSE",
      "LONG_FORM_AUDIO"
    ]
  }
}

хранилище для чтения и записи

Полную информацию об использовании различных функций хранилища см. в документации по хранилищу .

Node.js

//read
conv.session.params.key
conv.user.params.key
conv.home.params.key

// write
conv.session.params.key = value
conv.user.params.key = value
conv.home.params.key = value 

Запрос в формате JSON

{
  "handler": {
    "name": "handler_name"
  },
  "intent": {
    "name": "actions.intent.MAIN",
    "params": {},
    "query": ""
  },
  "scene": {
    "name": "SceneName",
    "slotFillingStatus": "UNSPECIFIED",
    "slots": {}
  },
  "session": {
    "id": "session_id",
    "params": {
      "key": "value"
    },
    "typeOverrides": [],
    "languageCode": ""
  },
  "user": {
    "locale": "en-US",
    "params": {
      "verificationStatus": "VERIFIED",
      "key": "value"
    }
  },
  "home": {
    "params": {
      "key": "value"
    }
  },
  "device": {
    "capabilities": [
      "SPEECH",
      "RICH_RESPONSE",
      "LONG_FORM_AUDIO"
    ]
  }
}

Ответ в формате JSON

{
  "session": {
    "id": "session_id",
    "params": {
      "key": "value"
    }
  },
  "prompt": {
    "override": false,
    "firstSimple": {
      "speech": "Hello world.",
      "text": ""
    }
  },
  "user": {
    "locale": "en-US",
    "params": {
      "verificationStatus": "VERIFIED",
      "key": "value"
    }
  },
  "home": {
    "params": {
      "key": "value"
    }
  }
}

Проверьте возможности устройства

Вы можете проверить возможности устройства для предоставления различных вариантов взаимодействия или сценариев общения.

Node.js

const supportsRichResponse = conv.device.capabilities.includes("RICH_RESPONSE");
const supportsLongFormAudio = conv.device.capabilities.includes("LONG_FORM_AUDIO");
const supportsSpeech = conv.device.capabilities.includes("SPEECH");
const supportsInteractiveCanvas = conv.device.capabilities.includes("INTERACTIVE_CANVAS");

Запрос в формате JSON

{
  "handler": {
    "name": "handler_name"
  },
  "intent": {
    "name": "actions.intent.MAIN",
    "params": {},
    "query": ""
  },
  "scene": {
    "name": "SceneName",
    "slotFillingStatus": "UNSPECIFIED",
    "slots": {}
  },
  "session": {
    "id": "session_id",
    "params": {},
    "typeOverrides": [],
    "languageCode": ""
  },
  "user": {
    "locale": "en-US",
    "params": {
      "verificationStatus": "VERIFIED"
    }
  },
  "home": {
    "params": {}
  },
  "device": {
    "capabilities": [
      "SPEECH",
      "RICH_RESPONSE",
      "LONG_FORM_AUDIO",
      "INTERACTIVE_CANVAS"
    ]
  }
}

Полный перечень возможностей надводных систем см. в справочнике Capability .

Переопределение типов во время выполнения

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

Для использования типов времени выполнения необходимо запустить веб-хук из вашего действия, который вызовет обработчик в вашем запросе на выполнение. После этого вы можете заполнить параметр session.typeOverrides в ответе, отправленном вашему действию. Доступные режимы включают TYPE_MERGE для сохранения существующих записей типов или TYPE_REPLACE для замены существующих записей переопределениями.

Node.js

conv.session.typeOverrides = [{
    name: type_name,
    mode: 'TYPE_REPLACE',
    synonym: {
      entries: [
        {
          name: 'ITEM_1',
          synonyms: ['Item 1', 'First item']
        },
        {
          name: 'ITEM_2',
          synonyms: ['Item 2', 'Second item']
       },
       {
          name: 'ITEM_3',
          synonyms: ['Item 3', 'Third item']
        },
        {
          name: 'ITEM_4',
          synonyms: ['Item 4', 'Fourth item']
        },
    ]
  }
}];

Ответ в формате JSON

{
  "session": {
    "id": "session_id",
    "params": {},
    "typeOverrides": [
      {
        "name": "type_name",
        "synonym": {
          "entries": [
            {
              "name": "ITEM_1",
              "synonyms": [
                "Item 1",
                "First item"
              ]
            },
            {
              "name": "ITEM_2",
              "synonyms": [
                "Item 2",
                "Second item"
              ]
            },
            {
              "name": "ITEM_3",
              "synonyms": [
                "Item 3",
                "Third item"
              ]
            },
            {
              "name": "ITEM_4",
              "synonyms": [
                "Item 4",
                "Fourth item"
              ]
            }
          ]
        },
        "typeOverrideMode": "TYPE_REPLACE"
      }
    ]
  },
  "prompt": {
    "override": false,
    "firstSimple": {
      "speech": "This is an example prompt.",
      "text": "This is an example prompt."
    }
  }
}

Обеспечьте предвзятость в высказываниях.

Функция смещения речи позволяет задавать подсказки для системы обработки естественного языка (NLU) для улучшения сопоставления намерений. Можно указать до 1000 записей.

Node.js

conv.expected.speech = ['value_1', 'value_2']
conv.expected.language = 'locale_string'

Ответ в формате JSON

{
  "session": {
    "id": "session_id",
    "params": {}
  },
  "prompt": {
    "override": false,
    "firstSimple": {
      "speech": "This is an example prompt.",
      "text": "This is an example prompt."
    }
  },
  "expected": {
    "speech": "['value_1', 'value_2']",
    "language": "locale_string"
  }
}

Переходные сцены

Помимо определения статических переходов в вашем проекте Actions, вы можете настроить переходы между сценами во время выполнения.

Node.js

app.handle('transition_to_hidden_scene', conv => {
  // Dynamic transition
  conv.scene.next.name = "HiddenScene";
});

Ответ в формате JSON

{
  "session": {
    "id": "session_id",
    "params": {}
  },
  "prompt": {
    "override": false,
    "firstSimple": {
      "speech": "This is an example prompt.",
      "text": ""
    }
  },
  "scene": {
    "name": "SceneName",
    "slots": {},
    "next": {
      "name": "HiddenScene"
    }
  }
}

Прочитайте слоты сцен.

В процессе заполнения слота вы можете использовать функцию проверки выполнения для подтверждения слота или проверки статуса заполнения слота ( SlotFillingStatus ).

Node.js

conv.scene.slotFillingStatus  // FINAL means all slots are filled
conv.scene.slots  // Object that contains all the slots
conv.scene.slots['slot_name'].<property_name> // Accessing a specific slot's properties

Например, предположим, вы хотите извлечь часовой пояс из ответа. В этом примере имя слота — datetime1 . Чтобы получить часовой пояс, вы бы использовали:

conv.scene.slots['datetime1'].value.time_zone.id

Запрос в формате JSON

{
  "handler": {
    "name": "handler_name"
  },
  "intent": {
    "name": "",
    "params": {
      "slot_name": {
        "original": "1",
        "resolved": 1
      }
    },
    "query": ""
  },
  "scene": {
    "name": "SceneName",
    "slotFillingStatus": "FINAL",
    "slots": {
      "slot_name": {
        "mode": "REQUIRED",
        "status": "SLOT_UNSPECIFIED",
        "updated": true,
        "value": 1
      }
    },
    "next": {
      "name": "actions.scene.END_CONVERSATION"
    }
  },
  "session": {
    "id": "session_id",
    "params": {
      "slot_name": 1
    },
    "typeOverrides": []
  },
  "user": {
    "locale": "en-US",
    "params": {
      "verificationStatus": "VERIFIED"
    }
  },
  "home": {
    "params": {}
  },
  "device": {
    "capabilities": [
      "SPEECH",
      "RICH_RESPONSE",
      "LONG_FORM_AUDIO"
    ]
  }
}

Аннулировать слоты сцен

Вы можете сделать слоты недействительными и попросить пользователя ввести новое значение.

Node.js

conv.scene.slots['slot_name'].status = 'INVALID'

Ответ в формате JSON

{
  "session": {
    "id": "session_id",
    "params": {
      "slot_name": 1
    }
  },
  "prompt": {
    "override": false,
    "firstSimple": {
      "speech": "This is an example prompt.",
      "text": ""
    }
  },
  "scene": {
    "name": "SceneName",
    "slots": {
      "slot_name": {
        "mode": "REQUIRED",
        "status": "INVALID",
        "updated": true,
        "value": 1
      }
    },
    "next": {
      "name": "actions.scene.END_CONVERSATION"
    }
  }
}

Варианты развития

Actions Builder предоставляет встроенный редактор, называемый редактором облачных функций , который позволяет создавать и развертывать облачные функции для Firebase непосредственно в консоли. Вы также можете создавать и развертывать функции обработки запросов на выбранном вами хостинге и регистрировать конечную точку обработки HTTPS в качестве обработчика веб-хуков.

Встроенный редактор

Для разработки с использованием редактора Cloud Functions:

  1. Создайте файл sdk/webhooks/ActionsOnGoogleFulfillment.yaml и определите обработчики для вашего действия и встроенной облачной функции, используемой для выполнения запроса.
    handlers:
    - name: questionOnEnterFunc
    - name: fruitSlotValidationFunc
    inlineCloudFunction:
      executeFunction: ActionsOnGoogleFulfillment
        
  2. Создайте папку sdk/webhooks/ActionsOnGoogleFulfillment и добавьте в неё файл index.js , реализующий ранее определённые обработчики, а также файл package.json , определяющий требования npm для вашего кода.
    // index.js
    const {conversation} = require('@assistant/conversation');
    const functions = require('firebase-functions');
    
    const app = conversation();
    
    app.handle('questionOnEnterFunc', conv => {
      conv.add('questionOnEnterFunc triggered on webhook');
    });
    
    app.handle('fruitSlotValidationFunc', conv => {
      conv.add('fruitSlotValidationFunc triggered on webhook');
    });
    
    exports.ActionsOnGoogleFulfillment = functions.https.onRequest(app);
        
    // package.json
    {
      "name": "ActionsOnGoogleFulfillment",
      "version": "0.1.0",
      "description": "Actions on Google fulfillment",
      "main": "index.js",
      "dependencies": {
        "@assistant/conversation": "^3.0.0",
        "firebase-admin": "^5.4.3",
        "firebase-functions": "^0.7.1"
      }
    }
        

Внешняя HTTPS-конечная точка

В этом разделе описывается, как настроить Cloud Functions для Firebase в качестве службы выполнения запросов для вашего диалогового действия. Однако вы можете развернуть службу выполнения запросов на любом хостинге по вашему выбору.

Настройка среды

При использовании Cloud Functions для Firebase в качестве сервиса выполнения заказов мы рекомендуем следующую структуру проекта:

ProjectFolder        - Root folder for the project
  sdk                - Actions project configuration files
  functions          - Cloud functions for Firebase files

Для настройки среды выполните следующие шаги:

  1. Скачайте и установите Node.js.
  2. Настройте и инициализируйте Firebase CLI. Если следующая команда завершится ошибкой EACCES , возможно, потребуется изменить права доступа npm .

    npm install -g firebase-tools
    
  3. Аутентифицируйте инструмент Firebase с помощью своей учетной записи Google:

    firebase login
    
  4. Запустите каталог проекта, в котором вы сохранили свой проект Actions . Вам будет предложено выбрать, какие функции Firebase CLI вы хотите настроить для своего проекта Actions. Выберите Functions и другие функции, которые вы, возможно, захотите использовать, например Firestore, затем нажмите Enter для подтверждения и продолжения:

    $ cd <ACTIONS_PROJECT_DIRECTORY>
    $ firebase init
    
  5. Свяжите инструмент Firebase с вашим проектом Actions, выбрав его с помощью клавиш со стрелками для навигации по списку проектов:

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

    === Functions Setup
    A functions directory will be created in your project with a Node.js
    package pre-configured. Functions can be deployed with firebase deploy.
    
    ? What language would you like to use to write Cloud Functions? (Use arrow keys)
    > JavaScript
    TypeScript
    
  7. Выберите, хотите ли вы использовать ESLint для обнаружения вероятных ошибок и обеспечения правильного стиля ввода, набрав Y или N :

    ? Do you want to use ESLint to catch probable bugs and enforce style? (Y/n)
  8. Чтобы получить зависимости проекта, введите Y в командной строке:

    ? Do you want to install dependencies with npm now? (Y/n)

    После завершения настройки вы увидите результат, похожий на следующий:

    ✔  Firebase initialization complete!
    
  9. Установите зависимость @assistant/conversation :

    $ cd <ACTIONS_PROJECT_DIRECTORY>/functions
    $ npm install @assistant/conversation --save
    
  10. Получите зависимости для выполнения и разверните функцию выполнения:

    $ npm install
    $ firebase deploy --only functions
    

    Развертывание займет несколько минут. После завершения вы увидите результат, похожий на следующий. Вам потребуется ввести URL-адрес функции в Dialogflow.

    ✔  Deploy complete!
    Project Console: https://console.firebase.google.com/project/<PROJECT_ID>/overview Function URL (<FUNCTION_NAME>): https://us-central1-<PROJECT_ID>.cloudfunctions.net/<FUNCTION_NAME>
  11. Скопируйте URL-адрес для выполнения заказа, чтобы использовать его в следующем разделе.

Зарегистрировать обработчик веб-перехватчика

  1. Создайте файл sdk/webhooks/ActionsOnGoogleFulfillment.yaml и определите обработчики для вашего действия и URL-адрес для запросов веб-перехватчика.
    httpsEndpoint:
      baseUrl: https://my.web.hook/ActionsOnGoogleFulfillment
      endpointApiVersion: 2
    handlers:
    - name: questionOnEnterFunc
    - name: fruitSlotValidationFunc