Skip to content

Instantly share code, notes, and snippets.

@SpiffGreen
Created July 25, 2021 00:41
Show Gist options
  • Save SpiffGreen/9d6cbb39ffcd8e18510dbf0f96fa2c6c to your computer and use it in GitHub Desktop.
Save SpiffGreen/9d6cbb39ffcd8e18510dbf0f96fa2c6c to your computer and use it in GitHub Desktop.
A simple rule-based chatbot developed with javascript
const bot = require("./training");
console.log("Hello I'm Bujo. Let's Talk :)");
bot.converse();
"use strict";
const readline = require("readline");
const chalk = require("chalk");
const prompt = readline.createInterface({
input: process.stdin,
output: process.stdout
});
// Utilities
function input(self, str = "> ") {
prompt.question(str, (value) => {
const result = self.process(value);
if(result.answer) {
process.stdout.write(chalk.yellow(result.answer) + "\n");
if(value.includes("bye")) {
prompt.close();
process.exit();
}
input(self, str);
} else {
process.stdout.write("Sorry please could you rephrase that?" + "\n");
input(self, str);
}
});
// prompt.close();
}
function randomBetween(min, max) {
return Math.floor(Math.random() * (max - min + 1) + min);
}
function flattenArray(arr) {
let result = [];
arr.forEach(i => {
if(!Array.isArray(i)) {
result.push(i);
} else {
result.push(...flattenArray(i));
}
});
return result;
};
/** Test
const testArr = [
[1, 2, 3, 4],
5, 6, 7,
[8, 9, 10, [11, 12, [13, 14, 15], 16]],
];
*/
// function processData(reg, str, template) {
// // const m = /hello|hi\s+([^\s]+)/g.exec(str);
// const m = reg.exec(str);
// for(let i = 1; i < m.length; i++) {
// console.log(i);
// template = template.replace(`%${i}`, m[i]);
// }
// return template;
// }
function processData(match, templates) {
const newTemp = templates.map(template => {
for(let i = 1; i < match.length; i++) {
template = template.replace(`%${i}`, match[i]);
}
return template;
});
return newTemp;
}
/**
* @description A simple example of nlp functions for building chatbots
*
*/
class Simple_Nlp {
constructor() {
this.__Markers = Object.create(null);
this.__Rules = Object.create(null);
this.__Answers = Object.create(null);
// Bind methods
this.addRule = this.addRule.bind(this);
this.addAnswer = this.addAnswer.bind(this);
this.train = this.train.bind(this);
this.process = this.process.bind(this);
this.converse = this.converse.bind(this);
}
// Use String.raw to create string using
addRule(rule, marker) {
this.__Markers[marker] ? this.__Markers[marker] += `|${rule}` : this.__Markers[marker] = rule;
if(!this.__Answers[marker]) this.__Answers[marker] = Array();
}
addAnswer(marker, answer) {
if(!this.__Answers[marker]) throw new Error(`Sorry '${marker} does not exist`);
this.__Answers[marker].push(answer);
}
train() {
for(let marker in this.__Markers) {
this.__Rules[marker] = new RegExp(this.__Markers[marker], "gim");
}
}
/**
* @todo Add formatted output
*/
process(str) {
const result = Object.create(null);
result.utterance = str;
result.possibleAnswers = Array();
result.classifications = Object.create(null);
for(let marker in this.__Rules) {
// let match = str.match(this.__Rules[marker]);
let match = this.__Rules[marker].exec(str);
if(match) {
result.classifications[marker] = match;
result.possibleAnswers.push(processData(match, this.__Answers[marker]))
}
}
result.possibleAnswers = flattenArray(result.possibleAnswers);
result.answer = result.possibleAnswers[randomBetween(0, result.possibleAnswers.length - 1)];
return result;
}
converse() {
input(this);
}
}
const nlp = new Simple_Nlp();
module.exports = {
bot: nlp,
r: String.raw
};
const {bot, r} = require("./simple-nlp");
// console.log(r);
// Possible questions
// bot.addRule('hi', "greeting.hi");
bot.addRule("hey", "greeting.hi");
bot.addRule("hello", "greeting.hi");
bot.addRule("how are you", "ask.about");
bot.addRule("whatsup", "ask.about");
bot.addRule("howfar", "ask.about");
bot.addRule("your name", "ask.self");
bot.addRule("sex", "ask.sex");
bot.addRule("bye", "greeting.bye");
bot.addRule("fine", "answer.greeting");
bot.addRule("great", "answer.greeting");
bot.addRule("good", "answer.greeting");
bot.addRule("sorry", "answer.plead");
bot.addRule("order", "business.order");
bot.addRule("purchase", "business.order");
bot.addRule(r`i want ([^\s]+)`, "business.order");
bot.addRule(r`i need ([^\s]+)`, "business.order");
bot.addRule("Menu", "business.menu");
bot.addRule("List", "business.menu");
bot.addRule("Products", "business.menu");
// Answers
bot.addAnswer("greeting.hi", "Hello dear how are you?");
bot.addAnswer("greeting.hi", "How are you?");
bot.addAnswer("greeting.hi", "Hi, how can i help you?");
bot.addAnswer("greeting.bye", "Ok see you around");
bot.addAnswer("greeting.bye", "It was nice talking with you");
bot.addAnswer("ask.about", "I'm doing great, how can I help you?");
bot.addAnswer("ask.self", "I am a bot Created by Spiff");
bot.addAnswer("ask.sex", "๐Ÿ˜‚ Hey I am a bot");
bot.addAnswer("ask.sex", "๐Ÿ˜‚ Ha thats funny, you know i'm not human right?");
bot.addAnswer("answer.greeting", "That's good to know");
bot.addAnswer("answer.greeting", "That's great");
bot.addAnswer("answer.plead", "It's all good.");
bot.addAnswer("business.order", "You want to place an order, Contact +234 701 0990 0405");
bot.addAnswer("business.order", "You want to make a purchase, Contact +234 701 0990 0405");
bot.addAnswer("business.order", "Your order for %1 has been placed. :)")
bot.addAnswer("business.menu", "We sell eggs, milk, chickens, chicken feed, fish, etc");
// Test
bot.addRule(r`my name is ([^\s]+)`, "intro.name");
bot.addAnswer("intro.name", "Hello %1");
// Train bot
bot.train();
module.exports = bot;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment