recime-bot-runtime
Version:
This runtime is intended to run inside a micro-service container with platform specific integration and module interpreter.
253 lines (252 loc) • 11.1 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
var request = require("request");
var flattern = require("lodash.flatten");
var bot_model_1 = require("./../bot-model");
var not_supported_1 = require("./services/not-supported");
var luis_1 = require("./services/luis");
var wit_1 = require("./services/wit");
var rasa_1 = require("./services/rasa");
var DefaultBlock = 'default';
var ConfidenceThreshold = 0.8;
var Nlp = /** @class */ (function () {
function Nlp() {
}
Nlp.request = function (context) {
var _this = this;
var args = context.args;
var body = this.processBody(args);
return new Promise(function (resolve, reject) {
return _this.getIntents(context).then(function (intents) {
var model = new bot_model_1.BotModel(context.bot.id);
if (body.event) {
var normalizedEvent_1 = body.event.toLowerCase();
var intent_1 = intents.find(function (i) { return i.name.toLowerCase() === normalizedEvent_1; });
if (!intent_1 || !intent_1.response || !intent_1.response.length) {
intent_1 = intents.find(function (i) { return i.name.toLowerCase() === DefaultBlock; });
}
return model.logIntentHit(intent_1.title).then(function () {
resolve({
response: intent_1.response
});
});
}
// const fuzzyMatched = FuzzyMatcher.findMatch(intents, body);
// if (fuzzyMatched
// && fuzzyMatched.response
// && fuzzyMatched.response.length) {
// console.log('fuzzy-response', fuzzyMatched.response);
// return model.logIntentHit(fuzzyMatched.title).then(() => {
// resolve({
// response: fuzzyMatched.response,
// nlp : {
// entities: [],
// intent : {
// name : fuzzyMatched.title,
// confidence: 1
// }
// }
// });
// });
// }
return _this.response(context, body).then(function (r) {
var unmapped = void 0;
if (r.intent === DefaultBlock) {
unmapped = true;
}
var intent = intents.find(function (i) { return i.name.toLowerCase() === r.intent; });
var tasks = [model.logIntentHit(intent.title)];
if (unmapped && body.text) {
tasks.push(model.logUnhandledMessage(body.text));
}
return Promise.all(tasks).then(function () { return resolve({
response: intent && intent.response,
nlp: r.response
}); });
}).catch(function (error) {
var intent = intents.find(function (i) { return i.name.toLowerCase() === DefaultBlock; });
return model.logIntentHit(intent.title).then(function () {
return resolve({
response: intent.response
});
});
});
});
});
};
Nlp.normalizeNlpResponse = function (context, nlp) {
var meta = context.bot.meta.rasa;
if (meta) {
return {
entities: (nlp.entities || []).map(function (e) {
e.entity = meta.entities.find(function (entity) {
return entity.name === e.entity;
}).title || e.entity;
return { confidence: e.confidence, entity: e.entity, value: e.value, start: e.start, end: e.end };
}), intent: {
name: nlp.intent.name ? flattern(meta.groups.map(function (g) {
return g.intents || [];
})).find(function (i) {
return i.name === nlp.intent.name;
}).title : nlp.intent.name || DefaultBlock, confidence: nlp.intent.confidence
}
};
}
return nlp;
};
Nlp.response = function (context, body) {
var _this = this;
var provider = this.getProvider(context.bot);
// process using NLP.
return provider.process(body).then(function (result) {
if (!result) {
return result;
}
console.log('nlp-response:', result);
var bestMatch;
if (provider instanceof wit_1.Wit) {
if (result.entities
&& result.entities.intent
&& result.entities.intent.length) {
var filteredMatches = result.entities.intent
.filter(function (x) { return x.confidence > ConfidenceThreshold; })
.sort(function (x, y) {
if (x.confidence > y.confidence) {
return 1;
}
if (x.confidence < y.confidence) {
return -1;
}
return 0;
})
.map(function (intent) { return intent.value; });
bestMatch = filteredMatches.length && filteredMatches[0];
}
}
else if (provider instanceof not_supported_1.NotSupported) {
if (result.intents && result.intents.length) {
var filteredMatches = result.intents
.filter(function (x) { return x.confidence > ConfidenceThreshold; })
.sort(function (x, y) {
if (x.confidence > y.confidence) {
return 1;
}
if (x.confidence < y.confidence) {
return -1;
}
return 0;
})
.map(function (intent) { return intent.slug; });
bestMatch = filteredMatches.length && filteredMatches[0];
}
}
else if (provider instanceof luis_1.Luis) {
bestMatch = result && result.topScoringIntent;
if (bestMatch &&
(bestMatch.intent || '').toLowerCase() !== 'none' &&
bestMatch.score > ConfidenceThreshold) {
bestMatch = bestMatch.intent;
}
else {
bestMatch = void 0;
}
}
else if (provider instanceof rasa_1.Rasa) {
bestMatch = result && result.intent;
if (bestMatch && bestMatch.confidence > ConfidenceThreshold) {
bestMatch = bestMatch.name;
}
else {
bestMatch = void 0;
}
}
return {
intent: bestMatch || DefaultBlock,
response: _this.normalizeNlpResponse(context, result)
};
});
};
Nlp.getProvider = function (bot) {
switch (bot.config.SYSTEM_RECIME_NLP.toLowerCase()) {
case 'wit': {
return new wit_1.Wit(bot);
}
case 'luis': {
return new luis_1.Luis(bot);
}
case 'rasa': {
return new rasa_1.Rasa(bot);
}
}
return new not_supported_1.NotSupported(bot);
};
Nlp.getIntents = function (context) {
var env = context.bot.config;
return new Promise(function (resolve, reject) {
request({
uri: 'https://nlp-api.recime.io/v1/graphql',
method: 'POST',
json: true,
headers: {
'x-recime-api-key': env.SYSTEM_RECIME_API_KEY
},
body: {
query: "\n query intents($botId: ID!) {\n intents(botId: $botId) { \n id\n name\n title\n expressions {\n id\n text\n }\n response {\n id\n type\n content\n }\n }\n }",
variables: {
botId: context.bot.id
}
}
}, function (error, response, body) {
if (body.errors) {
// eslint-disable-next-line no-console
console.error('ERROR:', JSON.stringify(body.errors, void 0, 2));
return reject(new Error(body.errors[0].message));
}
resolve(body.data['intents']);
});
});
};
Nlp.processBody = function (args) {
if (args.event && args.event.name) {
return {
event: args.event.name
};
}
var rawBody = args.rawBody || {};
if (process.env['SYSTEM_RECIME_NLP'] === 'wit') {
if (rawBody.message && rawBody.message.nlp) {
var confidenceThreshold_1 = 0.8;
var nlp = rawBody.message.nlp;
var bestMatch = void 0;
if (nlp.entities && nlp.entities["intent"]) {
bestMatch = nlp.entities.intent
.filter(function (x) { return x.confidence > confidenceThreshold_1; })
.sort(function (x, y) {
if (x.confidence > y.confidence) {
return 1;
}
if (x.confidence < y.confidence) {
return -1;
}
return 0;
})
.map(function (intent) { return intent.value; });
console.log('wit', bestMatch);
return {
event: bestMatch.length ? bestMatch[0] : DefaultBlock
};
}
if (!bestMatch) {
return {
event: DefaultBlock
};
}
}
}
return {
text: args.text
};
};
return Nlp;
}());
exports.Nlp = Nlp;