Motores NLU Externos
O NLU nativo do Botpress é executado no local e oferece suporte a um conjunto finito de idiomas. Se planeja desenvolver chatbots em idiomas que o Botpress não suporta ou se deseja usar outra solução NLU, precisará configurar um conector NLU de terceiros.
Para conseguir isso, usaremos o poder dos ganchos do Botpress.
Definir Idiomas
Um caso de uso para um NLU de terceiros é oferecer suporte a mais idiomas além daqueles manipulados pelo Botpress Native NLU.
Para que o Botpress continue funcionando corretamente com um idioma adicional (definindo intenções e conteúdo), será necessário informar ao Botpress os novos idiomas aos quais deseja oferecer suporte.
Para fazer isso, abra o botpress.config.json e defina a propiedade de additionalLanguages.
Digamos que queremos dar suporte ao sueco e ao norueguês, a configuração ficaria assim:
{
"additionalLanguages":
[
{
"code": "sv",
"name": "Swedish"
},
{
"code": "no",
"name": "Norwegian"
}
]
}Agora que já terminou, acesse sua página de configuração do chatbot e escolha o(s) idioma(s) que deseja que seu chatbot suporte.
Observe que multilíngue é um recurso de licença do Botpress Enterprise.
Sincronize dados NLU
Esta função permite que você use a interface Botpress NLU para definir suas intenções, entidades e slots. As intenções e as entidades são armazenadas como JSON no BPFS (anteriormente fantasma) no sistema de arquivos local ou no banco de dados.
Para sincronizar dados, precisamos ouvir todas as alterações de intents ou entidades e persistir os dados em nosso NLU de terceiros (consulte o tutorial de escuta de alterações de arquivos para obter mais informações).
Dessa forma, quando alguém edita intents ou entidades na interface do usuário NLU, somos notificados. Podemos fazer isso com um gancho Botpress após a montagem do bot.
É possível utilizar o módulo do editor de código para criar ganchos facilmente. Veja como o código para o gancho fileWatcher se parece:
async function sync(bp: typeof sdk, botId: string) {
// create a BPFS (ghost) instance for our bot
const ghost = bp.ghost.forBot(botId)
// listen on file changes
ghost.onFileChanged(async file => {
console.log(file)
})
}
//those parameters are accessible in the current scope
return sync(sdk, botId)onFileChanged é chamado com o nome do arquivo que contém as alterações quando um arquivo é criado, editado ou excluído.
O que queremos fazer agora é verificar se a alteração é relevante (por exemplo, alteração nas intenções ou entidades) e sincronizar os dados com seu NLU personalizado.
Nosso gancho agora ficará assim:
const axios = require('axios')
async function sync(bp: typeof sdk, botId: string) {
const ghost = bp.ghost.forBot(botId)
ghost.onFileChanged(async f => {
if (f.includes('intents') || f.includes('entities')) {
// we get all intents
const intentNames = await ghost.directoryListing('intents', '*.json')
const intents = await Promise.all(intentNames.map(name => ghost.readFileAsObject('intents', name)))
// we get all entities
const entNames = await ghost.directoryListing('entities', '*.json')
const entities = await Promise.all(entNames.map(name => ghost.readFileAsObject('entities', name)))
// TODO process intents and entities in the format required by your NLU
/*
* Here, you would call your own NLU provider by HTTP with processed data
*
* await axios.post('http://NLUprovider/train', {intents, entities})
*
*/
}
})Aqui está agora ainda é possível usar a interface do usuário do Botpress NLU para definir suas intenções e entidades, assim como enviar dados de treinamento para seu motor NLU.
Use seu NLU de terceiros para classificação e extração
Usaremos uma estratégia semelhante durante o tempo de previsão. O que queremos fazer é chamar nosso NLU de terceiros para cada mensagem de usuário recebida. Usaremos um gancho antes da entrada, executado quando o Botpress receber uma mensagem do usuário.
O código não é complexo caso tenha em mente que o Botpress trabalha com uma estrutura de dados precisa, então será necessário mapear os dados de resposta do seu provedor NLU para o formato de dados Botpress NLU.
O gancho terá a seguinte aparência:
async function hook(bp: typeof sdk, event: sdk.IO.IncomingEvent) {
/** Your code starts below */
const myHook = async (bp, event) => {
const _ = require('lodash')
/**
* Returns the detected language (e.g. 'en', 'fr', 'es', etc) given a string of text
*/
const detectLanguage = async text => {
// Here, you can use your own service to detect the language given the user's text
const response = await axios.get('https://langdetect.yourdomain.com', { input: text })
return response.data.lang
}
/**
* Given an input and its language, returns a nlu-compatible object
*/
const predict = async (lang, text) => {
// Important: the result must have this structure in order
// for Botpress to process it correctly downstream
const result = {
entities: [],
language: lang,
detectedLanguage: lang,
ambiguous: false,
slots: {},
intent: { name: 'none', confidence: 1, context: 'global' },
intents: [],
errored: false,
includedContexts: ['global'],
ms: 0
}
let response
switch (lang) {
case 'en':
// You
response = await axios.get('https://en-server.yourdomain.com', { input: text })
// You are responsible for mapping the response's data
// to the result object, so it conforms with Botpress's expected format
result.intent = response.data.intent
break
case 'fr':
// We only use intents from this service
response = await axios.get('https://detect.nlpfrancais.fr', { input: text })
result.intents = response.data.result.intentions
break
case 'es':
// This service returns more relevant information. We reuse
// slots, intents and intent from the service's response
response = await axios.get('https://nlufrancais.anothercompany.com', { input: text })
result.slots = response.data.slots
result.intents = response.data.intents
result.intent = response.data.intent
break
default:
break
}
return result
}
// Filter out unwanted events
if (event.type === 'session_reset' || event.type === 'visit' || event.type === 'bp_dialog_timeout') {
return
}
// We must disable the native NLU for this even,
event.setFlag(bp.IO.WellKnownFlags.SKIP_NATIVE_NLU, true)
// Now, we detect the language from the user's input
const detectedLanguage = await detectLanguage(event.payload.text)
// Then we process the user's input, knowing the user's language
const result = await predict(detectedLanguage, event.payload.text)
// Finally, we overwrite the nlu property of the event with our results
_.assign(event, {
nlu: result
})
}
return myHook(bp, event)
/** Your code ends here */
}Agora, o Botpress está integrado ao seu NLU de terceiros.