Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Table of Contents
minLevel1
maxLevel2
outlinefalse
typelist
printablefalse

Prolog and Patterns

This section is about implementing the dialog management capabilities of the conversational agent but also about implementing the domain logic that the agent needs to be able to perform its task. As our conversational agent is a task-based agent for recipe recommendation, the conversational competence of our agent focuses on patterns and responses for recipe recommendation. The logic that we need to implement concerns the capabilities our agent needs to reason about user requests about recipes that are available in the agent’s database. We will first focus on adding some conversational capabilities for our agent to respond to a user request to provide a (random) recipe. As before, the approach to dialog management that we use here will require the definition of a pattern and the specification of a (textual) response to the user request. When we have completed that part, we will continue with the part focusing on implementing the reasoning capabilities for extracting such a recipe from the database in Prolog. This will require the definition of several rules for extracting a suitable recipe from the agent’s recipe database.

...

Warning

To test the pattern you just added, as before, you still need to do one more thing: In the dialog_init.mod2g file, this time add the a50recipeSelect pattern also to the agenda of the agent after c10 that is already in it.

You can now [TBU] Run your Conversational Agent again to hear your agent ask you for your recipe preferences.

Note that your team must have also added the recipe recommendation page (but not the recipe confirmation page; see Visuals section below) to enable you to respond to the agent’s inquiry. This page is needed to display a microphone icon that you will need to respond to the agent.

...

This clause specifies that if there are no filters to apply (i.e., the filter list is empty), the output of this filtering of a list of RecipeIDs thus remains unchanged and is that same list of recipe identifiers RecipeIDs.

Visuals

Recipe

...

Overview 1 page

The objective of this capability is to create a page that facilitates users in having a conversation about recipes with the agent. We will walk you through the detailed steps to illustrate how to implement the code for such a page below. You should add the code for a page to the html.pl file.

At this stage, for this capability, we will only provide code for a very basic skeleton page that provides the minimal functionality needed to implement the main requirement for this page: enable a user to talk to the agent using a microphone button. The design is kept minimal below and in the step-by-step walkthrough below we will only use a single and simple alert element to style the page. As the recipe recommendation page will be the first interaction point for users who are actually interested in finding a recipe, we leave it up to you to try and make this page more inviting and add clear and useful content that the agent will show. Note that we will also ask you to extend this page at a later stage when you are implementing [TBU]Filtering by Inclusion.

Step 1: Adding the head of a Prolog rule for a recipe recommendation page.

  • The Prolog predicate that we use for displaying a webpage is the page/3 predicate. We use page(+Name, +Txt, -Html) as the head of a rule for generating the HTML code returned in the output argument Html for a page called Name. For the name of the page that we need to specify in the first argument of the predicate, as a convention, we choose to use the pattern ID of a conversational pattern in the agenda. The idea is that the page is shown when the conversational pattern is ongoing. We want to show our recipe recommendation page when the a50recipeSelect pattern is active. As we do not use the second argument here, you should add the following code to the html.pl file (as indicated also in that file itself):

    page(a50recipeSelect, _, Html) :-

Step 2: Adding a condition for when to display the page.

  • The condition that we always will add to a rule for generating pages is a condition to only show a page when the associated pattern, in our case a50recipeSelect, is the currently active top-level pattern. We can use the pre-defined predicate currentTopLevel/1 for this (check out its definition in the dialog.pl file). Add the following condition to the rule that we are implementing:

    currentTopLevel(a50recipeSelect),

Step 3: Generating the HTML code for the page.

  • Implement the code for generating the HTML code for the page after the condition we just added. For now, we will just add a simple https://www.w3schools.com/bootstrap4/bootstrap_alerts.asp to the page to inform the user about the recipe recommendation task the agent and the user should engage in. We use the div/4 predicate (see the [TBU]Visual Support Guide) to add an alert class with a centered heading text. Add the following code to the rule that we are implementing:

    div('<center><h1>What recipe are you looking for?</h1></center>', 'alert alert-success', '', MainElementContent),

