Comments (18)
It is very unlikely that somebody will give you that, especially if you want a Spark specific example.
I could try to help if you shared your code and asked about specific issues with it.
from botkit-middleware.
Fair answer, although I'm literally trying to put together a sample bot using the sample code in this readme, especially the section on implementing actions using the updateContext method. So the question is, given that I want to use the code in this section, what is the minimum amount of code that's required in addition to that (that is, registration of the Watson middleware and basic triggers, etc.) for that code to work as expected? (assuming that Watson returns an action to execute, together with a 'please wait', etc.) I think that if you have an answer for Slack, it should be useful to see anyway.
This is what I tried:
- I hooked up middleware as follows:
controller.hears(['.*'], ['direct_message'], function(bot, message) {
watsonMiddleware.interpret(bot, message, function() {
if (message.watsonError) {
bot.reply(message, "I'm sorry, but for technical reasons I can't respond to your message");
} else {
processWatsonResponse(bot, message);
}
});
});
- I then used the 'processWatsonResponse' method in that section
Given the above combination, the bot runs into a loop apparently responding always to the same action, which leads me to believe that the sample code in that section is actually not really a working example. I'd be glad to see one such sample that really works. Hope this makes sense.
from botkit-middleware.
Please show the code of your processWatsonResponse function.
from botkit-middleware.
I took it literally from the relevant section in the readme file. In other words, just copying it below:
var processWatsonResponse = function (bot, message) {
if (message.watsonError) {
return bot.reply(message, "I'm sorry, but for technical reasons I can't respond to your message");
}
if (typeof message.watsonData.output !== 'undefined') {
//send "Please wait" to users
bot.reply(message, message.watsonData.output.text.join('\n'));
if (message.watsonData.output.action === 'check_balance') {
var newMessage = clone(message);
newMessage.text = 'balance result';
//check balance
checkBalanceAsync(message.watsonData.context).then(function (context) {
//update context in storage
return watsonMiddleware.updateContextAsync(message.user, context);
}).then(function () {
//send message to watson (it reads updated context from storage)
return watsonMiddleware.sendToWatsonAsync(bot, newMessage);
}).catch(function (error) {
newMessage.watsonError = error;
}).then(function () {
//send results to user
return processWatsonResponse(bot, newMessage);
});
}
}
};
Note that I've also used literally the checkBalance
function also defined in the same section in the readme.
from botkit-middleware.
Are you using the latest version of middleware?
I used this exact code in my bot and it worked correctly. The only difference was in fields set by checkBalance function. And I used middleware as a middleware, not with hears
.
from botkit-middleware.
Ah, interesting. Since you're not using 'hears', could you share your middleware registration? And, are you also using the following statement:
controller.on('message_received', processWatsonResponse);
or is it not necessary?
I suspect that the combination of all these things is what could be causing trouble for me
from botkit-middleware.
I can't look at my bot code until Monday, but I am pretty sure that it uses controller.on('message_received', processWatsonResponse);
There is nothing special in middleware registration too.
from botkit-middleware.
That is odd. In looking at my code and the logs again, I see the following problems:
1- the context is apparently not getting updated (I am using only temporary storage, not sure whether this is why) with the call to watson.updateContextAsync
2- Also, 'newMessage' appears to still have the field 'watsonData.output.action' set to the 'check_balance' action, which causes the loop :-)
If I manually update the context within newMessage before sending it Watson -inside of processWatsonResponse-, and also clear the 'action' field above, then the process does not loop. However, I've seen it misbehave at times in that the order of the responses might not be the correct one (that is, sometimes I seem to get the 'Please wait' message after the presentation of results (of the action) to the user. :-(.
Thanks for all your help with this!
from botkit-middleware.
Actually I have delete (newMessage.watsonData);
right after var newMessage = clone(message);
I thought that it is unimportant, because watsonData should be overwritten by the next response.
from botkit-middleware.
Unless I leave the 'hears' statement in place, Watson is not called at all in my case, which is why I had to leave it in :-(. So there must be something else distinguishing your bot from the sample, I believe. Could you include here your middleware registration steps? (even if there's nothing special to them)
from botkit-middleware.
To have a persistent storage you have to pass json_file_store
option to controller constructor or use a storage module:
var bot_options = {
json_file_store: __dirname + '/../.data/db/'
};
var controller = Botkit.sparkbot(bot_options);
Middleware registration code:
controller.middleware.receive.use(watsonMiddleware.receive);
from botkit-middleware.
Thanks for providing that. Even with those statements, my code does not appear to call Watson middleware at all unless I include the hears statement.
Here's the complete code I have right now for dealing with Watson (in theory should be pretty much equivalent to what you've described you had - note that I've replaced 'checkBalance' with 'createTicket' but this should not be an issue.).
var watsonMiddleware = require("botkit-middleware-watson")({
username: process.env.watson_username,
password: process.env.watson_pass,
workspace_id: process.env.watson_id1,
version_date: '2017-05-26',
minimum_confidence: 0.50, // (Optional) Default is 0.75
});
controller.middleware.receive.use(watsonMiddleware.receive);
var Promise = require("bluebird");
var clone = require("clone");
function createTicket(context, callback) {
context.ticketNum = 123;
context.ticketSuccess = true;
for (var i = 0; i < 1000000; i++) {
}
callback(null, context);
}
Promise.promisifyAll(watsonMiddleware);
var createTicketAsync = Promise.promisify(createTicket);
var processWatsonResponse = function (bot, message) {
if (typeof message !== 'undefined') {
if (typeof message !== 'undefined' && message.watsonError ) {
return bot.reply(message, "I'm sorry, but for technical reasons I can't respond to your message");
}
if (typeof message !== 'undefined' && typeof message.watsonData !== 'undefined' &&
typeof message.watsonData.output !== 'undefined') {
//send "Please wait" to users
bot.reply(message, message.watsonData.output.text.join('\n'));
if (message.watsonData.output.action && message.watsonData.output.action === 'create_ticket') {
var newMessage = clone(message);
newMessage.text = 'Ticket Creation Results';
// newMessage.watsonData.action = null; // NOTE: I had to add this to prevent infinite looping
createTicketAsync(message.watsonData.context).then(function (context) {
//update context in storage
return watsonMiddleware.updateContextAsync(message.user, context);
}).then(function () {
//send message to watson (it reads updated context from storage)
return watsonMiddleware.sendToWatsonAsync(bot, newMessage);
}).catch(function (error) {
newMessage.watsonError = error;
}).then(function () {
//send results to user
return processWatsonResponse(bot, newMessage);
});
} else {
console.log("Apparently no Watson action is present here...");
}
}
};
};
controller.on('message_received', processWatsonResponse);
As I mentioned, this code does not call Watson Middleware at all; the bot responds with the built-in sample responses (I've commented out most of the sample skills file, but still a few things remain in there, like the basic hello greeting, etc.).
from botkit-middleware.
Hey @pgoldweic where you able to fix this issue?
from botkit-middleware.
Thanks for asking. I got the code above working only when I do the following 3 things:
1- comment out the "controller.on('message_received', ...)" statement
2- use 'hears' as in the following:
controller.hears(['.*'], ['direct_message'], function(bot, message) {
watsonMiddleware.interpret(bot, message, function() {
if (message.watsonError) {
bot.reply(message, "I'm sorry, but for technical reasons I can't respond to your message");
} else {
processWatsonResponse (bot, message);
}
});
});
3- comment out the middleware registration line
In summary: I cannot get the example code working 'literally'. I think it's pretty unclear from the documentation how to combine the example code (for processing actions) with the middleware registration requirements.
Aside from this, I am now running into the problem that there are two messages presented to the user almost simultaneously (the 'please wait...' message that gets sent first within 'processWatsonResponse', and the next message for the user (that presumable explains to the user the results of having executed the action (in my example this action is 'createTicket', while the docs had a 'checkBalance')). The documentation does not cover this at all (that is, how to prevent these messages from being presented to the user simultaneously? Do we need to use 'startConversation'? Would be great if the example code for handling actions accounted for this problem and offered a solution.
from botkit-middleware.
It looks like you need a hands-on assistance, it should be something trivial, but you haven't shared your code yet, so we have no idea what went wrong.
I've read through CiscoSparkbot.js
- It calls receiveMessage.
- receiveMessage runs receive middleware and emits
message_receive
event after getting a result from middleware. - CiscoSparkbot handles message_received event and emits
direct_message event
.
Everything looks correct, please provide your code.
from botkit-middleware.
Thanks for providing that list of steps @Naktibalda; that's quite helpful. At least now I understand that any 'hears' statement (that filters on 'direct_message' events) will execute after the 'controller.on('message_received', processWatsonResponse);'
BTW, I did provide my code above (a big chunk of code, almost literally the sample code for implementing app actions using Watson middleware). In any case, I got the basic behavior working by using the 3 things I mentioned above, that is:
1- no middleware registration for Watson
2- a 'hears' statement that filters events and only calls middleware on 'direct_message'
3- no 'on message_received' event handler
For the record, here is the code once again:
var watsonMiddleware = require("botkit-middleware-watson")({
username: process.env.watson_username,
password: process.env.watson_pass,
workspace_id: process.env.watson_id1,
version_date: '2017-05-26',
minimum_confidence: 0.50, // (Optional) Default is 0.75
});
controller.hears(['.*'], ['direct_message'], function(bot, message) {
watsonMiddleware.interpret(bot, message, function() {
if (message.watsonError) {
bot.reply(message, "I'm sorry, but for technical reasons I can't respond to your message");
} else {
processWatsonResponse (bot, message);
}
});
});
var Promise = require("bluebird");
var clone = require("clone");
function createTicket(context, callback) {
context.ticketNum = 123;
context.ticketSuccess = true;
for (var i = 0; i < 1000000; i++) { // faking something happens
}
callback(null, context);
}
Promise.promisifyAll(watsonMiddleware);
var createTicketAsync = Promise.promisify(createTicket);
var processWatsonResponse = function (bot, message) {
if (typeof message !== 'undefined') {
if (typeof message !== 'undefined' && message.watsonError ) {
return bot.reply(message, "I'm sorry, but for technical reasons I can't respond to your message");
}
if (typeof message !== 'undefined' && typeof message.watsonData !== 'undefined' &&
typeof message.watsonData.output !== 'undefined') {
//send "Please wait" to users
bot.reply(message, message.watsonData.output.text.join('\n'));
if (message.watsonData.output.action && message.watsonData.output.action === 'create_ticket') {
var newMessage = clone(message);
newMessage.text = 'Ticket Creation Results';
newMessage.watsonData.action = null; // this was needed to prevent infinite loop
createTicketAsync(message.watsonData.context).then(function (context) {
//update context in storage
return watsonMiddleware.updateContextAsync(message.user, context);
}).then(function () {
//send message to watson (it reads updated context from storage)
return watsonMiddleware.sendToWatsonAsync(bot, newMessage);
}).catch(function (error) {
newMessage.watsonError = error;
}).then(function () {
//send results to user
return processWatsonResponse(bot, newMessage);
});
} else {
console.log("Apparently no Watson action is present here...");
}
}
};
};
My current issue then is that I am getting the two replies to the user essentially simultaneously (the first being the 'please wait...', the second reply being the response given to the user after this 'createTicket' action is taken. I am wondering whether I need to do something explicit to prevent that (e.g. use 'startConversation' or something like it? I have no experience with conversations in Botkit yet), or whether this is happening simply due to the shape of my 'createTicket' function (which is imitating the 'checkBalance' of the example).
from botkit-middleware.
Instead of heating CPU with for (var i = 0; i < 1000000; i++) { }
you could use setTimeout(function() { callback(null, context); }, 5000);
from botkit-middleware.
Thanks, that actually worked! So in fact it was the silly function causing the problem after all :-). Glad that it's not necessary to use 'startConversation' to get this to work.
Thanks again for your help @Naktibalda
from botkit-middleware.
Related Issues (20)
- Is there a WhatsApp step-by-step tutorial similar to FB integration? HOT 1
- An in-range update of botkit is breaking the build 🚨
- An in-range update of botbuilder-adapter-slack is breaking the build 🚨
- An in-range update of botbuilder-adapter-web is breaking the build 🚨 HOT 1
- TypeError: this.sendToWatson is not a function HOT 8
- need some migration help (migrating out of 1.4.0) HOT 5
- Can't set context before middleware starts HOT 2
- watson middleware is not working behind http proxy - Response not received. Body of error is HTTP ClientRequest object HOT 1
- Which version of watson-developer-cloud is safe to upgrade to, if using middleware version 1.8.2? HOT 2
- intent matching not working as intended on controller.hears HOT 4
- Cannot connect to Slack HOT 4
- Make sure Watson Assistant context has an expiry value (Redis storage) HOT 4
- Sample code for Watson and Facebook Integration HOT 4
- controller.hears doesn't trigger when use wrapper for receive handler HOT 3
- Next() function for receive function HOT 3
- Upgrade ibm-watson dependency to v6 HOT 1
- Found a couple of documentation bugs HOT 1
- odd context resetting problem and question HOT 3
- Slack Integration with IBM Watson Assistant won't accept new line in user queries. HOT 1
- Error: 404 Resource not Found HOT 17
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from botkit-middleware.