I am using dialogflow to build a chatbot. Following is a sample question array but the format of the actual and the sample is same:
qstion[{
Question 1, What is 33+32?,
Okay, Question 2, What is 76+32?,
Okay, Last Question, Did you like the game?
}]
I am using the following code to get the length of the array:
app.intent('First', (conv) => {
const ans = conv.parameters.any;
if(ans == 65){
senddata[0] = qstion[0] + ans;
conv.add(qstion.length);
conv.ask(qstion[1]);
}
else{
conv.add('Please enter a valid number');
conv.ask(qstion[0]);
}
});
The app crashes here. Can you help me get the length of the array?
Update:
This is how it shows on the log when I use console.log(qstion) :
qstion[
'Question1, What is 33+32',
'Okay, Question2, What is 76+32',
'Okay, Last Question, Did you like the game'
]
As your question has the "dialogflow" tag I assume you are using the actions-on-google library. The problem you're seeing is not that your array length is wrong, but that you're using the wrong method to send a response.
In actions-on-google, you would call conv.ask or conv.close to ask a question or close the conversation respectively.
Your code snippet shows conv.add(qstion.length). However, in the library you are using conv.add does not exist, likely the cause of the crash. conv.add only works when using the new Actions Builder and the #assistant/conversation library, both of which aren't compatible with Dialogflow.
That is not a valid array, or rather a valid object in an array. I assume you meant for this to be an array of strings like
qstion = [
"Question 1",
"What is 33+32?",
"Okay",
"Question 2",
"What is 76+32?",
"Okay",
"Last Question",
"Did you like the game?"
]
Related
I'm trying to extract variable(s) from sentences with node-nlp using the following code:
const { NlpManager, ConversationContext } = require('node-nlp');
const manager = new NlpManager({ languages: ['en'] });
const context = new ConversationContext();
(async () => {
manager.addDocument('en', 'Hello my name is %name%', 'greeting.hello');
manager.addDocument('en', 'I have to go', 'greeting.bye');
manager.addAnswer('en', 'greeting.hello', 'Hey there!');
manager.addAnswer('en', 'greeting.bye', 'Till next time, {{name}}!');
manager.train();
const result1 = await manager.process('en', 'Hello my name is Thierry', context);
console.log(result1);
console.log(context);
const result2 = await manager.process('en', 'I have to go', context);
console.log(result2);
})();
The context doesn't contain a name variable...
I opened an issue directly on the github project page but the answer suggested to add this:
manager.addNamedEntityText(
'name',
'John',
['en'],
['john', 'John'],
);
But it's not exactly what I want because a variable name is added only if there is either "John" or "john" for the name in the sentence.
I also saw in this issue https://github.com/axa-group/nlp.js/issues/133#issuecomment-503223171 what there are restrictions on variable names.
Thanks for your help!
Thierry
Is an error in the documentation.
This can be implemented, but the problem is the "limitations" or the misanderstanding of how it will work.
I mean, it can be implemented that way: when training, it can detect entities present in the utterances that are not in the NER, then detect if the entities are the last part of a sentence, and then build a new Trim entity based on the words before the entity. So given "hello my name is %name%" it can resolve that given this intent, it should try to search the word "is" and the things after can be the entity.
But now then are problems, and are the reasons why is not implemented:
- Someone can write "Hello my name is John and I want a beer", then the chatbot can extract the entity and think that the name is "John and I want a beer".
- If to avoid that you think on extracting only one word, then "Hello my name is Paul Henri" will think that the name is "Paul".
- If it's searching by the word "is" then "Hello today is a wonderfull day and my name is John" will think that the name is "a wonderfull day and my name is John".
So to achieve what you want I recommend you to take a look here: https://github.com/axa-group/nlp.js/blob/master/docs/ner-manager.md#trim-named-entities
This tell you how to implement trim named entities based on the position to another words.
By the way, I'll fix the error in the docs.
I hope someone can help me with this.
I have built an application that uses node.js to fulfil my intent in dialogflow.
For example, I have an intent with one required action:
It goes to my fulfilment:
// Handle the Dialogflow intent named 'Default Welcome Intent'.
app.intent(DEFAULT_INTENT, (conv, params) => {
let categoryId = params.category;
let options = {
'method': 'GET',
'url': apiUrl + 'questions/categories/' + categoryId + '/scenario',
'json': true
};
return request(options).then(response => {
// TODO: What happens if there is more than one question?
let question = response[0];
conv.ask(question.text);
}, error => {
conv.ask('There was an issue with the request: ' + options.url);
});
});
As you can see, this asks a question based on the category sent to the fulfilment.
The problem I have is that the response I want from the user is different for each question.
Once they have responded, it will also have a fulfilment that will ask another question.
Is it possible to do it this way and if so, can someone give me an example of how? If not, can someone help me work out what the alternative is?
The approach you're using makes sense. The key thing to remember is that Intents capture what the user says, not how you handle what they say. You can influence which Intent gets triggered by setting an Input Context, and making sure you have previously set an Output Context for it.
One possible approach would be that for each question you're asking, you set a corresponding Output Context for that question. You can then have one or more Intents that take this as the Input Context. These are otherwise regular Intents, so you'd handle them normally. You might want to clear the context (by setting its lifespan to 0) after it matches, so you don't accidentally match it later.
For example, if your question contains, not only the text of the question, but also the context name of the question, the code might look something like this:
conv.ask( question.text );
conv.contexts.set( question.contextName, 5 );
Let's say that the question object looks something like this
{
text: "What is your favorite color?",
contextName: "color-favorite"
}
You might have a Dialogflow Intent that handles this that looks something like this
Note that the Output Context has explicitly set it to 0, which will remove it. You can also do this in your fulfillment code with something like
conv.contexts.delete( 'color-favorite' );
Heyo!
So, I made a discord bot with a command that randomly picks an anime out of a list of variables. But since I am new I kind of no idea how to Combine that with an embed, meaning the Chose item is displayed in an embed.
var facts = ["Item1", "Item2", "Item 3", "Item 4" ];
var fact = Math.floor(Math.random() * facts.length);
if (message.content.startsWith (prefix + "random")){
message.channel.send(facts[fact])
}
I was trying several things but none of my attempts worth showing here - I hope this is enough of code getting the permission to post it here.
Assuming you're using Discord.js because your code looks like Javascript, have a look at AnIdiotsGuide about Discord.js's embeds in messages.
For a very basic embed, your code needs to be something along the lines of
if (message.content.startsWith (prefix + "random")){
message.channel.send({embed: {
color: 3447003, // Or any other color desired
description: "Here is your random Fact: " + facts[fact]
}});
}
I've got a prompt for an SMS bot in which the user can make multiple choices. I'm looking for a pattern for a ChoicePrompt that allows me to do this:
show multiple selections
then after the user selects and answer, re-prompt them to answer again
Remove their previous choice(s) and add an "exit" option to move on
Automatically end the step if they've selected everything.
I'd like to avoid creating a new prompt w/switch cases for each answer tier, as this pattern needs to be implemented in a lot of places...
Example:
bot: User, what do you do to relax?
Exercise
Read a book
Nothing
user: Exercise
bot: Exercise, cool. What else?
Read a book
Nothing else
user: Read a book
bot: OK, you've done everything so we're moving on!
The botframework don't have a ListPrompt that I can see, at least for v4. They do however, have Suggested Actions you can use for this!!! The Botbuilder-Samples repo has a Suggested Action sample that shows a list of three colors:
async onTurn(turnContext) {
// See https://aka.ms/about-bot-activity-message to learn more about the message and other activity types.
if (turnContext.activity.type === ActivityTypes.Message) {
const text = turnContext.activity.text;
// Create an array with the valid color options.
const validColors = ['Red', 'Blue', 'Yellow'];
// If the `text` is in the Array, a valid color was selected and send agreement.
if (validColors.includes(text)) {
await turnContext.sendActivity(`I agree, ${ text } is the best color.`);
} else {
await turnContext.sendActivity('Please select a color.');
}
// After the bot has responded send the suggested actions.
await this.sendSuggestedActions(turnContext);
} else if (turnContext.activity.type === ActivityTypes.ConversationUpdate) {
await this.sendWelcomeMessage(turnContext);
} else {
await turnContext.sendActivity(`[${ turnContext.activity.type } event detected.]`);
}
}
An option would be to programatically create the array (in the example above, it's "const validColors") and if the reply is in the list of colors, recreate the array however you want without the chosen option.
I'm trying to figure out how to parse a form entry to set the model attribute to something else; e.g., extracting the video ID of a youtube video from a URL input. Is there a way to use parsers/formatters (6.21 features?) to accomplish this easily? I hoped to find a good example for this, and maybe there is one somewhere, but perhaps this would make a good one if there's not.
Here is a working example of what I'm attempting to accomplish, but in multiple steps and without the use of parsers. Any help adapting the code to set model.videoID from a URL in a single step (or fewer than 3 steps, at least) would be very appreciated. Thank you for your help with this and my other past questions. :)
Wow, this was much easier than I expected to implement. Here is the modification of the JS Bin which uses parsers, recently added with angular-formly#6.21.0, to extract the video ID from a YouTube URL in one function. It also, conveniently, validates itself!
Here is the relevant code, to summarize:
{
key: 'vidid',
type: 'input',
parsers: [extractID],
templateOptions: {
label: 'YouTube Video',
placeholder: 'Insert video URL here'
},
...
function extractID(value) {
if (value != undefined || value != '') {
var regExp = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=|\?v=)([^#\&\?]*).*/;
var match = value.match(regExp);
if (match && match[2].length == 11) {
return match[2];
}
}
};