asksuite-core
Version:
232 lines (190 loc) • 8.23 kB
JavaScript
const AWSLambdaCaller = require('./services/AWSLambdaCaller');
const Util = require('./util');
const MediaResolver = require('./util/MediaResolver');
const DialogFlowAccessor = require('./services/DialogFlowAccessor');
const QuoteDataAccessor = require('./services/QuoteDataAccessor');
const KeyMatcherAccessor = require('./services/KeyMatcherAccessor');
const RasaAccessor = require('./services/RasaAccessor');
const RasaLayersAccessor = require('./services/RasaLayersAccessor');
const RasaLayersRedisService = require('./services/RasaLayersRedisService');
const defaultFallbackIntent = require('./util/defaultFallbackIntent');
const RequestPreprocessor = require('./util/RequestPreprocessor');
const AsksuiteProcessingNaturalUtils = require('./AsksuiteProcessingNaturalUtils');
const NodeCache = require('node-cache');
const DEFAULT_LANGUAGE = 'pt-br';
const intentsNotFoundCache = new NodeCache({ stdTTL: 300, checkperiod: 120 });
class AsksuiteProcessingNatural {
static get ORDERED_ACCESSORS() {
return ['RASA_LAYERS', 'DIALOG_FLOW', 'RASA', 'KEY_MATCHER'];
} // Robot will search for intents in this order default
static get RASA_FIRST_ORDERED_ACCESSORS() {
return ['RASA', 'RASA_LAYERS', 'DIALOG_FLOW', 'KEY_MATCHER'];
} // Robot will search for intents in this order if tryRasaFirst option is set to true
constructor(config) {
this.config = config;
this.utils = new AsksuiteProcessingNaturalUtils(this.config);
this.rasaLayersRedisService = new RasaLayersRedisService({
config: config.config,
redis: config.redis,
});
}
findIntent(request) {
return new Promise((resolve, reject) => {
const executor = async request => {
let intent = {
fromCache: false,
};
request = await RequestPreprocessor.process(request);
const awsLambdaCaller = new AWSLambdaCaller(request.config.CORE_LAMBDA_AWS);
const dialogFlowAccessor = new DialogFlowAccessor(awsLambdaCaller);
const keyMatcherAccessor = new KeyMatcherAccessor(awsLambdaCaller);
const rasaAccessor = new RasaAccessor(
request.config.RASA_URL,
request.config.RASA_CONFIDENCE_THRESHOLD,
);
const rasaLayersAccessor = new RasaLayersAccessor(awsLambdaCaller);
let orderOption = AsksuiteProcessingNatural.ORDERED_ACCESSORS;
if (request.tryRasaFirst) {
orderOption = AsksuiteProcessingNatural.RASA_FIRST_ORDERED_ACCESSORS;
}
request.findIntent = defaultFallbackIntent(request.companyId);
request.translated = false;
request.translation = null;
for (const accessorName of orderOption) {
switch (accessorName) {
case 'DIALOG_FLOW':
intent = await this.utils.findIntentDialogFlow(dialogFlowAccessor, request, false);
if (
Util.isNaoentendi(intent.intent) &&
this.utils.resolveLanguage(request.language, request.languages) !== DEFAULT_LANGUAGE
) {
intent = await this.utils.findIntentDialogFlow(dialogFlowAccessor, request, true);
}
break;
case 'KEY_MATCHER':
intent = await keyMatcherAccessor.resolveText(request);
if (
Util.isNaoentendi(intent.intent) &&
this.utils.resolveLanguage(request.language, request.languages) !== DEFAULT_LANGUAGE
) {
const toSend = await this.utils.copyRequestToDefaultLanguage(request);
intent = await keyMatcherAccessor.resolveText(toSend);
}
intent.keywordTry = { try: true };
break;
case 'RASA':
intent = await rasaAccessor.resolveText(request, request.needsRasaEntityConfident);
break;
case 'RASA_LAYERS':
if (request.order && request.order.length) {
let cached = null;
try {
cached = await this.rasaLayersRedisService.resolveText(
request.text,
request.language,
request.order,
request.languages,
);
} catch (e) {
console.error(e);
}
intent = cached ? cached : await rasaLayersAccessor.resolveText(request);
}
break;
}
request.findIntent = intent;
if (intent.intent && !Util.isNaoentendi(intent.intent)) {
intent.resolver = accessorName;
if (intent.resolver === 'KEY_MATCHER') {
intent.keywordTry.match = intent.intent;
intent.keywordTry.intent = intent.intent;
} else if (intent.resolver === 'RASA_LAYERS') {
await this.rasaLayersRedisService
.saveToCache(
intent,
request.text,
request.language,
intent.order,
request.languages,
)
.catch(console.error);
}
//FOR exit condition
break;
}
}
const language = this.utils.resolveLanguage(request.language, request.languages);
const key = `${request.companyId}.${request.userId}.${language}`;
if (Util.isNaoentendi(intent.intent)) {
let count = intentsNotFoundCache.get(key) || 0;
intentsNotFoundCache.set(key, ++count);
const {
ATTEMPTS_BEFORE_DETECTING_LANGUAGE,
LANGUAGE_DETECTION_CONFIDENCE,
} = request.config;
if (count === ATTEMPTS_BEFORE_DETECTING_LANGUAGE) {
const detection = await this.utils.detectLanguage(request);
if (detection.confidence >= LANGUAGE_DETECTION_CONFIDENCE) {
const languageCode = detection.isSupported
? detection.language.code
: detection.fallbackLanguage;
if (request.language.substring(0, 2) !== languageCode.substring(0, 2)) {
intent.languageDetected = detection;
intentsNotFoundCache.del(key);
}
}
}
if (count > 1 && !intent.languageDetected) {
const fallbackIntent = defaultFallbackIntent(request.companyId, count);
intent = this.utils.findDialogByIntent(request, fallbackIntent.intent);
}
} else {
intentsNotFoundCache.del(key);
}
intent.translated = request.translated;
intent.translation = request.translation;
return intent;
};
executor(request)
.then(resolve)
.catch(reject);
});
}
resolveMedia(request) {
return new Promise((resolve, reject) => {
try {
const mediaResolver = new MediaResolver(request.companyId);
mediaResolver
.resolve(request.media, request.intents)
.then(resolve)
.catch(reject);
} catch (e) {
reject(e);
}
});
}
async extractQuoteData(request) {
request = await RequestPreprocessor.process(request);
const awsLambdaCaller = new AWSLambdaCaller(request.config.CORE_LAMBDA_AWS);
const quoteDataAccessor = new QuoteDataAccessor(awsLambdaCaller);
return await quoteDataAccessor.resolveText(request);
}
async extractTextNumbers(request) {
request = await RequestPreprocessor.process(request);
const awsLambdaCaller = new AWSLambdaCaller(request.config.CORE_LAMBDA_AWS);
const quoteDataAccessor = new QuoteDataAccessor(awsLambdaCaller);
return await quoteDataAccessor.resolveTextNumbers(request);
}
async findRasaIntent(request) {
let intent = {};
intent = defaultFallbackIntent(request.companyId);
request.findIntent = intent;
request = await this.utils.copyRequestToDefaultLanguage(request);
const rasaAccessor = new RasaAccessor(
request.config.RASA_URL,
request.config.RASA_CONFIDENCE_THRESHOLD,
);
return await rasaAccessor.resolveText(request, request.needsRasaEntityConfident);
}
}
module.exports = AsksuiteProcessingNatural;