Conversar, extrair: a arquitetura de chatbots complexos

Os usuários, conversando com assistentes de voz inteligentes, esperam inteligência dos bots de bate-papo. Se você está desenvolvendo um bot para negócios, as expectativas são ainda maiores: o cliente deseja que o usuário siga o cenário pré-prescrito desejado e o usuário deseja que o robô responda de forma inteligente e humanamente às perguntas feitas, ajude a resolver problemas e, às vezes, apenas apoie conversa fiada.


Fazemos bots de bate-papo no idioma inglês que se comunicam com os usuários através de vários canais - Facebook Messenger, SMS, Amazon Alexa e web. Nossos bots substituem serviços de suporte, agentes de seguros e podem apenas conversar. Cada uma dessas tarefas requer sua própria abordagem de desenvolvimento.

Neste artigo, mostraremos em que módulos nosso serviço consiste, como cada um deles é criado, qual a abordagem que escolhemos e por quê. Compartilharemos nossa experiência na análise de diferentes ferramentas: quando as redes neurais generativas não são a melhor opção, por que, em vez do Doc2vec, usamos o Word2vec, qual é o charme e o horror do ChatScript e assim por diante.


À primeira vista, pode parecer que os problemas que estamos resolvendo são bastante triviais. No entanto, no campo do processamento de linguagem natural, existem várias dificuldades associadas à implementação técnica e ao fator humano.
  1. Um bilhão de pessoas fala inglês, e cada falante nativo o usa à sua maneira: existem vários dialetos, recursos individuais de fala.
  2. Muitas palavras, frases e expressões são ambíguas: um exemplo típico está nesta imagem.
  3. A interpretação correta do significado das palavras requer contexto. No entanto, o bot que faz perguntas esclarecedoras ao cliente não parece tão legal quanto aquele que pode mudar para qualquer tópico a pedido do usuário e responder a qualquer pergunta.
  4. Freqüentemente, em discursos e correspondências vivas, as pessoas negligenciam as regras gramaticais ou respondem tão brevemente que é quase impossível restaurar a estrutura das frases.
  5. Às vezes, para responder à pergunta de um usuário, é necessário comparar sua solicitação com os textos da FAQ. Ao mesmo tempo, você precisa ter certeza de que o texto encontrado nas Perguntas frequentes é realmente a resposta, e não apenas contém várias palavras que correspondem à solicitação.


Esses são apenas alguns dos aspectos mais óbvios e também existem gírias, jargões, humor, sarcasmo, erros de ortografia e pronúncia, abreviações e outros problemas que dificultam o trabalho nessa área.

Para resolver esses problemas, desenvolvemos um bot que usa um conjunto de abordagens. A parte de IA do nosso sistema consiste em um gerenciador de diálogo, serviço de reconhecimento e importantes microsserviços complexos que resolvem problemas específicos: Classificador de Intenções, Serviço de Perguntas Frequentes, Conversa Pequena.

Inicie uma conversa. Gerenciador de Diálogo


A tarefa do Dialog Manager no bot é uma simulação de comunicação da comunicação com um agente ativo: deve guiar o usuário através de um cenário de conversa para algum objetivo útil.
Para fazer isso, primeiro descubra o que o usuário deseja (por exemplo, calcule o custo do seguro para carros) e, em segundo lugar, descubra as informações necessárias (endereço e outros dados do usuário, dados sobre motoristas e carros). Depois disso, o serviço deve fornecer uma resposta útil - preencha o formulário e forneça ao cliente o resultado desses dados. Ao mesmo tempo, não devemos perguntar ao usuário o que ele já indicou.

O Dialog Manager permite criar um cenário assim: descreva-o programaticamente, crie a partir de pequenos blocos - problemas ou ações específicos que devem ocorrer em um determinado ponto. De fato, o cenário é um gráfico direcionado, em que cada nó é uma mensagem, pergunta, ação e a borda determina a ordem e as condições da transição entre esses nós, se houver uma escolha múltipla de transição de um nó para outro.
Os principais tipos de nós
  • Nós aguardando até atingirem a fila e aparecerão nas mensagens.
  • Nós aguardando o usuário mostrar uma certa intenção (por exemplo, escreva: "Quero obter seguro").
  • Nós aguardando dados do usuário para validar e salvar.
  • Nós para a implementação de vários projetos algorítmicos (loops, ramificações, etc.).

