@cxco/google-assistant

2.0.1 • Public • Published

Introduction

The Google Assistant Integration (GAI) between DigitalCX and Google Assistant. This package:

  • adds basic intent handling
  • offers hooks to apply custom logic
  • allows you to add custom intents

The basic intents that are supported are:

Description Google Actions Intent DCX endpoint
Initialize the conversation actions.intent.MAIN DCX event (onLoad)
Quit the conversation actions.intent.CANCEL DCX event (onCancel)
Any follow up interactions actions.intent.TEXT DCX ask

Features

  • Hooks into any Express.js server as Express middleware.
  • Offers full support for Q&A's, events, dialogs and transactional dialogs.
  • Each instance can be configured to integrate with a single customer-project-culture combination.
  • Multiple instances can easily be created.
  • Custom intents can easily be added.
  • Default intents can be overwritten.
  • Offers hooks to apply custom logic.

Pre-requisites

In order to get the GAI package up and running you need to:

  • Have Node.js installed. This Node.js module was developed using Node.js v8.12.0.
  • Create an Express.js server to set up the GAI as middleware.
  • Setup an Google Actions project through the Google Action SDK to communicate to Google Assistant.
  • Have a project in Actions on Google of the type conversational.

First steps

In order to configure it properly with the google assistant you need to have the gactions SDK in your system so you can hook up the actions to the project that is running in google.

For this:

  • Install the gactions sdk
  • Make the gactions sdk executable by running chmod ugo+x gactions
  • Run ./gactions init, this will create an action.json file that you will use to set up the calls to your project
  • Change the action.json to be similar to the one underneath
  • After having a proper action.json run the command ./gactions update --action_package action.json --project <GOOGLE-ACTION-PROJECT-ID> to configure which are the intents that exist and where do they map
    • The <GOOGLE-ACTION-PROJECT-ID> can be seen in the Actions on Google project settings

action.json

{
  "actions": [
    {
      "description": "Default Welcome Intent",
      "name": "MAIN",
      "fulfillment": {
        "conversationName": "localhost" // You can define here the conversations that fulfill this intent
      },
      "intent": {
        "name": "actions.intent.MAIN",
        "trigger": {
          "queryPatterns": [
            "talk to digitalcx support portal" // Define a pattern that you use to talk to the actions on google project
          ]
        }
      }
    }
  ],
  "conversations": {
    "localhost": { // Define the conversation "server"
      "name": "localhost", // Give it a name
      "url": "https://example.com/googleassistant" // Your favorite URL
    }
  },
  "locale": "en"
}

Installation

npm i @cxco/google-assistant

Configuration

The Google Assistant Integration offers a number of project configuration options, some of them required and some of them optional. All configuration options need to be assigned to a single 'actionsProject' object.

Parameter Name Type Description Required Example
project object An object containing the information required to connect and authenticate your application with and to the DigitalCX engine. yes {
   "customerKey":"ckey",
   "projectKey":"pkey",
   "culture":"en",
   "apiKey":"api key",
   "env":"production"
}
onLoadEvent string A string representing the DigitalCX event you'd like the Google Assistant to trigger and welcome the end user with. yes dcx-google-assistant-onload
onCancelEvent string A string representing the DigitalCX event you'd like the Google Assistant to trigger and end the conversation with. no dcx-google-assistant-oncancel

Basic Usage

const express = require('express')
const { actionssdk } = require('actions-on-google')
const googleAssistant = require('@cxco/google-assistant')
const bodyParser = require('body-parser')
const app = express()

const actionsApp = actionssdk()

const actionsProject = {
    project: {
        customerKey: 'customerA',
        projectKey: 'projectB',
        culture: 'en',
        apiKey: 'xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx',
        env: 'cms'
    },  
    onLoadEvent: 'on_load',
    onCancelEvent: 'on_end'
}

const googleAssistantPayload = { 
    actionsProject, 
    actionsApp 
}

app.use(bodyParser.json())

app.use('/googleassistant', (req, res, next) => {
    googleAssistant(googleAssistantPayload)(req, res)
})

app.listen(3000)

Hooks

With hooks you can add logic between DigitalCX and Google Assistant. There are three hooks for every Google Action Intent. You can add custom logic and manipulate the input data inside every hook. All specified hooks will trigger for every basic intent ('actions.intent.MAIN', 'actions.intent.TEXT', 'actions.intent.CANCEL').

The defined hooks ordered on callstack:

Hooks Description
onAsk Executes before request to DCX
onAnswer Executes after response from DCX
onSSML Executes after SSML formatting and before request to Google Assistant

Hook signature

The hooks are methods of the Hooks class derived from the GAI package. To define a hook you initiate a new hooks instance. Then assign a callback function to the method. This curried function uses two arguments, the intentName and the input. The intentName is a string that can be used inside the hook to add logic for a specific intent. The input argument can be modified inside the hook and must be returned! Assign the class to the Google Assistant payload.

    hooks.onAsk = (intentName) => (input) => {
      return input
    }

Example of multiple hooks:

const express = require('express')
const { actionssdk } = require('actions-on-google')
const googleAssistant = require('@cxco/google-assistant')
const bodyParser = require('body-parser')
const app = express()
const actionsApp = actionssdk()

// Require hooks class
const Hooks = require('@cxco/google-assistant/hooks')

const actionsProject = {
    project: {
        customerKey: 'customerA',
        projectKey: 'projectB',
        culture: 'en',
        apiKey: 'xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx',
        env: 'cms'
    },  
    onLoadEvent: 'on_load',
    onCancelEvent: 'on_end'
}


