[Actualité] Bot Framework : création d’un agent conversationnel avec FormFlow
par
, 22/04/2018 à 20h13 (4983 Affichages)
Il y a de nos jours un réel engouement pour les chats bots. Ils sont utilisés dans les applications pour par exemple guider les utilisateurs à effectuer des achats, comme s’ils s’adressaient à un être humain, effectuer des réservations, fournir des conseils, etc.
Microsoft offre le bot framework pour permettre aux développeurs d’intégrer facilement les bots dans leurs solutions.
Dans ce billet de blog, nous verrons comment mettre en place un agent conversationnel en utilisant Bot Framework et FormFlow.
Prérequis
Pour la bonne compréhension de cet article, vous devez avoir des connaissances en :
- Programmation C# ;
- ASP.NET Web API ;
- Visual Studio ;
- Bot Framework.
Outils à installer
Cet article suppose que vous disposez des outils suivants sur votre ordinateur :
- Visual Studio 2017 ;
- Bot Framework emulator ;
- Les templates pour Bot Application, Bot Controller et Bot Dialog installés.
Si votre environnement n’est pas encore configuré, vous pouvez consulter l’article suivant pour voir comment procéder. https://docs.microsoft.com/en-us/bot...net-quickstart
Introduction à FormFlow
Imaginez que vous devez mettre en place un bot qui va guider un client dans la commande d’une Pizza à partir d’un large catalogue de choix avec des options : quelles questions doivent être posées, quelles questions ne doivent pas être posées en fonction des réponses du client, quel doit être la prochaine question en fonction du choix du client, quand revenir en arrière, comment permettre au client de modifier ses choix, quand est-ce que la conversation doit être interrompue, etc. La mise sur pied d’un algorithme qui permettra de guider l’utilisateur de façon optimale en utilisant Dialogs peut s’avérer assez complexe.
C’est pour fournir une solution à cette problématique que Microsoft a mis en place FormFlow. Il s’agit d’une fonctionnalité disponible avec le SDK Bot Builder pour .NET, qui permet de générer automatiquement « les dialogues » qui sont nécessaires pour mettre en place une conversation guidée.
Selon Microsoft, le recours à FormFlow peut réduire de façon significative le temps nécessaire à la création d’un Bot. Par ailleurs, FormFlow peut s’intégrer facilement avec les autres types de dialogues disponibles.
Création de l’application
Voyons maintenant comment mettre en place un Bot avec FormFlow. Nous allons développer un bot en mesure de procéder à une enquête. Le bot doit donc être capable de poser des questions à l’utilisateur et récupérer ses réponses. Il doit permettre à celui-ci de modifier ses réponses ou encore afficher un résumé des réponses de ce dernier. Bref, il doit offrir la meilleure expérience utilisateur possible.
Nous allons commencer par créer l’application en utilisant Visual Studio et le modèle BotApplication :
Création du questionnaire avec FormFlow
Notre questionnaire va être représenté par une classe SurveyForm. Cette classe aura des propriétés qui définiront les informations que le bot aura besoin de collecter dans le cadre de notre enquête. Les types supportés par FormFlow sont les suivants :
- Integral (sbyte, byte, short, ushort, int, uint, long, ulong)
- Floating point (float, double)
- String
- DateTime
- Enumeration
- List of enumerations
Cette classe doit également disposer d’une fonction BuildForm. Elle doit retourner un Iform<SurveyForm>. Dans cette méthode, vous devez créer et retourner une nouvelle instance de FormBuilder<SurveyForm>.
Pour mettre cela en place, nous allons donc créer un nouveau fichier SurveyForm.cs dans le dossier Forms (que vous devez créer).
Nous devons dans un premier temps définir les différentes réponses à nos questions. Nous allons utiliser des énumérations :
Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 public enum JobOptions {Developpeur_junior=1, Developpeur_senior, Architecte, Autre}; public enum ExperienceOptions {Moins_de_5_ans=1, De_5_a_10_ans, Plus_de_10_ans}; public enum PlatformOptions {Web =1, Mobile, Cloud, Desktop}; public enum LanguageOptions {Csharp=1, Java, JavaScript, C, Ruby, Python, Autre}; public enum WebFrameworkOptions { ASPNET_Core = 1, AngularJS, Laravel, ReactJS, NodeJS, Autre}; public enum CloudOptions {Microsoft_Azure=1, Google_Cloud_platform, Amazon_Web_Services, IBM_Cloud, Autre};
Il faut noter qu’avec FormFlow, lorsque vous utilisez une énumération pour définir une propriété, la valeur 0 représente par défaut nul. Si votre propriété n’a pas de valeur nulle, l’énumération doit commencer à 1.
Ensuite, nous devons définir les propriétés de notre SurveyForm :
Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 public JobOptions Job; public ExperienceOptions Experience; public PlatformOptions Platform; public List<LanguageOptions> Language; public WebFrameworkOptions WebFramework; public CloudOptions Cloud;
Et afin, ajouter la méthode BuildForm qui permettra de générer un formulaire FormFlow :
Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 public static IForm<SurveyForm> BuildForm() { return new FormBuilder<SurveyForm>() .Message("Merci de prendre quelques minutes pour répondre aux questions de cette enquête.") .Build(); }
Le code complet de cette classe est le suivant :
Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 using System; using System.Collections.Generic; using Microsoft.Bot.Builder.FormFlow; namespace FormFowBasic.Forms { [Serializable] public class SurveyForm { public JobOptions Job; public ExperienceOptions Experience; public PlatformOptions Platform; public List<LanguageOptions> Language; public WebFrameworkOptions WebFramework; public CloudOptions Cloud; public static IForm<SurveyForm> BuildForm() { return new FormBuilder<SurveyForm>() .Message("Merci de prendre quelques minutes pour répondre aux questions de cette enquête.") .Build(); } } public enum JobOptions {Developpeur_junior=1, Developpeur_senior, Architecte, Autre}; public enum ExperienceOptions {Moins_de_5_ans=1, De_5_a_10_ans, Plus_de_10_ans}; public enum PlatformOptions {Web =1, Mobile, Cloud, Desktop}; public enum LanguageOptions {Csharp=1, Java, JavaScript, C, Ruby, Python, Autre}; public enum WebFrameworkOptions { ASPNET_Core = 1, AngularJS, Laravel, ReactJS, NodeJS, Autre}; public enum CloudOptions {Microsoft_Azure=1, Google_Cloud_platform, Amazon_Web_Services, IBM_Cloud, Autre}; }
Mise à jour de la classe MessagesController
Notre bot est une WebAPI. Le point d’entrée de toute communication avec le bot est le contrôleur MessagesController. Nous allons modifier son code pour utiliser SurveyForm.
La première chose à faire sera d’ajouter une méthode statique MakeRootDialog(). Cette méthode doit permettre de générer un nouveau dialogue en utilisant la méthode BuildForm de notre classe SurveyForm. Nous devons utiliser la classe Chain qui est utilisée pour le chainage des dialogues, ensuite faire appel à sa méthode From pour construire notre dialogue. La méthode From crée une nouvelle copie d’un autre dialogue. C’est pourquoi nous devons utiliser la fabrique FromDialog pour créer un dialogue à partir de notre SurveyFrom.
Ensuite, nous allons utiliser le delegate Do de la classe Chain pour définir ce qui sera exécuté à la fin du dialogue. Elle peut être due :
- à une exception ;
- à un arrêt volontaire de l’utilisateur ;
- ou à l’atteinte de la fin du questionnaire.
Nous allons donc implémenter ce qui sera affiché à l’utilisateur dans les différents scénarios ci-dessus. Le code de MakeRootDialog est le suivant :
Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 internal static IDialog<SurveyForm> MakeRootDialog() { return Chain.From(() => FormDialog.FromForm(SurveyForm.BuildForm)) .Do(async (context, survey) => { try { var completed = await survey; await context.PostAsync("Merci pour votre participation !"); } catch (FormCanceledException<SurveyForm> e) { string reply; if (e.InnerException == null) { reply = "Vous navez pas complété lenquête !"; } else { reply = "Erreur. Essayez plus tard !."; } await context.PostAsync(reply); } }); }
Nous devons maintenant modifier la méthode Post pour utiliser makeRootDialog :
Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14 public async Task<HttpResponseMessage> Post([FromBody]Activity activity) { if (activity.Type == ActivityTypes.Message) { await Conversation.SendAsync(activity, MakeRootDialog); } else { await HandleSystemMessage(activity); } var response = Request.CreateResponse(HttpStatusCode.OK); return response; }
Pour finir, nous souhaitons que le bot soit en mesure d’afficher un message pour engager la conversation avec un utilisateur. Pour le faire, nous devons modifier la méthode HandleSystemMessage comme suit :
Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 private async Task HandleSystemMessage(Activity message) { if (message.Type == ActivityTypes.DeleteUserData) { // Implement user deletion here // If we handle user deletion, return a real message } else if (message.Type == ActivityTypes.ConversationUpdate) { if (message.MembersAdded.Any(o => o.Id == message.Recipient.Id)) { var reply = message.CreateReply("Bonjour"); ConnectorClient connector = new ConnectorClient(new Uri(message.ServiceUrl)); await connector.Conversations.ReplyToActivityAsync(reply); } } else if (message.Type == ActivityTypes.ContactRelationUpdate) { } else if (message.Type == ActivityTypes.Typing) { // Handle knowing tha the user is typing } else if (message.Type == ActivityTypes.Ping) { } }
En effet, au démarrage d’une nouvelle session de chat, le type de message sera ConversationUpdate. Si c’est un nouvel utilisateur qui rejoint la section, nous devons lui afficher le message Bonjour. Nous devons éviter que le message soit affiché plusieurs fois pour le même utilisateur.
Si vous exécutez l’application et testez ce dernier en utilisateur le bot emulator, vous obtiendrez ce qui suit :
Vous pouvez répondre en cliquant directement sur votre réponse dans le texte, ou en saisissant votre réponse. Une fois la réponse à une question obtenue, le bot affiche la prochaine question. Si vous saisissez une réponse qui n’est pas valide, il vous affiche un message :
Il est aussi capable de filtrer ses choix de réponses, pour afficher uniquement ce qui correspond à ce que vous avez saisi si votre réponse est incomplète :
À la fin du sondage, il affiche le récapitulatif de vos réponses, afin que vous puissiez les valider :
Si vous répondez Non, il va afficher l’ensemble des questions avec les réponses que vous avez choisies, en vous donnant la possibilité de modifier celles que vous souhaitez changer.
Il est intéressant de noter, comme vous l’avez probablement remarqué, que FormFlow supporte le français. Pour déterminer le langage à utiliser, FormFlow utilise CurrentUICulture et CurrentCulture du thread courant.
Imaginez le degré de complexité de notre application si c’était à nous de développer ce comportement. FormFlow nous rend la vie beaucoup plus facile.
C’est tout pour ce billet. Dans le prochain billet, nous verrons les options de personnalisation que nous pouvons utiliser pour améliorer le texte et le rendu de notre questionnaire.
Le code source de cet exemple est disponible sur mon GitHub