Se o nó estiver fechado, o controle não será mais transferido para ele e o usuário não verá a pergunta que já foi feita. Assim, se fizermos uma pesquisa aprofundada em um gráfico desse tipo no primeiro nó aberto, obteremos uma pergunta que precisa ser feita ao usuário em um determinado momento. Por sua vez, respondendo às perguntas que o Dialog Manager gera, o usuário fechará gradualmente todos os nós no gráfico e será considerado que ele executou o script prescrito. Então, por exemplo, fornecemos ao usuário uma descrição das opções de seguro que podemos oferecer.


"Eu já disse tudo!"


Suponha que solicitemos um nome ao usuário e, em uma mensagem, ele também fornecerá sua data de nascimento, nome, sexo, estado civil, endereço ou enviará uma foto da carteira de motorista. O sistema extrairá todos os dados relevantes e fechará os nós correspondentes, ou seja, não serão mais feitas perguntas sobre a data de nascimento e sexo.

"A propósito ..."


O Dialog Manager também oferece a capacidade de se comunicar simultaneamente em vários tópicos. Por exemplo, um usuário diz: "Quero obter seguro". Então, sem concluir esse diálogo, ele acrescenta: "Quero efetuar um pagamento em uma política anexada anteriormente". Nesses casos, o Dialog Manager salva o contexto do primeiro tópico e, após a conclusão do segundo script, oferece a retomada da caixa de diálogo anterior do local em que foi interrompida.

É possível retornar às perguntas que o usuário já respondeu. Para isso, o sistema salva o instantâneo do gráfico ao receber cada mensagem do cliente.

Quais são as opções?


Além da nossa, consideramos outra abordagem de IA para a implementação do gerenciador de diálogo: a intenção e os parâmetros do usuário são alimentados à entrada da rede neural, e o próprio sistema gera os estados correspondentes, a próxima pergunta a ser feita. No entanto, na prática, esse método requer a adição de uma abordagem baseada em regras. Talvez essa opção de implementação seja adequada para cenários triviais - por exemplo, para pedir comida, onde você precisa obter apenas três parâmetros: o que o usuário deseja solicitar, quando deseja receber o pedido e para onde trazê-lo. Mas no caso de cenários complexos, como em nossa área de assunto, isso ainda é inatingível. No momento, as tecnologias de aprendizado de máquina não são capazes de orientar qualitativamente o usuário para a meta em um cenário complexo.

O Dialog Manager é escrito em Python, estrutura Tornado, pois inicialmente nossa parte de IA foi escrita como um único serviço. Foi escolhida uma linguagem na qual tudo isso pode ser realizado sem gastar recursos em comunicação.

"Vamos decidir." Serviço de reconhecimento


Nosso produto é capaz de se comunicar através de diferentes canais, mas a parte de IA é completamente independente do cliente: essa comunicação ocorre apenas na forma de texto em proxy. O gerenciador de diálogo transfere o contexto, a resposta do usuário e os dados coletados para o Serviço de Reconhecimento, responsável por reconhecer a intenção do usuário e recuperar os dados necessários.
Hoje, o Serviço de Reconhecimento consiste em duas partes lógicas: o Gerenciador de Reconhecimento, que gerencia o pipeline de reconhecimento, e extratores.

Gerente de reconhecimento


O Reconhecimento Manager é responsável por todos os estágios básicos do reconhecimento do significado da fala: tokenização, lematização etc. Também determina a ordem dos extratores (objetos que reconhecem entidades e atributos nos textos) pelos quais uma mensagem será ignorada e decide quando parar o reconhecimento e o retorno. resultado final. Isso permite executar apenas os extratores necessários na ordem mais esperada.

Se perguntamos qual é o nome do usuário, é lógico verificar primeiro se o nome veio na resposta. O nome chegou e não há mais texto útil - o que significa que o reconhecimento pode ser concluído nesta etapa. Chegaram outras entidades úteis, o que significa que o reconhecimento deve ser continuado. Provavelmente, a pessoa adicionou alguns outros dados pessoais - portanto, você precisa executar o extrator para processar dados pessoais.

Dependendo do contexto, a ordem de inicialização dos extratores pode variar. Essa abordagem nos permite reduzir significativamente a carga em todo o serviço.

Extratores


Como mencionado acima, os extratores são capazes de reconhecer certas entidades e atributos nos textos. Por exemplo, um extrator reconhece números de telefone; outro determina se uma pessoa respondeu positiva ou negativamente a uma pergunta; o terceiro - reconhece e verifica o endereço na mensagem; o quarto são os dados sobre o veículo do usuário. Passando uma mensagem através de um conjunto de extratores - este é o processo de reconhecimento de nossas mensagens recebidas.

