Implementar Fluxos de Conversas

Aqui estão algumas práticas recomendadas para implementar fluxos de conversas em assistentes digitais.

Com um modelo bem projetado, você está pronto para começar a criar os fluxos de conversa para suas intenções regulares. As conversas são definidas por uma série de etapas do fluxo de caixas de diálogo nas habilidades do Oracle Digital Assistant.

Usar Modo Visual

Ao criar uma habilidade, você tem a opção de defini-la para usar o modo de design Visual ou YAML legado. Você deve sempre usar o modo Visual, que também é a opção padrão. O modo visual oferece uma série de vantagens sobre o modo YAML legado, incluindo o seguinte:

  • Uma experiência de design visual, com estados de fluxo representados visualmente em uma tela, editores de propriedades de componentes e validação em tempo de design.
  • A capacidade de dividir o fluxo de caixas de diálogo geral em vários fluxos.
  • A capacidade de criar fluxos reutilizáveis que podem ser chamados de outros fluxos para tratar coisas que são usadas por vários fluxos.
  • Com muito mais facilidade de leitura e manutenção.

Conversas Orientadas por Diálogo

As conversas orientadas por diálogo coletam as informações necessárias ao usuário para concluir uma tarefa navegando por um usuário em uma série de estados de fluxo de caixas de diálogo. Cada estado é vinculado a um componente para renderizar respostas de bot e prompts do usuário, ou para tratar condições, lógica e outras funcionalidades.

Com essa abordagem, você desenvolve o fluxo de caixas de diálogo como um script de filme derivado dos casos de uso projetados na fase de planejamento do seu projeto. Como as etapas individuais de uma conversa são controladas pelo fluxo de caixas de diálogo, seu fluxo de caixas de diálogo pode rapidamente se tornar bastante grande. Para evitar fluxos de caixas de diálogo que não podem ser gerenciados em tamanho, você deve particionar seus casos de uso em habilidades diferentes.

Usar uma Convenção de Nomenclatura para Nomes de Estado do Fluxo de Caixas de Diálogo

Considere os nomes dos estados do fluxo de caixas de diálogo como parte da documentação. Se o nome do estado do fluxo de caixas de diálogo fornecer um contexto, os revisores de código acharão mais fácil entender o que um estado do fluxo de caixas de diálogo faz e a qual fluxo de conversas ele pertence. Por exemplo :

  • promptForOrderNumber
  • findOrder
  • cancelOrder

Além disso, se sua habilidade estiver no modo YAML, considere manter os estados de fluxo de caixas de diálogo relacionados intimamente juntos dentro do BotML para que seja mais fácil seguir o curso das ações em uma conversa ao revisar seu código.

Melhores Práticas para Usar Variáveis

As variáveis contêm as informações que uma habilidade coleta de um usuário. Sempre que possível, use variáveis de um tipo de entidade para as informações que você deseja coletar. Faça isso pelos seguintes motivos:

  • A entrada do usuário é validada e os usuários são solicitados novamente após uma entrada de dados inválida.

  • Os assistentes digitais lidam com a navegação não sequencial, o que significa que os usuários podem iniciar uma nova conversa enquanto estiverem em uma conversa existente sem que você precise codificá-la.

  • Para entidades incorporadas encapsuladas em uma entidade composta e para entidades personalizadas, você pode definir prompts, uma mensagem de erro de validação e um prompt de desambiguação (que é mostrado automaticamente pelos componentes Resposta Comum e Resolver Entidades).

  • Uma variável de um tipo de entidade poderá ser dividida em slots a partir das mensagens iniciais do usuário se você associar a entidade à intenção. Para habilidades desenvolvidas no modo de diálogo Visual, esse slot acontece automaticamente com os componentes Resposta Comum e Resolver Entidades. Para habilidades desenvolvidas no modo de diálogo YAML, use a propriedade nlpResultVariable nos componentes de entrada para obter essa funcionalidade.

Uso de palavras-chave em itens de ação

Os componentes de Resposta Comum e os componentes personalizados permitem que você defina palavras-chave para seus itens de ação. Com uma palavra-chave, os usuários podem invocar uma ação enviando um atalho como um número ou uma abreviação. Isso significa que eles não precisam pressionar um item de ação, o que eles não poderiam usar um canal ou voz somente texto, ou digitar o texto completo do rótulo do item de ação exibido.

