@cxco/google-assistant
v2.0.1
Published
DigitalCX's ready-to-go integration between DigitalCX and the Google Assistant
Downloads
6
Readme
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 runningchmod ugo+x gactions
- Run
./gactions init
, this will create anaction.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
- The
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