Para a operação ideal de qualquer sistema complexo, é necessário combinar abordagens. Aderimos a esse princípio ao trabalhar com extratores. Vou destacar alguns dos princípios de trabalho que usamos em extratores.

Usando nossos microsserviços com o Machine Learning interno (os extratores enviam uma mensagem para este serviço, algumas vezes complementam com as informações que eles têm e retornam o resultado).

  • Usando marcação POS, análise sintática, análise semântica (por exemplo, determinando a intenção do usuário pelo verbo)
  • Usando a pesquisa de texto completo (pode ser usado para encontrar a marca e o modelo da máquina nas mensagens)
  • Usando expressões regulares e padrões de resposta
  • Uso de APIs de terceiros (como API do Google Maps, SmartyStreets etc.)
  • Uma pesquisa literal de sentenças (se uma pessoa respondeu "sim" em breve, não faz sentido passar isso pelos algoritmos de ML para procurar intenção).
  • Também usamos soluções de processamento de linguagem natural prontas em extratores.

Quais são as opções?


Analisamos as bibliotecas NLTK, Stanford CoreNLP e SpaCy. O NLTK sai primeiro nos SERPs do Google quando você inicia uma revisão da PNL. É muito legal para soluções de prototipagem, possui uma funcionalidade abrangente e é bastante simples. Mas seu desempenho é ruim.

O Stanford CoreNLP tem um sério problema: ele puxa uma máquina virtual Java com módulos muito grandes, bibliotecas integradas e consome muitos recursos. Além disso, é difícil personalizar a saída desta biblioteca.

Como resultado, optamos pelo SpaCy, porque ele tem funcionalidade suficiente para nós e possui a proporção ideal de leveza e velocidade. A biblioteca SpaCy é executada dezenas de vezes mais rápido que o NLTK e oferece dicionários muito melhores. No entanto, é muito mais fácil que o Stanford CoreNLP.

No momento, usamos spaCy para tokenização, vetorização de mensagens (usando a rede neural treinada interna), reconhecimento primário de parâmetros do texto. Como a biblioteca cobre apenas 5% de nossas necessidades de reconhecimento, tivemos que adicionar muitas funções.

"Costumava ser ..."


O serviço de reconhecimento nem sempre foi uma estrutura de duas partes. A primeira versão foi a mais trivial: nos revezamos usando diferentes extratores e tentamos entender se havia algum parâmetro ou intenção no texto. A IA nem cheirava lá - era uma abordagem completamente baseada em regras. A dificuldade era que a mesma intenção pode ser expressa de várias maneiras, cada uma das quais deve ser descrita nas regras. Nesse caso, é necessário levar em consideração o contexto, pois a mesma frase de usuário, dependendo da pergunta colocada, pode exigir ações diferentes. Por exemplo, no diálogo: "Você é casado?" - “Já dois anos”, você pode entender que o usuário é casado (significado booleano). E a partir do diálogo "Quanto tempo você dirige este carro?" - “Já dois anos”, você precisa extrair o valor “2 anos”.

Desde o início, entendemos que o suporte a soluções baseadas em regras exigiria muito esforço e, à medida que o número de intenções suportadas aumenta, o número de regras aumentará muito mais rapidamente do que no caso de um sistema baseado em ML. No entanto, o ponto de vista dos negócios. precisávamos executar o MVP, uma abordagem baseada em regras nos permitiu fazer isso rapidamente. Portanto, nós o usamos e, paralelamente, trabalhamos no modelo ML de reconhecimento de intenções. Assim que apareceu e começou a dar resultados satisfatórios, eles gradualmente começaram a se afastar da abordagem baseada em regras.

Para a maioria dos casos de extração de informações, usamos o ChatScript. Essa tecnologia fornece sua própria linguagem declarativa que permite escrever modelos para extrair dados de uma linguagem natural. Graças ao WordNet, esta solução é muito poderosa (por exemplo, você pode especificar uma "cor" no modelo de reconhecimento e o WordNet reconhece qualquer conceito de restrição, como "vermelho"). Não vimos análogos na época. Mas o ChatScript é escrito de forma muito torta e com erros, sendo quase impossível implementar uma lógica complexa.

No final, as desvantagens foram superadas e abandonamos o ChatScript em favor das bibliotecas de PNL no Python.
Na primeira versão do Serviço de reconhecimento, atingimos o limite de flexibilidade. A introdução de cada novo recurso desacelerou bastante o sistema inteiro como um todo.