Considere o seguinte ao definir palavras-chave usando Resposta Comum ou componentes personalizados, incluindo handlers de eventos de entidade.

  • As palavras-chave não precisam ter o mesmo texto mostrado no rótulo.

  • As palavras-chave não fazem distinção entre maiúsculas e minúsculas. Não é necessário definir uma palavra-chave em todas as variantes possíveis com distinção entre maiúsculas e minúsculas.

  • Se você planeja criar bots para vários idiomas, suas palavras-chave não podem ser definidas apenas em inglês. Para suportar palavras-chave multilíngues, você pode fazer referência a uma string de pacote de recursos da propriedade keyword dos componentes de Resposta Comum (${rb('resource_key_name')}). A string do pacote de recursos então contém uma lista de palavras-chave separadas por vírgulas.

  • Forneça pistas visuais indicando que as palavras-chave podem ser usadas, por exemplo, adicionando um número de índice na frente do rótulo.

    Por exemplo, um menu de ação para enviar ou cancelar uma prescrição pode ser definido com os seguintes rótulos: "1. Enviar", "2. Cancelar". E as palavras-chave podem ser definidas como "1,1., enviar" e "2,2., cancelar". Assim, para cancelar um pedido, o usuário pode digitar "cancelar", "2" ou "2".

    Observação

    Observe que, neste caso, "enviar" e "cancelar" também precisam ser definidos como palavras-chave porque os rótulos são "1". Enviar" e "2. Cancelar", não apenas "Enviar" um "Cancelar".
  • Palavras-chave não funcionam se usadas em uma frase. Se, por exemplo, um usuário escrever "Prefiro cancelar meu pedido", "cancelar" não será detectado como palavra-chave. Se você espera que seus usuários usem conversa em vez de palavras-chave para selecionar em uma opção, considere os menus de ação baseados em NLU, conforme explicado na próxima seção.

Se você está se perguntando como criar palavras-chave baseadas em índice para itens de ação criados dinamicamente, aqui estão as opções:

  • Ative a numeração automática em suas habilidades por meio da definição de configuração Ativar Numeração Automática em Ações de Postback nos Fluxos de Tarefas da habilidade. Isso configura os componentes para adicionar a palavra-chave à lista de palavras-chave e o índice ao rótulo.

  • Use expressões FreeMarker do Apache para adicionar o número do índice e/ou fazer referência a uma string de pacote de recursos que contenha o valor do item de ação em seu nome.

Considerar Menus de Ação Baseados em NLU

Os menus de ação geralmente usam itens de ação que um usuário pode pressionar para executar a navegação para uma conversa específica ou para enviar, confirmar ou cancelar uma operação. Quando um item de ação é pressionado, uma mensagem é enviada à habilidade com um payload opcional para atualizar variáveis e uma string de ação para determinar o estado do fluxo de caixas de diálogo para o qual fazer a transição.

Se um usuário digitar uma mensagem que não corresponde ao rótulo do item de ação ou uma palavra-chave definida para um item de ação, a próxima transição será seguida. Por exemplo, imagine um par de itens de ação que usem Enviar relatório de despesas e Cancelar relatório de despesas como rótulos. Se um usuário digitar "Sim, envie", a próxima transição será acionada, em vez do item de ação marcado com Send Expense Report. O motivo disso acontecer é porque uma implementação que exige que os usuários pressionem um botão ou item de ação não é conversacional!

Para criar menus de ação robustos e verdadeiramente conversacionais, você precisa criá-los com base em entidades de lista de valores, em que os valores da lista indicam a ação a ser seguida e os sinônimos definem possíveis palavras-chave que um usuário usaria em uma mensagem para chamar uma ação.

Para fazer isso, primeiro você cria uma entidade de lista de valores para a qual define uma variável no fluxo de caixas de diálogo. Em seguida, você pode usar um componente Resposta Comum ou Resolver Entidades para exibir a lista de opções. A variável criada deve ser configurada como o valor da propriedade da variável do componente. Dessa forma, a próxima transição é acionada quando o usuário digita "Sim, envie" e navega até um estado de fluxo de caixas de diálogo que verifica o valor armazenado na variável.

O valor armazenado na variável é um dos valores definidos na entidade value-list. Usando um componente Alternar, você pode definir o próximo estado do fluxo de caixas de diálogo com o qual a conversa continua.

Se o usuário informar uma mensagem que não esteja na entidade da lista de valores ou como um de seus sinônimos, o menu de ação será chamado novamente. Como você usou uma inicialização de lista de valores, pode usar a mensagem de erro definida para a entidade para ajudar os usuários a entender o que é esperado deles. Além disso, como você pode configurar vários prompts para a entidade da lista de valores, é possível exibir prompts alternativos e até mesmo mensagens que gradualmente revelam informações adicionais, incluindo informações sobre como cancelar a exibição do menu de ação.

