Como eu Gravo Fluxos de Caixas de Diálogo no OBotML?
O OBotML usa uma sintaxe simples para definir variáveis e estados. Por ser uma variante do YAML, tenha em mente as convenções de espaço do YAML ao definir o fluxo de caixas de diálogo. Você não precisa começar do zero. Em vez disso, use a definição de fluxo de caixas de diálogo padrão como modelo básico.
context
e states
, de modo que você pode simplesmente excluir o padrão existente e adicionar seu próprio conteúdo. Para ajudar você a criar definições de estado sintaticamente adequadas, use os modelos de componentes no menu + Componente. Consulte Sintaxe de Fluxo de Caixas de Diálogo para obter dicas sobre a definição de variáveis e estados.
Dica:
Clique em Validar conforme você escreve seu fluxo de caixas de diálogo para verificar erros de sintaxe e aplicar melhores práticas.Sintaxe de Fluxo de Caixas de Diálogo
O Que Fazer? | Use isto |
---|---|
Definir variáveis que persistem no contexto em todo o fluxo de caixas de diálogo? |
No nó
context , use a seguinte sintaxe: variablename: "variableType" Por exemplo:
Você pode definir variáveis como entidades ( |
Definir um handler de erros para sua habilidade? |
Defina o nó
defaultTransitions que aponta para um estado de tratamento de erros. Geralmente, você adicionaria esse estado no fim da definição do fluxo de caixas de diálogo. Por exemplo :
Consulte Configurar o Fluxo de Caixas de Diálogo para Ações Inesperadas. |
Defina uma variável que mantenha o valor da intenção resolvida? |
No nó
context , defina uma variável que nomeie a entidade nlpresult . Como seu nome indica ("nlp" significa "Natural Language Processing), essa entidade extrai a intenção resolvida pelo Mecanismo de Intenções. Quase todos os bots de referência declaram as variáveis nlpresult . Por exemplo :
|
Controlar o fluxo de caixas de diálogo com base na entrada do usuário? |
Normalmente (embora nem sempre), você definiria uma propriedade Conforme descrito em A Estrutura do Fluxo de Caixa de Diálogo no Modo YAML, você pode declarar uma variável |
Equipar minha habilidade para tratar intenções não resolvidas? |
Defina um estado para a ação Exemplo:
|
Ativar componentes para acessar valores de variáveis? |
Use a propriedade
.value em suas expressões (${crust.value} ). Para substituir um valor padrão, use ${variable.value!\"default value\"} . Por exemplo, thick é o valor padrão em ${crust.value!\"thick\"} . Por exemplo :
Use o operador padrão do Apache FreeMarker ( |
Salvar valores do usuário para visitas de retorno? |
Em uma definição de estado, adicione uma definição de variável com um prefixo
user. . Consulte Componentes YAML Incorporados para Definir Valores do Usuário. Por exemplo :
Para saber mais sobre variáveis do usuário, consulte o fluxo de caixas de diálogo do bot de referência PizzaBotWithMemory. |
Saia de um fluxo de caixas de diálogo e encerre a sessão do usuário. |
Use uma transição Exemplo:
|
Navegação e Transições de Fluxo
Você pode definir o mecanismo de caixa de diálogo em um caminho específico no fluxo de caixas de diálogo, definindo a propriedade de transições para um estado. As transições descrevem como a caixa de diálogo é bifurcada quando valores de variáveis são definidos ou não. Elas permitem traçar a rota típica por meio da conversa (o fluxo “feliz”) e definir rotas alternativas que acomodem valores ausentes ou comportamento imprevisível do usuário.
Para isso... | ... Usar esta transição |
---|---|
Especifique o próximo estado a ser executado. | Defina uma transição next (next: "statename" ) para instruir o Mecanismo de Caixa de Diálogo a pular para o estado nomeado pela chave next . Conforme observado na próxima Transição, você pode adicionar uma transição next em qualquer estado, exceto aqueles que têm uma transição return .
|
Redefina a conversa. | Use uma transição return para limpar qualquer valor definido para as variáveis de contexto e redefinir o fluxo de caixas de diálogo. Você pode dar a essa transição qualquer valor de string. A definição de uma transição return: "done" encerra a sessão do usuário e posiciona o Mecanismo de Caixa de Diálogo no início do fluxo.
|
Dispare ações condicionais. | Defina chaves actions para acionar a navegação para um estado específico. Quando um componente conclui seu processamento, ele retorna uma string de ação que instrui o Mecanismo de Caixa de Diálogo para onde ir em seguida. Se você não definir qualquer chave de ação, o Mecanismo de Caixa de Diálogo dependerá da transição padrão ou de uma transição next (se houver alguma). Você pode definir quantas ações precisar. Alguns componentes incorporados têm ações específicas. Por exemplo, um componente como System.MatchEntity que avalia uma expressão do Apache FreeMarker, usa as ações match e nomatch . System.OAuthAccountLink tem ações textReceived , pass e fail , e as componentes da interface do usuário usam suas próprias ações (descritas em Transições para Componentes Comuns de Resposta ). Use os modelos de componentes como guia. Você pode definir uma transição actions em qualquer estado, exceto aqueles que tenham uma transição return .
|
Trate os erros. | Os componentes às vezes geram erros. Geralmente, isso acontece por causa de um problema ou falha relacionado ao sistema (senhas inválidas, nomes de host inválidos ou erros de comunicação). A definição de uma transição error que nomeia um estado de tratamento de erros permite que sua habilidade trate normalmente os problemas: Se você não definir uma transição error , a habilidade irá gerar o Prompt de Erro Inesperado ( Oops! I’m encountering a spot of trouble) e encerrar a sessão. Você pode definir uma transição error em qualquer estado, exceto aqueles que têm uma transição return .
Alguns componentes têm um erro definido como ação. Essas transições de erro incorporadas tratam erros específicos do componente:
|
next
:state_name:
component: "component name"
properties:
component_property: "value"
component_proprety: "value"
transitions:
next: "go_to_state"
error: "go_to_error_handler"
actions:
action_string1: "go_to_state1"
action_string2: "go_to_state2"
Embora você possa definir mais de uma transição, a transição
return
é uma exceção: não é possível combinar uma transição return
com as transições error
, next
ou actions
.
próxima transição
Use a transição next
para especificar o próximo estado padrão. Quando um estado combina as transições error
, actions
e next
, a transição next
só é acionada quando o componente não consegue retornar uma string que satisfaz a uma das transições error
ou actions
.
next
seja acionada sempre que erros ou ações não puderem, defina uma ação next
no nó defaultTransition
.
context:
variables:
name: "string"
defaultTransitions:
next: "nextRules"
states:
getName:
component: "System.Text"
properties:
prompt: "What's your name please?"
variable: "name"
transitions:
next: "printName"
printName:
component: "System.Output"
properties:
text: "Hello ${name.value}."
transitions:
return: "done"
nextRules:
component: "System.Output"
properties:
text: "Hello ${name.value}. I told you! Next transitions rule the game!"
transitions:
return: "done"
Configurar o Fluxo de Caixas de Diálogo para Ações Inesperadas
Cenário | Solução |
---|---|
Em vez de tocar nos botões, o usuário responde inadequadamente digitando texto. | Para permitir que seu bot trate essa situação adequadamente, roteie para um estado em que o componente System.Intent possa resolver a entrada de texto, como textReceived: Intent no seguinte trecho de código do CrcPizzaBot:
|
Os usuários rolam para trás para uma mensagem anterior e tocam nas opções dessa mensagem, mesmo que o esperado seja ele tocar nos botões da resposta atual. |
Por padrão, o Assistente Digital trata mensagens fora da ordem, mas você pode substituir ou personalizar esse comportamento, conforme descrito em Como as Ações Fora da Ordem São Detectadas.
Por exemplo, a adição de uma transição
system.outofOrderMessage informa ao Mecanismo de Caixa de Diálogo a transição para um único estado que trata todas as mensagens fora da ordem, como o estado HandleUnexpectedAction no trecho de código do OBotML anterior. Você pode usar outras abordagens para criar esse estado:
|
Call a Skill from Another Skill from a YAML Dialog Flow
Pode acontecer de você desejar fornecer aos usuários a opção explícita de deixar temporariamente a habilidade com a qual eles estão envolvidos para fazer algo em uma segunda habilidade no assistente digital. Por exemplo, se eles estiverem em uma habilidade de compra e tiverem feito algumas seleções, você poderá exibir um botão que permita a eles passar para uma habilidade de banco (para verificar se eles têm dinheiro suficiente para a compra) e, em seguida, retornar à habilidade de compra para concluir um pedido.
Para tratar isso em um fluxo de caixas de diálogo YAML, você pode configurar uma ação em uma habilidade para iniciar a interação com outra habilidade no mesmo assistente digital e depois retornar ao fluxo original.
Veja como funciona:
-
Use o componente
System.CommonResponse
para apresentar ao usuário um botão para fazer algo em outra habilidade.O botão se baseia em uma ação de postback, na qual você configura o payload para fornecer uma declaração direcionada para a habilidade de destino. O ideal é que a declaração contenha o nome de chamada da habilidade de destino (isto é, ser uma chamada explícita) para maximizar a probabilidade de que o roteamento para essa habilidade ocorrerá. Ao fazer isso, você essencialmente codifica uma declaração para acionar a intenção desejada.
Veja o formato desse código:
component: "System.CommonResponse" properties: metadata: ... responseItems: - type: "cards" ... actions: ... - label: "Press me to switch to different skill" type: "postback" payload: action: "system.textReceived" variables: system.text: "utterance with invocation name that you want passed to the digital assistant" ...
Usando uma ação
system.textReceived
e especificando o texto na variávelsystem.text
, você garante que o postback seja tratado como mensagem do usuário que pode ser roteada corretamente pelo assistente digital.Observação
Quando você usasystem.textReceived
dessa forma,system.text
é a única variável que você pode definir no payload de postback. Todas as outras variáveis no payload são ignoradas. - Você define a transição
textReceived
para o estado que contém o componenteSystem.Intent
.transitions: actions: .... textReceived: "Name of the state for the System.Intent component"
Isso é necessário para garantir que o assistente digital forneça uma resposta de fallback apropriada se o assistente digital não contiver a habilidade de destino.
Para que isso funcione, o componente
System.Intent
da habilidade deve ter sua propriedadedaIntercept
definida como"always"
(que é o padrão).
Se a habilidade de destino estiver no assistente digital, ele reconhecerá a chamada explícita, assumirá o controle da solicitação (que normalmente seria tratada pelo componente) e roteará a solicitação para o componente System.Intent
da habilidade de destino. Quando o fluxo na habilidade de destino for finalizado, o usuário será retornado para a habilidade de chamada.
Se a habilidade de destino não estiver no assistente digital (ou a habilidade de chamada for exposta sem um assistente digital), o componente System.Intent
da habilidade de chamada será chamado e a intenção deverá ser resolvida como unresolvedIntent
.
Dica:
Para tratar o caso em que o nome da chamada da habilidade de destino é alterado quando é adicionado a um assistente digital, você pode usar um parâmetro personalizado para informar o nome da chamada da habilidade na variável system.text
.
Por exemplo, você poderia criar um parâmetro chamado da.CrcPizzaCashBankInvocationName
na habilidade de pizza e dar a ele um valor padrão CashBank
. Você então poderia referenciar o parâmetro como:
system.text: "ask ${system.config.daCrcPizzaFinSkillInvocationName}, what is my balance"
Se o nome da chamada da habilidade for alterado, basta alterar o valor do parâmetro personalizado para que corresponda ao novo nome da chamada.
Consulte Parâmetros Personalizados.
Quando você usa uma chamada explícita na variável
system.text
, o usuário pode ver a mensagem com esse botão duas vezes:
- Quando eles são apresentados ao botão para navegar até a outra habilidade.
- Quando eles concluem o fluxo na outra habilidade.
system.text
em vez da chamada explícita. Chamada implícita é uma declaração que corresponde bem a uma determinada habilidade sem usar o nome da chamada da habilidade (ou uma variante do nome da chamada com outro espaçamento ou capitalização).
Exemplo: Chamar uma Habilidade de Outra Habilidade
Por exemplo, aqui está uma intenção para pedir uma pizza (OrderPizza
) que dá ao usuário a opção de verificar o saldo da conta bancária antes de fechar o pedido. O saldo da conta é fornecido por outra habilidade (CashBank
). Se o usuário selecionar a opção Check Balance
, o texto "ask CashBank, what is my balance" será postado novamente no assistente digital e o usuário será roteado para a intenção apropriada na habilidade CashBank
.
OrderPizza:
component: "System.CommonResponse"
properties:
metadata:
...
responseItems:
- type: "cards"
headerText: "Our pizzas:"
cardLayout: "vertical"
name: "PizzaCards"
actions:
- label: "More Pizzas"
...
- label: "Check bank account balance"
type: "postback"
payload:
action: "system.textReceived"
variables:
system.text: "ask CashBank, do I have enough money?"
...
processUserMessage: true
transitions:
actions:
order: "AskPizzaSize"
more: "OrderPizza"
textReceived: "Intent" # where the value of textReceived is the name CashBank's System.Intent state
...
Supondo que sua habilidade de pizza esteja no mesmo assistente digital da habilidade Cash Bank, veja o que aconteceria se você abrisse o assistente digital no testador, acessasse a habilidade de pizza e, em seguida, clicasse em Verificar saldo da conta bancária.

Descrição da ilustração hábil-skill.png
Na guia Roteamento do testador, você pode ver que a chamada explícita foi reconhecida e tem a preferência:
Posteriormente, você poderá ver que a intenção Verificar Saldo da habilidade Cash Bank tem correspondência:
Variáveis com Escopo do Usuário em Fluxos de Caixas de Diálogo YAML
Quando a conversa termina, os valores de variáveis que foram definidos na entrada do usuário são destruídos. Sem esses valores, os usuários de habilidades deverão reclassificar para refazer suas etapas toda vez que retornarem às suas habilidades. Você pode poupar os usuários desse trabalho definindo variáveis com escopo do usuário no fluxo de caixas de diálogo. Sua habilidade pode usar essas variáveis, que armazenam a entrada dos usuários das sessões anteriores, para fazê-los passar rapidamente pela conversa.
context
, são prefixadas com user.
O estado checklastorder
no trecho a seguir do fluxo de caixas de diálogo PizzaBotWithMemory inclui a variável user.lastsize
que retém o tamanho da pizza da sessão de usuário anterior. A variável user.
persiste no ID do usuário. Esse ID é específico do canal, dessa forma, embora você possa retornar a uma conversa ou ignorar um pedido usando entradas anteriores nas habilidades executadas no mesmo canal, não será possível fazer isso entre canais distintos.
main: true
name: "PizzaBot"
parameters:
age: 18
context:
variables:
size: "PizzaSize"
type: "PizzaType"
crust: "PizzaCrust"
iResult: "nlpresult"
sameAsLast: "YesNo"
states:
intent:
component: "System.Intent"
properties:
variable: "iResult"
transitions:
actions:
OrderPizza: "checklastorder"
CancelPizza: "cancelorder"
unresolvedIntent: "unresolved"
checklastorder:
component: "System.ConditionExists"
properties:
variable: "user.lastsize"
transitions:
actions:
exists: "lastorderprompt"
notexists: "resolvesize"
lastorderprompt:
component: "System.List"
properties:
options: "Yes,No"
prompt: "Same pizza as last time?"
variable: "sameAsLast"
transitions:
next: "rememberchoice"
rememberchoice:
component: "System.ConditionEquals"
properties:
variable: "sameAsLast"
value: "No"
transitions:
actions:
equal: "resolvesize"
notequal: "load"
...
load:
component: "System.CopyVariables"
properties:
from: "user.lastsize,user.lasttype,user.lastcrust"
to: "size,type,crust"
transitions:
...
Componentes YAML Incorporados para Definir Valores do Usuário
Defina a propriedade value
dos componentes a seguir com expressões como “${user.age.value}”
para definir valores de usuário armazenados.
Componente | Usos |
---|---|
System.SetVariable | Define o valor do usuário armazenado. |
System.ResetVariables | Redefine um valor de usuário armazenado. |
System.CopyVariables | Copia o valor do usuário armazenado. |
System.Output | Gera o valor do usuário armazenado como texto. |
System.ConditionExists | Verifica se a variável com escopo do usuário já está no contexto. |
System.ConditionEquals | Verifica a variável com escopo do usuário. |
System.Switch | Usa o valor armazenado para alternar de um estado para outro. |
Numeração Automática para Canais Somente Texto em Fluxos de Caixas de Diálogo YAML
A estrutura de numeração automática permite que seu bot de habilidades seja executado em canais somente texto porque ela prefixa botões e lista de opções com números. Quando os usuários não podem usar gestos de toque, eles ainda podem acionar as ações de postback do botão digitando um número. Por exemplo, quando o CrcPizzaBot é executado em um canal que suporta botões, ele exibe Pizzas e Pastas.
Mas quando ele é executado em um canal somente texto, ele renderiza as opções Pizza e Pasta como texto e as prefixa com números sequenciais (1. Pizza 2. Pasta).
A numeração automática não é limitada a canais somente texto; ativá-la onde botões são suportados adiciona outra maneira de os usuários fazerem suas escolhas. Por exemplo, os usuários podem tocar em Pizza ou digitar 1.
Definir Numeração Automática para Fluxos de Caixas de Diálogo YAML
Para fluxos de caixas de diálogo YAML, você pode definir a funcionalidade de numeração automática em escala global (o que significa que ela afeta todos os componentes nomeados em sua definição de fluxo de caixas de diálogo) ou no nível do componente para os componentes que disparam ações de postback, ou seja, os componentes System.List
, System.CommonResponse
, System.ResolveEntities
, System.QnA
, System.Webview
, System.OAuthAccountLinkComponent
e System.OAuth2AccountLinkComponent
.
-
No nó de contexto, adicione
autoNumberPostbackActions: "boolean"
. Isso, assim comotextOnly
eautoTranslate
, é uma variável comum que pode ser usada em todos os seus bots.context: variables: pizzaSize: "PizzaSize" pizzaType: "PizzaType" pizzaCrust: "PizzaCrust" pizzaCheese: "CheeseType" autoNumberPostbackActions: "boolean" iResult: "nlpresult"
-
Defina a propriedade
autoNumberPostbackActions
comotrue
:type: component: "System.List" properties: prompt: "What Type of Pizza do you want?" options: "${pizzaType.type.enumValues}" variable: "pizzType" autoNumberPostbackActions: "true" footerText: "Enter a number or tap your selection." transitions: ...
Se for necessário substituir a numeração automática para um componente específico (seja ele do sistema ou personalizado), defina a propriedadeautoNumberPostbackActions
comofalse
. Para substituir a numeração automática de uma ação de postback específica no componente System.CommonResponse, adicione uma propriedadeskipAutoNumber
e nomeie a ação.Observação
Como a numeração automática é aplicada pelo processamento do servidor, ela só funciona em ações de postback, não para ações de URL do cliente. Consequentemente, os componentes que renderizam duas ações de botão, uma ação de URL e uma ação de postback resulta em uma experiência do usuário abaixo do ideal, por causa da numeração inconsistente dos vários elementos da IU. No caso dos componentes do OAuth que renderizam uma ação de URL de log-in e uma ação de cancelamento de postback, apenas a ação de cancelamento é prefixada com um número. Para manter a consistência em casos como esse, defina a propriedadeautoNumberPostbackActions
comofalse
. -
Você pode ativar condicionalmente a numeração automática definindo a variável
autoNumberPostbackActions
com o canal atual. Por exemplo :
Depois de definir a variávelsetAutoNumbering: component: "System.SetVariable" properties: variable: "autoNumberPostbackActions" value: "${(system.channelType=='facebook')?then('true','false')}"
autoNumberPostbackActions
, você pode referenciá-la para modificar o textoprompt
:
Da mesma forma, você pode condicionar o texto de rodapé:prompt: "Hello ${profile.firstName}, this is our menu today<#if autoNumberPostbackActions.value>. Make your choice by entering the menu option number</#if>:"
footerText: <#if autoNumberPostbackActions.value>"Make your choice by entering the menu option number."</#if>
Renderizar Conteúdo para Canais Somente Texto em Fluxos de Caixas de Diálogo YAML
textOnly
nos componentes com ramificação de fluxo de caixas de diálogo, como System.ConditionEquals ou System.Switch. Para poder ramificar o fluxo com base em mensagens somente texto, declare textOnly
como variável de contexto e, em seguida, defina o valor. Estas são as etapas básicas:
-
Adicione a variável
textOnly: "boolean"
ao nócontext
.context: variables: autoNumberingPostbackActions: "boolean" textOnly: "boolean"
-
Referencie
textOnly
nos componentes de definição de variável, como System.SetVariable e System.Switch. -
Use a propriedade
system.message
para expor a mensagem completa do usuário. O trecho de código a seguir mostra como definir um booliano na expressãosystem.channelType
que indica se um canal somente para texto (Twilio, nesse caso) está sendo usado ou não.setTextOnly: component: "System.SetVariable" properties: variable: "textOnly" value: "${(system.channelType=='twilio')?then('true','false')}"
Você pode ativar condicionalmente a numeração automática referenciando o canal de mensagens do usuário. Por exemplo :setAutoNumbering: component: "System.SetVariable" properties variable: autoNumeringPostbackActions value: "${(system.channelType=='twilio')?then('true','false')}"