how to run the dialogflow node js? - node.js

i am still confused about the documentation on Dialogflow nodejs, can I get clear for this?
I have read the documentation this -> https://cloud.google.com/dialogflow/docs/reference/rest/v2/projects.agent.sessions/detectIntent
how to test my code and see the result of my query I input then ?
should I do POST via Axios inside this functions
async function runSample(projectId = 'your-project-id') {
// A unique identifier for the given session
const sessionId = uuid.v4();
// Create a new session
const sessionClient = new dialogflow.SessionsClient();
const sessionPath = sessionClient.sessionPath(projectId, sessionId);
// The text query request.
const request = {
session: sessionPath,
queryInput: {
text: {
// The query to send to the dialogflow agent
text: 'hello',
// The language used by the client (en-US)
languageCode: 'en-US',
},
},
};
// Send request and log result
const responses = await sessionClient.detectIntent(request);
console.log('Detected intent');
const result = responses[0].queryResult;
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.`);
}
}
i still not get clear for this, so do we need use HTTP request also in local to check this?
I already follow the Dialogflow nodejs example, but what next?
it said on google we must POST to
POST https://dialogflow.googleapis.com/v2/{session=projects//agent/sessions/}:detectIntent
nd the req body is on the request variable inside that functions,
but I still not clear on dialogflow nodejs for the next step to run that method

You can run this directly using the express app. Just call this function from your express app route or you can call the given function in the file and use node <filename.js> to run the code. Make sure you add your google cloud credentials in the path name using process.env.GOOGLE_APPLICATION_CREDENTIALS = "<your_json_file_path>";

const sessionClient = new dialogflow.SessionsClient(
// below can be used to set the variable in code itself, if below is not working you can run following in the terminal
//export GOOGLE_APPLICATION_CREDENTIALS="/<path of the json file"
{
keyFilename: "/<path of the json file"
}
);

Related

Google Application Credentials with nodejs on Heroku: how to store a JSON file to an ENV variable with dotenv?

I am using the Google Cloud API (dialogflow) with my NodeJS application, following the steps on google documentation, referencing a JSON file in a enviroment variable (using dotenv) I was able to use the API.
GOOGLE_APPLICATION_CREDENTIALS="./dialogflow_credentials.json"
But my actual project that I'm trying to implement the API are on Heroku, with automatic deploys based on my github repo. So, if I use the actual code, my JSON credentials will be visible on github.
Is there a way to put this JSON file direct on the ENV, as a string? (On heroku I can define the enviroment variables) or have a better way to do this?
I tried to use info from this question Is it possible to store a JSON file to an ENV variable with dotenv?, but doesn't work.
I'm testing with this example code on my index.js:
const dialogflow = require('dialogflow');
const uuid = require('uuid');
/**
* Send a query to the dialogflow agent, and return the query result.
* #param {string} projectId The project to be used
*/
async function runSample(projectId = 'your-project-id') {
// A unique identifier for the given session
const sessionId = uuid.v4();
// Create a new session
const sessionClient = new dialogflow.SessionsClient();
const sessionPath = sessionClient.sessionPath(projectId, sessionId);
// The text query request.
const request = {
session: sessionPath,
queryInput: {
text: {
// The query to send to the dialogflow agent
text: 'hello',
// The language used by the client (en-US)
languageCode: 'en-US',
},
},
};
// Send request and log result
const responses = await sessionClient.detectIntent(request);
console.log('Detected intent');
const result = responses[0].queryResult;
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.`);
}
}
Had a similar issue and managed to make it work following the documentation [here][1]. There are basically two main options:
Option 1) Use explicit credentials and save the credentials in different env variables
You should have dowloaded a service-account.json, but instead of providing its path, you provide some of its details explicitly:
const { client } = require('google-cloud-bigquery')
const bigQuery = client.new({
credentials: {
project_id: 'test',
location_id: 'australia-southeast1',
client_email:'something-1234#your-project-id.iam.gserviceaccount.com',
private_key: '-----BEGIN PRIVATE KEY-----\n123456789-----END PRIVATE KEY-----\n'
}
})
And then replace the strings for different env variables of your choice, e.g.
YOUR_CUSTOM_ENV_VARIABLE_FOR_PROJECT_ID='test'
Option 2) Following Google Cloud's naming for env variables (no need to specify them explicitly)
const { client } = require('google-cloud-bigquery')
const bigQuery = client.new()
The above will only work if all the following environment variables are set:
GOOGLE_CLOUD_BIGQUERY_PROJECT_ID or GOOGLE_CLOUD_PROJECT_ID
GOOGLE_CLOUD_BIGQUERY_LOCATION_ID or GOOGLE_CLOUD_LOCATION_ID
GOOGLE_CLOUD_BIGQUERY_CLIENT_EMAIL or GOOGLE_CLOUD_CLIENT_EMAIL
GOOGLE_CLOUD_BIGQUERY_PRIVATE_KEY or GOOGLE_CLOUD_PRIVATE_KEY

