Вебхуки

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

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

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

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

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

Когда вы запускаете вебхук в своих действиях, Google Assistant отправляет вам запрос с полезной нагрузкой 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"
    }
  }
}

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

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

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

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

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 Assistant.

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

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

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

Мы рекомендуем следующую структуру проекта, если вы используете облачные функции для Firebase в качестве услуги выполнения:

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

Чтобы настроить среду, выполните следующие действия:

  1. Загрузите и установите Node.js.
  2. Настройте и инициализируйте интерфейс командной строки Firebase. Если следующая команда завершается с ошибкой 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