Step 4: Combining the different HTML elements (rows).

  • We have kept things here very simple and just added one HTML element to our page above. When you add more elements, typically you will have to combine them using a built-in Prolog predicate such as atomic_list_concat/2 to piece everything together. This time we have nothing to do here.

Step 5: Create the main element for the HTML page.

  • Finally, use the html/4 predicate to create the main element for your HTML page that will be added to the body of the HTML page. You should feed the HTML code generated above (and pieced together, if needed), into the first argument of this predicate. In our case, we should use the output argument of the div/4 predicate MainElementContent that we introduced above. The second is used to indicate whether you want your page to have a header (use true when you do, false if not) and the third argument is used to indicate whether you want your page to have a footer. The header is predefined in the html.pl file and displays a microphone button. Finally, the generated code for the main element is returned in the fourth output argument Html. Add the following code to the rule to finish implementing it:

    html(MainElementContent, true, true, Html).

Warning

If your team has implemented the Dialogflow intents and patterns for this capability, you can already test the page you just implemented for the a50recipeSelect pattern. You don’t need the extraction logic for retrieving a recipe from the database for this.

So try and [TBU]Run your Conversational Agent again to see the page you just created. Also, check out the MARBEL agent’s state using the introspector. You should see that the top-level pattern that is at the front of the session is a50recipeConfirm after you tell your agent to just show a recipe.

Recipe confirmation page

The next page that we want you to add is a recipe confirmation page. At the end of the pattern enabling a user to request a (random) recipe, the agent inserts the a50recipeConfirm pattern ID in the agenda. No pattern has been added for this pattern ID yet, but because it will appear at the top level in the agent’s agenda, we can already create a confirmation page for the recipe that is selected. The idea is that this page allows the user to preview the recipe and indicate whether they are satisfied with the recipe (confirm) or not (disconfirm). To enable a user to make this decision, the main requirement for this page is that it shows the recipe’s name, and what the result of cooking the recipe will look like (a picture of the recipe). A second requirement is that the page shows a microphone button to enable the user to inform the agent about whether they want to (dis)confirm the recipe. Note that at a later stage, we will ask you to extend the recipe confirmation page when you implement [TBU]Filtering by Inclusion .

For the design, a https://www.w3schools.com/bootstrap4/bootstrap_cards.asp element seems a suitable element for styling the page. We will use it below to create a first (but still simple) recipe confirmation page with a basic recipe card. We will want to generate the following HTML code for this card:

Code Block
<div class="card" style="width:400px">
  <div class="card-body">
    <h4 class="card-title">A RECIPE TITLE HERE</h4>
  </div>
  <img class="card-img-bottom" src="..." alt="Card image">
</div>

We will also use various predicates to collect the information about the recipe we want to display from the agent’s database and memory. We will briefly introduce those predicates here first:

  • currentRecipe(-RecipeID): predicate for retrieving the currently selected recipe ID from the agent’s memory; you are asked to implement this predicate above in the Prolog and patterns section.

  • recipeName(ID, Name): Retrieves the Name of a recipe uniquely identified by ID from the agent’s recipe database recipe_database.pl.

  • picture(ID, URL): Retrieves the URL to a(n online) recipe picture for the recipe uniquely identified by ID from the agent’s database recipe_database.pl.

Step 1: Adding the head of a Prolog rule for a recipe confirmation page.

  • We use the page/3 predicate again to define the head of a rule for generating the recipe confirmation page HTML code. Add the following code to the html.pl file (as indicated also in that file itself):

    page(a50recipeConfirm, _, Html) :-

Step 2: Adding a condition for when to display the page.

  • You should add a condition such that the recipe confirmation page is only shown when the associated pattern a50recipeConfirm is the currently active top-level pattern. Add the following condition to the rule that we are implementing:

    currentTopLevel(a50recipeConfirm),