How to set dialogflow context from node.js dialogflow package

I am using sessionClient.detectIntent() to send text to dialogflow and it is working fine, now I want to send context too with the text. How can I do that?
I usually create contexts in the following way:
exports.createContext = async function(contextId, parameters, sessionPath, sessionId, lifespan = 333) {
let contextPath;
try {
contextPath = contextClient.contextPath(projectId, sessionId, contextId);
} catch (e) {
console.error("Error => ");
console.error(e)
}
const request = {
parent: sessionPath,
context: {
name: contextPath,
parameters: struct.encode(parameters),
lifespanCount: lifespan
}
};
contextClient.createContext(request)
};
And simply call this method when I have to create a context before I call the detectIntent method:
bot.createContext('CONTEXT_NAME_GOES_HERE', '{PARAMETER: VALUE}', sessionPath, session_id, lifespan = 1);
You can send contexts on detectIntent alongside with the Query Text by adding it on the context array field under queryParams. Note that this method of sending context via detectIntent will create (if not created) and activates the context before the query is executed.
You can refer to the code snippet below:
const dialogflow = require('#google-cloud/dialogflow');
/**
* Send a query and a context to the Dialogflow agent, and return the query result.
* #param {string} projectId The project to be used
*/
async function detectIntent(projectId, sessionId, text) {
// Create a new session
const sessionClient = new dialogflow.SessionsClient();
const sessionPath = sessionClient.projectAgentSessionPath(projectId, sessionId);
// The text query request.
const request = {
session: sessionPath,
queryParams:{
//List of context to be sent and activated before the query is executed
contexts:[
{
// The context to be sent and activated or overrated in the session
name: `projects/${projectId}/agent/sessions/${sessionId}/contexts/CONTEXT_NAME`,
// The lifespan of the context
lifespanCount: 8
}
]
},
queryInput: {
text: {
// The query to send to the dialogflow agent
text: text,
// The language used by the client (en-US)
languageCode: 'en-US',
},
},
};
// Send request and log result
const responses = await sessionClient.detectIntent(request);
console.log('Detected intent');
const result = responses[0].queryResult;
console.log(` Query: ${result.queryText}`);
console.log(` Response: ${result.fulfillmentText}`);
console.log(` Output Contexts: ${JSON.stringify(result.outputContexts)}`)
}
detectIntent("PROJECT_ID","SESSION_ID","TEXT_QUERY");
Output:
Detected intent
Query: Hi
Response: Hello! How can I help you?
Output Contexts: [{"name":"projects/PROJECT_ID/agent/sessions/SESSION_ID/contexts/CONTEXT_NAME","lifespanCount":7,"parameters":null}]

Possibility to send context data to dialogflow without webhook being called from Dialogflow, but from server itself

Currently I have a webhook which is being called from Dialogflow (fulfillment) and checks which intent is currently applicable. (I do everything via JSON) once I know which Intent, I send back (via the webhook) a JSON response. I was wondering if it is possible to initiate a JSON object and send it to Dialogflow. (I want to send context without letting the user type first and Dialogflow receiving a fallback) (NodeJS Server -> Dialogflow) Currently the only way I can do it is (Dialogflow -> NodeJS Server (JSON object with contex) -> Dialogflow)
CURRENT:
var dialog_flow = {
// Create context using Google dialogflow
createContext: async function(projectId, sessionId, contextId, parameters, lifespanCount){
console.log("params to be sent: ", parameters);
//Instantiates client to create the actual context before sending
const contextsClient = new dialogflow.ContextsClient({
keyFilename: './dialogflow_credentials.json'
});
const sessionPath = contextsClient.sessionPath(projectId, sessionId);
const contextPath = contextsClient.contextPath(
projectId,
sessionId,
contextId
);
const createContextRequest = {
parent: sessionPath,
context: {
name: contextPath,
lifespanCount: lifespanCount,
parameters: parameters
},
};
const response = await contextsClient.createContext(createContextRequest);
console.log(`Created ${response[0].name}`);
}
};
PARAMETERS:
let testobj = {
firstname: 'test name',
lastname: 'itworks!!',
dd: 'fgfgf',
ff: 'fgfg'
}
You can call directly Dialogflow from Node.js, without the need of receiving a webhook. For that you will need to use the dialogflow package.
const sessionClient = new dialogflow.SessionsClient();
const session = sessionClient.sessionPath(projectId, sessionId);
const request = {
session,
queryInput: {
text: {
text: 'Some text'
}
},
queryParams: {
contexts: [context] // here you send the data
}
};
sessionClient.detectIntent(request)
.then(console.log)
.catch(console.error);
In order to send a context, with data, you will need to use dialogflow.ContextsClient
I give a detailed explanation about that in these other questions:
set input or output context dialogflow nodejs v2
Dialogflow pass parameters through NodeJS
And in order to authenticate the client you can check:
Dialogflow easy way for authorization
UPDATE: 2 weeks ago, Dialogflow, removed the structjson.js sample from the repository, but in favor of an npm package to handle the encoding/decoding of the protobuf struct: pb-util

