fix(kb.gbapp): Importing improved.

This commit is contained in:
Rodrigo Rodriguez 2020-08-26 17:50:42 -03:00
parent 31588a2f8a
commit 4cb9d5b906
4 changed files with 95 additions and 66 deletions

View file

@ -7,9 +7,9 @@ if installments > 60 then
talk "The maximum number of payments is 60" talk "The maximum number of payments is 60"
else else
talk "What is the amount requested?" talk "What is the amount requested?"
hear ammount hear amount
if ammount >100000 then if amount >100000 then
talk "We are sorry, we can only accept proposals bellow 100k" talk "We are sorry, we can only accept proposals bellow 100k"
else else
@ -57,12 +57,12 @@ else
' TODO: This must be reviewed in terms of financing logic. ' TODO: This must be reviewed in terms of financing logic.
nInstallments = parseInt(installments) nInstallments = parseInt(installments)
vAmmount = parseFloat(ammount) vamount = parseFloat(amount)
initialPayment = vAmmount * 0.3 ' 30% of the value initialPayment = vamount * 0.3 ' 30% of the value
tac = 800 tac = 800
adjustment = 1.3 adjustment = 1.3
totalValue = ammount - initialPayment + tac totalValue = amount - initialPayment + tac
paymentValue = totalValue * adjustment paymentValue = totalValue * adjustment
finalValue = paymentValue * nInstallments + initialPayment finalValue = paymentValue * nInstallments + initialPayment

View file

@ -1,17 +1,17 @@
' General Bots Copyright (c) Pragmatismo.io. All rights reserved. Licensed under the AGPL-3.0. ' General Bots Copyright (c) Pragmatismo.io. All rights reserved. Licensed under the AGPL-3.0.
talk "Quer pagar quanto?" talk "Quer pagar quanto?"
hear ammount hear amount
talk "Para onde?" talk "Para onde?"
hear address hear address
if ammount < 5 then if amount < 5 then
talk "O mínimo que vendo este produto é 5." talk "O mínimo que vendo este produto é 5."
else else
if address is in "Rio" then if address is in "Rio" then
get payment ammount get payment amount
delivery to address delivery to address
else else
talk "Vou ver se tenho um parceiro para entregar aí e te falo. Eu só entrego no Rio." talk "Vou ver se tenho um parceiro para entregar aí e te falo. Eu só entrego no Rio."

View file

@ -1,12 +1,12 @@
' General Bots Copyright (c) Pragmatismo.io. All rights reserved. Licensed under the AGPL-3.0. ' General Bots Copyright (c) Pragmatismo.io. All rights reserved. Licensed under the AGPL-3.0.
talk "Quer pagar quanto?" talk "Quer pagar quanto?"
hear ammount hear amount
if ammount < 5 then if amount < 5 then
talk "O mínimo que vendo este produto é 5." talk "O mínimo que vendo este produto é 5."
else else
get payment ammount get payment amount
end if end if
talk "Valeu!" talk "Valeu!"

View file