Por isso, decidimos reescrever completamente o Serviço de Reconhecimento, dividindo-o em duas partes lógicas: extratores pequenos e leves e o Gerenciador de Reconhecimento, que gerenciará o processo.

"O que você quer?" Classificador de Intenção


Para que o bot se comunique adequadamente - forneça as informações necessárias mediante solicitação e registre os dados do usuário - é necessário determinar a intenção (intenção) do usuário com base no texto enviado a ele. A lista de intenções pelas quais podemos interagir com os usuários é limitada pelas tarefas de negócios do cliente: pode ser a intenção de descobrir as condições de seguro, preencher informações sobre você, obter uma resposta a uma pergunta freqüente e assim por diante.

Existem muitas abordagens para a classificação de intenções com base em redes neurais, em particular em LSTM / GRU recorrente. Eles se provaram em estudos recentes, mas têm uma desvantagem comum: uma amostra muito grande é necessária para a operação adequada. Em uma pequena quantidade de dados, essas redes neurais são difíceis de treinar ou produzem resultados insatisfatórios. O mesmo vale para a estrutura Fast Text do Facebook (nós a revimos porque é uma solução de ponta para o processamento de frases curtas e médias).

Nossas amostras de treinamento são de alta qualidade: os conjuntos de dados são compostos por uma equipe de linguistas em período integral, proficiente em inglês e que conhece as especificidades da área de seguros. No entanto, nossas amostras são relativamente pequenas. Tentamos diluí-los com conjuntos de dados públicos, mas aqueles, com raras exceções, não correspondiam às nossas especificidades. Também tentamos atrair freelancers com o Amazon Mechanical Turk, mas esse método também se mostrou inoperante: os dados que eles enviaram eram de baixa qualidade, as amostras tiveram que ser verificadas duas vezes.

Portanto, estávamos procurando uma solução que funcionasse em uma pequena amostra. A boa qualidade do processamento de dados foi demonstrada pelo classificador Random Forest, treinado em dados que foram convertidos nos vetores do nosso modelo de saco de palavras. Usando a validação cruzada, selecionamos os parâmetros ideais. Entre as vantagens do nosso modelo estão a velocidade e o tamanho, bem como a relativa facilidade de implantação e reciclagem.

No processo de trabalho no Intent Classifier, ficou claro que, para algumas tarefas, seu uso não é ideal. Suponha que um usuário queira alterar o nome indicado no seguro ou no número do carro. Para que o classificador determine corretamente essa intenção, seria necessário adicionar manualmente ao conjunto de dados todas as frases de modelo usadas neste caso. Encontramos outra maneira: criar um pequeno extrator para o Serviço de Reconhecimento, que determina a intenção por palavras-chave e métodos da PNL, e usar o Classificador de Intenção para frases não-padrão nas quais o método com palavras-chave não funciona.

"Eles sempre perguntam sobre isso." Perguntas frequentes


Muitos de nossos clientes têm seções de perguntas frequentes. Para que o usuário receba essas respostas diretamente do chatbot, era necessário fornecer uma solução que: a) reconhecesse a solicitação de FAQ; b) encontraria a resposta mais relevante em nosso banco de dados e a emitisse.

Existem vários modelos treinados no conjunto de dados Stanford SQUAD. Eles funcionam bem quando o texto da resposta da FAQ contém as palavras da pergunta do usuário. Digamos que o FAQ diz: "Frodo disse que levaria o Anel para Mordor, embora ele não soubesse o caminho para lá". Se o usuário perguntar: “Para onde Frodo levará o anel?”, O sistema responderá: “Para Mordor”.

Nosso cenário, via de regra, era diferente. Por exemplo, para dois pedidos semelhantes - "Posso pagar?" e "Posso pagar online?" O bot deve responder de maneira diferente: no primeiro caso, ofereça uma forma de pagamento a uma pessoa, na segunda resposta - sim, você pode pagar on-line, eis o endereço da página.

Outra classe de soluções para avaliar a semelhança de documentos está focada em respostas longas - pelo menos algumas frases, entre as quais contêm informações de interesse do usuário. Infelizmente, em casos com perguntas e respostas curtas ("Como pago on-line?" - "Você pode pagar usando o PayPal"), eles funcionam muito instáveis.

