Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Generating an HTML webpage

Prolog rules are used to add a condition to a webpage (i.e. webpage X is shown when Clause Y is true).

You add a condition that checks for a particular pattern ID to a Prolog rule in the html.pl file. Other simple conditions that you can add involve counting the number of recipes that are still available while in the recipe selection phase, etc. The general form of the page lay-out rules would be something like:

Code Block
myPage(Txt, Button, Html) :-
  <HERE YOUR CONDITION FOR SHOWING THIS PAGE>, 
  % e.g. while recipe is being selected (check for e.g. currently active top level pattern id), we'll display recipe features
  % below code that specifies the page layout for this context
  applyTemplate('<div class="card mx-auto" style="width:67vw">~a</div>, Text, Html),
  …
  .

There are still many options to vary. For example, you can choose the parameters for the myPage predicate that fit your approach best.

Example Prolog Rule for a Page

...

breakoutModefull-width

...

Above we have illustrated how to generate individual HTML elements but not yet shown how to generate a complete webpage using one or more of those elements. We will show in this section how you can generate such a webpage and make the agent render it.

Another key question that we have not addressed so far is when to display a webpage. To answer the latter question first, we will use a generic approach where we show a specific webpage when a specific subdialog is ongoing. For example, when the conversation with the user is still in its opening stages and a greeting is ongoing, we can show a welcoming page to a user. As greeting and other subdialogs correspond with names of conversational pattetrns, the idea is to show a webpage when the top level ongoing dialog part corresponds with a name of one of the patterns defined in our conversational agent. The agent will retrieve the body of the HTML webpage that we want to display for such a pattern using the query page(+PatternID, +Txt, -Html) where PatternID is the name of the conversational pattern, Txt is the text the agent will say if its their turn, and Html is the output argument with the HTML code for the body of our webpage.

As before, but now for complete webpages, we will use a structural template to create a page. The typical structure of these templates looks like this:

Code Block
page(PatternID, Txt, Html) :-
  %%% 1. Condition for when the webpage that will be generated is shown
  currentTopLevel(PatternID),
  [OPTIONAL: OTHER CONDITIONS FOR SHOWING THIS PAGE,] 
  %%% 2. HTML code generation part
  % First row: Prolog code (queries) that generates HTML code for the first 'row' of the page
  % with FirstRow the output argument that is unified with that HTML code
  ... , FirstRow),
  ...
  % Nth row: Prolog code (queries) that generates HTML code for the Nth 'row' of the page
  % with NthRow the output argument that is unified with that HTML code
  ... , NthRow),
  %%% 3. Putting everything together
  atomic_list_concat([FirstRow, ..., NthRow], Body),
  %%% 4. Generate the HTML webpage code
  % Create the HTML page with:
  html(Body, Html)
  % or, alternatively, without a header and footer:
  [OPTIONAL: html_without_header_footer(Body, Html). % replaces previous html(Body, Html)!
  .

The template consists of four consecutive parts. The first part uses the currentTopLevel(PatternID) query to check whether the currently ongoing top level conversation pattern is PatternID. The variable PatternID should be instantiated with a specific name of a conversation pattern, and a page rule for each pattern that can be a top level conversation pattern should be created to be able to show a webpage during each ongoing part of the conversation. If you want to differentiate which page is shown also based on other conditions, (optionally) multiple page rules should be defined and (optionally) additional Prolog queries can be added to define more complex conditions for showing a webpage. For example, you could (and will be asked to) add a condition that checks how many recipes still match the requests (preferences, constraints) of a user and show a different page if that drops below a certain number. The second part consists of Prolog code for generating the HTML code for some of the components and elements introduced above. See below for a simple example, and at the end of this page a more complex example for a card deck. Typically, to define a complete webpage, multiple elements will be used that would usually be organized in one or more rows of HTML code (think of these literally as rows on the page, in line with the basic structure of a Bootstrap grid). The third part simply concatenates the HTML code for each of the individual rows using the atomic_list_concat/2 predicate that we explained in detail above. And, finally, the fourth part generates the HTML code for the complete body of the webpage using the predefined html/2 predicate in html.pl (or, alternatively, the predicates html_without_header or html_without_header_footer).

In this project, we generate the HTML code for the body of an HTML webpage (that is what the template for a page/3 rule above is supposed to do). The head of the webpage (a container for metadata, not to be confused with the header of or headings on a webpage!) is predefined and cannot be modified by our MARBEL agent.

Check out the code for the header/2 and footer/2 predicates in the html.pl to see what HTML code is generated for the header and footer. You are free to change these too if you like, but you should make sure that the microphone icon always is displayed on the relevant pages so a user can engage in talking to your conversational agent (by making it open their microphone and start listening to the user).

Example Prolog Rule for a Page

As indicated above, the idea is to add a rule defining a page(+PatternId, +Txt, -Html) for each conversation pattern that might be ongoing at the top level during the conversation. You will be asked to add a range of different patterns in the patterns.pl file during the project. One of those hinted at above is a greeting pattern with a pattern ID code c10. We will now provide a simple example of rule that generates a page that will be shown when the pattern c10 is active (or ongoing):

Code Block
% A very basic and simple welcoming page to show when a greeting is still ongoing
page(c10, _, Html) :-
	% Part 1: Show this page only when a greeting pattern c10 is ongoing
	currentTopLevel(c10),
	% Part 2: Constructing HTML for the body of the page
	% If the agent has a name (agentName/1 will succeed), 
	% we want the agent to introduce itself with its name
	(agentName(Name) -> N = Name ; N = 'your recipe recommendation assistant'),
	% replace the placeholder ~a with the value of variable N
	applyTemplate('<h1>I am ~a</h1><br></center>', N, IntroHeading)
    % piece a quoted text and our intro self-introduction text elements together
	atomic_list_concat(['<center><h2>Hello!</h2><br>', IntroHeading], AlertContent),
	% put the introductory text HTML as content into an alert component
	div(AlertContent, 'alert alert-light', '', Body),
	% Part 3: page is so simple that there is no second row so nothing to do here
	% Part 4: Create the HTML page using the HTML code unified with the Body variable
	html(Body, Html).

Now suppose that the query currentTopLevel(c10) succeeds. In that case the page(c10, _, Html) query will also succeed (why?). Suppose, moreover, that our conversational agent is called Cookpanion (you think of a good name for your own agent!) and the query agentName(Name) succeeds with Name='Cookpanion'. What HTML code will then be generated (and bound to the Html output argument variable)? To answer this question, you need to understand how the applyTemplate query works (more on that you can find at the end of this page: https://socialrobotics.atlassian.net/wiki/spaces/PM2/pages/2264236033/Visual+Support+Guide#Defining-new-predicates-for-generating-HTML-elements). But for now the comment just above the query will be sufficient to piece things together. We get the HTML code <h1>I am Cookpanion</h1><br></center> that binds to IntroHeading. The atomic_list_concat query add this to the end of the <center><h2>Hello!</h2></br> HTML code, which then is used as the content for the alert class using the div predicate. By inspecting the html/2 predicate (check out the html.pl file) we can then figure out that the resulting HTML code will look like this:

Code Block
% Next line makes sure (a user is asked to) enable audio interaction via the browser
<div class="audioEnabled"></div>
% A row that we use as header
<div class="row" style="position: static; height: 75px">
  <nav class="navbar mb-1" style="position: static">
    <button class="btn" style="position: fixed; top: 0; left: 0; z-index: 1">
      <img class="img-fluid" style="width:4rem" data-value="Mic" src="data:image/png;base64,MISSING-VERY-LONG-BASE64-CODE-FOR-MIC-ICON>
      <h6></h6>
    </button>
  </nav>
</div>
% Main part of the page
<main class="container-fluid p-3">
% Next three lines represent the code generated by the page(c10,_,Html) predicate
  <div class="alert alert-light"><center></br><h1>Hello" style="">
    <center><h2>Hello!</br></br>','Ih2></br><h1>I am ~a<Cookpanion</h1></br></br></center></div>'], Template),
	% Get the bot's name if it has one; other call it 'your assistant'
	(agentName(Name) -> N = Name ; N = 'your recipe selection assistant'), applyTemplate(Template, N, Body),
	% Create the HTML page
	html(Body, Html)h1><br></center>
  </div>
</main>
% Footer
<footer class="fixed-bottom">
  <p class="lead mb-0 bg-light text-center" style="min-height:0rem">
    <button>End interaction</button>
  </p>
</footer>

Perhaps the code that is generated is a bit surprising and it is hard to locate the (just!) three lines that the page(c10,_,Html) query generates (somewhere in the middle, as main part of the page). The code illustrates that the html/2 predicate also does quite a bit of the work for generating the complete body of our webpage, including the generation of a header and footer, and a line at the top to make sure the browser will allow for audio interaction.

Adding a chatbox to your page layout for testing purposes

The speech interface is fitting to the context of a user in a kitchen, but not always feasible for testing. It may take additional time for the system to process speech input, you may be in a noisy environment, and there may be speech recognition failures. Hereby a pointer to easily enable a textbox to be rendered for input.

In the html.pl file, where you format the pages to render during the conversation, for each of the pages that you may display at any point in the conversation add the following code:

...

You will soon enough learn that using speech as the main interface for interaction can be challenging, adding delays and misunderstandings, depending on factors such as the context where it is used (a noisy environment makes ASR much more challenging and may lead to failures), perhaps the accent of the speaker, and other related factors. For testing purposes, it therefore may be useful to also be able to test without these factors potentially complicating the interaction. To this end, we have made a chatbox element available too which makes text-based interaction available as an alternative to (just) speech-based interaction. To add this element to your webpage, we suggest you add the following HTML code to the footer of pages:

Code Block
<div class="text-center"><p class="chatbox mx-auto"></p></div>, for example,
to the footer.

We have already added the code for doing this in the html.pl file, but it is still commented out.

Note

Although we provide the chatbox option for testing purposes, it is up to you and your team to make sure the agent works also without the chatbox option. The chatbox should not be enabled in the conversational agent code that you submit as final deliverable!

Using and Understanding the code in html.pl

...