Se você criar nomes de string do pacote de recursos para os valores na entidade da lista de valores, poderá garantir que os rótulos exibidos nos itens de ação possam ser traduzidos usando uma das seguintes expressões:

  • ${rb(enumValue)}
  • ${rb(enumValue.value.primaryLanguageValue)} (se a propriedade fullEntityMatches estiver definida como true para o componente Resposta Comum)

Para definir dinamicamente os valores em um item de ação, os componentes de Resposta Comum são mais fáceis de trabalhar. Se você estiver familiarizado com processadores de eventos de entidade de programação, o uso das Entidades de Resolução também será possível.

Com menus de ação baseados em NLU, os usuários podem pressionar um item de ação ou digitar uma mensagem que não precisa ser a correspondência exata de um rótulo de ação ou palavra-chave.

Interrompendo uma Conversa Atual para uma Nova Conversa

Uma pergunta frequente é como configurar uma conversa para que os usuários possam iniciar uma conversa nova ou diferente quando for solicitada uma entrada. No entanto, esta questão é mais uma decisão de design que você precisa fazer do que sobre o know-how técnico. Aqui estão as considerações de design:

  • Sua habilidade está exposta por meio de um assistente digital? Em caso afirmativo, a habilidade participa do roteamento não sequencial do assistente digital, que roteia mensagens para outra habilidade ou outra intenção na mesma habilidade se a mensagem do usuário não puder ser validada com sucesso para o estado do fluxo de caixas de diálogo atual. Para fazer com que essa navegação não sequencial aconteça, certifique-se de que a entrada do usuário seja validada em relação a uma variável baseada em entidade.

  • Sua habilidade está exposta como uma habilidade independente? Se assim for, então não há navegação não sequencial incorporada, e você precisa projetar para isso. Para fazer isso, você usa uma variável baseada em entidade para o estado do fluxo de caixas de diálogo que deseja permitir que os usuários ramifiquem em uma nova conversa. Em seguida, defina a propriedade maxPrompts do componente de entrada do usuário como 1 e configure a transição da ação cancel para iniciar uma nova conversa. Seria um erro apontar diretamente a transição de cancelamento para o estado de intenção, pois provavelmente causaria um loop infinito. Portanto, antes de navegar de volta para o estado de intenção, certifique-se de usar um estado de fluxo de caixas de diálogo configurado com o componente Redefinir Variáveis para redefinir a variável de tipo nlpresult e outras variáveis necessárias para a conversa.

Observação

Embora a criação de habilidades independentes que você expõe diretamente em um canal seja uma opção, não recomendamos. O principal motivo é que você perde todos os benefícios de conversação e desenvolvimento obtidos com o uso de um assistente digital. Alguns dos benefícios que você perderia são:
  • Navegação não sequencial, que é a capacidade do assistente digital de suspender uma conversa atual para alterar temporariamente o tópico para outra conversa.

  • Desenvolvimento modular que permite dividir seu esforço de desenvolvimento em várias habilidades, permitindo desenvolvimento incremental e melhorias em seu bot.

  • Tratamento automático de solicitações de ajuda.

  • Reutilização de habilidades comumente necessárias, como perguntas frequentes, conversa fiada e integração de agentes.

Conversas Orientadas a Modelos

Conversas orientadas por modelos são uma extensão de conversas orientadas por caixas de diálogo. Com conversas orientadas por modelo, você reduz a quantidade de código de fluxo de caixas de diálogo que escreve, fornecendo uma navegação madura e focada em objetos de domínio de interações bot-usuário.

A ideia por trás do que chamamos de conversa orientada por modelo é tratar a conversa resolvendo entidades compostas usando os componentes Resolver Entidades ou Resposta Comum. As entidades compostas são semelhantes aos objetos de domínio, pois agrupam um conjunto de entidades para formar um objeto do mundo real que representa um pedido, reserva, cliente ou similar.

Cada entidade no repositório composto é resolvida automaticamente por um componente Resolver Entidades ou Resposta Comum, o que significa que todas as respostas e prompts de bot são gerados para você sem a necessidade de criar estados de fluxo de caixas de diálogo para cada um deles. Com conversas orientadas por modelo, você escreve menos código de fluxo de caixas de diálogo e obtém mais funcionalidade.

Abordagem Recomendada

As melhores práticas para criar uma conversa orientada por modelo são usar entidades compostas, processadores de eventos de entidade e o componente Resolver Entidades.