Outra solução é a abordagem Doc2vec: o texto grande é destilado em uma representação vetorial, que é então comparada com outros documentos da mesma forma e o coeficiente de similaridade é revelado. Essa abordagem também teve que ser retirada: ela se concentra em textos longos, mas lidamos principalmente com perguntas e respostas de uma ou duas frases.

Nossa decisão foi baseada em duas etapas. Primeiro: usando incorporação, traduzimos todas as palavras de uma frase em vetores usando o modelo Google Word2vec.Depois disso, consideramos o vetor médio para todas as palavras, representando uma frase na forma de um vetor. A segunda etapa, pegamos o vetor da pergunta e encontramos no banco de dados da FAQ, armazenado no mesmo formato vetorial, a resposta mais próxima até certo ponto, no nosso caso, cosseno.

As vantagens incluem facilidade de implementação, extensibilidade muito fácil e interpretabilidade bastante simples. As desvantagens são uma fraca oportunidade de otimização: esse modelo é difícil de modificar - ele funciona bem na maioria dos casos de usuários ou é necessário abandoná-lo.

"E conversar?" Conversa fiada


Às vezes, o usuário escreve algo completamente irrelevante, por exemplo: "O clima está bom hoje". Isso não está incluído na lista de intenções que nos interessa, mas ainda queremos responder de maneira significativa, demonstrando a inteligência do nosso sistema.

Para tais decisões, é usada uma combinação das abordagens descritas acima: elas são baseadas em soluções muito simples baseadas em regras ou em redes neurais generativas. Como queríamos obter um protótipo com antecedência, pegamos um conjunto de dados público da Internet e usamos uma abordagem muito semelhante à usada nas Perguntas frequentes. Por exemplo, um usuário escreveu algo sobre o clima - e, usando um algoritmo que compara representações vetoriais de duas sentenças com uma certa medida de cosseno, procuramos uma sentença no conjunto de dados público que seja o mais próximo possível do tema climático.

Treinamento


Agora, não temos o objetivo de criar um bot que seja treinado em todas as mensagens recebidas dos clientes: primeiro, a experiência mostrou que esse é o caminho para a morte do bot (lembre-se de como o IBM Watson teve que apagar a base porque começou a diagnosticar com um tapete e o robô do Twitter da Microsoft conseguiu se tornar racista em apenas um dia). Em segundo lugar, nos esforçamos para fechar as tarefas das companhias de seguros da maneira mais qualitativa possível; um bot de auto-aprendizado não é nossa tarefa comercial. Escrevemos várias ferramentas para linguistas e comandos de controle de qualidade com as quais eles podem treinar bots manualmente, explorando diálogos e correspondências com os usuários durante a pós-moderação.

No entanto, nosso bot já parece pronto para passar no teste de Turing. Alguns usuários iniciam uma conversa séria com ele, acreditando que estão conversando com um agente de seguros, e um deles começa a ameaçar uma reclamação ao chefe quando o bot o interpreta mal.

Planos


Agora, estamos trabalhando na parte visual: exibindo o gráfico inteiro do script e a capacidade de compor usando a GUI.

No lado do Serviço de Reconhecimento, estamos introduzindo uma análise linguística para reconhecer e entender o significado de cada palavra na mensagem. Isso melhorará a precisão da reação e extrairá dados adicionais. Por exemplo, se uma pessoa preenche o seguro de automóvel e menciona que tem uma casa sem seguro, o bot será capaz de se lembrar dessa mensagem e passá-la ao operador para entrar em contato com o cliente e oferecer seguro de casa.

Outro recurso no trabalho é o processamento de feedback. Após concluir o diálogo com o bot, perguntamos ao usuário se ele gostou do serviço. Se a Análise de sentimentos reconheceu a avaliação do usuário como positiva, convidamos o usuário a compartilhar sua opinião nas redes sociais. Se a análise mostrar que o usuário reagiu negativamente, o bot esclarece o que está errado, corrige a resposta, diz: “OK, vamos consertar” e não oferece compartilhar a revisão no fluxo.

Uma das chaves para tornar a comunicação com o bot o mais natural possível é torná-lo modular e expandir o leque de reações disponíveis. Estamos trabalhando nisso. Talvez por isso, o usuário estivesse pronto para levar sinceramente o nosso bot a um agente de seguros. O próximo passo: verifique se a pessoa está tentando agradecer ao bot.



O artigo foi escrito com Sergei Kondratyuk e Mikhail Kazakov . Escreva suas perguntas nos comentários, prepararemos materiais mais práticos sobre eles.

Source: https://habr.com/ru/post/pt429638/


All Articles