asksuite-core
Version:
150 lines (133 loc) • 4.4 kB
JavaScript
const request = require('request');
const FallbackResolver = require('../util/FallbackResolver');
const RequestPreprocessor = require('../util/RequestPreprocessor');
const { ErrorHandlerService } = require('./ErrorHandlerService');
const URLRegex =
/^[(http(s)?):\/\/(www\.)?a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)$/gi;
class OpenAiAccessor {
constructor(baseUrl, enabled, corePayload) {
this.baseUrl = baseUrl;
this.enabled = !!enabled;
this.corePayload = corePayload;
}
resolveText(request) {
console.log('[OpenAiAccessor.resolveText started]');
return new Promise((resolve) => {
const defaultIntent = FallbackResolver.fallbackWithDefaultIntent(request.intents) || {};
if (!this.enabled) {
console.warn('[OpenAiAccessor disabled]');
resolve(defaultIntent);
return;
}
const executor = async () => {
const cleanText = RequestPreprocessor.removeUtilityTexts(
RequestPreprocessor.removeEmoji(request.text),
).trim();
const companyId = this.parseCompanyId(request.companyId);
if (this.isNotUnderstandable(cleanText)) {
defaultIntent.processingStep = {
fallbackReason: 'text_not_understandable',
intentFound: 'naoentendi',
text: cleanText || '',
};
resolve(defaultIntent);
return;
}
try {
const result = await this.requestData(this.baseUrl, {
question: cleanText,
companyId,
language: request.language,
conversationId: (this.corePayload || {}).conversationId,
});
if (!result.body.choices) {
throw { message: result.statusMessage, code: result.statusCode };
}
const textResponse = result.body.choices[0].message.content;
console.log('[OpenAiAccessor textResponse]', textResponse);
if (this.textToKeyword(textResponse).endsWith('naoentendi')) {
defaultIntent.processingStep = {
fallbackReason: 'intent_not_found',
intentFound: null,
extraInfo: result.body.usage || null,
text: cleanText || '',
answer: textResponse || '',
};
resolve(defaultIntent);
return;
}
const generateDialog = this.generateDialog(companyId, textResponse);
resolve({
...generateDialog,
processingStep: {
fallbackReason: null,
intentFound: generateDialog.intent,
extraInfo: result.body.usage || null,
text: cleanText || '',
answer: textResponse || '',
context: result.body.metadata,
},
});
} catch (e) {
console.error('[OpenAiAccessor error]', e);
const errorData = ErrorHandlerService.accessorErrorHandler(e);
defaultIntent.processingStep = {
fallbackReason: 'intent_not_found',
intentFound: null,
errorData,
};
resolve(defaultIntent);
}
};
executor().then();
});
}
requestData(url, json) {
return new Promise((resolve, reject) => {
request.post(url, { json }, (err, res) => {
if (err) {
reject(err);
}
resolve(res);
});
});
}
parseCompanyId(name) {
let companyId = name;
if (companyId.indexOf('.') > -1) {
const splited = companyId.split('.');
companyId = splited[splited.length - 1];
}
return companyId;
}
generateDialog(companyId, text) {
return {
intent: 'openai',
dialog: `${companyId}.openai`,
value: this.clearResponse(text),
type: 'text',
goToDialog: `${companyId}.encerramento`,
};
}
clearResponse(text) {
if (text.startsWith('Resposta:')) {
return text.substr(10);
}
return text;
}
textToKeyword(text = '') {
return text
.toLowerCase()
.normalize('NFD')
.replace(/[^a-z]/g, '');
}
isNotUnderstandable(cleanText) {
return (
!cleanText || // empty string
!/\w/gi.test(cleanText) || // Only special chars
!/\D/gi.test(cleanText) || // Only digits
URLRegex.test(cleanText) // Only link
);
}
}
module.exports = OpenAiAccessor;