¿Cómo se escriben los flujos de diálogo en OBotML?
OBotML utiliza una sintaxis simple para definir variables y estados. Puesto que es una variante de YAML, tenga en cuenta las convenciones de espaciado de YAML al definir el flujo de diálogo. No es necesario que empiece desde cero. En lugar de ello, puede utilizar la definición del flujo de diálogo por defecto como plantilla básica.
context
y states
, por lo que puede simplemente suprimir el texto fijo existente y agregar su propio contenido. Para ayudarle a crear definiciones de estado con una sintaxis correcta, utilice las plantillas de componentes del menú + Componente. Consulte Sintaxis de flujo de diálogo para obtener consejos sobre la configuración de variables y la definición de estados.
Consejo:
Haga clic en Validar mientras escribe el flujo de diálogo para comprobar los errores de sintaxis y aplicar las mejores prácticas.Sintaxis del flujo de diálogo
Cómo... | Use lo siguiente: |
---|---|
¿Definir variables que mantengan el contexto en todo el flujo de diálogo? |
En el nodo
context , utilice la siguiente sintaxis: variablename: "variableType" Por ejemplo:
Puede definir variables como entidades (como |
¿Definir un manejador de errores para la aptitud? |
Defina el nodo
defaultTransitions que apunta a un estado que maneja los errores. Normalmente, este estado se agrega al final de la definición del flujo de diálogo. Por ejemplo:
Consulte Configuración del flujo de diálogo para acciones inesperadas. |
¿Definir una variable que contenga el valor de la intención resuelta? |
En el nodo
context , defina una variable que nombre la entidad nlpresult . Como implica su nombre ("nlp" significa procesamiento de lenguaje natural), esta entidad extrae la intención resuelta por el motor de intenciones. Casi todos los bots de referencia declaran las variables nlpresult . Por ejemplo:
|
¿Controlar el flujo de diálogo según la entrada del usuario? |
Normalmente (aunque no siempre), puede definir una propiedad Como se describe en Estructura de flujo de diálogo en el modo YAML, puede declarar una variable |
¿Equipar a mi aptitud para gestionar intenciones no resueltas? |
Defina un estado para la acción Por ejemplo:
|
¿Activar los componentes para acceder a los valores de variables? |
Utilice la propiedad
.value en las expresiones (${crust.value} ). Para sustituir un valor por defecto, utilice ${variable.value!\"default value\"} . Por ejemplo, thick es el valor por defecto en ${crust.value!\"thick\"} . Por ejemplo:
Utilice el operador por defecto de Apache FreeMarker ( |
¿Guardar los valores de usuario para visitas posteriores? |
En una definición de estado, agregue una definición de variable con un prefijo
user. . Consulte Componentes de YAML creados para definir valores de usuario. Por ejemplo:
Para obtener más información sobre las variables de usuario, consulte el flujo de diálogo del bot de referencia PizzaBotWithMemory. |
¿Salir de un flujo de diálogo y finalizar la sesión de usuario? |
Utilice una transición Por ejemplo:
|
Navegación de flujo y transiciones
Puede establecer el motor de diálogo en una ruta específica del flujo de diálogo estableciendo la propiedad de transiciones de un estado. Las transiciones describen cómo se ramifica el cuadro de diálogo cuando se definen valores de variables o no. Permiten trazar la ruta típica de la conversación (el flujo “feliz”) y definir rutas alternativas que den cabida a valores que faltan o a comportamientos impredecibles del usuario.
Para ello... | ... Utilice esta transición |
---|---|
Especificar el estado siguiente que ejecutar. | Defina una transición next (next: "statename" ) para indicar al motor de diálogo que pase al estado designado por la clave next . Como se indica en la siguiente transición, puede agregar una transición next a cualquier estado, excepto a los que tienen una transición return .
|
Restablecer la conversación. | Utilice una transición return para borrar todos los valores definidos para las variables de contexto y restablecer el flujo de diálogo. Puede asignar a esta transición cualquier valor de cadena. La definición de una transición return: "done" finaliza la sesión de usuario y coloca el motor de diálogo al principio del flujo.
|
Disparar acciones condicionales. | Defina las claves actions para disparar la navegación a un estado específico. Cuando un componente completa su procesamiento, devuelve una cadena de acción que indica al motor de diálogo dónde ir a continuación. Si no define ninguna clave de acción, el motor de diálogo depende de la transición por defecto o de una transición next (si hay alguna). Puede definir tantas acciones como sea necesario. Algunos componentes incorporados contienen acciones específicas. Por ejemplo, un componente como System.MatchEntity, que evalúa una expresión de Apache FreeMarker, utiliza las acciones match y nomatch . System.OAuthAccountLink contiene las acciones textReceived , pass y fail , y los componentes de la interfaz de usuario usan sus propias acciones (descritas en Transiciones para componentes de respuesta comunes). Utilice las plantillas de componentes como guía. Puede definir una transición actions en cualquier estado, excepto en aquellos que contienen una transición return .
|
Gestionar errores. | A veces, los componentes devuelven errores. Esto suele ocurrir debido a un problema o un fallo relacionado con el sistema (contraseñas no válidas, nombres de host no válidos o errores de comunicaciones). La configuración de una transición error que designa un estado de manejo de errores permite que la aptitud gestione los problemas correctamente: Si no define una transición error , la aptitud genera un indicador de error inesperado (¡Vaya! Parece que hay un problema) y finaliza la sesión. Puede definir una transición error en cualquier estado, excepto en aquellos que contienen una transición return .
Algunos componentes contienen un error definido como acción. Estas transiciones de error incorporadas manejan errores específicos de los componentes:
|
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"
Si bien puede definir más de una transición, la transición
return
es una excepción: no puede combinar una transición return
con las transiciones error
, next
o actions
.
Siguiente transición
Utilice la transición next
para especificar el siguiente estado por defecto. Si un estado combina transiciones error
, actions
y next
, la transición next
solo se dispara si el componente no puede devolver una cadena que cumpla las transiciones error
o actions
.
next
siempre que no se puedan disparar errores o acciones, defina una acción next
en el nodo 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"
Configuración del flujo de diálogo para acciones inesperadas
Caso | Solución |
---|---|
En lugar de pulsar los botones, el usuario responde introduciendo texto, lo que no es adecuado. | Para permitir que el bot gestione esta situación con eficacia, defina el enrutamiento a un estado en el que el componente System.Intent pueda resolver la entrada de texto, como textReceived: Intent en el siguiente fragmento de CrcPizzaBot:
|
Los usuarios vuelven a un mensaje anterior y pulsan las opciones, aunque se espera que pulsen los botones de la respuesta actual. |
Por defecto, Digital Assistant gestiona los mensajes en secuencia incorrecta, pero puede sustituir o personalizar este comportamiento, tal y como se describe en Cómo se detectan las acciones en secuencia incorrecta.
Por ejemplo, al agregar una transición
system.outofOrderMessage por defecto, se indica al motor de diálogo que realice la transición a un único estado que gestione todos los mensajes en secuencia incorrecta, como el estado HandleUnexpectedAction en el fragmento OBotML anterior. Puede utilizar diferentes enfoques para crear este estado:
|
Llamada a una aptitud desde otra aptitud desde un flujo de diálogo de YAML
En ocasiones, es posible que quiera que los usuarios tengan la opción de dejar temporalmente la aptitud con la que están interactuando para realizar otra tarea en una segunda aptitud dentro del asistente digital. Por ejemplo, si el usuario está interactuando con una aptitud de compra y ya ha hecho alguna elección, usted podría motrar un botón que le permitiera pasar a una aptitud bancaria (para asegurarse de que tiene suficiente dinero para la compra) y, a continuación, volver a la aptitud de compra para finalizar la orden.
Para abordar esto en un flujo de diálogo de YAML, puede configurar una acción en una aptitud para iniciar la interacción con otra aptitud del mismo asistente digital y, a continuación, volver al flujo original.
Así es como funciona:
-
Utilice el componente
System.CommonResponse
para presentar al usuario un botón para realizar una tarea en otra aptitud.El botón se basa en una acción de devolución, en la que se configura la carga útil para proporcionar una expresión que se dirige a la aptitud de destino. Lo ideal es que la expresión contenga el nombre de llamada de la aptitud de destino (es decir, una llamada explícita), con el fin de maximizar la probabilidad de que se produzca el enrutamiento a dicha aptitud. Al hacer esto, básicamente se codifica una expresión para disparar la intención deseada.
Este es el formato del 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" ...
Al utilizar una acción
system.textReceived
y especificar el texto en la variablesystem.text
, se asegura de que la devolución sea tratada como un mensaje de usuario que el asistente digital puede encaminar correctamente.Nota
Cuando utilicesystem.textReceived
de esta manera,system.text
es la única variable que puede definir de la carga útil de devolución. Se ignoran todas las demás variables de la carga útil. - Defina la transición
textReceived
en el estado que contiene el componenteSystem.Intent
.transitions: actions: .... textReceived: "Name of the state for the System.Intent component"
Es necesario hacerlo así para garantizar que el asistente digital proporcione una respuesta de reserva adecuada si el asistente digital no contiene la aptitud de destino.
Para que esto funcione, el componente
System.Intent
de la aptitud debe tener la propiedaddaIntercept
definida en"always"
(que es el valor por defecto).
Si la aptitud de destino está en el asistente digital, este reconoce la llamada explícita, toma el control de la solicitud (que normalmente sería gestionada por el componente) y encamina la solicitud al componente System.Intent
de la aptitud de destino. Una vez finalizado el flujo en la aptitud de destino, el usuario vuelve a la aptitud de llamada.
Si la aptitud de destino no se encuentra en el asistente digital (o la aptitud de llamada se expone sin un asistente digital), se llama al componente System.Intent
de la aptitud de llamada y la intención se resuelve en unresolvedIntent
.
Consejo:
Para manejar una situación en la que se cambia el nombre de llamada de la aptitud de destino al agregarla a un asistente digital, puede utilizar un parámetro personalizado para transferir el nombre de llamada de la aptitud en la variable system.text
.
Por ejemplo, podría crear un parámetro denominado da.CrcPizzaCashBankInvocationName
en la aptitud Pizza y darle el valor por defecto CashBank
. A continuación, podría hacer referencia al parámetro, por ejemplo, así:
system.text: "ask ${system.config.daCrcPizzaFinSkillInvocationName}, what is my balance"
Si se modifica el nombre de llamada de la aptitud, solo tiene que cambiar el valor del parámetro personalizado para que coincida con el nuevo nombre de llamada.
Consulte Parámetros personalizados.
Al utilizar una llamada explícita en la variable
system.text
, el usuario puede ver el mensaje con ese botón dos veces:
- Cuando se les presenta el botón para desplazarse a la otra aptitud.
- Cuando completan el flujo en la otra aptitud.
system.text
en lugar de una llamada explícita. Una llamada implícita es una expresión que coincide bastante con una aptitud determinada sin utilizar el nombre de llamada de la aptitud (o una variante del nombre de llamada con diferentes espacios o minúsculas/mayúsculas).
Ejemplo: llamada a una aptitud desde otra aptitud
Por ejemplo, a continuación se muestra una intención para pedir una pizza (OrderPizza
) que ofrece al usuario la opción de comprobar el saldo de su cuenta bancaria antes de completar el pedido. El saldo de la cuenta lo proporciona otra aptitud (CashBank
). Si el usuario selecciona la opción Check Balance
, el texto "consultar a CashBank mi saldo" se publica de nuevo en el asistente digital y el usuario se encamina a la intención adecuada en la aptitud 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
...
Siempre que la aptitud Pizza se encuentre en el mismo asistente digital que la aptitud CashBank, este es el aspecto que debería tener si se abre el asistente digital en el comprobador, se accede a la aptitud Pizza y, a continuación, se hace clic en Comprobar saldo de cuenta bancaria.

Descripción de la ilustración skill-skill.png
En el separador Enrutamiento del comprobador, puede ver que se ha reconocido la llamada explícita y que se le ha dado prioridad:
Más abajo, puede ver que la intención Check Balance de la aptitud Cash Bank se ha pareado:
Variables de ámbito de usuario en flujos de diálogo de YAML
Cuando finaliza la conversación, se destruyen los valores de variable definidos a partir de la entrada de usuario. Cuando estos valores desaparecen, los usuarios de aptitudes deben recurrir a volver sobre sus pasos cada vez que vuelven a la aptitud. Para que no tengan que hacerlo, defina variables con ámbito de usuario.en el flujo de diálogo. Su aptitud puede utilizar estas variables, que almacenan las entradas del usuario en sesiones anteriores, para guiar rápidamente a los usuarios a través de la conversación.
context
, tienen el prefijo user.
El estado checklastorder
en el siguiente extracto del flujo de diálogo PizzaBotWithMemory incluye la variable user.lastsize
que conserva el tamaño de pizza de la sesión de usuario anterior. La variable user.
mantiene el ID de usuario. Este ID es específico del canal, por lo que, si bien es posible volver a una conversación o moverse por un pedido utilizando las entradas anteriores de aptitudes que se ejecutan en el mismo canal, esto no se puede hacer si hay distintos canales implicados.
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 de YAML incorporados para definir valores de usuario
Defina la propiedad value
de los siguientes componentes con expresiones como “${user.age.value}”
para definir los valores de usuario almacenados.
Componente | Usos |
---|---|
System.SetVariable | Define el valor de usuario almacenado. |
System.ResetVariables | Restablece un valor de usuario almacenado. |
System.CopyVariables | Copia el valor de usuario almacenado. |
System.Output | Genera el valor de usuario almacenado como texto. |
System.ConditionExists | Comprueba si la variable con ámbito de usuario ya está en el contexto. |
System.ConditionEquals | Busca la variable con ámbito de usuario. |
System.Switch | Utiliza el valor almacenado para pasar de un estado a otro. |
Numeración automática para canales de solo texto en flujos de diálogo de YAML
El marco de numeración automática permite al bot de aptitud ejecutarse en canales de solo texto, ya que prefija con números los botones y las opciones de lista. Aunque los usuarios no puedan utilizar gestos de pulsación, pueden disparar las acciones de devolución de los botones introduciendo un número. Por ejemplo, cuando CrcPizzaBot se ejecuta en un canal que admite botones, muestra Pizzas y Pastas.
Sin embargo, cuando se ejecuta en un canal de solo texto, representa las opciones Pizza y Pasta en forma de texto y las prefija con números secuenciales (1. Pizza 2. Pasta).
La numeración automática no se limita a los canales de solo texto; si se activa en canales que admiten botones, los usuarios tienen otro modo de indicar su elección. Por ejemplo, los usuarios pueden pulsar Pizza o introducir 1.
Definir numeración automática para flujos de diálogo de YAML
Para los flujos de diálogo de YAML, puede definir la función de numeración automática en una escala global (lo que significa que afecta a todos los componentes especificados en la definición del flujo de diálogo) o a nivel de componente para los componentes que disparan acciones de devolución, es decir, los componentes System.List
, System.CommonResponse
, System.ResolveEntities
, System.QnA
, System.Webview
, System.OAuthAccountLinkComponent
y System.OAuth2AccountLinkComponent
.
-
En el nodo context, agregue
autoNumberPostbackActions: "boolean"
. Se trata de una variable común, comotextOnly
yautoTranslate
, que se puede utilizar en todos los bots.context: variables: pizzaSize: "PizzaSize" pizzaType: "PizzaType" pizzaCrust: "PizzaCrust" pizzaCheese: "CheeseType" autoNumberPostbackActions: "boolean" iResult: "nlpresult"
-
Establezca la propiedad
autoNumberPostbackActions
entrue
: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: ...
Si necesita sustituir la numeración automática de un componente determinado (ya sea un componente del sistema o uno personalizado), establezca la propiedadautoNumberPostbackActions
enfalse
. Para sustituir la numeración automática de una acción de devolución específica en System.CommonResponse, agregue una propiedadskipAutoNumber
y asígnele un nombre a la acción.Nota
Dado que la numeración automática se aplica mediante el procesamiento del servidor, solo funciona en acciones de devolución, no en las acciones de URL del cliente. Por lo tanto, los componentes que representan dos acciones de botón, una acción de URL y una acción de devolución, generan una experiencia de usuario deficiente debido a las incoherencias en la numeración de los distintos elementos de la interfaz de usuario. En el caso de los componentes de OAuth que presentan una acción de URL de conexión y una acción de devolución de cancelación, solo la acción de cancelación se prefija con un número. Para mantener la coherencia en casos como este, defina la propiedadautoNumberPostbackActions
enfalse
. -
Puede activar la numeración automática condicionalmente estableciendo la variable
autoNumberPostbackActions
con el canal actual. Por ejemplo:
Una vez definida la variablesetAutoNumbering: component: "System.SetVariable" properties: variable: "autoNumberPostbackActions" value: "${(system.channelType=='facebook')?then('true','false')}"
autoNumberPostbackActions
, puede hacer referencia a ella para modificar el texto deprompt
:
Del mismo modo, puede condicionar el texto del pie de página: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>
Representación del contenido en canales de solo texto en flujos de diálogo YAML
textOnly
en los componentes de ramificación del flujo de diálogo,como System.ConditionEquals o System.Switch. Para poder ramificar el flujo en función de mensajes de solo texto, debe declarar textOnly
como variable de contexto y, a continuación, definir su valor. Estos son los pasos básicos:
-
Agregue la variable
textOnly: "boolean"
al nodocontext
.context: variables: autoNumberingPostbackActions: "boolean" textOnly: "boolean"
-
Haga referencia a
textOnly
en los componentes de definición de la variable, como System.SetVariable y System.Switch. -
Utilice la propiedad
system.message
para mostrar el mensaje del usuario completo. El siguiente fragmento muestra cómo definir un valor booleano dentro de la expresiónsystem.channelType
que indica si se está utilizando o no un canal de solo texto (Twilio, en este caso).setTextOnly: component: "System.SetVariable" properties: variable: "textOnly" value: "${(system.channelType=='twilio')?then('true','false')}"
Puede activar la numeración automática de manera condicional haciendo referencia al canal de mensajes del usuario. Por ejemplo:setAutoNumbering: component: "System.SetVariable" properties variable: autoNumeringPostbackActions value: "${(system.channelType=='twilio')?then('true','false')}"