Não há nada de errado em usar o componente Resposta Comum em vez de ResolveEntities, mas, graças aos processadores de eventos de entidade, Resolver Entidades é suficiente para a maioria das implementações.

  • Entidades de repositório composto são objetos de domínio que têm itens de repositório para cada informação a ser coletada de um usuário. Cada item da bolsa tem prompts, mensagens de erro e um prompt de desambiguação definido que é exibido, se necessário. Para itens compostos baseados em entidades de lista de valores, você também pode exibir listas com várias seleções. Um benefício das entidades compostas é sua capacidade de coletar entrada do usuário para muitos de seus itens de repositório de uma única mensagem do usuário. Essa funcionalidade é chamada de extração fora da ordem e é ativada por padrão.

  • O componente Resolver Entidades resolve entidades exibindo prompts definidos na entidade, validando a entrada do usuário, exibindo mensagens de erro de validação definidas na entidade e mostrando uma caixa de diálogo de desambiguação quando os usuários fornecem mais informações do que o esperado em uma mensagem. Para entidades compostas, o componente Resolver Entidades renderiza interfaces de usuário para todos os itens do repositório na entidade composta na ordem em que eles são definidos.

  • Um Manipulador de Eventos de Entidade é um componente JavaScript registrado em uma entidade composta e contém funções chamadas pelo componente Resolver Entidades ao resolver a entidade composta. Essa abordagem orientada a eventos permite executar lógica de código personalizada e até mesmo chamar serviços REST remotos enquanto um usuário está trabalhando em uma entidade composta. Abordaremos os processadores de eventos de entidades mais detalhadamente mais adiante neste guia.

Como Criar Conversas Orientadas a Modelos

O melhor projeto para conversas orientadas por modelo é minimizar o número de itens de repositório exigidos por uma entidade composta. Imagine entidades compostas como módulos de conversação individuais que você encadeia até uma conversa.

Verifique com o usuário após cada entidade composta que você resolver para dar a ele a oportunidade de continuar ou interromper a conversa.

Claro, isso não deve ser implementado com um prompt como "devo continuar" seguido por um par de botões "sim" e "não". Deixe seu designer de conversas criar uma transição menos intrusiva que une dois módulos de conversa.

Pacotes de Recursos para Mensagens e Prompts

Como acontece com todas as mensagens e prompts, recomendamos fortemente o uso de strings de pacotes de recursos para prompts e mensagens definidas em itens de entidade composta. Veja alguns exemplos de entidades compostas:

  • cbe.<entity_name>.bag_item_name.errorMessage

  • cbe.<entity_name>.bag_item_name.disambiguationMessage

  • cbe.<entity_name>.bag_item_name.prompt1

  • cbe.<entity_name>.bag_item_name.prompt2

Melhores Práticas do Apache FreeMarker

O Apache FreeMarker é uma linguagem de expressão avançada que você pode usar em seus fluxos de caixas de diálogo, bem como em configurações de entidade e habilidade. No entanto, as expressões FreeMarker do Apache tornam-se problemáticas quando ficam muito complexas, tornando-as propensas a erros e difíceis de usar devido à falta de opções de depuração.

Nossa recomendação é evitar expressões FreeMarker complexas de várias linhas do Apache e, em vez disso, considerar uma das seguintes opções:

  • Divida expressões FreeMarker complexas salvando valores em variáveis com nomes curtos antes de usá-los na expressão.

  • Use as diretivas <#/if ...> para melhorar a legibilidade das suas expressões FreeMarker.

  • Use processadores de eventos de entidade com entidades compostas para lidar com código de validação complexo ou ao calcular valores a serem atribuídos a uma variável.

  • Verifique se há valores nulos para variáveis referenciadas usando a expressão incorporada ?has_content. Forneça um valor padrão razoável se a expressão for resolvida como falsa, por exemplo, ?has_content?then(...,<SENSIBLE_DEFAULT_VALUE>).

Lista de Verificação para Implementar Conversas

  • ☑ Escolha nomes sensatos e descritivos para seus fluxos e estados de fluxo.
  • ☑ Usar variáveis de tipo de entidade.
  • ☑ Os prompts de entrada do usuário para variáveis de tipo de entidade devem ler o prompt da entidade.
  • ☑ Crie conversas orientadas a modelos.
  • ☑ Crie menus de ação a partir de entidades de lista de valores.
  • ☑ Evite expressões FreeMarker complexas do Apache.
  • ☑ Usar pacotes de recursos. Nenhuma mensagem de texto ou prompt deve ser adicionado diretamente ao fluxo de caixas de diálogo.
  • ☑ Crie fluxos reutilizáveis para partes da conversa que são comuns a diferentes fluxos.