Uma nova abordagem para softwares conversacionais

Nós estamos construindo a melhor maneira para o seu bot manter uma conversa com contexto — e de forma open-source.

Atenção: esta é uma tradução para o Português do artigo de Alan Nichol , publicado originalmente em 4 de Outubro de 2017— Você pode encontrar a versão original clicando aqui.

Em 2016, após ter passado mais de seis meses construindo bots para o Slack, nós escrevemos um artigo detalhando alguns pontos que nós acreditávamos estarem faltando para criar bons softwares de conversação.

Desde então, aqui no Rasa, nós temos feito pesquisas aplicadas à esta área e construído ferramentas para preencher algumas dessas lacunas. Em dezembro de 2016 nós lançamos o Rasa NLU, e hoje ele é utilizado por milhares de desenvolvedores.

Agora, nós estamos prontos para lançar o Rasa Core, que é a coisa mais ambiciosa que nós já construímos. Deixe-me explicar o que é, como nós chegamos aqui, e para onde estamos indo.


É tudo sobre contexto

Nós já vimos bots inevitavelmente falharem em gerenciar contexto. Este é um problema tão conhecido que até apareceu na sacola da ChatbotConf:

Logo, quais ferramentas os desenvolvedores precisam para fazer melhor do que isso? Há muita pesquisa sobre o uso de aprendizado de máquina para resolver este problema. No entanto, embora tenha havido um progresso significativo neste tópico nas últimas décadas, isso não se traduziu em excelentes ferramentas de desenvolvimento.

Hoje em dia, as bibliotecas disponíveis para os desenvolvedores confiam em regras definidas manualmente. Com o Rasa Core, nós propusemos o desafio de construir um framework de diálogo baseado em aprendizado de máquina, que esteja pronto para produção, flexível o suficiente para suportar pesquisa e experimentação, e acessível para não-especialistas.


Todo mundo utiliza máquina de estados, e máquina de estados não escalam

Aqui estão algumas das abordagens caseiras que eu tenho visto as pessoas utilizarem para criar bots.

Digamos que queremos criar um bot que ajude os usuários a entender os produtos oferecidos por um grande banco. Para começar, os clientes podem perguntar sobre duas coisas: renda fixa e conta poupança. Você quer deixá-los comparar as opções, por isso, se alguém fizer uma pergunta contextual como "Qual deles tem a menor taxa de juros?", precisamos saber se estão falando sobre a renda fixa ou a conta poupança.

A implementação de uma máquina de estados deve-se parecer com o diagrama abaixo. Você tem estados como info_renda_fixa e info_poupanca, além de algumas regras para alternar entre elas de acordo com o que o usuário acabou de dizer.

Um típico fluxo de máquina de estados.

Aqui está um pseudocódigo mostrando como nós poderíamos lidar com a intenção comparar_taxas:

if intent == comparar_taxas:
  if current_state == INFO_POUPANCA:
poupanca = tracker.recent_suggestions["poupanca"]
ActionInformarSobrePoupanca.run(poupanca)
  else if current_state == INFO_RENDA_FIXA:
renda_fixa = tracker.recent_suggestions["renda_fixa"]
ActionInformarSobreRendaFixa.run(renda_fixa)
  else:
ActionIncerteza.run()

De forma simples, isto consegue construir uma conversação como esta:

Exemplo simples de conversação.

O caminho feliz

Agora se o usuário disser, "Certo, eu gosto da ideia da renda fixa", ou "legal, vamos com a segunda opção", podemos lidar com isso também (nós podemos chamar uma nova intenção de fazer_escolha):

if intent == fazer_escolha:
if current_state == INFO_POUPANCA:
# select the right savings account from suggestions
selected_account = resolve_choice(
entities,
tracker.recent_suggestions["poupanca"]
)
if selected_account is not None:
ActionIniciarAplicacao.run()
else:
ActionPerguntarQualAcao.run()
else if current_state == INFO_RENDA_FIXA:
# select the right application from suggestions
selected_application = resolve_choice(
entities,
tracker.recent_suggestions["renda_fixa"]
)
if selected_account is not None:
ActionIniciarAplicacao.run()
else:
ActionPerguntarQualAplicacao.run()
else:
ActionIncerteza.run()

Tivemos que aninhar algumas novas regras, mas isto ainda é bastante gerenciável.

Indo além do caminho feliz

É aqui que as coisas ficam difíceis! Como você lida com respostas como:

"Não tem outras opções? Não gostei de nenhuma dessas."

"Gostei da terceira opção." (quando não há terceira opção! 😱)

Ou outras sequências, como: "Porque as taxas são tão diferentes?"

Uma opção é adicionar mais níveis de lógica ao código acima. Outra é adicionar um estado extra à sua máquina de estado, com outro conjunto de regras sobre como entrar e sair desse estado. Ambas as abordagens levam a um código frágil e difícil de manter. Qualquer pessoa que tenha criado e depurado um bot moderadamente complexo, conhece esta dor.

Existem apenas alguns caminhos felizes, mas a grande maioria das conversas é um "caso extremo… de um caso extremo… de um caso extremo". Os sistemas tradicionais de URA funcionam desta forma, assim como a maioria dos chatbots hoje em dia. Como desenvolvedor, você analisa as milhares de conversas que as pessoas tiveram e adiciona regras manualmente para lidar com cada caso. Então você testa e percebe que elas colidem com outras regras que você escreveu anteriormente, e a vida se torna cada vez mais difícil.


Como é a abordagem da comunidade científica: Aprendizagem por Reforço

Como nós podemos utilizar o aprendizado de máquina para ir além do conjunto de regras? Como mencionado, nas últimas décadas foram feitas excelentes pesquisas sobre este assunto.

Muitas delas focaram em utilizar Aprendizagem por Reforço (AR) para construir sistemas que possam aprender tarefas complexas, apenas tentando e retentando até receber um feedback positivo — ou, uma recompensa.

Crédito da imagem: Megajuice

Por exemplo, um problema de AR pode ser descrito assim:

  1. O usuário está procurando por alguma coisa (digamos, um restaurante) e possui alguns critérios em mente; como o tipo de culinária, a localização e a faixa de preço;
  2. O bot questiona o usuário e sugere recomendações;
  3. O bot recebe uma recompensa caso tenha sugerido algo que atende aos critérios. No entanto, a recompensa é reduzida caso tenha ocorrido uma conversa de longa duração.

Esta especificação oferece a você um problema bem estruturado onde você pode fazer progressos significativos. Porém, nem sempre isso se correlaciona com o que você quer em um sistema comercial.

Na nossa experiência, os usuários não sabem realmente o que querem, e muitas vezes você não consegue mapear suas restrições para colunas em um banco de dados. Não é uma coincidência que as bem conhecidas histórias de sucesso no aprendizado por reforço sejam em videogames e jogos de tabuleiro, casos que você sabe que a pontuação é a recompensa correta.

A simplicidade do aprendizado por reforço é ao mesmo tempo uma força e uma fraqueza. Seu sistema não precisa entender nada sobre o seu próprio comportamento, apenas quais ações resultam em uma recompensa.

Por outro lado, o seu sistema pode realizar dezenas ou centenas de decisões antes de receber uma recompensa, e então, descobrir quais dessas decisões ajudaram e quais atrapalharam. Isso requer muita experiência.

Eu estou totalmente convencido de que o aprendizado por reforço é uma ferramenta importante para o futuro da IA conversacional. Contudo, no momento, esta não é a melhor abordagem para desenvolvedores que desejam construir um sistema de diálogo funcional.

Existem algumas dificuldades práticas e técnicas que dificultam a aplicação da AR, embora todas elas estejam sendo abordadas pela comunidade cientifica.

  1. AR tem fome de dados. Você precisa de milhares de conversas para aprender comportamentos simples. Além do quê, a maioria dos algoritmos de AR não podem aprender com dados fora da política, o que significa que você só pode aprender com uma conversa uma única vez, no momento em que estiver tendo. Embora é possível fazer melhor.
  2. Treinar com humanos reais em um ciclo de recompensas parece ótimo, mas avaliações humanas são notoriamente não confiáveis. Amigos que competiram no Alexa Prize me disseram que estavam frustrados porque algumas de suas melhores conversas receberam apenas uma estrela, enquanto os usuários atribuíram aleatoriamente cinco estrelas para conversas que não faziam sentido algum.
  3. Treinar utilizando um usuário simulado lhe restringe a problemas que você consegue especificar uma recompensa, o que causa problemas como os que eu mencionei em uma postagem anterior:
…se nós otimizarmos nosso sistema para o máximo valor de compra, podemos acabar com um bot de vendas muito agressivo, ou um que explore pontos fracos em nossa psicologia.

