UNPKG

asksuite-core

Version:
251 lines (197 loc) 6.67 kB
const Util = require('./util'); const RequestPreprocessor = require('./util/RequestPreprocessor'); const _ = require('lodash'); const md5 = require('md5'); const IntentResolver = require('./util/IntentResolver'); const AsksuiteTranslator = require('./util/Translator'); const AsksuiteUtil = require('./asksuite.util')({}); const DEFAULT_LANGUAGE = 'pt-br'; class AsksuiteProcessingNaturalUtils { static get EXPIRATION_TIME() { return 60 * 60 * 24; } // 24 hrs constructor(config) { this.config = config; if (!_.isEmpty(_.get(this.config, 'redis'))) { this.redis = this.config.redis; } } withRedis() { return !_.isEmpty(_.get(this.config, 'redis')); } resolveLanguage(paramLanguage, languages) { let language; if (languages) { language = _.find(languages, _.matchesProperty('formatIso', paramLanguage)); if (language) { return language.formatIso; } language = _.find( languages, _.matchesProperty('parentLanguage', paramLanguage.substring(0, 2)), ); if (language) { return language.formatIso; } } language = paramLanguage.toLowerCase(); if (language.startsWith('pt')) { return DEFAULT_LANGUAGE; } else if (language.startsWith('en')) { return 'en-us'; } else if (language.startsWith('es')) { return 'es-es'; } else { return language; } } async getInCacheDialogflow(request) { if (!this.withRedis()) { return Promise.resolve(null); } const hash = this.generateHash(request); const language = this.resolveLanguage(request.language, request.languages); const data = await this.getInCache(`dialogflow:${language}:${hash}`); if (!data) { return Promise.resolve(null); } const { intent, extractedData } = data; console.log(`OBTAINED BY CACHE ${intent}`); return { intent, extractedData }; } findDialogByIntent(request, intent) { const { intents, companyId, text } = request; const intentResolver = new IntentResolver(intents, companyId, text); return intentResolver.findDialogByIntent(intent); } generateHash(request) { const { text } = request; const plainText = _.chain(text) .deburr() // special characters .toLower() // lowercase .value() // get value from chain .replace(/\s{2,}/g, ' ') // remove duplicate spaces .replace(/[^\w\/@ ]/g, ''); // remove all characters dont in (word, /, @, space) return md5(plainText || text); } async saveInCacheDialogflow(intent, request) { if (!this.withRedis()) { return Promise.resolve(null); } if (Util.isNaoentendi(intent.intent)) { return Promise.resolve(null); } const { text } = request; const hash = this.generateHash(request); const language = this.resolveLanguage(request.language, request.languages); return this.setInCache(`dialogflow:${language}:${hash}`, { intent: intent.intent, extractedData: intent.extractedData, text, hash, }); } async removeInCacheDialogflow({ text, language }) { if (!this.withRedis()) { return Promise.resolve(null); } const normalizedLanguage = this.resolveLanguage(language); const hash = this.generateHash({ text }); const key = `dialogflow:${normalizedLanguage}:${hash}`; return this.removeInCache(key); } async removeInCache(key) { return this.redis.remove(`${key}`); } async getInCache(key) { return this.redis.getValue(`${key}`); } async setInCache(key, intent) { return this.redis.setValueWithExpirationTime( `${key}`, intent, true, AsksuiteProcessingNaturalUtils.EXPIRATION_TIME, ); } async translateRequest(request) { if ( this.resolveLanguage(request.language, request.languages) !== DEFAULT_LANGUAGE && !request.translation ) { request.translated = true; const asksuiteTranslator = new AsksuiteTranslator( request.config.INFOCHAT_DATA_SERVER, request.config.GOOGLE_TRANSLATE_KEY, ); const { translation } = await asksuiteTranslator.googleTranslateIfNeeded( request.text, request.language, request.languages, ); request.translation = translation; } } defineRegexLanguages(languages) { if (!languages || _.isEmpty(languages)) { return new RegExp('(pt|en|es|fr)', 'i'); } const joinedLanguages = _.chain(languages) .split(formatIso => formatIso.split('-')[0]) .uniq() .join('|') .value(); return new RegExp(`(${joinedLanguages})`, 'i'); } async detectLanguage(request) { const { GOOGLE_TRANSLATE_KEY } = request.config; const [detection] = await AsksuiteTranslator.detectLanguage(GOOGLE_TRANSLATE_KEY, request.text); const re = this.defineRegexLanguages(request.companyLanguages); const fallbackLanguage = 'en'; const languageCode = detection.language; const isSupported = re.test(languageCode); const outputLanguageCode = isSupported ? this.resolveLanguage(languageCode, request.languages) : fallbackLanguage; const language = await AsksuiteTranslator.getLanguageByCode( GOOGLE_TRANSLATE_KEY, AsksuiteUtil.resolveLanguageGoogle(languageCode, request.languages, 'formatGoogle'), AsksuiteUtil.resolveLanguageGoogle(outputLanguageCode, request.languages, 'formatGoogle'), ); return Object.assign(detection, { isSupported, language, fallbackLanguage, }); } async copyRequestToDefaultLanguage(request) { await this.translateRequest(request); const toSend = _.clone(request); toSend.text = toSend.translation || toSend.text; toSend.language = DEFAULT_LANGUAGE; return RequestPreprocessor.process(toSend); } async findIntentDialogFlow(dialogFlowAccessor, request, toDefaultLanguage) { if (toDefaultLanguage) { await this.translateRequest(request); } let fromCache = false; let toSend = request; if (toDefaultLanguage) { toSend = await this.copyRequestToDefaultLanguage(request); } let intent = await this.getInCacheDialogflow(toSend); if (!intent) { intent = await dialogFlowAccessor.resolveText(toSend); await this.saveInCacheDialogflow(intent, toSend); } else { fromCache = true; } const extractedData = intent.extractedData; intent = this.findDialogByIntent(toSend, intent.intent); intent.fromCache = fromCache; intent.extractedData = extractedData; return intent; } } module.exports = AsksuiteProcessingNaturalUtils;