Comment écrire des flux de dialogue dans OBotML ?
OBotML utilise une syntaxe simple pour la définition des variables et des états. Comme il s'agit d'une variante du langage YAML, vous devez tenir compte des conventions d'espacement YAML lorsque vous définissez le flux de dialogue. Vous n'êtes pas obligé de partir de zéro. A la place, vous pouvez utiliser la définition de flux de dialogue par défaut comme modèle de base.
context
et states
. Vous pouvez donc supprimer le boilerplate existant et ajouter votre propre contenu. Pour vous aider à créer des définitions d'état avec une syntaxe correcte, utilisez les modèles de composant du menu + Composant. Reportez-vous à Syntaxe de flux de dialogue pour obtenir des conseils sur la définition des variables et des états.
Conseil :
Cliquez sur Valider à mesure que vous écrivez votre flux de dialogue pour rechercher les erreurs de syntaxe et appliquer les meilleures pratiques.Syntaxe de flux de dialogue
Procédure | Utiliser |
---|---|
Définir des variables qui conservent le contexte dans l'ensemble du flux de dialogue |
Dans le noeud
context , utilisez la syntaxe suivante : variablename: "variableType" . Par exemple :
Vous pouvez définir des variables en tant qu'entités (comme |
Définir un gestionnaire d'erreurs pour votre brique |
Définissez le noeud
defaultTransitions qui pointe vers un état gérant les erreurs. En règle générale, vous devez ajouter cet état à la fin de la définition de votre flux de dialogue. Par exemple :
Reportez-vous à Configuration du flux de dialogue pour les actions inattendues. |
Définir une variable qui stocke la valeur de l'intention résolue |
Dans le noeud
context , définissez une variable qui nomme l'entité nlpresult . Comme son nom l'indique ("nlp" désigne le traitement du langage naturel), cette entité extrait l'intention résolue par le moteur d'intentions. Presque tous les bots de référence déclarent des variables nlpresult . Par exemple :
|
Contrôler le flux de dialogue en fonction de la saisie utilisateur |
En règle générale (mais pas toujours), vous devez définir une propriété Comme décrit dans Structure du flux de dialogue en mode YAML, vous pouvez déclarer une variable |
Equiper la brique de façon à pouvoir gérer les intentions non résolues |
Définissez un état pour l'action Exemple :
|
Autoriser les composants à accéder aux valeurs de variable |
Utilisez la propriété
.value dans vos expressions (${crust.value} ). Pour remplacer une valeur par défaut, utilisez ${variable.value!\"default value\"} . Par exemple, thick est la valeur par défaut de ${crust.value!\"thick\"} . Par exemple :
Utilisez l'opérateur par défaut d'Apache FreeMarker ( |
Enregistrer les valeurs utilisateur pour les visites ultérieures |
Dans une définition d'état, ajoutez une définition de variable avec un préfixe
user. . Reportez-vous à Composants YAML intégrés pour la configuration des valeurs utilisateur. Par exemple :
Pour en savoir plus sur les variables utilisateur, reportez-vous au flux de dialogue du bot de référence PizzaBotWithMemory. |
Quitter un flux de dialogue et mettre fin à la session utilisateur |
Utilisez une transition Exemple :
|
Navigation dans le flux et transitions
Vous pouvez définir le moteur de dialogue sur un parcours spécifique du flux de dialogue en définissant la propriété des transitions d'un état. Les transitions décrivent comment le dialogue s'oriente selon que des valeurs de variable sont définies ou non. Elles permettent de tracer l'acheminement classique à travers la conversation (le flux idéal) et de définir d'autres acheminements qui prennent en charge les valeurs manquantes ou les comportements utilisateur imprévisibles.
Procédez comme suit... | ... Utiliser cette transition |
---|---|
Indiquer l'état suivant à exécuter | Définissez une transition next (next: "statename" ) pour demander au moteur de dialogue de passer à l'état nommé par la clé next . Comme indiqué dans la prochaine transition, vous pouvez ajouter une transition next à n'importe quel état, à l'exception de ceux comportant une transition return .
|
Réinitialiser la conversation | Utilisez une transition return afin d'effacer les valeurs définies pour les variables de contexte et réinitialiser le flux de dialogue. Vous pouvez indiquer n'importe quelle valeur de chaîne pour cette transition. La définition d'une transition return: "done" met fin à la session utilisateur et positionne le moteur de dialogue au début du flux.
|
Lancer des actions conditionnelles | Définissez les clés actions de façon à déclencher la navigation vers un état spécifique. Lorsqu'un composant termine son traitement, il renvoie une chaîne d'action qui indique l'étape suivante au moteur de dialogue. Si vous ne définissez aucune clé d'action, le moteur de dialogue utilise la transition par défaut ou une transition next (le cas échéant). Vous pouvez définir autant d'actions que nécessaire. Certains composants intégrés disposent d'actions spécifiques. Par exemple, un composant tel que System.MatchEntity qui évalue une expression Apache FreeMarker, utilise les actions match et nomatch . System.OAuthAccountLink inclut les actions textReceived , pass et fail . Les composants d'interface utilisateur utilisent leurs propres actions (décrites dans Transitions for Common Response Components). Reportez-vous aux modèles de composant pour vous guider. Vous pouvez définir une transition actions sur n'importe quel état, à l'exception de ceux comportant une transition return .
|
Gestion des erreurs. | Les composants génèrent parfois des erreurs. Cela se produit souvent en raison d'un problème ou d'un échec lié au système (mots de passe non valides, noms d'hôte non valides ou erreurs de communication). La définition d'une transition error nommant un état de gestion des erreurs permet de résoudre les problèmes sans erreur : Si vous n'avez pas défini de transition error , la brique génère l'invite d'erreur inattendue (Oups ! Je rencontre quelques problèmes) et met fin à la session. Vous pouvez définir une transition error dans n'importe quel état, à l'exception de ceux comportant une transition return .
Pour certains composants, une erreur est définie en tant qu'action. Ces transitions d'erreur intégrées gèrent les erreurs propres aux composants :
|
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"
Vous pouvez définir plusieurs transitions. La transition
return
constitue une exception : vous ne pouvez pas combiner une transition return
avec les transitions error
, next
ou actions
.
prochaine transition
Utilisez la transition next
pour indiquer l'état suivant par défaut. Lorsqu'un état combine les transitions error
, actions
et next
, la transition next
est déclenchée uniquement lorsque le composant ne peut pas renvoyer de chaîne répondant à l'une des transitions error
ou actions
.
next
est déclenchée lorsque des erreurs ou des actions ne peuvent pas l'être, définissez une action next
dans le noeud 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"
Configuration du flux de dialogue pour les actions inattendues
scénario | Solution |
---|---|
Au lieu d'appuyer sur des boutons, l'utilisateur répond de façon inappropriée en entrant du texte. | Pour permettre à votre bot de gérer cette situation sans erreur, effectuez un acheminement vers un état où le composant System.Intent peut résoudre l'entrée textuelle, par exemple textReceived: Intent dans le fragment de code suivant issu de CrcPizzaBot :
|
Les utilisateurs peuvent revenir à un message précédent et toucher ses options, même lorsqu'ils sont censés toucher les boutons de la réponse en cours. |
Par défaut, Digital Assistant gère les messages dans le désordre, mais vous pouvez remplacer ou personnaliser ce comportement, comme décrit dans Comment les actions dans le désordre sont détectées.
Par exemple, l'ajout d'une transition
system.outofOrderMessage par défaut indique au moteur de dialogue qu'il doit passer à un état unique qui gère tous les messages dans le désordre, comme l'état HandleUnexpectedAction dans le fragment de code OBotML ci-dessus. Vous pouvez utiliser différentes approches pour créer cet état :
|
Appel d'une brique à partir d'une autre brique à partir d'un flux de dialogue YAML
Il est parfois utile de proposer aux utilisateurs une possibilité de quitter temporairement la brique afin de réaliser une tâche dans une autre brique du même assistant numérique. Par exemple, si les utilisateurs se trouvent dans une brique permettant de réaliser des achats et qu'ils ont sélectionné quelques articles, vous pouvez afficher un bouton qui leur permet de passer à une brique bancaire (pour s'assurer qu'ils disposent de suffisamment d'argent pour l'achat), puis revenir à la brique d'achat pour terminer leur commande.
Pour résoudre ce problème dans un flux de dialogue YAML, vous pouvez configurer une action dans une brique de façon à initier une interaction avec une autre brique dans le même assistant numérique, puis à revenir au flux initial.
Voici comment cela fonctionne :
-
Vous utilisez le composant
System.CommonResponse
pour présenter à l'utilisateur un bouton lui permettant d'effectuer une action dans une autre brique.Le bouton est basé sur une action de postback, dans laquelle vous configurez la charge utile afin de fournir une variation orientée vers la brique cible. Dans l'idéal, la variation doit contenir le nom d'appel de la brique cible (appel explicite) afin d'optimiser la probabilité de l'acheminement vers cette brique. Ainsi, vous pouvez coder en dur une variation de façon à déclencher l'intention voulue.
Le format de ce code est le suivant :
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" ...
En utilisant une action
system.textReceived
et en spécifiant le texte dans la variablesystem.text
, vous vous assurez que le postback est traité comme un message utilisateur pouvant être correctement acheminé par l'assistant numérique.Remarque
Lorsque vous utilisezsystem.textReceived
de cette manière,system.text
est la seule variable que vous pouvez définir dans la charge utile de postback. Toutes les autres variables de la charge utile sont ignorées. - Vous définissez la transition
textReceived
sur l'état contenant le composantSystem.Intent
.transitions: actions: .... textReceived: "Name of the state for the System.Intent component"
Cela est nécessaire pour veiller à ce que l'assistant numérique fournisse une réponse de secours appropriée si l'assistant numérique ne comporte pas la brique cible.
Pour que cela fonctionne, dans le composant
System.Intent
, la propriétédaIntercept
de la brique doit être définie sur"always"
(valeur par défaut).
Si la brique cible figure dans l'assistant numérique, celui-ci reconnaît l'appel explicite, prend le contrôle de la demande (qui serait normalement gérée par le composant) et achemine la demande vers le composant System.Intent
de la brique cible. Une fois que le flux de la brique cible est terminé, l'utilisateur est renvoyé à la brique qui a émis l'appel.
Si la brique cible ne figure pas dans l'assistant numérique (ou si la brique qui émet l'appel est mise à disposition sans assistant numérique), le composant System.Intent
de la brique qui émet l'appel est appelé et l'intention est résolue en unresolvedIntent
.
Conseil :
Pour gérer les situations où le nom d'appel de la brique cible est modifié lorsqu'il est ajouté à un assistant numérique, vous pouvez utiliser un paramètre personnalisé permettant de transmettre le nom d'appel de la brique dans la variable system.text
.
Par exemple, vous pouvez créer un paramètre nommé da.CrcPizzaCashBankInvocationName
dans la brique Pizza et lui attribuer une valeur par défaut de CashBank
. Vous pouvez ensuite référencer le paramètre comme suit :
system.text: "ask ${system.config.daCrcPizzaFinSkillInvocationName}, what is my balance"
Si le nom d'appel de la brique est modifié, modifiez simplement la valeur du paramètre personnalisé afin qu'elle corresponde au nouveau nom d'appel.
Reportez-vous à Paramètres personnalisés.
Lorsque vous utilisez un appel explicite dans la variable
system.text
, l'utilisateur peut voir le message avec ce bouton deux fois :
- Lorsqu'un bouton permettant d'accéder à l'autre brique apparaît
- Une fois le flux terminé dans l'autre brique
system.text
au lieu d'un appel explicite. Un appel implicite est une variation qui correspond bien à une brique donnée sans utiliser le nom d'appel de la brique (ou une variante du nom d'appel avec une mise en majuscule ou un espacement différent).
Exemple : appel d'une brique à partir d'une autre brique
Par exemple, voici une intention permettant de commander une pizza (OrderPizza
) qui offre à l'utilisateur la possibilité de vérifier le solde de son compte bancaire avant de terminer sa commande. Le solde du compte est fourni par une autre brique (CashBank
). Si l'utilisateur sélectionne l'option Check Balance
, le texte "ask CashBank, what is my balance" est soumis à l'assistant numérique et l'utilisateur est acheminé vers l'intention appropriée de la brique 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
...
Si la brique Pizza se trouve dans le même assistant numérique que la brique Cash Bank, voici ce que vous devriez voir si vous ouvrez l'assistant numérique dans le testeur, accédez à la brique Pizza et cliquez sur Check bank account balance.

Description de l'illustration skill-skill.png
Dans l'onglet Acheminement du testeur, vous pouvez voir que l'appel explicite a été reconnu et qu'une priorité lui a été accordée :
Plus bas, vous pouvez également voir que l'intention Check Balance de la brique Cash Bank est mise en correspondance :
Variables de portée utilisateur dans les flux de dialogue YAML
Lorsque la conversation prend fin, les valeurs de variable définies à partir de la saisie utilisateur sont détruites. Sans ces valeurs, vos utilisateurs doivent revenir en arrière chaque fois qu'ils font appel à votre brique. Vous pouvez épargner cet effort à vos utilisateurs en définissant des variables de portée utilisateur dans le flux de dialogue. Votre brique peut utiliser ces variables, qui stockent les saisies utilisateur des sessions précédentes, afin de guider rapidement les utilisateurs dans la conversation.
context
, sont préfixées par user.
L'état checklastorder
dans l'extrait suivant du flux de dialogue PizzaBotWithMemory inclut la variable user.lastsize
, qui conserve la taille de pizza de la session utilisateur précédente. La variable user.
conserve l'ID utilisateur. Cet ID est propre au canal. Vous pouvez donc uniquement revenir à une conversation ou ignorer l'ordre en utilisant les entrées précédentes pour des briques exécutées sur le même canal, et non sur des canaux différents.
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:
...
Composants YAML intégrés pour la définition des valeurs utilisateur
Définissez la propriété value
des composants suivants avec des expressions telles que “${user.age.value}”
pour définir les valeurs utilisateur stockées.
Composant | Utilisations |
---|---|
System.SetVariable | Définit la valeur utilisateur stockée. |
System.ResetVariables | Réinitialise une valeur utilisateur stockée. |
System.CopyVariables | Copie la valeur utilisateur stocké. |
System.Output | Génère la valeur utilisateur stockée sous forme de texte. |
System.ConditionExists | Vérifie si la variable de niveau utilisateur est déjà dans le contexte. |
System.ConditionEquals | Recherche la variable de niveau utilisateur. |
System.Switch | Utilise la valeur stockée pour basculer d'un état vers un autre. |
Numérotation automatique pour les canaux de texte uniquement dans les flux de dialogue YAML
La structure de numérotation automatique permet à votre brique de s'exécuter sur des canaux de type texte uniquement, car elle ajoute des nombres en guise de préfixe aux boutons et aux options de liste. Lorsque les utilisateurs ne peuvent pas utiliser le toucher, ils peuvent toujours déclencher les actions de postback du bouton en saisissant un nombre. Par exemple, lorsque CrcPizzaBot est exécuté sur un canal prenant en charge les boutons, il affiche Pizzas et Pastas.
En revanche, lorsqu'il est exécuté sur un canal de type texte uniquement, il affiche les options Pizza et Pastas sous forme de texte et ajoute des nombres séquentiels en guise de préfixe (1. Pizza 2. Pastas).
La numérotation automatique n'est pas limitée aux canaux de type texte uniquement. Ainsi, lorsque les boutons sont pris en charge, vous pouvez l'activer pour ajouter une autre méthode permettant aux utilisateurs de saisir leurs choix. Par exemple, les utilisateurs peuvent toucher Pizza ou entrer 1.
Définir la numérotation automatique pour les flux de dialogue YAML
Pour les flux de dialogue YAML, vous pouvez définir la fonctionnalité de numérotation automatique à l'échelle globale (elle s'appliquera donc à tous les composants nommés dans la définition de flux de dialogue) ou au niveau des composants qui déclenchent des actions de postback, à savoir les composants System.List
, System.CommonResponse
, System.ResolveEntities
, System.QnA
, System.Webview
, System.OAuthAccountLinkComponent
et System.OAuth2AccountLinkComponent
.
-
Dans le noeud de contexte, ajoutez
autoNumberPostbackActions: "boolean"
. CommetextOnly
etautoTranslate
, il s'agit d'une variable courante qui peut être utilisée dans tous vos bots.context: variables: pizzaSize: "PizzaSize" pizzaType: "PizzaType" pizzaCrust: "PizzaCrust" pizzaCheese: "CheeseType" autoNumberPostbackActions: "boolean" iResult: "nlpresult"
-
Définissez la propriété
autoNumberPostbackActions
surtrue
: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 vous devez remplacer la numérotation automatique pour un composant particulier (composant système ou personnalisé), définissez la propriétéautoNumberPostbackActions
surfalse
. Pour remplacer la numérotation automatique d'une action de postback spécifique de System.CommonResponse, ajoutez une propriétéskipAutoNumber
et nommez l'action.Remarque
La numérotation automatique étant appliquée via le traitement côté serveur, elle fonctionne uniquement sur les actions de postback, et non sur les actions d'URL côté client. Par conséquent, les composants qui affichent deux actions de bouton, une action d'URL et une action de postback génèrent une expérience utilisateur non optimale en raison de la numérotation incohérente des différents éléments de l'interface utilisateur. Dans le cas des composants OAuth qui affichent à la fois une action d'URL de connexion et une action d'annulation de postback, seule cette dernière est précédée d'un nombre. Pour assurer la cohérence dans les cas comme celui-ci, définissez la propriétéautoNumberPostbackActions
surfalse
. -
Vous pouvez activer la numérotation automatique de manière conditionnelle en définissant la variable
autoNumberPostbackActions
sur le canal en cours. Par exemple :
Une fois que vous avez défini la variablesetAutoNumbering: component: "System.SetVariable" properties: variable: "autoNumberPostbackActions" value: "${(system.channelType=='facebook')?then('true','false')}"
autoNumberPostbackActions
, vous pouvez la référencer pour modifier le texte deprompt
:
De même, vous pouvez conditionner le texte du pied de page :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>
Affichage du contenu des canaux de texte uniquement dans les flux de dialogue YAML
textOnly
dans les composants d'orientation du flux de dialogue, tels que System.ConditionEquals ou System.Switch. Pour pouvoir orienter le flux sur la base de messages de type texte uniquement, vous devez déclarer textOnly
comme variable de contexte, puis définir sa valeur. Voici les étapes de base :
-
Ajoutez la variable
textOnly: "boolean"
au noeudcontext
.context: variables: autoNumberingPostbackActions: "boolean" textOnly: "boolean"
-
Référencez
textOnly
dans les composants de définition de variable, tels que System.SetVariable et System.Switch. -
Utilisez la propriété
system.message
pour afficher le message utilisateur complet. Le fragment de code suivant montre comment définir une valeur booléenne dans l'expressionsystem.channelType
afin d'indiquer si un canal de type texte uniquement (Twilio, dans ce cas) est en cours d'utilisation.setTextOnly: component: "System.SetVariable" properties: variable: "textOnly" value: "${(system.channelType=='twilio')?then('true','false')}"
Vous pouvez activer la numérotation automatique de manière conditionnelle en référençant le canal de message utilisateur. Par exemple :setAutoNumbering: component: "System.SetVariable" properties variable: autoNumeringPostbackActions value: "${(system.channelType=='twilio')?then('true','false')}"