{"id":2118,"date":"2017-02-14T02:08:04","date_gmt":"2017-02-14T10:08:04","guid":{"rendered":"https:\/\/www.microsoft.com\/reallifecode\/index.php\/2017\/02\/14\/collecting-form-data-with-a-luis-based-bot\/"},"modified":"2020-03-19T10:19:34","modified_gmt":"2020-03-19T17:19:34","slug":"collecting-form-data-with-a-luis-based-bot","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/ise\/collecting-form-data-with-a-luis-based-bot\/","title":{"rendered":"Collecting Form Data with a LUIS-Based Bot"},"content":{"rendered":"<h2 id=\"background\">Background<\/h2>\n<p>One major advantage of chatbots, over traditional form-based applications, is that they can extract information from natural language and reduce the amount of time spent on repeat typing and entry of information. For example, if a user wants to order a medium mushroom pizza to their house at 4:00 pm, they could just type \u201cCan I have a medium mushroom pizza sent to me at 4:00 pm\u201d and the bot will understand what the user wants.<\/p>\n<p>In order to provide this functionality, chatbots must be able to process natural language queries and convert user intents and entities into actions. For example, a user might ask the bot: \u201cWhat is the weather in Tel Aviv?\u201d The chatbot must then be able to understand the user wants to know the weather in the city of Tel Aviv, and map this information to a function such as <code class=\"highlighter-rouge\">getWeather(City)<\/code>. This function then takes a <code class=\"highlighter-rouge\">City<\/code> parameter like <code class=\"highlighter-rouge\">Tel Aviv<\/code> as input and returns the weather in Tel Aviv to the user. In this case, <em>getting the weather<\/em> is the <strong>intent<\/strong> and <em>Tel Aviv<\/em> is the <strong>location entity<\/strong>.<\/p>\n<p>Chatbots often rely on language understanding services such as <a href=\"https:\/\/www.luis.ai\">Microsoft LUIS<\/a> to determine intents and entities. While these services are great at identifying intents and good at extracting associated entities, they are unable to guarantee that they will identify all the entities from a user\u2019s query that are needed to perform an operation associated with a given intent. Additionally, even when services such as LUIS correctly identify all the provided associated entities in a given query, the user still might not have provided all the information required to process their request. In these cases, it is important to have a mechanism that continues to query a user in an unobtrusive manner until all the required information is gathered.<\/p>\n<h2 id=\"the-engagement\">The Engagement<\/h2>\n<p>We recently utilized these insights about chatbots during an engagement with a partner, <a href=\"http:\/\/moed.ai\">moed.ai<\/a>, that offers a configuration-based platform for scheduling services. Their customers use moed.ai\u2019s designated dashboard to manage the availability of their resources independently. We worked with moed.ai to create a scheduling assistance bot that their customers could then embed on their websites or Facebook pages. To read more about our work with moed.ai, please refer to <a href=\"\/developerblog\/2017\/01\/10\/Multiple-Bots-Service.html\">a previous code story<\/a> on this blog that describes how we created a single bot service to serve all of their customers.<\/p>\n<p>This code story will specifically detail how we optimized the accuracy of the intent and entity extraction process for moed.ai\u2019s scheduling assistance bot. We wanted to create a flow that interacts with a user to collect any missing information before processing their request. Our solution prompts the user for additional data related to the intent when it is not already provided and cannot be resolved automatically by LUIS.<\/p>\n<h2 id=\"the-solution\">The Solution<\/h2>\n<p>The success of an entity extraction process depends on the following factors:<\/p>\n<h3 id=\"training-the-model\">Training the Model<\/h3>\n<p>The more annotated utterances (text samples) you provide to the model, the more accurate it will be in resolving the user intent and extracting the relevant entities. This increased accuracy from training the model occurs because the algorithm executed on the user\u2019s input is based on insights it generates from these samples.<\/p>\n<h3 id=\"partial-user-provided-details\">Partial User-Provided Details<\/h3>\n<p>One possible scenario for the scheduling assistance bot we created is booking test drives at a car dealership. When a user requests a test drive, LUIS can probably identify the user intent, and (depending on what details the user provides) the entities. For example, if a user says \u201cI want to schedule a test drive of a SEAT Leon for tomorrow,\u201d LUIS will probably extract the intent of test driving a vehicle, and the entities of car type (<code class=\"highlighter-rouge\">SEAT Leon<\/code>) and time (<code class=\"highlighter-rouge\">tomorrow<\/code>). If the user only says \u201cI want to schedule a test drive,\u201d LUIS can still identify the intent, but we will need to figure out the critical related entities such as car type, time, etc. We can collect this missing data that is necessary to schedule a test drive by questioning the user directly before processing the scenario.<\/p>\n<h2 id=\"the-code\">The Code<\/h2>\n<p>A <a href=\"https:\/\/github.com\/CatalystCode\/bot-luis-form\">sample bot app<\/a> is available on GitHub. You can use this example as a reference for creating your own solution.<\/p>\n<h3 id=\"configuration\">Configuration<\/h3>\n<p>We wanted our solution to be configuration-based so that we could define the supported intents and which entities needed to be provided to process each of them:<\/p>\n<p>For example, in the following configuration, we describe <code class=\"highlighter-rouge\">schedule<\/code> and <code class=\"highlighter-rouge\">cancel<\/code> intents, and the entities are <code class=\"highlighter-rouge\">service<\/code>, <code class=\"highlighter-rouge\">time<\/code>, <code class=\"highlighter-rouge\">carType<\/code>, <code class=\"highlighter-rouge\">name<\/code>, <code class=\"highlighter-rouge\">phone<\/code> and <code class=\"highlighter-rouge\">age<\/code>. Each intent defines a list of entities that are necessary for a successful processing.<\/p>\n<p>Examples of requests a user might make:<\/p>\n<ul>\n<li><code class=\"highlighter-rouge\">I would like to schedule a test drive for SEAT Leon for Sunday.<\/code><\/li>\n<li><code class=\"highlighter-rouge\">Hi, my name is Ami, and I would like to schedule a test drive.<\/code><\/li>\n<\/ul>\n<div class=\"language-json highlighter-rouge\">\n<pre class=\"highlight\"><code><span class=\"p\">{<\/span>\r\n  <span class=\"nt\">\"intents\"<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\r\n    <span class=\"nt\">\"schedule\"<\/span><span class=\"p\">:<\/span> <span class=\"p\">[<\/span><span class=\"s2\">\"service\"<\/span><span class=\"p\">,<\/span> <span class=\"s2\">\"time\"<\/span><span class=\"p\">,<\/span> <span class=\"s2\">\"carType\"<\/span><span class=\"p\">,<\/span> <span class=\"s2\">\"name\"<\/span><span class=\"p\">,<\/span> <span class=\"s2\">\"phone\"<\/span><span class=\"p\">,<\/span> <span class=\"s2\">\"age\"<\/span><span class=\"p\">],<\/span>\r\n    <span class=\"nt\">\"cancel\"<\/span><span class=\"p\">:<\/span> <span class=\"p\">[<\/span><span class=\"s2\">\"service\"<\/span><span class=\"p\">,<\/span> <span class=\"s2\">\"time\"<\/span><span class=\"p\">,<\/span> <span class=\"s2\">\"name\"<\/span><span class=\"p\">]<\/span>\r\n  <span class=\"p\">},<\/span>\r\n  <span class=\"nt\">\"fields\"<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\r\n    <span class=\"nt\">\"name\"<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\r\n      <span class=\"nt\">\"type\"<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"text\"<\/span><span class=\"p\">,<\/span>\r\n      <span class=\"nt\">\"prompt\"<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"what's your name?\"<\/span>\r\n    <span class=\"p\">},<\/span>\r\n    <span class=\"nt\">\"service\"<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\r\n      <span class=\"nt\">\"type\"<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"choice\"<\/span><span class=\"p\">,<\/span>\r\n      <span class=\"nt\">\"prompt\"<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"select a service:\"<\/span><span class=\"p\">,<\/span>\r\n      <span class=\"nt\">\"options\"<\/span><span class=\"p\">:<\/span> <span class=\"p\">[<\/span> \r\n        <span class=\"p\">{<\/span>\r\n          <span class=\"nt\">\"title\"<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"test drive\"<\/span><span class=\"p\">,<\/span> \r\n          <span class=\"nt\">\"value\"<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"testDrive\"<\/span>\r\n        <span class=\"p\">},<\/span>\r\n        <span class=\"p\">{<\/span>\r\n          <span class=\"nt\">\"title\"<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"cancel an appoinment\"<\/span><span class=\"p\">,<\/span> \r\n          <span class=\"nt\">\"value\"<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"cancel\"<\/span>\r\n        <span class=\"p\">}<\/span>\r\n      <span class=\"p\">]<\/span>\r\n    <span class=\"p\">},<\/span>\r\n    <span class=\"err\">.<\/span>\r\n    <span class=\"err\">.<\/span>\r\n    <span class=\"err\">.<\/span>\r\n  <span class=\"err\">}<\/span>\r\n<span class=\"p\">}<\/span>\r\n<\/code><\/pre>\n<\/div>\n<h3 id=\"main-loop-dialog\">Main Loop Dialog<\/h3>\n<p>This dialog asks the user to provide their request, then calls on LUIS to extract the user\u2019s intent and available entities:<\/p>\n<div class=\"language-js highlighter-rouge\">\n<pre class=\"highlight\"><code>\r\n<span class=\"c1\">\/\/ main loop- ask for text, process intent and start over<\/span>\r\n<span class=\"nx\">bot<\/span><span class=\"p\">.<\/span><span class=\"nx\">dialog<\/span><span class=\"p\">(<\/span><span class=\"s1\">'\/loop'<\/span><span class=\"p\">,<\/span> <span class=\"p\">[<\/span>\r\n\r\n  <span class=\"c1\">\/\/ ask for input<\/span>\r\n  <span class=\"nx\">session<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\r\n    <span class=\"nx\">builder<\/span><span class=\"p\">.<\/span><span class=\"nx\">Prompts<\/span><span class=\"p\">.<\/span><span class=\"nx\">text<\/span><span class=\"p\">(<\/span><span class=\"nx\">session<\/span><span class=\"p\">,<\/span> <span class=\"s1\">'How can I help?'<\/span><span class=\"p\">);<\/span>\r\n  <span class=\"p\">},<\/span>\r\n\r\n  <span class=\"c1\">\/\/ get text, call LUIS to extract intent and entities, <\/span>\r\n  <span class=\"c1\">\/\/ prompt user to fill in missing fields<\/span>\r\n  <span class=\"p\">(<\/span><span class=\"nx\">session<\/span><span class=\"p\">,<\/span> <span class=\"nx\">args<\/span><span class=\"p\">,<\/span> <span class=\"nx\">next<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\r\n\r\n    <span class=\"k\">return<\/span> <span class=\"nx\">luis<\/span><span class=\"p\">.<\/span><span class=\"nx\">query<\/span><span class=\"p\">(<\/span><span class=\"nx\">args<\/span><span class=\"p\">.<\/span><span class=\"nx\">response<\/span><span class=\"p\">).<\/span><span class=\"nx\">then<\/span><span class=\"p\">(<\/span><span class=\"nx\">luisResult<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\r\n      <span class=\"kr\">const<\/span> <span class=\"nx\">intent<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">luisResult<\/span><span class=\"p\">.<\/span><span class=\"nx\">topScoringIntent<\/span><span class=\"p\">.<\/span><span class=\"nx\">intent<\/span><span class=\"p\">;<\/span>\r\n\r\n      <span class=\"c1\">\/\/ prepare fields list based on intent (get from configuration)<\/span>\r\n      <span class=\"kd\">var<\/span> <span class=\"nx\">form<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">prepareForm<\/span><span class=\"p\">(<\/span><span class=\"nx\">intent<\/span><span class=\"p\">);<\/span>\r\n  \r\n      <span class=\"c1\">\/\/ update field with LUIS result if available<\/span>\r\n      <span class=\"nx\">form<\/span><span class=\"p\">.<\/span><span class=\"nx\">forEach<\/span><span class=\"p\">(<\/span><span class=\"nx\">field<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\r\n        <span class=\"nx\">luisResult<\/span><span class=\"p\">.<\/span><span class=\"nx\">entities<\/span><span class=\"p\">.<\/span><span class=\"nx\">forEach<\/span><span class=\"p\">(<\/span><span class=\"nx\">entity<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\r\n          <span class=\"k\">if<\/span> <span class=\"p\">(<\/span><span class=\"nx\">entity<\/span><span class=\"p\">.<\/span><span class=\"nx\">type<\/span> <span class=\"o\">===<\/span> <span class=\"nx\">field<\/span><span class=\"p\">.<\/span><span class=\"nx\">name<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\r\n            <span class=\"nx\">field<\/span><span class=\"p\">.<\/span><span class=\"nx\">luisEntity<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">entity<\/span><span class=\"p\">;<\/span>\r\n          <span class=\"p\">}<\/span>\r\n        <span class=\"p\">});<\/span>\r\n      <span class=\"p\">});<\/span>\r\n\r\n      <span class=\"c1\">\/\/ collect missing fields<\/span>\r\n      <span class=\"k\">return<\/span> <span class=\"nx\">session<\/span><span class=\"p\">.<\/span><span class=\"nx\">beginDialog<\/span><span class=\"p\">(<\/span><span class=\"s1\">'\/collectFormData'<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">form<\/span> <span class=\"p\">});<\/span>\r\n    <span class=\"p\">})<\/span>\r\n  <span class=\"p\">},<\/span>\r\n\r\n  <span class=\"c1\">\/\/ get filled-in form and process the request<\/span>\r\n  <span class=\"p\">(<\/span><span class=\"nx\">session<\/span><span class=\"p\">,<\/span> <span class=\"nx\">args<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\r\n\r\n    <span class=\"kd\">var<\/span> <span class=\"nx\">form<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">args<\/span><span class=\"p\">.<\/span><span class=\"nx\">form<\/span><span class=\"p\">;<\/span>\r\n    <span class=\"nx\">session<\/span><span class=\"p\">.<\/span><span class=\"nx\">send<\/span><span class=\"p\">(<\/span><span class=\"s1\">'processing request..'<\/span><span class=\"p\">);<\/span>\r\n\r\n    <span class=\"c1\">\/\/ now that we have the filled in form with all fields populated either <\/span>\r\n    <span class=\"c1\">\/\/ from LUIS or the user, we can implement the request processing here...<\/span>\r\n    <span class=\"c1\">\/\/ TODO: process intent using the filled in form object<\/span>\r\n\r\n    <span class=\"c1\">\/\/ start over<\/span>\r\n    <span class=\"nx\">session<\/span><span class=\"p\">.<\/span><span class=\"nx\">send<\/span><span class=\"p\">(<\/span><span class=\"s1\">'bye bye'<\/span><span class=\"p\">);<\/span>\r\n    <span class=\"k\">return<\/span> <span class=\"nx\">session<\/span><span class=\"p\">.<\/span><span class=\"nx\">replaceDialog<\/span><span class=\"p\">(<\/span><span class=\"s1\">'\/loop'<\/span><span class=\"p\">);<\/span>\r\n  <span class=\"p\">}<\/span>\r\n<span class=\"p\">]);<\/span>\r\n\r\n<\/code><\/pre>\n<\/div>\n<h3 id=\"collectformdata-dialog\">CollectFormData Dialog<\/h3>\n<p>This dialog retrieves a list of fields to fill in like you would with a form. Then, it attempts to determine a value for each field based on the entities extracted by LUIS from the user input. If it is unable, it prompts the user to enter a value for that field.<\/p>\n<div class=\"language-js highlighter-rouge\">\n<pre class=\"highlight\"><code><span class=\"c1\">\/\/ collect form data dialog<\/span>\r\n<span class=\"nx\">bot<\/span><span class=\"p\">.<\/span><span class=\"nx\">dialog<\/span><span class=\"p\">(<\/span><span class=\"s1\">'\/collectFormData'<\/span><span class=\"p\">,<\/span> <span class=\"p\">[<\/span>\r\n\r\n  <span class=\"c1\">\/\/ prompt for field value<\/span>\r\n  <span class=\"p\">(<\/span><span class=\"nx\">session<\/span><span class=\"p\">,<\/span> <span class=\"nx\">args<\/span><span class=\"p\">,<\/span> <span class=\"nx\">next<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\r\n\r\n    <span class=\"kr\">const<\/span> <span class=\"nx\">form<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">args<\/span><span class=\"p\">.<\/span><span class=\"nx\">form<\/span><span class=\"p\">;<\/span>\r\n    <span class=\"nx\">session<\/span><span class=\"p\">.<\/span><span class=\"nx\">dialogData<\/span><span class=\"p\">.<\/span><span class=\"nx\">form<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">form<\/span><span class=\"p\">;<\/span>\r\n    \r\n    <span class=\"c1\">\/\/ iterate through the form fields and pick the first one without a value<\/span>\r\n    <span class=\"k\">for<\/span> <span class=\"p\">(<\/span><span class=\"kd\">var<\/span> <span class=\"nx\">i<\/span><span class=\"o\">=<\/span><span class=\"mi\">0<\/span><span class=\"p\">;<\/span> <span class=\"nx\">i<\/span><span class=\"o\">&lt;<\/span> <span class=\"nx\">form<\/span><span class=\"p\">.<\/span><span class=\"nx\">length<\/span><span class=\"p\">;<\/span> <span class=\"nx\">i<\/span><span class=\"o\">++<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\r\n      <span class=\"kd\">var<\/span> <span class=\"nx\">field<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">form<\/span><span class=\"p\">[<\/span><span class=\"nx\">i<\/span><span class=\"p\">];<\/span>\r\n      <span class=\"nx\">session<\/span><span class=\"p\">.<\/span><span class=\"nx\">dialogData<\/span><span class=\"p\">.<\/span><span class=\"nx\">fieldIndex<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">i<\/span><span class=\"p\">;<\/span>\r\n      \r\n      <span class=\"k\">if<\/span> <span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"nx\">field<\/span><span class=\"p\">.<\/span><span class=\"nx\">value<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\r\n        <span class=\"c1\">\/\/ if this was resolved by LUIS, move to the next handler to process the value<\/span>\r\n        <span class=\"k\">if<\/span> <span class=\"p\">(<\/span><span class=\"nx\">field<\/span><span class=\"p\">.<\/span><span class=\"nx\">luisEntity<\/span><span class=\"p\">)<\/span> <span class=\"k\">return<\/span> <span class=\"nx\">next<\/span><span class=\"p\">();<\/span>\r\n\r\n        <span class=\"c1\">\/\/ prompt for value for this field<\/span>\r\n        <span class=\"k\">return<\/span> <span class=\"nx\">builder<\/span><span class=\"p\">.<\/span><span class=\"nx\">Prompts<\/span><span class=\"p\">.<\/span><span class=\"nx\">text<\/span><span class=\"p\">(<\/span><span class=\"nx\">session<\/span><span class=\"p\">,<\/span> <span class=\"nx\">field<\/span><span class=\"p\">.<\/span><span class=\"nx\">prompt<\/span><span class=\"p\">,<\/span> <span class=\"nx\">options<\/span><span class=\"p\">);<\/span>\r\n      <span class=\"p\">}<\/span>\r\n    <span class=\"p\">}<\/span>\r\n\r\n    <span class=\"k\">return<\/span> <span class=\"nx\">session<\/span><span class=\"p\">.<\/span><span class=\"nx\">endDialogWithResult<\/span><span class=\"p\">({<\/span> <span class=\"na\">form<\/span><span class=\"p\">:<\/span> <span class=\"nx\">session<\/span><span class=\"p\">.<\/span><span class=\"nx\">dialogData<\/span><span class=\"p\">.<\/span><span class=\"nx\">form<\/span> <span class=\"p\">});<\/span>\r\n  <span class=\"p\">},<\/span>\r\n\r\n  <span class=\"c1\">\/\/ process input (either by LUIS or the user)<\/span>\r\n  <span class=\"p\">(<\/span><span class=\"nx\">session<\/span><span class=\"p\">,<\/span> <span class=\"nx\">result<\/span><span class=\"p\">,<\/span> <span class=\"nx\">next<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\r\n\r\n    <span class=\"kd\">var<\/span> <span class=\"nx\">field<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">session<\/span><span class=\"p\">.<\/span><span class=\"nx\">dialogData<\/span><span class=\"p\">.<\/span><span class=\"nx\">form<\/span><span class=\"p\">[<\/span><span class=\"nx\">session<\/span><span class=\"p\">.<\/span><span class=\"nx\">dialogData<\/span><span class=\"p\">.<\/span><span class=\"nx\">fieldIndex<\/span><span class=\"p\">];<\/span>\r\n\r\n    <span class=\"k\">switch<\/span> <span class=\"p\">(<\/span><span class=\"nx\">field<\/span><span class=\"p\">.<\/span><span class=\"nx\">type<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\r\n\r\n      <span class=\"k\">case<\/span> <span class=\"s1\">'number'<\/span><span class=\"p\">:<\/span>\r\n        <span class=\"c1\">\/\/ implement parsing a number from user's input or LUIS<\/span>\r\n        <span class=\"c1\">\/\/break;<\/span>\r\n\r\n      <span class=\"k\">case<\/span> <span class=\"s1\">'choice'<\/span><span class=\"p\">:<\/span>\r\n        <span class=\"c1\">\/\/ implement parsing a selection from user's input or LUIS<\/span>\r\n        <span class=\"c1\">\/\/break;<\/span>\r\n\r\n      <span class=\"k\">case<\/span> <span class=\"s1\">'time'<\/span><span class=\"p\">:<\/span>\r\n        <span class=\"c1\">\/\/ implement parsing a time from user's input or LUIS<\/span>\r\n        <span class=\"c1\">\/\/break;<\/span>\r\n\r\n      <span class=\"c1\">\/\/ text<\/span>\r\n      <span class=\"na\">default<\/span><span class=\"p\">:<\/span> \r\n        <span class=\"nx\">field<\/span><span class=\"p\">.<\/span><span class=\"nx\">value<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">field<\/span><span class=\"p\">.<\/span><span class=\"nx\">luisEntity<\/span> <span class=\"p\">?<\/span> <span class=\"nx\">field<\/span><span class=\"p\">.<\/span><span class=\"nx\">luisEntity<\/span><span class=\"p\">.<\/span><span class=\"nx\">entity<\/span> <span class=\"p\">:<\/span> <span class=\"nx\">result<\/span><span class=\"p\">.<\/span><span class=\"nx\">response<\/span><span class=\"p\">;<\/span>\r\n        \r\n    <span class=\"p\">}<\/span>\r\n    \r\n    <span class=\"k\">delete<\/span> <span class=\"nx\">field<\/span><span class=\"p\">.<\/span><span class=\"nx\">luisEntity<\/span><span class=\"p\">;<\/span>\r\n\r\n    <span class=\"c1\">\/\/ call collectFormData again to continue to the next field<\/span>\r\n    <span class=\"nx\">session<\/span><span class=\"p\">.<\/span><span class=\"nx\">replaceDialog<\/span><span class=\"p\">(<\/span><span class=\"s1\">'\/collectFormData'<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span> <span class=\"na\">form<\/span><span class=\"p\">:<\/span> <span class=\"nx\">session<\/span><span class=\"p\">.<\/span><span class=\"nx\">dialogData<\/span><span class=\"p\">.<\/span><span class=\"nx\">form<\/span> <span class=\"p\">});<\/span>\r\n  <span class=\"p\">}<\/span>\r\n<span class=\"p\">]);<\/span>\r\n\r\n<\/code><\/pre>\n<\/div>\n<h3 id=\"suggestions\">Suggestions<\/h3>\n<p>If you are designing a similar system, it might be a good idea to provide options for the user to choose from in the event that LUIS doesn\u2019t recognize the intent correctly. In this case, we would switch from the <em>free text<\/em> approach to a <em>closed<\/em> approach. We would then guide the user through the available options, asking them to choose what they would like to do, and then prompting them to provide the extra information required to process his request, the same way we did before.<\/p>\n<h2 id=\"opportunities-for-reuse\">Opportunities for Reuse<\/h2>\n<p>For our scenario with moed.ai, our solution helps ensure their customer\u2019s requests are understood and scheduled correctly without a need for additional intervention. This approach could be reused in other scenarios where LUIS is being utilized to extract intents and entities, and it is necessary to guarantee that all form fields are filled out before processing a request. For instance, an example scenario might be a pizza ordering bot, which needs to gather information like the user\u2019s address, toppings, drinks, etc. before submitting their order.<\/p>\n<p>In addition, this approach could be extended to support more data types, such as media files like images or videos, that might be useful in processing a user\u2019s intent. Validation logics could also be implemented as part of this flow, to verify the input before moving on the next field.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This post outlines the steps of creating a bot that interacts with a user to collect missing LUIS entity data before processing their request.<\/p>\n","protected":false},"author":21349,"featured_media":2295,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[13],"tags":[110,231,261],"class_list":["post-2118","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-bots","tag-bots","tag-language-understanding-intelligent-service-luis","tag-moed-ai"],"acf":[],"blog_post_summary":"<p>This post outlines the steps of creating a bot that interacts with a user to collect missing LUIS entity data before processing their request.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/posts\/2118","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/users\/21349"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/comments?post=2118"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/posts\/2118\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/media?parent=2118"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/categories?post=2118"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/tags?post=2118"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}