Lex V1 group message - node.js

I am working on chat bot in Amazon lex v1 ,In that I want to display two messages when the client invoke the bot. But I am facing issue .with lambda
var messageToUse = {
contentType : "Composite",
content :{"messages":[{"type":"PlainText","group":1,"value":"welcome"},{"type":"PlainText","group":2,"value":"To GAC"}]}
};
const response = {
"dialogAction":
{"type": "Close",
"fulfillmentState": "Fulfilled",
"message": messageToUse
}
};
callback(response);
Expected Result should be this

Lex V1 is limited when it comes to working with the API for message groups. The tutorial you were following was able to get multiple messages by using message groups in the content designer (Lex's designer UI). This is different than returning multiple messages through a Lambda function.
Adding the responses in the content designer
A preview of how the responses will look
Unfortunately, the JSON for messages was not a list/array in Lex V1. It only supported key value pairs. This means that a Lex V1 Bot only expects a single message from the Lambda and you cannot return more than one at a time.
The only way you can make Lex V1 appear like it is returning multiple messages is to use a custom front end. If you plan on using a custom front end, you can parse the message.content JSON into different message bubbles yourself.
If you would like to be able to set message groups through a lambda function, I recommend you try using Lex V2. The JSON for messages in Lex V2 expects a list, meaning that you can return multiple messages at once and they will appear in separate bubbles in the Lex V2 test console.
Here is an example of how to do this in Lex V2:
return {
"sessionState": {
"dialogAction": {
"type": "Close"
},
"intent": {
"confirmationState": "None",
"name": "TestIntent",
"state": "Fulfilled"
}
},
"messages": [
{ "contentType": "PlainText", "content": "Hi" },
{ "contentType": "PlainText", "content": "How are you?" },
{ "contentType": "PlainText", "content": "How may I help?" }
]};
And also how they appear in the test console.
I'm sorry this isn't the answer you were hoping for but I hope it helps anyway.

Related

Lex bot getting value only in digit representation not from words

I am a newbie to Amazon Lex, I have created a bot that offers several services:
open a case
check status
status via email
when a user checks the status, he is forced to provide a "case number." The issue I am facing is that it only gets value from digits such as digit representation.
When the user uses "nine" instead of 9, it doesn't work. You can see it here.
Guide me on that issue, I would be very thankful to you.
It seems an AWS Lambda will be best suited to assist you with what you're trying to achieve.
When testing via the AWS Lex console, click the "Inspect" button and view the JSON-formatted requests and responses.
What you will find is that when the user enters a numeric value in words - as in your example "nine" instead of "9" - Lex will provide you with the original input as well as the numeric form of the input.
Take a look at the JSON payload below that I've extracted from my own example:
{
"messages":[
{
"content":"Well done!",
"contentType":"PlainText"
}
],
"sessionState":{
"dialogAction":{
"type":"Close"
},
"intent":{
"name":"MainIntent",
"slots":{
"quantity":{
"value":{
"originalValue":"two",
"interpretedValue":"2",
"resolvedValues":[
"2"
]
}
}
},
"state":"ReadyForFulfillment",
"confirmationState":"None"
},
"originatingRequestId":"e309a92b-124b-4250-bbd3-2fb8891aa90f"
},
"interpretations":[
{
"nluConfidence":{
"score":1
},
"intent":{
"name":"MainIntent",
"slots":{
"quantity":{
"value":{
"originalValue":"two",
"interpretedValue":"2",
"resolvedValues":[
"2"
]
}
}
},
"state":"ReadyForFulfillment",
"confirmationState":"None"
}
},
{
"intent":{
"name":"FallbackIntent",
"slots":{
}
}
}
],
"sessionId":"858917309331613"
}
Have a look at the interpretedValue field in the payload. This is the numeric value that you're looking for.
Using a Lambda function, you can extract this value and perform any validation that you may need before continuing with the rest of the flow or user journey.
You can find out more about integrating Lambda functions into Lex from the developer guide:
https://docs.aws.amazon.com/lexv2/latest/dg/lambda.html

postback button in dialogflow messenger cx

Hello I'm trying to create a flow in dialogflow cx, where in case of multiple options I want my user to select 1 option where all the options are buttons.
I have used the default payload but not sure how can I send back which button got clicked to my webhook and return respective info, currently if I click on button it simply open example.com, if I exclude the link it opens same page in new tab.
{
"type": "button",
"icon": {
"type": "chevron_right",
"color": "#FF9800"
},
"text": "Button text 1",
"link" : "www.example.com",
"event": {
"name": "some name",
"languageCode": "en",
"parameters": {}
}
}
For your use case, since the button response type always redirects to a page when clicked, you can consider using suggestion chips instead.
{
"richContent": [
[
{
"options": [
{
"text": "Chip 1"
},
{
"text": "Chip 2"
}
],
"type": "chips"
}
]
]
}
Suggestion chips act like a user text query when the user clicks on it, therefore, you can just create a route that can be triggered by text of the chip and get the text query from the webhook request sent to your webhook to return the respective information. For example:
Intent:
Route:
Then in your webhook, you can get the parameter value in the text field of the webhook request which you will refer to in order to create a webhook response with the respective information.
Here’s an example in Node.js using Express:
app.post("/webhook", (req, res) => {
let option = req.body.text;
let jsonResponse = {
fulfillment_response: {
messages: [
{
text: {
//fulfillment text response to be sent to the agent
text: [`You've chosen the ${option} option`]
}
}
]
}
};
res.json(jsonResponse);
});
Alternatively, you can also use entity types and assign the selected chip into a parameter that will be also sent to your webhook.
To assign the text of the chip to a parameter, the intent of the route should contain training phrases that are annotated to an entity type containing all of the options. For example:
Intent:
Entity Type:
Then in your webhook, you can get the parameter value in the intentInfo.parameters.parameter_id.resolvedValue field of the webhook request which you will refer to in order to create a webhook response with the respective information.
Here’s an example in Node.js using Express:
app.post("/webhook", (req, res) => {
let option = req.body.intentInfo.parameters.options.resolvedValue;
let jsonResponse = {
fulfillment_response: {
messages: [
{
text: {
//fulfillment text response to be sent to the agent
text: [`You've chosen the ${option} option`]
}
}
]
}
};
res.json(jsonResponse);
});
Results:
There is a simple albeit hacky way I have discover possible (tested in es). Which is to make a chip and get its element then force clicking it
We can listen to button click and I detect that it was empty button with just text. Then I use renderCustomCard to make a chip. Everything inside dialogflow messenger are hidden deep inside nested shadowRoot. But as of now its structure allow us to get the chip out to call click() on it. In effect it make it seem very the same as user manually click the chip
const dfMessenger = document.querySelector('df-messenger');
dfMessenger.addEventListener('df-button-clicked',function(event) {
if(event.detail.element.event || event.detail.element.link)
return;
dfMessenger.renderCustomCard([
{
"type": "chips",
"options": [
{
"text": event.detail.element.text
}
]
}
]);
var messageList = dfMessenger.shadowRoot.querySelector("df-messenger-chat").shadowRoot.querySelector("df-message-list").shadowRoot;
var chips = [...messageList.querySelectorAll("df-chips")].flatMap((chips) => [...chips.shadowRoot.querySelectorAll(".df-chips-wrapper>a")]).filter((a) => a.innerHTML.indexOf(event.detail.element.text) > -1);
if(chips.length > 0)
chips.slice(-1)[0].click();
});
Working for today. No guarantee they will block this method in the future. But I actually guess they would implement actual postback button in similar manner later after beta version

How to make a welcome message then storing it to json or database

So I was wondering how to make a welcome command.
When using /welcome (text you want to display on users join). I want to store that text in json or database so every guild would have their welcome message.
you can compose your message like that in json :
"guild"{
"000000000000000001": //guild id here
{
"content": "your message here"
},
"000000000000000001":
{
"embeds": [
{
"title": "an embed",
"description": "with description"
}
]
}
}
after that in your bot code you can do that
const welcomeMessage = require('myjson');
and when you need to display your welcome message you juste need to acces at your json like that
chanToSend.send(welcomeMessage.myserveurid);
for json editing thing I send you into this question here

Actions on Google API v2 using c# webhook

I currently have an app running on actions on google using API.AI. I have modified all the response members to be camelCase as suggested and got it working. Now I am trying to return a basic card, but I can not figure out how to properly return it.
Does anyone have the most basic JSON response, returning a basic card to the Google assistant?
currently, the most basic v2 API response I can have is the following:
{
speech: "",
displayText: "",
data: {
google: {
expectUserResponse: true,
isSsml: true,
permissionsRequest: null
}
},
contextOut: [ ],
source: "webhook"
}
I have some Gists showing the JSON responses here.
Right now, it includes Lists, Basic Card and Carousel, but I will add Transactions hopefully soon. Hope it might help somehow
This is what I use for Voice Tic Tac Toe
"google": {
"expect_user_response": true,
"rich_response": {
"items": [
{
"simple_response": {
"text_to_speech": "Your move was top. I moved left"
}
},
{
"basic_card": {
"image": {
"url": "https://server/010200000.png",
"accessibility_text": "Tic Tac Toe game board"
}
}
}
]
}
}
I ran the facts about google action and looked at the fulfillment JSON output to learn how to do this.
https://github.com/actions-on-google/apiai-facts-about-google-nodejs
Note that all responses must include at least one, and no more than two, simple_response items.

nodejs async: multiple dependant HTTP API calls

I'm working on a project that involves making multiple HTTP GET requests to different APIs, each requiring information from the last. I'm trying to avoid nested-callaback-and-counter-hell, and have been trying to get it working with the async module.
This is what I need to do: I have an array of 1..n course identifiers (['2014/summer/iat/100/d100', '2014/spring/bisc/372/d100']). For each course in the array, I need to fetch its course outline via a HTTP GET.
The resulting outline looks something like this:
{
"info": {
"nodePath": "2014/spring/bisc/372/d100",
"number": "372",
"section": "D100",
"title": "Special Topics in Biology",
"term": "Spring 2014",
"description": "Selected topics in areas not currently offered...",
"name": "BISC 372 D100",
"dept": "BISC",
},
"instructor": [
{
"lastName": "Smith",
"commonName": "Frank",
"phone": "1 555 555-1234",
"email": "franksmith#school.edu",
"name": "Frank Smith",
"roleCode": "PI"
},
{
"lastName": "Doe",
"commonName": "John",
"phone": "1 555 555-9876",
"email": "johndoe#school.edu",
"name": "John Doe",
"roleCode": "PI"
}
]
}
(a bunch of non-relevant fields omitted)
Each outline object may contain an instructor property which is an array of 0..n instructor objects for the course. For each member of the instructor array, I need to then call another API to get additional data. When that call returns, I need to insert it into the right instructor object.
Finally, when everything is done, the data gets passed to a template for express to render and return to the client.
I've tried getting this working using async and had some success with async.waterfall when doing a proof-of-concept with only getting one of the instructor profiles (e.g. not looping over the array, just getting instructor[0]). The async module's docs are comprehensive, but pretty dense and I'm having a hard time determining what I actually need to do. I had a Frankenstein combination of various nested async calls which still didn't work.
I don't really care how I accomplish the task - flow-control, promises, magic pixie dust, whatever. Any hints greatly appreciated.
Using Q for promises, you can probably do something like this:
return Q
.all(course_ids.map(function(course) {
return HTTP.GET(course); // Assuming this returns a promise
}))
.then(function(course_data) {
var instructors = [];
course_data.forEach(function(course) {
var p = Q
.all(course.instructor.map(function(instructor) {
return HTTP.GET(instructor.id);
}))
.then(function(instructors) {
course.instructors_data = instructors;
return course;
});
promises.push(p);
});
return Q.all(promises);
});
Will resolve with an array containing the courses, each of which contains
an array of instructor data in its instructors_data value.
You could use async.each(), which would do the API requests in parallel (assuming there is no concurrent API request limits on the server side, if that is the case, use async.eachLimit() instead):
async.each(instructors, function(instructor, callback) {
// call API here, store result on `instructor`,
// and call `callback` when done
}, function(err){
if (err)
console.log('An error occurred while processing instructors');
else
console.log('All instructors have been processed successfully');
});

Resources