dialogflow/detect.js (380 lines of code) (raw):
// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
'use strict';
function detectTextIntent(projectId, sessionId, queries, languageCode) {
// [START dialogflow_detect_intent_text]
/**
* TODO(developer): UPDATE these variables before running the sample.
*/
// projectId: ID of the GCP project where Dialogflow agent is deployed
// const projectId = 'PROJECT_ID';
// sessionId: String representing a random number or hashed user identifier
// const sessionId = '123456';
// queries: A set of sequential queries to be send to Dialogflow agent for Intent Detection
// const queries = [
// 'Reserve a meeting room in Toronto office, there will be 5 of us',
// 'Next monday at 3pm for 1 hour, please', // Tell the bot when the meeting is taking place
// 'B' // Rooms are defined on the Dialogflow agent, default options are A, B, or C
// ]
// languageCode: Indicates the language Dialogflow agent should use to detect intents
// const languageCode = 'en';
// Imports the Dialogflow library
const dialogflow = require('@google-cloud/dialogflow');
// Instantiates a session client
const sessionClient = new dialogflow.SessionsClient();
async function detectIntent(
projectId,
sessionId,
query,
contexts,
languageCode
) {
// The path to identify the agent that owns the created intent.
const sessionPath = sessionClient.projectAgentSessionPath(
projectId,
sessionId
);
// The text query request.
const request = {
session: sessionPath,
queryInput: {
text: {
text: query,
languageCode: languageCode,
},
},
};
if (contexts && contexts.length > 0) {
request.queryParams = {
contexts: contexts,
};
}
const responses = await sessionClient.detectIntent(request);
return responses[0];
}
async function executeQueries(projectId, sessionId, queries, languageCode) {
// Keeping the context across queries let's us simulate an ongoing conversation with the bot
let context;
let intentResponse;
for (const query of queries) {
try {
console.log(`Sending Query: ${query}`);
intentResponse = await detectIntent(
projectId,
sessionId,
query,
context,
languageCode
);
console.log('Detected intent');
console.log(
`Fulfillment Text: ${intentResponse.queryResult.fulfillmentText}`
);
// Use the context from this response for next queries
context = intentResponse.queryResult.outputContexts;
} catch (error) {
console.log(error);
}
}
}
executeQueries(projectId, sessionId, queries, languageCode);
// [END dialogflow_detect_intent_text]
}
async function detectEventIntent(
projectId,
sessionId,
eventName,
languageCode
) {
const {struct} = require('pb-util');
// Imports the Dialogflow library
const dialogflow = require('@google-cloud/dialogflow');
// Instantiates a session client
const sessionClient = new dialogflow.SessionsClient();
// The path to identify the agent that owns the created intent.
const sessionPath = sessionClient.projectAgentSessionPath(
projectId,
sessionId
);
// The text query request.
const request = {
session: sessionPath,
queryInput: {
event: {
name: eventName,
parameters: struct.encode({foo: 'bar'}),
languageCode: languageCode,
},
},
};
const [response] = await sessionClient.detectIntent(request);
console.log('Detected intent');
const result = response.queryResult;
// Instantiates a context client
const contextClient = new dialogflow.ContextsClient();
console.log(` Query: ${result.queryText}`);
console.log(` Response: ${result.fulfillmentText}`);
if (result.intent) {
console.log(` Intent: ${result.intent.displayName}`);
} else {
console.log(' No intent matched.');
}
const parameters = JSON.stringify(struct.decode(result.parameters));
console.log(` Parameters: ${parameters}`);
if (result.outputContexts && result.outputContexts.length) {
console.log(' Output contexts:');
result.outputContexts.forEach(context => {
const contextId =
contextClient.matchContextFromProjectAgentSessionContextName(
context.name
);
const contextParameters = JSON.stringify(
struct.decode(context.parameters)
);
console.log(` ${contextId}`);
console.log(` lifespan: ${context.lifespanCount}`);
console.log(` parameters: ${contextParameters}`);
});
}
}
async function detectAudioIntent(
projectId,
sessionId,
filename,
encoding,
sampleRateHertz,
languageCode
) {
// [START dialogflow_detect_intent_audio]
const fs = require('fs');
const util = require('util');
const {struct} = require('pb-util');
// Imports the Dialogflow library
const dialogflow = require('@google-cloud/dialogflow');
// Instantiates a session client
const sessionClient = new dialogflow.SessionsClient();
// The path to identify the agent that owns the created intent.
const sessionPath = sessionClient.projectAgentSessionPath(
projectId,
sessionId
);
// Read the content of the audio file and send it as part of the request.
const readFile = util.promisify(fs.readFile);
const inputAudio = await readFile(filename);
const request = {
session: sessionPath,
queryInput: {
audioConfig: {
audioEncoding: encoding,
sampleRateHertz: sampleRateHertz,
languageCode: languageCode,
},
},
inputAudio: inputAudio,
};
// Recognizes the speech in the audio and detects its intent.
const [response] = await sessionClient.detectIntent(request);
console.log('Detected intent:');
const result = response.queryResult;
// Instantiates a context client
const contextClient = new dialogflow.ContextsClient();
console.log(` Query: ${result.queryText}`);
console.log(` Response: ${result.fulfillmentText}`);
if (result.intent) {
console.log(` Intent: ${result.intent.displayName}`);
} else {
console.log(' No intent matched.');
}
const parameters = JSON.stringify(struct.decode(result.parameters));
console.log(` Parameters: ${parameters}`);
if (result.outputContexts && result.outputContexts.length) {
console.log(' Output contexts:');
result.outputContexts.forEach(context => {
const contextId =
contextClient.matchContextFromProjectAgentSessionContextName(
context.name
);
const contextParameters = JSON.stringify(
struct.decode(context.parameters)
);
console.log(` ${contextId}`);
console.log(` lifespan: ${context.lifespanCount}`);
console.log(` parameters: ${contextParameters}`);
});
}
// [END dialogflow_detect_intent_audio]
}
async function streamingDetectIntent(
projectId,
sessionId,
filename,
encoding,
sampleRateHertz,
languageCode
) {
// [START dialogflow_detect_intent_streaming]
const fs = require('fs');
const util = require('util');
const {Transform, pipeline} = require('stream');
const {struct} = require('pb-util');
const pump = util.promisify(pipeline);
// Imports the Dialogflow library
const dialogflow = require('@google-cloud/dialogflow');
// Instantiates a session client
const sessionClient = new dialogflow.SessionsClient();
// The path to the local file on which to perform speech recognition, e.g.
// /path/to/audio.raw const filename = '/path/to/audio.raw';
// The encoding of the audio file, e.g. 'AUDIO_ENCODING_LINEAR_16'
// const encoding = 'AUDIO_ENCODING_LINEAR_16';
// The sample rate of the audio file in hertz, e.g. 16000
// const sampleRateHertz = 16000;
// The BCP-47 language code to use, e.g. 'en-US'
// const languageCode = 'en-US';
const sessionPath = sessionClient.projectAgentSessionPath(
projectId,
sessionId
);
const initialStreamRequest = {
session: sessionPath,
queryInput: {
audioConfig: {
audioEncoding: encoding,
sampleRateHertz: sampleRateHertz,
languageCode: languageCode,
},
},
};
// Create a stream for the streaming request.
const detectStream = sessionClient
.streamingDetectIntent()
.on('error', console.error)
.on('data', data => {
if (data.recognitionResult) {
console.log(
`Intermediate transcript: ${data.recognitionResult.transcript}`
);
} else {
console.log('Detected intent:');
const result = data.queryResult;
// Instantiates a context client
const contextClient = new dialogflow.ContextsClient();
console.log(` Query: ${result.queryText}`);
console.log(` Response: ${result.fulfillmentText}`);
if (result.intent) {
console.log(` Intent: ${result.intent.displayName}`);
} else {
console.log(' No intent matched.');
}
const parameters = JSON.stringify(struct.decode(result.parameters));
console.log(` Parameters: ${parameters}`);
if (result.outputContexts && result.outputContexts.length) {
console.log(' Output contexts:');
result.outputContexts.forEach(context => {
const contextId =
contextClient.matchContextFromProjectAgentSessionContextName(
context.name
);
const contextParameters = JSON.stringify(
struct.decode(context.parameters)
);
console.log(` ${contextId}`);
console.log(` lifespan: ${context.lifespanCount}`);
console.log(` parameters: ${contextParameters}`);
});
}
}
});
// Write the initial stream request to config for audio input.
detectStream.write(initialStreamRequest);
// Stream an audio file from disk to the Conversation API, e.g.
// "./resources/audio.raw"
await pump(
fs.createReadStream(filename),
// Format the audio stream into the request format.
new Transform({
objectMode: true,
transform: (obj, _, next) => {
next(null, {inputAudio: obj});
},
}),
detectStream
);
// [END dialogflow_detect_intent_streaming]
}
const cli = require('yargs')
.demand(1)
.options({
projectId: {
alias: 'p',
default: process.env.GCLOUD_PROJECT || process.env.GOOGLE_CLOUD_PROJECT,
description:
'The Project ID to use. Defaults to the value of the ' +
'GCLOUD_PROJECT or GOOGLE_CLOUD_PROJECT environment variables.',
requiresArg: true,
type: 'string',
},
sessionId: {
alias: 's',
default: require('uuid').v1(),
type: 'string',
requiresArg: true,
description:
'The identifier of the detect session. Defaults to a random UUID.',
},
languageCode: {
alias: 'l',
default: 'en-US',
type: 'string',
requiresArg: true,
description: 'The language code of the query. Defaults to "en-US".',
},
encoding: {
alias: 'e',
default: 'AUDIO_ENCODING_LINEAR_16',
choices: [
'AUDIO_ENCODING_LINEAR_16',
'AUDIO_ENCODING_FLAC',
'AUDIO_ENCODING_MULAW',
'AUDIO_ENCODING_AMR',
'AUDIO_ENCODING_AMR_WB',
'AUDIO_ENCODING_OGG_OPUS',
'AUDIO_ENCODING_SPEEX_WITH_HEADER_BYTE',
],
requiresArg: true,
description: 'The encoding of the input audio.',
},
sampleRateHertz: {
alias: 'r',
type: 'number',
description:
'The sample rate in Hz of the input audio. Only ' +
'required if the input audio is in raw format.',
},
})
.demandOption(
'projectId',
"Please provide your Dialogflow agent's project ID with the -p flag or through the GOOGLE_CLOUD_PROJECT env var"
)
.command(
'text',
'Detects the intent for text queries.',
{
queries: {
alias: 'q',
array: true,
string: true,
demandOption: true,
requiresArg: true,
description: 'An array of text queries',
},
},
opts =>
detectTextIntent(
opts.projectId,
opts.sessionId,
opts.queries,
opts.languageCode
)
)
.command(
'event <eventName>',
'Detects the intent for a client-generated event name.',
{},
opts =>
detectEventIntent(
opts.projectId,
opts.sessionId,
opts.eventName,
opts.languageCode
)
)
.command(
'audio <filename>',
'Detects the intent for audio queries in a local file.',
{},
opts =>
detectAudioIntent(
opts.projectId,
opts.sessionId,
opts.filename,
opts.encoding,
opts.sampleRateHertz,
opts.languageCode
)
)
.command(
'stream <filename>',
'Detects the intent in a local audio file by streaming it to the ' +
'Conversation API.',
{},
opts =>
streamingDetectIntent(
opts.projectId,
opts.sessionId,
opts.filename,
opts.encoding,
opts.sampleRateHertz,
opts.languageCode
)
)
.example(
'node $0 text -q "hello" "book a room" "Mountain View" ' +
'"today" "230pm" "half an hour" "two people" "A" "yes"'
)
.example('node $0 event order_pizza')
.example('node $0 audio resources/book_a_room.wav -r 16000')
.example('node $0 stream resources/mountain_view.wav -r 16000')
.wrap(120)
.recommendCommands()
.epilogue(
'For more information, see https://cloud.google.com/dialogflow-enterprise/docs'
)
.help()
.strict();
if (module === require.main) {
cli.parse(process.argv.slice(2));
}