Step 3: Generating the HTML code for the page.

  • Before we can even begin to create the recipe card that we have in mind, we need to retrieve the ID for that recipe. So we begin by doing that. Add the following code to the rule:
    currentRecipe(ID),

  • Now we can begin to generate the HTML code for this recipe. We first generate the code for the recipe picture and use the picture(ID, URL) to retrieve the URL to the recipe’s picture to fill in the ... for the src attribute in the HTML card template above and the img/4 predicate defined in html.pl for creating an image element. Add the following code to the rule:

    picture(ID, URL),
    img(URL, 'card-img-bottom', '', ImageElement),

  • Next, we generate some HTML code for a card title heading. We want the recipe name to appear as the card’s title and will retrieve that using the recipeName(ID, Title) predicate and use the predefined to_upper_case/2 predicate (see utils.pl file) to make sure the recipe title starts with a capital. To fill in the recipe title in the right place in the card title heading template, we use applyTemplate/3 to replace the placeholder ~a in a template for a card title. Add the following code to the rule:
    recipeName(ID, Title), to_upper_case(Title, UpperTitle),
    applyTemplate('<h4 class="card-title">~a</h4>', UpperTitle, TitleHeading),

  • The next part that we will generate is the card body element using the div/4 predicate. We want our card title to be the content of that element and use that as the first argument of our div/4 predicate (the first arguments of our predefined predicates by convention are the content of an element, see also the [TBU]Visual Support Guide). Add the following code to the rule:
    div(TitleHeading, 'card-body', '', CardBodyElement),

  • Finally, we need to combine the card body and image elements (check for yourself to see that they are combined within the card element HTML code above) and create the card element. We use the atomic_list_concat/2 predicate for combining the elements together and the div/4 predicate again to create the card element. Add the following code to the rule:
    atomic_list_concat([CardBodyElement, ImageElement], CardContent),
    div(CardContent, 'card', 'width:400px', MainElementContent),

Step 4: Combining the different HTML elements (rows).

  • We have kept things again simple here and just created one HTML element for our recipe confirmation page. We, therefore, have nothing to do here either.

Step 5: Create the main element for the HTML page.

...

See Visual Requirements for more information.

Warning

If your team has implemented the Dialogflow intents and patterns for this capability, you can already test the page you just implemented for the a50recipeSelect pattern. You don’t need the extraction logic for retrieving a recipe from the database for this.

So try and Run your Conversational Agent again to see the page you just created. Also, check out the MARBEL agent’s state using the introspector. You should see that the top-level pattern that is at the front of the session is a50recipeConfirm after you tell your agent to just show a recipe.

Recipe Confirmation page

The next page that we want you to add is a recipe confirmation page. At the end of the pattern enabling a user to request a (random) recipe, the agent inserts the a50recipeConfirm pattern ID in the agenda. No pattern has been added for this pattern ID yet, but because it will appear at the top level in the agent’s agenda, we can already create a confirmation page for the recipe that is selected. The idea is that this page allows the user to preview the recipe and indicate whether they are satisfied with the recipe (confirm) or not (disconfirm). To enable a user to make this decision, the main requirement for this page is that it shows the recipe’s name, and what the result of cooking the recipe will look like (a picture of the recipe). A second requirement is that the page shows a microphone button to enable the user to inform the agent about whether they want to (dis)confirm the recipe. Note that at a later stage, we will ask you to extend the recipe confirmation page when you implement [TBU]Filtering by Inclusion .

We have introduced the bare essentials for these pages but you should feel free to modify it in any way you like to make it look more appealing. However, please note that the a50recipeConfirm page is extended later to include recipe information. More information about these extensions can be found here: https://socialrobotics.atlassian.net/wiki/spaces/PM2/pages/2229600267#Visuals.

It is important that you make sure that the requirements marked in bold in the text are met.

Test it Out

If you have not yet done this, add the a50recipeSelect pattern ID to the agent's agenda in the dialog_init.mod2g file. When you finished implementing this capability and you [TBU] Run your Conversational Agent again, you should be able to conduct the following conversational interaction and go through the following dialog moves:

...

Note

The conversational agent at this stage is not able to handle misunderstandings or speech recognition errors. Dialogflow will return a default fallback intent(fallback) (check the intents in your Dialogflow agent) if it is not able to classify speech into one of the intents created. We have not yet introduced a pattern, however, needed for handling such a fallback intent and the agent will therefore get stuck if speech recognition fails. Dialogflow should not have too much trouble with recognizing a simple greeting phrase, however.

...