O blog da AWS
Como construir Chatbots complexos encadeando intents no HAQM Lex (Chain Intents)
Por Giovanna Chiaratti, Arquiteta de Soluções AWS Brasil
Introdução
Digamos que você abriu uma pizzaria. A fim de automatizar o atendimento e baixar custos. Você pensa em construir um chatbot para automatizar a realização do pedido e, com isso agilizar o atendimento, dando mais autonomia aos clientes e ainda reduzindo custos. E seria interessante incluir a possibilidade de pedir uma entrada e uma sobremesa, além da pizza aumentando seu ticket médio por pedido. O HAQM Lex é uma solução para sua necessidade. Mas como segmentar isso no HAQM Lex de forma que o usuário passe por todas as possibilidades [entrada, pizza e sobremesa]?
Nesse blogpost vou explicar como criar um chatbot na AWS utilizando o HAQM Lex, serviço para a criação de interfaces de conversa em qualquer aplicativo usando voz e texto, encadeando intents e criando árvores de decisão para que o usuário tenha uma melhor experiência e você possa vender mais.
Visão Geral da Solução
HAQM Lex é o organizador do seu ChatBot. No HAQM Lex você irá configurar quais são as possíveis intenções (Intents) de um usuário. O “intent” é a ação principal que um usuário pode ter. No nosso exemplo, o usuário pode querer pedir uma entrada, uma pizza, uma sobremesa ou os três. Consideramos que: pedir uma entrada é um intent, pedir uma pizza seria o segundo intent e pedir uma sobremesa é o terceiro intent. Nosso objetivo é guiar o usuário a percorrer os três intents, na ordem lógica para o melhor atendimento e melhor funcionalidade da nossa aplicação.
O primeiro ponto é decidir ou desenhar a lógica que deve ter o seu chatbot, ou seja, qual intent deve ser apresentado primeiro ao usuário, o segundo e o terceiro. No nosso exemplo, parece que existe uma ordem lógica. Vale a pena essa reflexão quando pensamos em chatbots mais complexos antes de desenhar o chatbot em si. Nessa reflexão você deve levar em consideração a lógica da sua aplicação, formas de respostas adequadas e a intersecção de intents.
Vamos entender os componentes do chatbot. Como vimos antes, os intents são as intenções gerais que um usuário pode escolher no seu chatbot, então seriam: pedir uma entrada, pedir uma pizza, pedir uma sobremesa ou pedir os três. Os intents são construídos por slots. Os slots são parâmetros, são as características dos intents. Os slots são apresentados aos usuários, normalmente em forma de pergunta.
Pensando no nosso exemplo, o intent é “pedir uma pizza” e o slot seria “pizza com borda recheada ou não”, “pizza com massa fina ou grossa”, “pizza com queijo ou não”, assim por diante. No intent “pedir uma sobremesa”, os slots poderiam ser: “calda de chocolate?”, “gostaria de 01 ou 02 unidades?”, etc. Ou seja, os slots são parâmetros dos intents.
Spoiler: os slots coletam detalhes, informações ou parâmetros para que as AWS Lambdas possam fazer a query ou enviar o pedido. As AWS Lambdas retêm a lógica do chatbot.
Assim a conversa vai até o usuário preencher os slots do intent “pedirPizza”
. Importante lembrar que cada intent pode ter cinco slots, ou seja, são cinco especificações que podem ser feitas dentro do intent. Caso você queira colocar mais especificações, deve adicionar mais intents.
Agora, seguindo o fluxo do nosso chatbot da pizzaria, após completar o intent “pedirPizza”
o usuário será direcionado ao intent “pedirSobremesa”. Há duas opções para encadear esses intents. A primeira é: no momento em que o usuário responde todos os slots do intent “pedirPizza”
, o chatbot retorna uma resposta intuitiva, como exemplo:
“Seu pedido foi feito com sucesso! Gostaria de incluir:
a. uma entrada;
b. ou uma sobremesa?”.
No momento em que o usuário coloca a palavra “sobremesa”
, caso essas sejam palavras-chave (Utterance) do intent “pedirSobremesa”
, o Lex direcionará o usuário ao intent “pedirSobremesa”
e o direcionará a responder todos os slots desse intent.
A segunda forma de direcionar o usuário a outro intent é por meio da Lambda.
Mão na Massa
O HAQM Lex é integrado de forma nativa com as Funções Lambda. A Lambda é a lógica por traz do chatbot: as funções lambda recebem as respostas dos usuários aos slots (parâmetros) e as processam. A Lambda permite que utilizemos o HAQM Lex para desenvolvimento de chatbots complexos, como para queries, transformação e atualização de banco de dados ou de qualquer outro sistema, integrando com os mais de 175 serviços da AWS. A partir da sua Lambda, você pode chamar qualquer outro serviço da AWS ou outras Lambdas e podemos pensar de forma abrangente, como mandar mensagens para filas do SQS, atualizar um banco SQL, entre outros.
No nosso exemplo, o usuário será direcionado ao próximo intent “pedirSobremesa”
.
Perceba que, conforme falamos antes, cada intent pode ter até cinco slots (parâmetros). Para o encadeamento de intents feito por meio de funções lambda utilizaremos um dos slots do próximo intent para receber a resposta do intent anterior. Abaixo você pode ver uma explicação gráfica:
A resposta do usuário “brigadeiro” irá popular o primeiro slot “tipo” [tipo de sobremesa, brigadeiro ou beijinho] do intent “pedirSobremesa”. Como isso acontece?
Vamos ver como as funções lambda estão estruturadas para receber a resposta dos slots e também como encadear intents por meio de lambda.
Se lembre que sempre que mencionarmos usuário aqui, estaremos falando do o cliente da pizzaria.
O HAQM Lex é responsável por preencher os slots de um intent perguntando e obtendo respostas do usuário. Uma vez que o intent esteja completo, o HAQM Lex envia um “payload” json com as informações coletadas a uma Lambda que processa, guarda ou faz o que quer que seja necessário com elas e retorna uma resposta ao HAQM Lex indicando o que fazer em seguida.
RequestID: XXXXXXXX
{
"alternativeIntents": [
{
"intentName": "AMAZON.FallbackIntent",
"nluIntentConfidence": null,
"slots": {}
}
],
"botVersion": "$LATEST",
"dialogState": "ReadyForFulfillment",
"intentName": "pedirPizza",
"message": null,
"messageFormat": null,
"nluIntentConfidence": {
"score": 1
},
"responseCard": null, #caso houvesse um ResponseCard configurado
"sentimentResponse": null, # o HAQM Lex enviaria outra resposta.
"sessionAttributes": {},
"sessionId": "2021-02-03TXXXXXXXXXX ",
"slotToElicit": null,
"slots": {
"borda": "sim",
"queijo": "mozarela",
"sabor": "peperoni",
"slotFour": "fina",
"tamanho": "8"
}
}
Como dissemos, o json acima é preenchido pelo HAQM Lex com todos os slots que ele coletou do usuário para o intent pedirPizza
e enviado como parâmetro de entrada para Lambda que é definida no campo “Fulfillment – AWS Lambda Function”.
Esse json de entrada da Lambda reflete a configuração feita na figura 1.
Essa função Lambda deve retornar como resposta outro json no formato que o HAQM Lex espera. Esse formato é definido aqui.
Dica: se você adicionasse um ResponseCard, ele apareceria na posição apontada pela seta na figura acima.
Abaixo mostramos o código da função Lambda em Python 3.7 que processa o intent pedirPizza.
Essa Lambda recebe do HAQM Lex o json acima [def lambda_handler] e processa as informações coletadas nos slots de acordo com a lógica que você escreve [def c_pizza], como por exemplo, guardar a escolha do cliente num item de pedido num meio persistente (ex, um BD) para posteriormente enviar o pedido a cozinha. Após esse processamento, a Lambda responde as informações ao HAQM Lex no formato requerido aqui como retorno do método [def respostaPizza]:
def respostaPizza(pedidoPizza):
if pedidoPizza["success"]:
return {
"dialogAction": {
"type": "ElicitSlot",
"message": {
"contentType": "PlainText",
"content": "Seu pedido foi feito com sucesso. Gostaria de pedir um brigadeiro ou beijinho?."
},
"intentName": "pedirSobremesa",
"slotToElicit": "tipo"
}
}
else:
return {
"dialogAction": {
"type": "Close",
"fulfillmentState": "Fulfilled",
"message": {
"contentType": "PlainText",
"content": "Houve um erro"
},
}
}
def c_pizza(sabor, tamanho, borda, massa, queijo):
pedidoPizza = [] #sua lógica do código...
return pedidoPizza
def lambda_handler(event, context):
pedidoPizza = c_pizza(event["currentIntent"]["slots"]["sabor"], event["currentIntent"]["slots"]["tamanho"], event["currentIntent"]["slots"]["borda"], event["currentIntent"]["slots"]["massa"], event["currentIntent"]["slots"]["queijo"])
return respostaPizza(pedidoPizza) #aqui passamos os parâmetros dos slots para a #função respostaPizza.
O que foi descrito acima, completa o intent pedirPizza
. Mas também queríamos encadear o intent pedirSobremesa
para oferecer a oportunidade, ao usuário, de acrescentar a sobremesa ao seu pedido. Para direcionar o usuário ao intent pedirSobremesa
, ou seja, para encadearmos esse próximo intent, adicionamos à resposta retornada por nossa Lambda o dialogAction.Type:
ElicitSlot
e informamos o próximo intent através do campo intentName:pedirSobremesa
, como mostrado na figura abaixo.
Ao receber essa resposta, o HAQM Lex reassume o controle, orientando o usuário a negar ou responder aos slots desse intent, pedirSobremesa
, de acordo com seu desejo.
Chegando ao final dessa árvore de decisão, ou seja, chegado ao final do atendimento ao usuário, onde todos os possíveis intents foram oferecidos a ele que pode ter aceitado ou não a “oferta” de cada um, a última Lambda chamada pode compor o pedido por agregar os dados coletados e previamente armazenados num meio persistente e mandá-lo para uma fila do HAQM SQS. Mas isso é assunto para um próximo blog.
#O HAQM Lex espera um formato específico de resposta. Esse é um dos formatos #possíveis. Esse exemplo é simples e cobre o necessário para o funcionamento do #código. Para mais formatos, revisar a página de formatos de resposta do HAQM Lex
def respostaPizza(ordem):
if ordem["success"]:
return {
"dialogAction": {
"type": "ElicitSlot",
"message": {
"contentType": "PlainText",
"content": "Seu pedido foi feito com sucesso. Gostaria de pedir um brigadeiro ou beijinho?" #mensagem para o usuário
},
"intentName": "pedirSobremesa", #próximo intent a ser mostrado
"slotToElicit": "tipo" #próximo slot a ser mostrado
}
}
else:
return {
"dialogAction": {
"type": "Close",
"fulfillmentState": "Fulfilled",
"message": {
"contentType": "PlainText",
"content": "Houve um erro"
},
}
}
Conclusão
Com esse passo a passo verificamos que podemos encadear intents no HAQM Lex e criar árvores de decisão elaboradas, guiar o usuário de forma granular, adaptar o chatbot a necessidade da nossa aplicação e integrar o chatbot com sistemas externos por meio das chamadas API feitas pelas funções Lambda.
Podemos ir além e integrar o HAQM Lex com serviços que se conectam com funções Lambda, ou seja, é possível coordenar serviços dentro e fora da AWS, deployar HAQM Lex em múltiplas plataformas como Slack, Facebook e Twilio, entre outros sistemas enterprise como Salesforce e Zendesk. Ah, e não se esqueça: deployar um chatbot complexo precisa ser acompanhado de uma boa pizza!
Sobre a autora
Giovanna Chiaratti é Arquiteta de Soluções para Parceiros na América Latina focada em países de língua espanhola. Admiradora e estudiosa de tecnologias como Machine Learning, Inteligência Artificial e Serverless. Trabalha para escalar parceiros de consultoria e tecnologia para que possam apoiar a AWS em criar soluções seguras, inovadoras e inteligentes.
Revisores
Fernando Batagin Junior atua como Arquiteto de soluções para parceiros, guiando-os na jornada de integração ou implementação de suas soluções de software na AWS. Profundo conhecedor de engenharia de software, foca em modernizar soluções existentes de parceiros no Brasil. Possui vinte anos de experiência em projeto e desenvolvimento de software, principalmente na área bancária, passando por várias linguagens, como C, C++, Java, JavaScript, VisualBasic e C# e metodologias de modelagem como UML.
Gerson Itiro Hidaka atualmente trabalha como Arquiteto de Soluções da AWS e atua no atendimento a parceiros mundiais chamados de Global System Integrators and Influencers (GSIIs) na região da América Latina. Entusiasta de tecnologias como Internet das Coisas (IOT), Drones, Devops e especialista em tecnologias como virtualização, serverless, container e Kubernetes. Trabalha com soluções de TI a mais de 24 anos, tendo experiência em inúmeros projetos de otimização de infraestrutura, redes, migração, disaster recovery e DevOps em seu portifólio.