Nós queríamos que o Rasa Core fosse útil aos desenvolvedores na primeira tentativa. Logo, o primeiro passo não poderia ser: "Implemente um usuário simulado e uma função de recompensa que descreva completamente o comportamento que você deseja". Também não poderíamos dizer: "anote algumas milhares de conversas reais e depois volte aqui".

O Rasa Core precisou expandir o domínio de conhecimento existente dos desenvolvedores para ajudá-los a começar a partir do zero, sem dados de treinamento. Isto nos levou à abordagem do Aprendizado Interativo.


A abordagem do Rasa: Tornando a pesquisa aplicada acessível a todos os desenvolvedores.

Nós temos trabalhado com centenas de empresas desenvolvendo bots, e a nossa experiência diz que fluxos gráficos são úteis para o design inicial do bot e para descrever algumas interações corretas, mas você não deve levá-los ao pé da letra e codificá-los com um conjunto de regras. Já vimos muitas vezes como esta abordagem não escala além de conversas simples.

Há uma assimetria aqui que queremos explorar. Por um lado, é óbvio para qualquer um quando um bot faz a coisa errada. Mas, por outro lado, raciocinar sobre a sua máquina de estados e centenas de regras para descobrir o porquê ela deu errado é realmente complicado. E se eu simplesmente souber o que o bot deveria ter feito fosse o suficiente?

Com o Rasa Core, você especifica manualmente todas as coisas que o seu bot pode falar e fazer. Nós chamamos isto de actions. Uma ação pode ser cumprimentar o usuário, fazer uma chamada em uma API, ou consultar um banco de dados. Depois, você treina um modelo probabilístico para prever qual ação deve ser tomada de acordo com o histórico da conversa.

O treino pode acontecer de diferentes modos. Se você tem um banco de dados de conversas e quer aprender a partir delas, anote-as e inicie o aprendizado supervisionado. Contudo, poucas pessoas têm um conjunto utilizável de conversas anotadas. O que recomendamos aos novos usuários, é utilizar o aprendizado interativo para iniciar a partir de zero dados.

Construindo Diálogo com o Aprendizado Interativo

No modo de aprendizado interativo, você provê feedback passo a passo sobre o que o seu bot decidiu fazer. É um tipo de aprendizado por reforço, mas com feedbacks em todos os passos (ao invés de apenas no final da conversa).

Rasa Core em ação. O bot faz sugestões para o que deve ser feito a seguir, e o usuário fornece feedback para melhorar o modelo de diálogo.

Quando o seu bot escolhe a ação errada, você diz qual seria a correta. O modelo é atualizado imediatamente (fazendo com que seja menos provável encontrar o mesmo erro novamente) e assim que terminar, a conversa é registrada em um arquivo que pode ser adicionado aos seus dados de treinamento.

Você resolveu um caso extremo instantaneamente, sem observar seu código por muito tempo para descobrir o que deu errado. Além de que, como você está fornecendo feedback passo a passo, ao invés de uma única recompensa no final, está ensinando ao sistema muito mais diretamente o que está correto e errado.

Na nossa experiência, algumas dúzias de conversas curtas são suficientes para obter uma primeira versão do seu sistema em execução.


O que vem a seguir

Temos trabalhado no Rasa Core há quase um ano e meio, e está em produção com nossos clientes há quase um ano. Ele passou por várias revisões e reimplementações.

Nos últimos meses, tivemos dezenas de desenvolvedores construindo com o Rasa como parte do nosso programa beta. Graças a todos eles, conseguimos simplificar a documentação e as API's até ao ponto de estarmos prontos para lançá-lo ao mundo. Está licenciado sob uma licença comercialmente amigável (assim como o Rasa NLU) para que as pessoas possam construir coisas reais com ele. Queremos que o Rasa Core acelere a chegada de ótimos softwares de conversação.


O repositório do Rasa Core está aqui.

Se você quer trabalhar nestes problemas conosco, junte-se a nossa equipe.

Interessado em softwares conversacionais, processamento de linguagem natural, e construção de chatbots? Junte-se ao Rasa Forum.

Meus agradecimentos à Milica Gašić, Simon Willnauer, Matthäus Krzykowsky, e Alex Weidauer, por suas contribuições neste post, e muito obrigado à toda equipe do Rasa por fazer tudo isto acontecer. Vocês são world-class, todos vocês.


Este post foi traduzido por Matheus Matos para o Rasa Brasil.