General Bots in now almost globalized.
This commit is contained in:
parent
c573e33754
commit
7a33f6942e
19 changed files with 359 additions and 371 deletions
|
@ -41,6 +41,7 @@ import { GBImporter } from '../../core.gbapp/services/GBImporter'
|
|||
import { GBConfigService } from '../../core.gbapp/services/GBConfigService'
|
||||
import { KBService } from './../../kb.gbapp/services/KBService'
|
||||
import { BotAdapter } from "botbuilder"
|
||||
import {messages} from "./Strings"
|
||||
import { reject } from "async"
|
||||
|
||||
/**
|
||||
|
|
|
@ -30,46 +30,48 @@
|
|||
| |
|
||||
\*****************************************************************************/
|
||||
|
||||
"use strict"
|
||||
"use strict";
|
||||
|
||||
import { IGBDialog } from "botlib"
|
||||
import { GBMinInstance } from "botlib"
|
||||
import { BotAdapter } from "botbuilder"
|
||||
const messages = require("./strings.json").messages
|
||||
import { IGBDialog } from "botlib";
|
||||
import { GBMinInstance } from "botlib";
|
||||
import { BotAdapter } from "botbuilder";
|
||||
import { Messages } from "../strings";
|
||||
|
||||
export class WelcomeDialog extends IGBDialog {
|
||||
/**
|
||||
* Setup dialogs flows and define services call.
|
||||
*
|
||||
*
|
||||
* @param bot The bot adapter.
|
||||
* @param min The minimal bot instance data.
|
||||
*/
|
||||
static setup(bot: BotAdapter, min: GBMinInstance) {
|
||||
|
||||
min.dialogs.add("/", [
|
||||
|
||||
async (dc, args) => {
|
||||
const user = min.userState.get(dc.context);
|
||||
const locale = dc.context.activity.locale;
|
||||
|
||||
const user = min.userState.get(dc.context)
|
||||
let loc = dc.context.activity.locale;
|
||||
|
||||
if (!user.once) {
|
||||
user.once = true
|
||||
var a = new Date()
|
||||
const date = a.getHours()
|
||||
var msg =
|
||||
date < 12 ? messages[loc].good_morning : date < 18 ?
|
||||
messages[loc].good_evening : messages[loc].good_night
|
||||
user.once = true;
|
||||
var a = new Date();
|
||||
const date = a.getHours();
|
||||
var msg = 4;
|
||||
date < 12
|
||||
? Messages[locale].good_morning
|
||||
: date < 18
|
||||
? Messages[locale].good_evening
|
||||
: Messages[locale].good_night;
|
||||
|
||||
let messages1 = [`Oi, ${msg}.`, `Oi!`, `Olá, ${msg}`, `Olá!`]
|
||||
await dc.context.sendActivity(messages1[0])
|
||||
await dc.context.sendActivity(Messages[locale].hi(msg));
|
||||
|
||||
if (dc.context.activity && dc.context.activity.type == "message" &&
|
||||
dc.context.activity.text != "") {
|
||||
await dc.replace("/answer", { query: dc.context.activity.text })
|
||||
if (
|
||||
dc.context.activity &&
|
||||
dc.context.activity.type == "message" &&
|
||||
dc.context.activity.text != ""
|
||||
) {
|
||||
await dc.replace("/answer", { query: dc.context.activity.text });
|
||||
}
|
||||
}
|
||||
}
|
||||
])
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,37 +30,36 @@
|
|||
| |
|
||||
\*****************************************************************************/
|
||||
|
||||
"use strict"
|
||||
|
||||
import { IGBDialog } from "botlib"
|
||||
import { GBMinInstance } from "botlib"
|
||||
import { BotAdapter } from "botbuilder"
|
||||
"use strict";
|
||||
|
||||
import { IGBDialog } from "botlib";
|
||||
import { GBMinInstance } from "botlib";
|
||||
import { BotAdapter } from "botbuilder";
|
||||
import { Messages } from "../strings";
|
||||
|
||||
export class WhoAmIDialog extends IGBDialog {
|
||||
|
||||
/**
|
||||
* Setup dialogs flows and define services call.
|
||||
*
|
||||
*
|
||||
* @param bot The bot adapter.
|
||||
* @param min The minimal bot instance data.
|
||||
*/
|
||||
static setup(bot: BotAdapter, min: GBMinInstance) {
|
||||
|
||||
min.dialogs.add("/whoAmI", [
|
||||
async (dc, args) => {
|
||||
await dc.context.sendActivity(`${min.instance.description}`)
|
||||
async dc => {
|
||||
let locale = dc.context.activity.locale;
|
||||
await dc.context.sendActivity(`${min.instance.description}`);
|
||||
|
||||
if (min.instance.whoAmIVideo) {
|
||||
await dc.context.sendActivity("show_video")
|
||||
await dc.context.sendActivity(Messages[locale].show_video);
|
||||
await min.conversationalService.sendEvent(dc, "play", {
|
||||
playerType: "video",
|
||||
data: min.instance.whoAmIVideo.trim()
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
await dc.replace('/ask', { isReturning: true })
|
||||
await dc.replace("/ask", { isReturning: true });
|
||||
}
|
||||
])
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
{
|
||||
"messages": {
|
||||
"en-US": {
|
||||
"show_video": "I will show you a video, please wait...",
|
||||
"good_morning": "good morning",
|
||||
"good_evening": "good evening",
|
||||
"good_night": "good night"
|
||||
},
|
||||
"pt-BR": {
|
||||
"show_video": "Vou te mostrar um vídeo. Por favor, aguarde...",
|
||||
"good_morning": "bom dia",
|
||||
"good_evening": "boa tarde",
|
||||
"good_night": "boa noite"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -30,77 +30,73 @@
|
|||
| |
|
||||
\*****************************************************************************/
|
||||
|
||||
"use strict"
|
||||
"use strict";
|
||||
|
||||
const logger = require("../../../src/logger")
|
||||
const logger = require("../../../src/logger");
|
||||
|
||||
import { GBCoreService } from "./GBCoreService"
|
||||
import { IGBConversationalService } from "botlib"
|
||||
import { GBMinInstance } from "botlib"
|
||||
import { LuisRecognizer } from "botbuilder-ai"
|
||||
import { MessageFactory } from "botbuilder"
|
||||
import { GBCoreService } from "./GBCoreService";
|
||||
import { IGBConversationalService } from "botlib";
|
||||
import { GBMinInstance } from "botlib";
|
||||
import { LuisRecognizer } from "botbuilder-ai";
|
||||
import { MessageFactory } from "botbuilder";
|
||||
|
||||
export interface LanguagePickerSettings {
|
||||
defaultLocale?: string
|
||||
supportedLocales?: string[]
|
||||
defaultLocale?: string;
|
||||
supportedLocales?: string[];
|
||||
}
|
||||
|
||||
export class GBConversationalService implements IGBConversationalService {
|
||||
coreService: GBCoreService
|
||||
coreService: GBCoreService;
|
||||
|
||||
constructor(coreService: GBCoreService) {
|
||||
this.coreService = coreService
|
||||
this.coreService = coreService;
|
||||
}
|
||||
|
||||
getCurrentLanguage(dc: any) {
|
||||
return dc.context.activity.locale
|
||||
return dc.context.activity.locale;
|
||||
}
|
||||
|
||||
async sendEvent(dc: any, name: string, value: any): Promise<any> {
|
||||
const msg = MessageFactory.text("")
|
||||
msg.value = value
|
||||
msg.type = "event"
|
||||
msg.name = name
|
||||
return dc.context.sendActivity(msg)
|
||||
const msg = MessageFactory.text("");
|
||||
msg.value = value;
|
||||
msg.type = "event";
|
||||
msg.name = name;
|
||||
return dc.context.sendActivity(msg);
|
||||
}
|
||||
|
||||
async runNLP(dc: any, min: GBMinInstance, text: string): Promise<any> {
|
||||
async routeNLP(dc: any, min: GBMinInstance, text: string): Promise<boolean> {
|
||||
|
||||
// Invokes LUIS.
|
||||
|
||||
const model = new LuisRecognizer({
|
||||
appId: min.instance.nlpAppId,
|
||||
subscriptionKey: min.instance.nlpSubscriptionKey,
|
||||
serviceEndpoint: min.instance.nlpServerUrl
|
||||
})
|
||||
let res = await model.recognize(dc.context)
|
||||
});
|
||||
let res = await model.recognize(dc.context);
|
||||
|
||||
// Resolves intents returned from LUIS.
|
||||
|
||||
let topIntent = LuisRecognizer.topIntent(res)
|
||||
let topIntent = LuisRecognizer.topIntent(res);
|
||||
if (topIntent) {
|
||||
var intent = topIntent
|
||||
var intent = topIntent;
|
||||
var entity =
|
||||
res.entities && res.entities.length > 0
|
||||
? res.entities[0].entity.toUpperCase()
|
||||
: null
|
||||
logger.info("luis: intent: [" + intent + "] entity: [" + entity + "]")
|
||||
: null;
|
||||
|
||||
logger.info("NLP called:" + intent + ", " + entity);
|
||||
|
||||
try {
|
||||
await dc.replace("/" + intent)
|
||||
await dc.replace("/" + intent, res.entities);
|
||||
} catch (error) {
|
||||
logger.info("error: intent: [" + intent + "] error: [" + error + "]")
|
||||
await dc.context.sendActivity(
|
||||
"Desculpe-me, não encontrei nada a respeito..."
|
||||
)
|
||||
await dc.replace("/ask", { isReturning: true })
|
||||
let msg = `Error running NLP (${intent}): ${error}`;
|
||||
logger.info(msg);
|
||||
return Promise.reject(msg);
|
||||
}
|
||||
|
||||
return Promise.resolve({ intent, entities: res.entities })
|
||||
return Promise.resolve(true);
|
||||
} else {
|
||||
await dc.context.sendActivity("Lamento, não achei nada a respeito...")
|
||||
await dc.replace("/ask", { isReturning: true })
|
||||
|
||||
return Promise.resolve(null)
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -182,7 +182,7 @@ export class GBMinService {
|
|||
uiUrl,
|
||||
express.static(UrlJoin(GBDeployer.deployFolder, uiPackage, "build"))
|
||||
)
|
||||
logger.info(`Bot UI ${uiPackage} acessible at: ${uiUrl}.`)
|
||||
logger.info(`Bot UI ${uiPackage} accessible at: ${uiUrl}.`)
|
||||
|
||||
// Setups handlers.
|
||||
// send: function (context.activity, next) {
|
||||
|
|
16
deploy/core.gbapp/strings.ts
Normal file
16
deploy/core.gbapp/strings.ts
Normal file
|
@ -0,0 +1,16 @@
|
|||
export const Messages = {
|
||||
"en-US": {
|
||||
show_video: "I will show you a video, please wait...",
|
||||
good_morning: "good morning",
|
||||
good_evening: "good evening",
|
||||
good_night: "good night",
|
||||
hi: (msg ) => `Hello, ${msg}.`
|
||||
},
|
||||
"pt-BR": {
|
||||
show_video: "Vou te mostrar um vídeo. Por favor, aguarde...",
|
||||
good_morning: "bom dia",
|
||||
good_evening: "boa tarde",
|
||||
good_night: "boa noite",
|
||||
hi: (msg ) => `Oi, ${msg}.`
|
||||
}
|
||||
};
|
|
@ -1,5 +0,0 @@
|
|||
export const messages =
|
||||
{
|
||||
show_video: "I will show you a video, please wait..."
|
||||
}
|
||||
;
|
|
@ -1,4 +0,0 @@
|
|||
export const messages =
|
||||
{
|
||||
show_video: "Vou te mostrar um vídeo. Por favor, aguarde..."
|
||||
}
|
|
@ -30,13 +30,14 @@
|
|||
| |
|
||||
\*****************************************************************************/
|
||||
|
||||
"use strict"
|
||||
"use strict";
|
||||
|
||||
import { CSService } from "../services/CSService"
|
||||
import { AzureText } from "pragmatismo-io-framework"
|
||||
import { GBMinInstance } from "botlib"
|
||||
import { IGBDialog } from "botlib"
|
||||
import { BotAdapter } from "botbuilder"
|
||||
import { CSService } from "../services/CSService";
|
||||
import { AzureText } from "pragmatismo-io-framework";
|
||||
import { GBMinInstance } from "botlib";
|
||||
import { IGBDialog } from "botlib";
|
||||
import { BotAdapter } from "botbuilder";
|
||||
import { Messages } from "../strings";
|
||||
|
||||
export class FeedbackDialog extends IGBDialog {
|
||||
/**
|
||||
|
@ -46,70 +47,55 @@ export class FeedbackDialog extends IGBDialog {
|
|||
* @param min The minimal bot instance data.
|
||||
*/
|
||||
static setup(bot: BotAdapter, min: GBMinInstance) {
|
||||
const service = new CSService()
|
||||
const service = new CSService();
|
||||
|
||||
min.dialogs.add("/feedbackNumber", [
|
||||
async dc => {
|
||||
let messages = [
|
||||
"O que achou do meu atendimento, de 1 a 5?",
|
||||
"Qual a nota do meu atendimento?",
|
||||
"Como define meu atendimento numa escala de 1 a 5?"
|
||||
]
|
||||
await dc.prompt("choicePrompt", messages[0], [
|
||||
let locale = dc.context.activity.locale;
|
||||
await dc.prompt("choicePrompt", Messages[locale].what_about_me, [
|
||||
"1",
|
||||
"2",
|
||||
"3",
|
||||
"4",
|
||||
" 5"
|
||||
])
|
||||
"5"
|
||||
]);
|
||||
},
|
||||
async (dc, value) => {
|
||||
let rate = value.entity
|
||||
const user = min.userState.get(dc.context)
|
||||
await service.updateConversationRate(user.conversation, rate)
|
||||
let messages = ["Obrigado!", "Obrigado por responder."]
|
||||
await dc.context.sendActivity(messages[0]) // TODO: Handle rnd.
|
||||
let locale = dc.context.activity.locale;
|
||||
let rate = value.entity;
|
||||
const user = min.userState.get(dc.context);
|
||||
await service.updateConversationRate(user.conversation, rate);
|
||||
await dc.context.sendActivity(Messages[locale].thanks);
|
||||
}
|
||||
])
|
||||
|
||||
]);
|
||||
|
||||
min.dialogs.add("/feedback", [
|
||||
async (dc, args) => {
|
||||
let locale = dc.context.activity.locale;
|
||||
if (args && args.fromMenu) {
|
||||
let messages = [
|
||||
"Sugestões melhoram muito minha qualidade...",
|
||||
"Obrigado pela sua iniciativa de sugestão."
|
||||
]
|
||||
await dc.context.sendActivity(messages[0]) // TODO: Handle rnd.
|
||||
await dc.context.sendActivity(Messages[locale].about_suggestions);
|
||||
}
|
||||
|
||||
let messages = [
|
||||
"O que achou do meu atendimento?",
|
||||
"Como foi meu atendimento?",
|
||||
"Gostaria de dizer algo sobre meu atendimento?"
|
||||
]
|
||||
await dc.prompt("textPrompt", messages[0])
|
||||
await dc.prompt("textPrompt", Messages[locale].what_about_service);
|
||||
},
|
||||
async (dc, value) => {
|
||||
let locale = dc.context.activity.locale;
|
||||
let rate = await AzureText.getSentiment(
|
||||
min.instance.textAnalyticsKey,
|
||||
min.instance.textAnalyticsServerUrl,
|
||||
min.conversationalService.getCurrentLanguage(dc),
|
||||
value
|
||||
)
|
||||
);
|
||||
|
||||
if (rate > 0.50) {
|
||||
await dc.context.sendActivity(
|
||||
"Bom saber que você gostou. Conte comigo."
|
||||
)
|
||||
if (rate > 0.5) {
|
||||
await dc.context.sendActivity(Messages[locale].glad_you_liked);
|
||||
} else {
|
||||
await dc.context.sendActivity(
|
||||
"Vamos registrar sua questão, obrigado pela sinceridade."
|
||||
)
|
||||
await dc.context.sendActivity(Messages[locale].we_will_improve);
|
||||
|
||||
// TODO: Record.
|
||||
}
|
||||
await dc.replace("/ask", { isReturning: true })
|
||||
await dc.replace("/ask", { isReturning: true });
|
||||
}
|
||||
])
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -30,61 +30,50 @@
|
|||
| |
|
||||
\*****************************************************************************/
|
||||
|
||||
"use strict"
|
||||
"use strict";
|
||||
|
||||
import { IGBDialog } from "botlib"
|
||||
import { IGBDialog } from "botlib";
|
||||
|
||||
import { GBMinInstance } from "botlib"
|
||||
import { CSService } from "../services/CSService"
|
||||
import { BotAdapter } from "botbuilder"
|
||||
const logger = require("../../../src/logger")
|
||||
import { GBMinInstance } from "botlib";
|
||||
import { CSService } from "../services/CSService";
|
||||
import { BotAdapter } from "botbuilder";
|
||||
import { Messages } from "../strings";
|
||||
const logger = require("../../../src/logger");
|
||||
|
||||
export class QualityDialog extends IGBDialog {
|
||||
|
||||
/**
|
||||
* Setup dialogs flows and define services call.
|
||||
*
|
||||
*
|
||||
* @param bot The bot adapter.
|
||||
* @param min The minimal bot instance data.
|
||||
*/
|
||||
static setup(bot: BotAdapter, min: GBMinInstance) {
|
||||
|
||||
const service = new CSService()
|
||||
const service = new CSService();
|
||||
|
||||
min.dialogs.add("/quality", [
|
||||
async (dc, args) => {
|
||||
const user = min.userState.get(dc.context)
|
||||
var score = args.score
|
||||
const locale = dc.context.activity.locale;
|
||||
const user = min.userState.get(dc.context);
|
||||
var score = args.score;
|
||||
|
||||
setTimeout(
|
||||
() => min.conversationalService.sendEvent(dc, "stop", null),
|
||||
400
|
||||
)
|
||||
);
|
||||
|
||||
if (score == 0) {
|
||||
let msg = [
|
||||
"Desculpe-me, vamos tentar novamente.",
|
||||
"Lamento... Vamos tentar novamente!",
|
||||
"Desculpe-me. Por favor, tente escrever de outra forma?"
|
||||
]
|
||||
await dc.context.sendActivity(msg[0])
|
||||
await dc.context.sendActivity(Messages[locale].im_sorry_lets_try);
|
||||
} else {
|
||||
let msg = [
|
||||
"Ótimo, obrigado por contribuir com sua resposta.",
|
||||
"Certo, obrigado pela informação.",
|
||||
"Obrigado pela contribuição."
|
||||
]
|
||||
await dc.context.sendActivity(msg[0])
|
||||
await dc.context.sendActivity(Messages[locale].great_thanks);
|
||||
|
||||
await service.insertQuestionAlternate(
|
||||
min.instance.instanceId,
|
||||
user.lastQuestion,
|
||||
user.lastQuestionId
|
||||
)
|
||||
|
||||
await dc.replace('/ask', {isReturning: true})
|
||||
);
|
||||
await dc.replace("/ask", { isReturning: true });
|
||||
}
|
||||
}
|
||||
])
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
22
deploy/customer-satisfaction.gbapp/strings.ts
Normal file
22
deploy/customer-satisfaction.gbapp/strings.ts
Normal file
|
@ -0,0 +1,22 @@
|
|||
export const Messages = {
|
||||
"en-US": {
|
||||
about_suggestions: "Suggestions are welcomed and improve my quality...",
|
||||
what_about_service: "What about my service?",
|
||||
glad_you_liked: "I'm glad you liked. I'm here for you.",
|
||||
we_will_improve: "Let's take note of that, thanks for sharing.",
|
||||
what_about_me: "What about the service, please rate between 1 and 5.",
|
||||
thanks: "Thanks!",
|
||||
im_sorry_lets_try: "I'm sorry. Let's try again...",
|
||||
great_thanks: "Great, thanks for sharing your thoughts."
|
||||
},
|
||||
"pt-BR": {
|
||||
about_suggestions: "Sugestões melhoram muito minha qualidade...",
|
||||
what_about_service:"O que achou do meu atendimento?",
|
||||
glad_you_liked: "Bom saber que você gostou. Conte comigo.",
|
||||
we_will_improve: "Vamos registrar sua questão, obrigado pela sinceridade.",
|
||||
what_about_me: "O que achou do meu atendimento, de 1 a 5?",
|
||||
thanks: "Obrigado!",
|
||||
im_sorry_lets_try: "Desculpe-me, vamos tentar novamente.",
|
||||
great_thanks: "Ótimo, obrigado por contribuir com sua resposta."
|
||||
}
|
||||
};
|
|
@ -61,12 +61,12 @@ class SideBarMenu extends React.Component {
|
|||
<div className="IconsMenu">
|
||||
<div className="iconMenu">
|
||||
<span className="iconText" onClick={() => this.send("showFAQ")}>
|
||||
Perguntas frequentes
|
||||
FAQ
|
||||
</span>
|
||||
</div>
|
||||
<div className="iconMenu">
|
||||
<span className="iconText" onClick={() => this.send("whoAmI")}>
|
||||
Quem é você?
|
||||
Who are You?
|
||||
</span>
|
||||
</div>
|
||||
<div className="iconMenu">
|
||||
|
@ -74,7 +74,7 @@ class SideBarMenu extends React.Component {
|
|||
className="iconText"
|
||||
onClick={() => this.send("showSubjects")}
|
||||
>
|
||||
Assuntos
|
||||
Subjects
|
||||
</span>
|
||||
</div>
|
||||
<div className="iconMenu">
|
||||
|
@ -82,7 +82,7 @@ class SideBarMenu extends React.Component {
|
|||
className="iconText"
|
||||
onClick={() => this.send("giveFeedback")}
|
||||
>
|
||||
Sugestão
|
||||
Suggestions
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -30,87 +30,76 @@
|
|||
| |
|
||||
\*****************************************************************************/
|
||||
|
||||
"use strict"
|
||||
"use strict";
|
||||
|
||||
import { IGBDialog } from "botlib"
|
||||
import { AzureText } from "pragmatismo-io-framework"
|
||||
import { GBMinInstance } from "botlib"
|
||||
import { KBService } from './../services/KBService'
|
||||
import { BotAdapter } from "botbuilder"
|
||||
import { LuisRecognizer } from "botbuilder-ai"
|
||||
import { IGBDialog } from "botlib";
|
||||
import { AzureText } from "pragmatismo-io-framework";
|
||||
import { GBMinInstance } from "botlib";
|
||||
import { KBService } from "./../services/KBService";
|
||||
import { BotAdapter } from "botbuilder";
|
||||
import { Messages } from "../strings";
|
||||
import { LuisRecognizer } from "botbuilder-ai";
|
||||
|
||||
const logger = require("../../../src/logger")
|
||||
|
||||
const logger = require("../../../src/logger");
|
||||
|
||||
export class AskDialog extends IGBDialog {
|
||||
/**
|
||||
* Setup dialogs flows and define services call.
|
||||
*
|
||||
*
|
||||
* @param bot The bot adapter.
|
||||
* @param min The minimal bot instance data.
|
||||
*/
|
||||
static setup(bot: BotAdapter, min: GBMinInstance) {
|
||||
|
||||
const service = new KBService(min.core.sequelize)
|
||||
const service = new KBService(min.core.sequelize);
|
||||
|
||||
const model = new LuisRecognizer({
|
||||
appId: min.instance.nlpAppId,
|
||||
subscriptionKey: min.instance.nlpSubscriptionKey,
|
||||
serviceEndpoint: min.instance.nlpServerUrl
|
||||
})
|
||||
|
||||
});
|
||||
|
||||
min.dialogs.add("/answer", [
|
||||
|
||||
|
||||
|
||||
async (dc, args) => {
|
||||
|
||||
// Initialize values.
|
||||
|
||||
const user = min.userState.get(dc.context)
|
||||
let text = args.query
|
||||
const user = min.userState.get(dc.context);
|
||||
let text = args.query;
|
||||
if (!text) {
|
||||
throw new Error(`/answer being called with no args.query text.`)
|
||||
throw new Error(`/answer being called with no args.query text.`);
|
||||
}
|
||||
|
||||
let locale = await AzureText.getLocale(min.instance.textAnalyticsKey,
|
||||
min.instance.textAnalyticsServerUrl, text)
|
||||
if (locale != dc.context.activity.locale.split("-")[0])
|
||||
{
|
||||
switch(locale)
|
||||
{
|
||||
let locale = await AzureText.getLocale(
|
||||
min.instance.textAnalyticsKey,
|
||||
min.instance.textAnalyticsServerUrl,
|
||||
text
|
||||
);
|
||||
if (locale != dc.context.activity.locale.split("-")[0]) {
|
||||
switch (locale) {
|
||||
case "pt":
|
||||
await dc.context.sendActivity("OK, mundando de idioma para o Português...")
|
||||
dc.context.activity.locale = "pt-BR"
|
||||
break
|
||||
dc.context.activity.locale = "pt-BR";
|
||||
await dc.context.sendActivity(Messages[locale].changing_language);
|
||||
break;
|
||||
case "en":
|
||||
await dc.context.sendActivity("OK, changing language to English...")
|
||||
dc.context.activity.locale = "en-US"
|
||||
break
|
||||
dc.context.activity.locale = "en-US";
|
||||
await dc.context.sendActivity(Messages[locale].changing_language);
|
||||
break;
|
||||
default:
|
||||
await dc.context.sendActivity(`Unknown language: ${locale}`)
|
||||
break
|
||||
|
||||
await dc.context.sendActivity(`Unknown language: ${locale}`);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Stops any content on projector.
|
||||
|
||||
await min.conversationalService.sendEvent(dc, "stop", null)
|
||||
await min.conversationalService.sendEvent(dc, "stop", null);
|
||||
|
||||
// Handle extra text from FAQ.
|
||||
|
||||
if (args && args.query) {
|
||||
text = args.query
|
||||
text = args.query;
|
||||
} else if (args && args.fromFaq) {
|
||||
let messages = [
|
||||
`Ótima escolha, procurando resposta para sua questão...`,
|
||||
`Pesquisando sobre o termo...`,
|
||||
`Aguarde, por favor, enquanto acho sua resposta...`
|
||||
]
|
||||
|
||||
await dc.context.sendActivity(messages[0]) // TODO: Handle rnd.
|
||||
await dc.context.sendActivity(Messages[locale].going_answer);
|
||||
}
|
||||
|
||||
// Spells check the input text before sending Search or NLP.
|
||||
|
@ -118,127 +107,115 @@ export class AskDialog extends IGBDialog {
|
|||
if (min.instance.spellcheckerKey) {
|
||||
let data = await AzureText.getSpelledText(
|
||||
min.instance.spellcheckerKey,
|
||||
text)
|
||||
text
|
||||
);
|
||||
|
||||
if (data != text) {
|
||||
logger.info(`Spelling corrected: ${data}`)
|
||||
text = data
|
||||
logger.info(`Spelling corrected: ${data}`);
|
||||
text = data;
|
||||
}
|
||||
}
|
||||
|
||||
// Searches KB for the first time.
|
||||
|
||||
user.lastQuestion = text
|
||||
user.lastQuestion = text;
|
||||
let resultsA = await service.ask(
|
||||
min.instance,
|
||||
text,
|
||||
min.instance.searchScore,
|
||||
user.subjects)
|
||||
user.subjects
|
||||
);
|
||||
|
||||
// If there is some result, answer immediately.
|
||||
|
||||
if (resultsA && resultsA.answer) {
|
||||
|
||||
// Saves some context info.
|
||||
|
||||
user.isAsking = false
|
||||
user.lastQuestionId = resultsA.questionId
|
||||
user.isAsking = false;
|
||||
user.lastQuestionId = resultsA.questionId;
|
||||
|
||||
// Sends the answer to all outputs, including projector.
|
||||
|
||||
await service.sendAnswer(min.conversationalService, dc, resultsA.answer)
|
||||
await service.sendAnswer(
|
||||
min.conversationalService,
|
||||
dc,
|
||||
resultsA.answer
|
||||
);
|
||||
|
||||
// Goes to ask loop, again.
|
||||
|
||||
await dc.replace("/ask", { isReturning: true })
|
||||
|
||||
await dc.replace("/ask", { isReturning: true });
|
||||
} else {
|
||||
|
||||
// Second time running Search, now with no filter.
|
||||
|
||||
let resultsB = await service.ask(min.instance, text,
|
||||
min.instance.searchScore, null)
|
||||
let resultsB = await service.ask(
|
||||
min.instance,
|
||||
text,
|
||||
min.instance.searchScore,
|
||||
null
|
||||
);
|
||||
|
||||
// If there is some result, answer immediately.
|
||||
|
||||
if (resultsB && resultsB.answer) {
|
||||
|
||||
// Saves some context info.
|
||||
|
||||
const user = min.userState.get(dc.context)
|
||||
user.isAsking = false
|
||||
user.lastQuestionId = resultsB.questionId
|
||||
const user = min.userState.get(dc.context);
|
||||
user.isAsking = false;
|
||||
user.lastQuestionId = resultsB.questionId;
|
||||
|
||||
// Informs user that a broader search will be used.
|
||||
|
||||
if (user.subjects.length > 0) {
|
||||
let subjectText =
|
||||
`${KBService.getSubjectItemsSeparatedBySpaces(
|
||||
user.subjects
|
||||
)}`
|
||||
let messages = [
|
||||
`Respondendo nao apenas sobre ${subjectText}... `,
|
||||
`Respondendo de modo mais abrangente...`,
|
||||
`Vou te responder de modo mais abrangente...
|
||||
Não apenas sobre ${subjectText}`
|
||||
]
|
||||
await dc.context.sendActivity(messages[0]) // TODO: Handle rnd.
|
||||
let subjectText = `${KBService.getSubjectItemsSeparatedBySpaces(
|
||||
user.subjects
|
||||
)}`;
|
||||
await dc.context.sendActivity(Messages[locale].wider_answer);
|
||||
}
|
||||
|
||||
// Sends the answer to all outputs, including projector.
|
||||
|
||||
await service.sendAnswer(min.conversationalService, dc, resultsB.answer)
|
||||
await dc.replace("/ask", { isReturning: true })
|
||||
|
||||
await service.sendAnswer(
|
||||
min.conversationalService,
|
||||
dc,
|
||||
resultsB.answer
|
||||
);
|
||||
await dc.replace("/ask", { isReturning: true });
|
||||
} else {
|
||||
|
||||
let data = await min.conversationalService.runNLP(dc, min, text)
|
||||
if (!data) {
|
||||
let messages = [
|
||||
"Desculpe-me, não encontrei nada a respeito.",
|
||||
"Lamento... Não encontrei nada sobre isso. Vamos tentar novamente?",
|
||||
"Desculpe-me, não achei nada parecido. Poderia tentar escrever de outra forma?"
|
||||
]
|
||||
|
||||
await dc.context.sendActivity(messages[0]) // TODO: Handle rnd.
|
||||
await dc.replace("/ask", { isReturning: true })
|
||||
if (!(await min.conversationalService.runNLP(dc, min, text))) {
|
||||
await dc.context.sendActivity(Messages[locale].did_not_find);
|
||||
await dc.replace("/ask", { isReturning: true });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
])
|
||||
]);
|
||||
|
||||
min.dialogs.add("/ask", [
|
||||
async (dc, args) => {
|
||||
const user = min.userState.get(dc.context)
|
||||
user.isAsking = true
|
||||
const locale = dc.context.activity.locale;
|
||||
const user = min.userState.get(dc.context);
|
||||
user.isAsking = true;
|
||||
if (!user.subjects) {
|
||||
user.subjects = []
|
||||
user.subjects = [];
|
||||
}
|
||||
let text = []
|
||||
let text = [];
|
||||
if (user.subjects.length > 0) {
|
||||
text = [
|
||||
`Faça sua pergunta...`,
|
||||
`Pode perguntar sobre o assunto em questão... `,
|
||||
`Qual a pergunta?`
|
||||
]
|
||||
text = Messages[locale].which_question;
|
||||
}
|
||||
|
||||
if (args && args.isReturning) {
|
||||
text = [
|
||||
"Sobre o que mais posso ajudar?",
|
||||
"Então, posso ajudar em algo a mais?",
|
||||
"Deseja fazer outra pergunta?"
|
||||
]
|
||||
text = Messages[locale].anything_else;
|
||||
}
|
||||
|
||||
if (text.length > 0) {
|
||||
await dc.prompt('textPrompt', text[0])
|
||||
await dc.prompt("textPrompt", text[0]);
|
||||
}
|
||||
},
|
||||
async (dc, value) => {
|
||||
await dc.endAll()
|
||||
await dc.begin("/answer", { query: value })
|
||||
await dc.endAll();
|
||||
await dc.begin("/answer", { query: value });
|
||||
}
|
||||
])
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
import { KBService } from './../services/KBService'
|
||||
import { IGBDialog } from "botlib"
|
||||
import { BotAdapter } from "botbuilder"
|
||||
import { Messages } from "../strings";
|
||||
import { GBMinInstance } from "botlib"
|
||||
|
||||
export class FaqDialog extends IGBDialog {
|
||||
|
@ -51,19 +52,14 @@ export class FaqDialog extends IGBDialog {
|
|||
min.dialogs.add("/faq", [
|
||||
async (dc, args) => {
|
||||
let data = await service.getFaqBySubjectArray("faq", null)
|
||||
const locale = dc.context.activity.locale;
|
||||
if (data) {
|
||||
await min.conversationalService.sendEvent(dc, "play", {
|
||||
playerType: "bullet",
|
||||
data: data.slice(0, 10)
|
||||
})
|
||||
|
||||
let messages = [
|
||||
"Veja algumas perguntas mais frequentes logo na tela. Clique numa delas para eu responder.",
|
||||
"Você pode clicar em alguma destas perguntas da tela que eu te respondo de imediato.",
|
||||
"Veja a lista que eu preparei logo aí na tela..."
|
||||
]
|
||||
|
||||
await dc.context.sendActivity(messages[0]) // TODO: RND messages.
|
||||
|
||||
await dc.context.sendActivity(Messages[locale].see_faq) // TODO: RND messages.
|
||||
await dc.endAll()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,137 +30,138 @@
|
|||
| |
|
||||
\*****************************************************************************/
|
||||
|
||||
"use strict"
|
||||
"use strict";
|
||||
|
||||
const UrlJoin = require("url-join")
|
||||
const UrlJoin = require("url-join");
|
||||
|
||||
import { BotAdapter, CardFactory, MessageFactory } from "botbuilder"
|
||||
import { IGBDialog } from "botlib"
|
||||
import { GBMinInstance } from "botlib"
|
||||
import { GuaribasSubject } from '../models'
|
||||
import { KBService } from "../services/KBService"
|
||||
import { BotAdapter, CardFactory, MessageFactory } from "botbuilder";
|
||||
import { IGBDialog } from "botlib";
|
||||
import { GBMinInstance } from "botlib";
|
||||
import { GuaribasSubject } from "../models";
|
||||
import { KBService } from "../services/KBService";
|
||||
import { Messages } from "../strings";
|
||||
import { AzureText } from "pragmatismo-io-framework";
|
||||
|
||||
export class MenuDialog extends IGBDialog {
|
||||
|
||||
/**
|
||||
* Setup dialogs flows and define services call.
|
||||
*
|
||||
*
|
||||
* @param bot The bot adapter.
|
||||
* @param min The minimal bot instance data.
|
||||
*/
|
||||
static setup(bot: BotAdapter, min: GBMinInstance) {
|
||||
var service = new KBService(min.core.sequelize);
|
||||
|
||||
var service = new KBService(min.core.sequelize)
|
||||
|
||||
bot
|
||||
min.dialogs.add("/menu", [
|
||||
async (dc, args) => {
|
||||
var rootSubjectId = null
|
||||
const locale = dc.context.activity.locale;
|
||||
var rootSubjectId = null;
|
||||
|
||||
if (args && args.data) {
|
||||
var subject = args.data
|
||||
var subject = args.data;
|
||||
|
||||
// If there is a shortcut specified as subject destination, go there.
|
||||
|
||||
if (subject.to) {
|
||||
let dialog = subject.to.split(":")[1]
|
||||
await dc.replace("/" + dialog)
|
||||
await dc.end()
|
||||
return
|
||||
let dialog = subject.to.split(":")[1];
|
||||
await dc.replace("/" + dialog);
|
||||
await dc.end();
|
||||
return;
|
||||
}
|
||||
|
||||
// Adds to bot a perception of a new subject.
|
||||
|
||||
const user = min.userState.get(dc.context)
|
||||
user.subjects.push(subject)
|
||||
rootSubjectId = subject.subjectId
|
||||
const user = min.userState.get(dc.context);
|
||||
user.subjects.push(subject);
|
||||
rootSubjectId = subject.subjectId;
|
||||
|
||||
// Whenever a subject is selected, shows a faq about it.
|
||||
|
||||
|
||||
if (user.subjects.length > 0) {
|
||||
let data = await service.getFaqBySubjectArray("menu", user.subjects)
|
||||
let data = await service.getFaqBySubjectArray(
|
||||
"menu",
|
||||
user.subjects
|
||||
);
|
||||
await min.conversationalService.sendEvent(dc, "play", {
|
||||
playerType: "bullet",
|
||||
data: data.slice(0, 6)
|
||||
})
|
||||
|
||||
});
|
||||
}
|
||||
} else {
|
||||
const user = min.userState.get(dc.context)
|
||||
user.subjects = []
|
||||
const user = min.userState.get(dc.context);
|
||||
user.subjects = [];
|
||||
|
||||
let messages = [
|
||||
"Aqui estão algumas categorias de assuntos...",
|
||||
"Selecionando o assunto você pode me ajudar a encontrar a resposta certa...",
|
||||
"Você pode selecionar algum dos assuntos abaixo e perguntar algo..."
|
||||
]
|
||||
await dc.context.sendActivity(messages[0]) // TODO: Handle rnd.
|
||||
user.isAsking = false
|
||||
await dc.context.sendActivity(Messages[locale].here_is_subjects); // TODO: Handle rnd.
|
||||
user.isAsking = false;
|
||||
}
|
||||
|
||||
const msg = MessageFactory.text('')
|
||||
var attachments = []
|
||||
const msg = MessageFactory.text("");
|
||||
var attachments = [];
|
||||
|
||||
let data = await service.getSubjectItems(
|
||||
min.instance.instanceId,
|
||||
rootSubjectId)
|
||||
rootSubjectId
|
||||
);
|
||||
|
||||
msg.attachmentLayout = 'carousel'
|
||||
msg.attachmentLayout = "carousel";
|
||||
|
||||
data.forEach(function (item: GuaribasSubject) {
|
||||
|
||||
var subject = item
|
||||
data.forEach(function(item: GuaribasSubject) {
|
||||
var subject = item;
|
||||
var card = CardFactory.heroCard(
|
||||
subject.title,
|
||||
CardFactory.images([UrlJoin(
|
||||
"/kb",
|
||||
min.instance.kb,
|
||||
"subjects",
|
||||
subject.internalId + ".png" // TODO: or fallback to subject.png
|
||||
)]),
|
||||
CardFactory.images([
|
||||
UrlJoin(
|
||||
"/kb",
|
||||
min.instance.kb,
|
||||
"subjects",
|
||||
subject.internalId + ".png" // TODO: or fallback to subject.png
|
||||
)
|
||||
]),
|
||||
CardFactory.actions([
|
||||
{
|
||||
type: 'postBack',
|
||||
title: 'Selecionar',
|
||||
type: "postBack",
|
||||
title: Messages[locale].menu_select,
|
||||
value: JSON.stringify({
|
||||
title: subject.title,
|
||||
subjectId: subject.subjectId,
|
||||
to: subject.to
|
||||
})
|
||||
}]))
|
||||
}
|
||||
])
|
||||
);
|
||||
|
||||
attachments.push(card)
|
||||
|
||||
})
|
||||
attachments.push(card);
|
||||
});
|
||||
|
||||
if (attachments.length == 0) {
|
||||
const user = min.userState.get(dc.context)
|
||||
const user = min.userState.get(dc.context);
|
||||
|
||||
if (user.subjects && user.subjects.length > 0) {
|
||||
await dc.context.sendActivity(
|
||||
`Vamos pesquisar sobre ${KBService.getFormattedSubjectItems(
|
||||
user.subjects
|
||||
)}?`
|
||||
)
|
||||
Messages[locale].lets_search(
|
||||
KBService.getFormattedSubjectItems(user.subjects)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
await dc.replace("/ask", {})
|
||||
await dc.replace("/ask", {});
|
||||
} else {
|
||||
msg.attachments = attachments
|
||||
await dc.context.sendActivity(msg)
|
||||
msg.attachments = attachments;
|
||||
await dc.context.sendActivity(msg);
|
||||
}
|
||||
|
||||
const user = min.userState.get(dc.context)
|
||||
user.isAsking = true
|
||||
const user = min.userState.get(dc.context);
|
||||
user.isAsking = true;
|
||||
},
|
||||
async (dc, value) => {
|
||||
var text = value
|
||||
if (text === "no" || text === "n") { // TODO: Migrate to a common.
|
||||
await dc.replace("/feedback")
|
||||
var text = value;
|
||||
const locale = dc.context.activity.locale;
|
||||
if (AzureText.isIntentNo(locale, text)) {
|
||||
await dc.replace("/feedback");
|
||||
} else {
|
||||
await dc.replace("/ask")
|
||||
await dc.replace("/ask");
|
||||
}
|
||||
}
|
||||
])
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -40,6 +40,7 @@ const marked = require("marked")
|
|||
const path = require("path")
|
||||
const asyncPromise = require('async-promises')
|
||||
const walkPromise = require('walk-promise')
|
||||
import { Messages } from "../strings";
|
||||
|
||||
import { Sequelize } from 'sequelize-typescript'
|
||||
import { GBConfigService } from './../../core.gbapp/services/GBConfigService'
|
||||
|
@ -397,8 +398,7 @@ export class KBService {
|
|||
format = ".md"
|
||||
} else {
|
||||
logger.info(`[GBImporter] File not found: ${mediaFilename}.`)
|
||||
answer =
|
||||
"Por favor, contate a administração para rever esta pergunta."
|
||||
answer = ""
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -464,13 +464,9 @@ export class KBService {
|
|||
})
|
||||
} else if (answer.content.length > 140 &&
|
||||
dc.context._activity.channelId === "webchat") {
|
||||
let messages = [
|
||||
"Vou te responder na tela para melhor visualização...",
|
||||
"A resposta está na tela...",
|
||||
"Veja a resposta na tela..."
|
||||
]
|
||||
|
||||
await dc.context.sendActivity(messages[0]) // TODO: Handle rnd.
|
||||
const locale = dc.context.activity.locale;
|
||||
|
||||
await dc.context.sendActivity(Messages[locale].will_answer_projector) // TODO: Handle rnd.
|
||||
var html = answer.content
|
||||
|
||||
if (answer.format === ".md") {
|
||||
|
|
34
deploy/kb.gbapp/strings.ts
Normal file
34
deploy/kb.gbapp/strings.ts
Normal file
|
@ -0,0 +1,34 @@
|
|||
export const Messages = {
|
||||
"en-US": {
|
||||
did_not_find: "I'm sorry I didn't find anything.",
|
||||
changing_language: "OK, changing language to English...",
|
||||
going_answer: "Great choice, now looking for your answer...",
|
||||
wider_answer: subjectText =>
|
||||
`Answering to you in a broader way... Not just about ${subjectText}.`,
|
||||
which_question: "What's your question?",
|
||||
anything_else: "So, may I help with anything else?",
|
||||
here_is_subjects: "Here are some subjects to choose from...",
|
||||
menu_select: "Select",
|
||||
lets_search: query =>
|
||||
`Vamos pesquisar sobre ${query}... O que deseja saber?`,
|
||||
see_faq:
|
||||
"Please take a look at the FAQ I've prepared for you. You can click on them to get the answer.",
|
||||
will_answer_projector:"I'll answer on the projector to a better experience..."
|
||||
},
|
||||
"pt-BR": {
|
||||
did_not_find: "Desculpe-me, não encontrei nada a respeito.",
|
||||
changing_language: "OK, mundando de idioma para o Português...",
|
||||
going_answer: "Ótima escolha, procurando resposta para sua questão...",
|
||||
wider_answer: subjectText =>
|
||||
`Vou te responder de modo mais abrangente... Não apenas sobre ${subjectText}`,
|
||||
which_question: "Qual a pergunta?",
|
||||
anything_else: "Então, posso ajudar em algo a mais?",
|
||||
here_is_subjects: "Aqui estão algumas categorias de assuntos...",
|
||||
menu_select: "Selecionar",
|
||||
lets_search: query =>
|
||||
`Let's search about ${query}... What do you want to know?`,
|
||||
see_faq:
|
||||
"Veja algumas perguntas mais frequentes logo na tela. Clique numa delas para eu responder.",
|
||||
will_answer_projector:"Vou te responder na tela para melhor visualização..."
|
||||
}
|
||||
};
|
|
@ -3,8 +3,6 @@
|
|||
"allowJs": false,
|
||||
"baseUrl": "./",
|
||||
"declaration": false,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"esModuleInterop" : true,
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"skipLibCheck": true,
|
||||
|
|
Loading…
Add table
Reference in a new issue