Unable to handle multiple fulfillment responses

I am using the dialogflow enterprise edition bot,the issue is about receiving responses from rest api(node.js sdk).Recently we have shifted from dialogflow standard edition to Enterprise edition. We have referred and used the following code in this link
https://www.npmjs.com/package/dialogflow
We have created our own cloud function using rest Api which takes the user answer as the request and send the fulfillment text(questions in that particular intent) as the response to the user.When multiple request calls happen the the cloud function is not showing proper response which means
When user(Android/IOS) "A" started answering the bot then the cloud function triggering gets started and it send the questions as the response to the user but when the multiple users started answering the bot, due to multiple calls for the cloud function, the questions which are displayed to the one user are not going to be displayed to the other user say "B". Please help us in handling the multiple calls for node.js sdk
https://i.stack.imgur.com/BVAci.png
This is the view of an intent in dialogflow.
https://i.stack.imgur.com/aRAr6.png ,
https://i.stack.imgur.com/oMp0d.png
https://i.stack.imgur.com/T7Jo7.png
https://i.stack.imgur.com/7U3Rb.png
https://i.stack.imgur.com/EwWSo.png
Above five screenshots represent the first time when the user triggers
the cloud function, and the 1st question is displayed. When we answer the
first question and submit the answer, next question is not displayed.(I am
getting the empty response).
https://i.stack.imgur.com/rLI2I.png ,
https://i.stack.imgur.com/T5wZL.png
These screenshots represent the empty response after first question is answered.
const functions = require('firebase-functions');
const dialogflow = require('dialogflow');
const Firestore = require('#google-cloud/firestore');
const firestore = new Firestore();
admin.initializeApp();
var db = admin.firestore();
const {WebhookClient} = require('dialogflow-fulfillment');
exports.fulfillmenttext = functions.https.onRequest((req,res) =>{
runSample();
async function runSample() {
const projectId = 'bodha-192606';
const sessionId = uuid.v4();
const answer = req.body.Text;
console.log("Text said by the user",answer);
const languageCode = 'en-US';
const credentials = {
client_email: 'xxxx ',
Private_key:'xxxx ',
};
// Instantiate a DialogFlow client.
const dialogflow = require('dialogflow');
const sessionClient = new dialogflow.SessionsClient({
projectId,
credentials,
});
// Define session path
const sessionPath = sessionClient.sessionPath(projectId, sessionId);
// The text query request.
const request = {
session: sessionPath,
queryInput: {
text: {
text: answer,
languageCode,
},
},
};
const responses = await sessionClient.detectIntent(request);
console.log('Detected intent');
const result = responses[0].queryResult;
let action = result.action;
console.log("action is"+action);
console.log(` Query: ${result.queryText}`);
console.log(` Response: ${result.fulfillmentText}`);
if (result.intent) {
console.log(` Intent: ${result.intent.displayName}`);
res.status(200).send({"question":result.fulfillmentText});
} else {
console.log(` No intent matched.`);
res.status(400).send("No Intent matched");
}
}
});
It looks like you are using the same session ID for all of your clients. I'm not certain, but I can certainly understand that if Dialogflow gets two requests for the same session at the same time, that it can mix up the replies.
You should be generating a new session for each of your clients - possibly by putting something into an HTTP session (aha!) cookie when they first connect and continuing to use that during the session.

Dialogflow Node SDK permission fail (dialogflow.sessions.detectIntent)

I got a problem with Node DialogFlow API integration.
I can not have the necessary permissions to make calls to the API, although I have followed all possible documentation.
Here is my Agent Service Account from Dialogflow admin :
Then the Service Account roles :
The "Client de l'API Dialogflow" role detail, where we can see "dialogflow.sessions.detectIntent" :
And finally, the Node error after downloading the JSON file corresponding to the Service Account :
Am I missing something ?
I tried to generate other JSON files, create other Service Accounts, nothing worked...
The Node script is simple, just pasted from the official tutorial :
const projectId = 'newagent-9e77e '; //https://dialogflow.com/docs/agents#settings
const sessionId = 'quickstart-session-id';
const query = 'bonjour';
const languageCode = 'fr-FR';
// Instantiate a DialogFlow client.
const dialogflow = require('dialogflow');
const sessionClient = new dialogflow.SessionsClient();
// Define session path
const sessionPath = sessionClient.sessionPath(projectId, sessionId);
// The text query request.
const request = {
session: sessionPath,
queryInput: {
text: {
text: query,
languageCode: languageCode,
},
},
};
// Send request and log result
sessionClient
.detectIntent(request)
.then(responses => {
console.log('Detected intent');
const result = responses[0].queryResult;
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.`);
}
})
.catch(err => {
console.error('ERROR:', err);
});
Thanks !
The problem was on space on the "projectId" constant.
Shame on me.

Resources