// Create new hooks instance

hooks = new Hooks()

/**
* Hook that can modify the DigitalCX request payload per Intent
* @param {String} intentName 'actions.intent.MAIN' || 'actions.intent.TEXT' || 'actions.intent.CANCEL'
* @param {Object} dcxPayload payload for DigitalCX request(@cxco/dcx-connector)
* @return {Object} dcxPayload
*/
hooks.onAsk = intentName => dcxPayload => (
    // Return the DigitalCX payload adding custom context
    { 
        metadata: {
            dimensions: [{ Integration: 'Test' }]
        }
    })

/**
 * Hook that can modify the response from DigitalCX per Intent
 * @param {String} intentName 'actions.intent.MAIN' || 'actions.intent.TEXT' || 'actions.intent.CANCEL'
 * @param {Object} dcxResponse normalised response from DigitalCX (@cxco/dcx-connector)
 * @return {Object} dcxResponse
 */
hooks.onAnswer = intentName => dcxResponse => {

    // Modify the DigitalCX response before parsing it to SSML
    dcxResponse.data.answer = `${dcxResponse.data.answer} (DigitalCX answer is modified by the onAnswer hook)`

    return dcxResponse
}

/**
 * Hook that can modify the Google Actions request payload per Intent
 * https://www.npmjs.com/package/ssml-builder Formatted SSML response for Google Actions
 * @param {String} intentName 'actions.intent.MAIN' || 'actions.intent.TEXT' || 'actions.intent.CANCEL'
 * @param {Object} handlerResponse Result from dcxResponseHandler which contains : data, metadata and speech object
 * @return {Object} handlerResponse
 */
hooks.onSSML = intentName => handlerResponse => {

    // Modify the SSML object on the CANCEL intent / DCX onEnd event.
    if (intentName === 'actions.intent.CANCEL') {
        handlerResponse.speech.sentence('This added sentence to the SSML object is modified by the onSSML hook')
    }

    return handlerResponse
}

app.use(bodyParser.json())

app.use('/googleassistant', (req, res, next) => {
    googleAssistant({ actionsProject, actionsApp, hooks })(req, res)
})

app.listen(3000)

Custom Intents

You can add custom intents and / or overwrite default intents stated in the Google Assistant Integration. This can be done by mapping your custom intents and adding it to the Google Assistant Integration payload.

const express = require('express')
const { actionssdk } = require('actions-on-google')
const googleAssistant = require('@cxco/google-assistant')
const bodyParser = require('body-parser')
const app = express()
const actionsApp = actionssdk()
const actionsProject = {
    project: {
        customerKey: 'customerA',
        projectKey: 'projectB',
        culture: 'en',
        apiKey: 'xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx',
        env: 'cms'
    },  
    onLoadEvent: 'on_load',
    onCancelEvent: 'on_end'
}

const customIntents = new Map()

// Overwriting a custom intent
customIntents.set('customIntentName', (conv, input) => {
    conv.ask('Hello world!')
})

// Overwriting a default intent
customIntents.set('actions.intent.MAIN', (conv, input) => {
    conv.ask('Hello world!')
})

app.use(bodyParser.json())

app.use('/googleassistant', (req, res, next) => {
    googleAssistant({ actionsProject, actionsApp, customIntents })(req, res)
})

app.listen(3000)

Custom Intents using the dcx-connector

The dcx-connector package can be used to connect to the DCX endpoints and retrieve normalized answers. The dcxResponseHandler function (included in the GAI) returns data and metadata from the connector and formatted SSML.

Installing the dcx-connector:

npm i @cxco/dcx-connector

Usage:

const express = require('express')
const { actionssdk } = require('actions-on-google')
const googleAssistant = require('@cxco/google-assistant')
const { dcxResponseHandler } = require('@cxco/google-assistant/formatter')
const { doGetRequest } = require('@cxco/dcx-connector')
const bodyParser = require('body-parser')
const app = express()

const actionsApp = actionssdk()
const actionsProject = {
    project: {
        customerKey: 'customerA',
        projectKey: 'projectB',
        culture: 'en',
        apiKey: 'xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx',
        env: 'cms'
    },  
    onLoadEvent: 'on_load',
    onCancelEvent: 'on_end'
}

const customIntents = new Map()

customIntents.set('customIntentName', async (conv, input) => {
    
    const dcxPayload = {
        type: 'ask',
        data: {
            userInput: input
        },
        metadata: {
            sessionId: conv.user.storage.id,
            tDialogState: conv.user.storage.tDialogState,
        },
        config: {
            baseUrl: 'https://your-digitalcx-endpoint',
            apiKey: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx',
            culture: 'en'
        }
    }

    const dcxResponse = await doGetRequest(dcxPayload);
    const handlerResponse = await dcxResponseHandler({
        dcxResponse,
        conv,
        config
    })

    const { speech, data, metadata } = handlerResponse 

    conv.ask(speech.ssml())
})

app.use(bodyParser.json())

app.use('/googleassistant', (req, res, next) => {
    googleAssistant({ actionsProject, actionsApp, customIntents })(req, res)
}

Build and Test

To run the test suite, first install the dependencies, then run npm test:

npm i
npm test

Readme

Keywords

Package Sidebar

Install

npm i @cxco/google-assistant

Weekly Downloads

1

Version

2.0.1

License

ISC

Unpacked Size

43.3 kB

Total Files

22

Last publish

Collaborators

  • bo.strijker
  • cx-company
  • remcodevries