@ -45,7 +45,15 @@ const walkPromise = require('walk-promise');
const { SearchService } = require('azure-search-client'); const { SearchService } = require('azure-search-client');
var Excel = require('exceljs'); var Excel = require('exceljs');
import { GBServer } from '../../../src/app'; import { GBServer } from '../../../src/app';
import { IGBKBService, GBDialogStep, GBLog, IGBConversationalService, IGBCoreService, IGBInstance, GBMinInstance } from 'botlib'; import {
IGBKBService,
GBDialogStep,
GBLog,
IGBConversationalService,
IGBCoreService,
IGBInstance,
GBMinInstance
} from 'botlib';
import { Op } from 'sequelize'; import { Op } from 'sequelize';
import { Sequelize } from 'sequelize-typescript'; import { Sequelize } from 'sequelize-typescript';
import { AzureDeployerService } from '../../azuredeployer.gbapp/services/AzureDeployerService'; import { AzureDeployerService } from '../../azuredeployer.gbapp/services/AzureDeployerService';
@ -90,7 +98,9 @@ export class KBService implements IGBKBService {
public static getSubjectItemsSeparatedBySpaces(subjects: GuaribasSubject[]) { public static getSubjectItemsSeparatedBySpaces(subjects: GuaribasSubject[]) {
const out = []; const out = [];
if (subjects === undefined) { return ''; } if (subjects === undefined) {
return '';
}
subjects.forEach(subject => { subjects.forEach(subject => {
out.push(subject.internalId); out.push(subject.internalId);
}); });
@ -128,7 +138,6 @@ export class KBService implements IGBKBService {
} }
public async getAnswerByText(instanceId: number, text: string): Promise<any> { public async getAnswerByText(instanceId: number, text: string): Promise<any> {
text = text.trim(); text = text.trim();
const service = new CSService(); const service = new CSService();
let question = await service.getQuestionFromAlternateText(instanceId, text); let question = await service.getQuestionFromAlternateText(instanceId, text);
@ -185,9 +194,10 @@ export class KBService implements IGBKBService {
// tslint:disable:no-unsafe-any // tslint:disable:no-unsafe-any
if (instance.searchKey !== null && GBConfigService.get('STORAGE_DIALECT') === 'mssql') { if (instance.searchKey !== null && GBConfigService.get('STORAGE_DIALECT') === 'mssql') {
const client = new SearchService(instance.searchHost.split('.')[0], instance.searchKey); const client = new SearchService(instance.searchHost.split('.')[0], instance.searchKey);
const results = await client.indexes.use(instance.searchIndex) const results = await client.indexes
.use(instance.searchIndex)
.buildQuery() .buildQuery()
.filter((f) => f.eq('instanceId', instance.instanceId)) .filter(f => f.eq('instanceId', instance.instanceId))
.search(query) .search(query)
.top(1) .top(1)
.executeQuery(); .executeQuery();
@ -265,25 +275,39 @@ export class KBService implements IGBKBService {
instanceId: number, instanceId: number,
packageId: number packageId: number
): Promise<GuaribasQuestion[]> { ): Promise<GuaribasQuestion[]> {
GBLog.info(`Now reading file ${filePath}...`);
var workbook = new Excel.Workbook(); var workbook = new Excel.Workbook();
let data = await workbook.xlsx.readFile(filePath); let data = await workbook.xlsx.readFile(filePath);
let lastQuestionId: number; let lastQuestionId: number;
let lastAnswer: GuaribasAnswer; let lastAnswer: GuaribasAnswer;
let rows = data._worksheets[1]._rows;
// Finds a valid worksheet because Excel returns empty slots
// when loading worksheets collection.
let worksheet: any;
for (let t = 0; t < data._worksheets.length; t++) {
worksheet = data._worksheets[t];
if (worksheet)
{
break;
}
}
let rows = worksheet._rows;
GBLog.info(`Now importing ${rows.length} rows from tabular file ${filePath}...`); GBLog.info(`Now importing ${rows.length} rows from tabular file ${filePath}...`);
return asyncPromise.eachSeries(rows, async line => { return asyncPromise.eachSeries(rows, async line => {
// Skips the first line. // Skips the first line.
if (line._cells[0] !== undefined && if (
line != undefined &&
line._cells[0] !== undefined &&
line._cells[1] !== undefined && line._cells[1] !== undefined &&
line._cells[2] !== undefined && line._cells[2] !== undefined &&
line._cells[3] !== undefined && line._cells[3] !== undefined &&
line._cells[4] !== undefined) { line._cells[4] !== undefined
) {
// Extracts values from columns in the current line. // Extracts values from columns in the current line.
const subjectsText = line._cells[0].text; const subjectsText = line._cells[0].text;
@ -292,18 +316,17 @@ export class KBService implements IGBKBService {
const question = line._cells[3].text; const question = line._cells[3].text;
let answer = line._cells[4].text; let answer = line._cells[4].text;
if (!(subjectsText === 'subjects' && from === 'from') if (!(subjectsText === 'subjects' && from === 'from') && answer !== null && question !== null) {
&& (answer !== null && question !== null)) {
let format = '.txt'; let format = '.txt';
// Extracts answer from external media if any. // Extracts answer from external media if any.
let media = null; let media = null;
if (typeof (answer) !== "string") { if (typeof answer !== 'string') {
GBLog.info(`[GBImporter] Answer is NULL related to Question '${question}'.`); GBLog.info(`[GBImporter] Answer is NULL related to Question '${question}'.`);
answer = 'Existe um problema na base de conhecimento. Fui treinado para entender sua pergunta, avise a quem me criou que a resposta não foi informada para esta pergunta.'; answer =
'Existe um problema na base de conhecimento. Fui treinado para entender sua pergunta, avise a quem me criou que a resposta não foi informada para esta pergunta.';
} else if (answer.indexOf('.md') > -1) { } else if (answer.indexOf('.md') > -1) {
const mediaFilename = urlJoin(path.dirname(filePath), '..', 'articles', answer); const mediaFilename = urlJoin(path.dirname(filePath), '..', 'articles', answer);
if (Fs.existsSync(mediaFilename)) { if (Fs.existsSync(mediaFilename)) {
@ -381,13 +404,9 @@ export class KBService implements IGBKBService {
public async sendAnswer(min: GBMinInstance, channel: string, step: GBDialogStep, answer: GuaribasAnswer) { public async sendAnswer(min: GBMinInstance, channel: string, step: GBDialogStep, answer: GuaribasAnswer) {
if (answer.content.endsWith('.mp4')) { if (answer.content.endsWith('.mp4')) {
await this.playVideo(min, min.conversationalService, step, answer, channel); await this.playVideo(min, min.conversationalService, step, answer, channel);
} } else if (answer.format === '.md') {
else if (answer.format === '.md') {
await this.playMarkdown(min, answer, channel, step, min.conversationalService); await this.playMarkdown(min, answer, channel, step, min.conversationalService);
} else if (answer.content.endsWith('.ogg') && process.env.AUDIO_DISABLED !== 'true') {
} else if (answer.content.endsWith('.ogg') && process.env.AUDIO_DISABLED !== "true") {
await this.playAudio(min, answer, channel, step, min.conversationalService); await this.playAudio(min, answer, channel, step, min.conversationalService);
} else { } else {
await min.conversationalService.sendText(min, step, answer.content); await min.conversationalService.sendText(min, step, answer.content);
@ -395,21 +414,32 @@ export class KBService implements IGBKBService {
} }
} }
private async playAudio(min: GBMinInstance, answer: GuaribasAnswer, channel: string, step: GBDialogStep, conversationalService: IGBConversationalService) { private async playAudio(
min: GBMinInstance,
answer: GuaribasAnswer,
channel: string,
step: GBDialogStep,
conversationalService: IGBConversationalService
) {
conversationalService.sendAudio(min, step, answer.content); conversationalService.sendAudio(min, step, answer.content);
} }
private async playMarkdown(min: GBMinInstance, answer: GuaribasAnswer, channel: string, step: GBDialogStep, conversationalService: IGBConversationalService) { private async playMarkdown(
min: GBMinInstance,
answer: GuaribasAnswer,
channel: string,
step: GBDialogStep,
conversationalService: IGBConversationalService
) {
let sec = new SecService(); let sec = new SecService();
const member = step.context.activity.from; const member = step.context.activity.from;
const user = await sec.ensureUser(min.instance.instanceId, member.id, const user = await sec.ensureUser(min.instance.instanceId, member.id, member.name, '', 'web', member.name);
member.name, "", "web", member.name);
const minBoot = GBServer.globals.minBoot as any; const minBoot = GBServer.globals.minBoot as any;
// Calls language translator. // Calls language translator.
let text = await min.conversationalService.translate(min, let text = await min.conversationalService.translate(
min,
min.instance.translatorKey ? min.instance.translatorKey : minBoot.instance.translatorKey, min.instance.translatorKey ? min.instance.translatorKey : minBoot.instance.translatorKey,
min.instance.translatorEndpoint ? min.instance.translatorEndpoint : minBoot.instance.translatorEndpoint, min.instance.translatorEndpoint ? min.instance.translatorEndpoint : minBoot.instance.translatorEndpoint,
answer.content, answer.content,
@ -438,29 +468,30 @@ export class KBService implements IGBKBService {
// According to the channel, formats the output optimized to it. // According to the channel, formats the output optimized to it.
if (channel === 'webchat' && if (channel === 'webchat' && GBConfigService.get('DISABLE_WEB') !== 'true') {
GBConfigService.get('DISABLE_WEB') !== 'true') {
html = marked(text); html = marked(text);
await this.sendMarkdownToWeb(min, step, conversationalService, html, answer); await this.sendMarkdownToWeb(min, step, conversationalService, html, answer);
} } else if (channel === 'whatsapp') {
else if (channel === 'whatsapp') {
await conversationalService.sendMarkdownToMobile(min, step, user.userSystemId, text); await conversationalService.sendMarkdownToMobile(min, step, user.userSystemId, text);
} } else {
else {
html = marked(text); html = marked(text);
await min.conversationalService.sendText(min, step, html); await min.conversationalService.sendText(min, step, html);
} }
} }
private async sendMarkdownToWeb(min, step: GBDialogStep, conversationalService: IGBConversationalService, html: string, answer: GuaribasAnswer) { private async sendMarkdownToWeb(
min,
step: GBDialogStep,
conversationalService: IGBConversationalService,
html: string,
answer: GuaribasAnswer
) {
let sec = new SecService(); let sec = new SecService();
const member = step.context.activity.from; const member = step.context.activity.from;
const user = await sec.ensureUser(min.instance.instanceId, member.id, const user = await sec.ensureUser(min.instance.instanceId, member.id, member.name, '', 'web', member.name);
member.name, "", "web", member.name);
const minBoot = GBServer.globals.minBoot as any; const minBoot = GBServer.globals.minBoot as any;
html = await min.conversationalService.translate(min, html = await min.conversationalService.translate(
min,
min.instance.translatorKey ? min.instance.translatorKey : minBoot.instance.translatorKey, min.instance.translatorKey ? min.instance.translatorKey : minBoot.instance.translatorKey,
min.instance.translatorEndpoint ? min.instance.translatorEndpoint : minBoot.instance.translatorEndpoint, min.instance.translatorEndpoint ? min.instance.translatorEndpoint : minBoot.instance.translatorEndpoint,
html, html,
@ -481,11 +512,15 @@ export class KBService implements IGBKBService {
}); });
} }
private async playVideo(
private async playVideo(min, conversationalService: IGBConversationalService, min,
step: GBDialogStep, answer: GuaribasAnswer, channel: string) { conversationalService: IGBConversationalService,
if (channel === "whatsapp") { step: GBDialogStep,
await min.conversationalService.sendFile(min, step, null, answer.content, ""); answer: GuaribasAnswer,
channel: string
) {
if (channel === 'whatsapp') {
await min.conversationalService.sendFile(min, step, null, answer.content, '');
} else { } else {
await conversationalService.sendEvent(min, step, 'play', { await conversationalService.sendEvent(min, step, 'play', {
playerType: 'video', playerType: 'video',
@ -499,7 +534,6 @@ export class KBService implements IGBKBService {
packageStorage: GuaribasPackage, packageStorage: GuaribasPackage,
instance: IGBInstance instance: IGBInstance
): Promise<any> { ): Promise<any> {
// Imports subjects tree into database and return it. // Imports subjects tree into database and return it.
const subjectFile = urlJoin(localPath, 'subjects.json'); const subjectFile = urlJoin(localPath, 'subjects.json');
@ -525,18 +559,16 @@ export class KBService implements IGBKBService {
await CollectionUtil.asyncForEach(files, async file => { await CollectionUtil.asyncForEach(files, async file => {
if (file !== null && file.name.endsWith('.md')) { if (file !== null && file.name.endsWith('.md')) {
let content = await this.getAnswerTextByMediaName(instance.instanceId, file.name); let content = await this.getAnswerTextByMediaName(instance.instanceId, file.name);
if (content === null) { if (content === null) {
const fullFilename = urlJoin(file.root, file.name); const fullFilename = urlJoin(file.root, file.name);
content = Fs.readFileSync(fullFilename, 'utf-8'); content = Fs.readFileSync(fullFilename, 'utf-8');
await GuaribasAnswer.create({ await GuaribasAnswer.create({
instanceId: instance.instanceId, instanceId: instance.instanceId,
content: content, content: content,
format: ".md", format: '.md',
media: file.name, media: file.name,
packageId: packageId, packageId: packageId,
prevId: 0 // TODO: Calculate total rows and increment. prevId: 0 // TODO: Calculate total rows and increment.
@ -552,8 +584,7 @@ export class KBService implements IGBKBService {
if (file !== null && file.name.endsWith('.xlsx')) { if (file !== null && file.name.endsWith('.xlsx')) {
return await this.importKbTabularFile(urlJoin(file.root, file.name), instance.instanceId, packageId); return await this.importKbTabularFile(urlJoin(file.root, file.name), instance.instanceId, packageId);
} }
}) });
} }
public async importSubjectFile(packageId: number, filename: string, instance: IGBInstance): Promise<any> { public async importSubjectFile(packageId: number, filename: string, instance: IGBInstance): Promise<any> {
@ -595,8 +626,7 @@ export class KBService implements IGBKBService {
}); });
await this.undeployPackageFromStorage(instance, packageId); await this.undeployPackageFromStorage(instance, packageId);
GBLog.info("Remember to call rebuild index manually after package removal."); GBLog.info('Remember to call rebuild index manually after package removal.');
} }
private async undeployPackageFromStorage(instance: any, packageId: number) { private async undeployPackageFromStorage(instance: any, packageId: number) {
@ -614,12 +644,11 @@ export class KBService implements IGBKBService {
const packageName = Path.basename(localPath); const packageName = Path.basename(localPath);
GBLog.info(`[GBDeployer] Opening package: ${localPath}`); GBLog.info(`[GBDeployer] Opening package: ${localPath}`);
const instance = await core.loadInstanceByBotId(min.botId); const instance = await core.loadInstanceByBotId(min.botId);
GBLog.info(`[GBDeployer] Importing: ${localPath}`); GBLog.info(`[GBDeployer] Importing: ${localPath}`);
const p = await deployer.deployPackageToStorage(instance.instanceId, packageName); const p = await deployer.deployPackageToStorage(instance.instanceId, packageName);
await this.importKbPackage(localPath, p, instance); await this.importKbPackage(localPath, p, instance);
deployer.mountGBKBAssets(packageName,min.botId, localPath); deployer.mountGBKBAssets(packageName, min.botId, localPath);
await deployer.rebuildIndex(instance, new AzureDeployerService(deployer).getKBSearchSchema(instance.searchIndex)); await deployer.rebuildIndex(instance, new AzureDeployerService(deployer).getKBSearchSchema(instance.searchIndex));
GBLog.info(`[GBDeployer] Finished import of ${localPath}`); GBLog.info(`[GBDeployer] Finished import of ${localPath}`);