Josh Marinacci
Head of Developer Evangelism
Serverless Chatbots
[image of a chatbot]
AI + network = Chatbot
Your requirements
- Domain Knowledge
- Artificial Intelligence
- Realtime Infrastructure
Your requirements, not your focus
- Domain Knowledge
- Artificial Intelligence
- Realtime Infrastructure
Don't build your own infrastructure
Don't build your own AI
Focus on your domain knowledge
Demo Time
EmojiBot
HeartBot Code
export default (request) => {
var txt = request.message.text;
txt = txt.replace(/poop/g,"\uD83D\uDCA9");
txt = txt.replace(/crap/g,"\uD83D\uDCA9");
txt = txt.replace(/love/g,"\uD83D\uDE0D");
txt = txt.replace(/heart/g,"\uD83D\uDC9C");
txt = txt.replace(/sad/g,"\uD83D\uDE1E");
txt = txt.replace(/happy/g,"\uD83D\uDE04");
request.message.text = "Your message isn't hearty enough!"
+" There I fixed it: <br/>"
+ txt;
return request.ok(); // Return a promise when you're done
}
HeartBot Architecture
Serverless !== No Servers
Cloudinary
ImageBot
ImageBot Architecture
ImageBot NLP
var words = text.split(" ")
.map((w)=>w.toLowerCase())
.filter((w)=>{
if(w === 'the')return false;
if(w === 'it') return false;
if(w === 'to') return false;
if(w === 'at') return false;
if(w === 'in') return false;
return true;
});
console.log("words",words);
if(!words.includes("please")) return false;
var n = words.findIndex((w) => w === 'please');
var verb = words[n+1];
if(verb === 'upload') return upload(words);
if(verb === 'display') return display(rest);
if(verb === 'show') return show(rest);
if(verb === 'resize') return resize(rest);
if(verb === 'reset') return reset(rest);
if(verb === 'make' && nextWord === 'square') return makeSquare(rest);
...
{
"action":"resize"
}
ImageBot Cloudinary Service Calls
return db.get('context').then((context) => {
if(!context) context = {};
var command = request.message;
if(command.action === 'resize') context.width = command.size;
if(command.action === 'crop') {
context.crop = true;
context.shape = 'square';
context.gravity = command.gravity;
}
//generate the final url
let apiUrl = 'http://res.cloudinary.com/' +
cloudName + '/' + resource + '/' + operation + '/';
apiUrl += filename + '.' + context.format;
//save the url
request.message.cloudinaryURL = apiUrl;
db.set('context',context); //save the context
return request.ok(); // Return the final message
});
ImageBot lesson
Don't built your own NLP
MR ROCKBOT Architecture
IBM Watson Text Alchemy API
Detect Language and Translate
const query_params = {
outputMode:'json',
apikey:'494a8df6f920d85b1de4a8172c21dbc264d6446f',
extract:'keywords,relations,language',
maxRetrieve: 1,
text:request.message.text
};
var url = "http://gateway-a.watsonplatform.net/calls/text/TextGetCombinedData?"
+query.stringify(query_params);
return xhr.fetch(url).then((x)=>{
var ret = JSON.parse(x.body);
if(ret.language != 'english') {
return translateMessage(request.message, ret.language);
}
return cookMessage(ret);
});
IBM Watson Text Alchemy API
IBM Watson Conversations
Use Conversations API
var url = creds.url+'/v1/workspaces/'+creds.workspaceID+'/message?version=2016-09-20';
var payload = { input: { text: request.message.text } }
return kvstore.get("context").then((ctx) => {
if(ctx) payload.context = ctx;
const http_options = { method:'POST', body: JSON.stringify(payload) }
return xhr.fetch(url, http_options).then((x)=>{
var body = JSON.parse(x.body);
return kvstore.set("context",body.context).then(()=>{
request.message.text = body.output.text[0];
request.message.watson = body;
return request.ok();
});
}).catch((e)=>{
console.log("ERROR");
return request.ok();
});
});
Bonus!
Realtime isn't just for text
Don't build your own AI
Don't build your own realtime infrastructure.
- Cloudinary
- IBM Watson
- PubNub
@joshmarinacci
josh@pubnub.com