Conversation patterns represent parts of the flow or sequential order of a conversation. In our agent, such patterns are encoded with the Prolog predicate pattern/1
: pattern(Pattern)
where Pattern
is a list that consists of two elements: the name of the pattern as first element, and another list that represents a sequence of dialogue moves (intents). Some of these dialogue moves are performed by a user (and the corresponding intents should be available in the Dialogflow agent). The other dialogue moves are performed by your agent. Dialogue moves of an agent are also intents, but are specified in the MARBEL agent code, not in the Dialogflow agent. With agent dialogue moves, text what the agent will actually say should be provided. These agent responses are encoded using the predicate text/2
: text(IntentName, "Response Text")
.
Since your agent is supposed to be specialized in conducting conversations aimed at recipe recommendation, you should define a specific set of conversation patterns that such an agent can expect to happen in a conversation in which it assists a user with selecting a recipe. But even such conversations may have many variants and it is important to remember that such conversations can be conducted in many different ways. It is your job to account for as many of those variants as possible by means of the patterns that you create.
We shall walk you through the first patterns and responses. You should mainly work in the patterns.pl
and responses.pl
files, where you should place your (new) patterns and responses.
For this section, you will have to collaborate closely with your Dialogflow and Filter Functions Section team members. This is the case because, as explained above, patterns consist of agent and user intents. User intents are defined in the Dialogflow agent that your team members created. It is important that the labels that you use (your naming conventions) are the same! If you do not know what an intent is, it may be helpful to inspect the Dialogflow material and the agent itself. You may also find it useful to inspect the recipe database.
c10 Greeting Patterns
c10 Greeting with No Introduction
To make a pattern you need to use the Prolog predicate ‘pattern(_)’. This predicate only takes one argument, which should take the form of a prolog list.
We shall start by considering how a greeting could go. When the agent does not introduce itself, the most common greeting pattern would look as follows:
Example:
A: hello
U: hi
In this example conversation, we see A(Agent) greets the user and U(User) greets as well. The first thing in our list within our pattern predicate is always the pattern identification code. In the case of greeting, this is c10. After this identification code, the dialogue moves in the pattern are specified consecutively . Such a move is represented as a two-element list, where the first element is the person speaking ('agent' or ‘user’) and the second element is the agent response label or the user’s intent (which should share a name with an intent on Dialogflow, be sure to communicate with your groupmates). Thus for this greeting, we reach the following rule head:
pattern([c10, [agent, greeting], [user, greeting]])
As mentioned before, this greeting should occur if the agent does not know its name. If the agent knows its name it should introduce itself.
Thus the complete rule should specify this condition, which could be done as follows:
pattern([c10, [agent, greeting], [user, greeting]]) :- not(agentName(_)).
c10 Greeting with Introduction
Pattern C10.1: Opening Self-Identification (Agent)
Example:
A: hello
A: I'm _____
U: hi
This pattern will be quite similar to the one above but should include the predicate 'selfIdentification'. Also, note that the agent must have a name in order to self-identify.
c10 responses.pl
In responses.pl you will see the fact text(greeting, ""). Fill in the “” with a response you want your agent to give as a greeting
Next, we need to build the rule for selfIdentification: text(selfIdentification, Txt) :-
This rule should produce a response that is returned as Txt, and should include the agent's name.
c30 General Capability Check
Your user wants to know what your agent does. Create a pattern for this.
Example:
U: what can you do?
A: At the moment I can ….
You should use the intents/predicates 'checkCapability' (for the user) and 'describeCapability' (for the agent).
In responses.pl find text(describeCapability, ""). and fill in the atom with an appropriate response.
c40 Closing
This is the pattern that closes the conversation between the user and agent, a farewell. In this pattern, our agent should do the ‘sessionCloser’ and say ‘farewell’. (or another phrasing of goodbye that fits to the agent persona your team is designing).
In responses.pl, fill in a final remark from your agent about your program in the session closer and add a farewell.
B Patterns for Repair
A good handling of repair is vital to making your agent robust to misunderstanding. There are a few common ways in which misunderstanding occurs, that need to be addressed by proper repair patterns.
b12 The agent does not understand the user utterance
Example:
U: chicken soup
A: what do you mean?
Your user has just said something odd or not matching the current situation and so your Dialogflow cannot identify the user's intention and goes to a default fallback intent. In this pattern, your agent can try to come to an understanding by asking for a rephrasing with ‘paraphraseRequest’. Add a b12 pattern using the defaultFallback intent and paraphraseRequest response.
In responses.pl: paraphrase requests are determined depending on the context of the conversation (the pattern that is currently active). Under the paraphrase request section in responses.pl, you will see ‘text/3’, which specifies the active pattern, the agent response name, and what the agent should say. Fill all these in.
b13 Out of Context.
The user said something that Dialogflow can identify with the user’s intent, but your agent is not at a stage where that intent is appropriate.
Example:
A: what recipe would you like to cook?
U: goodbye
A: not sure what that means in this context.
Think about what feature in Prolog you could use to symbolize that there is some intent identified, regardless of what particular intent it is. The agent should respond with a ‘contextMismatch’ response.
Fill in all the contextMismatch responses in response.pl. Like the paraphrasing response, it depends on the context of the conversation what response to give.
b14 User Repetition
It may happen that the user repeats what it has said, while the agent has already responded with a ‘contextMismatch’ response. In this case, it would be unnatural to give the same response again. Think of a more sensible response in this case.
In patterns.pl, specify the b14 pattern. In responses.pl fill in a response for the repeatedUserIntent.
b42 Appreciation
Example:
U: Thanks
A: You're welcome.
Your user says thank you and shows some ‘appreciation’ and your agent should respond apropriately with an ‘appreciationReceipt’.
In patterns.pl specify the B42 pattern. Furthermore, go into responses.pl and fill in the corresponding text fact.
a50recipeSelect: Selecting a Recipe
Example:
A: Let us find a recipe together.
A: what recipe would you like to cook?
U: I'd like to make pasta (or, simply: pasta)
A: pasta is a great choice!
In the a50recipeSelect pattern, the pattern name is not just a50 but a50recipeSelect. Please note that when building your pattern. In this conversation your agent should specify its goal with the user and then inquire what recipe it likes to cook. Then it should interpret a recipe request from the user and respond to the user's choice. Finally, the agent should insert the next pattern in the conversation, which is a50recipeConfirm. To do this you should use the responses ‘specifyGoal’, ‘recipeInquiry’, and ‘recipeChoiceReceipt’. The user intent is called ‘recipeRequest’. To insert something into the agent’s agenda, you can use the insert() command as part of a pattern.
In patterns.pl, specify the pattern as indicated above. In responses.pl fill in the corresponding responses mentioned above. ‘recipeChoiceReceipt' requires a rule; to respond, the agent must find the current recipe, access a list of all recipe IDs using the predicate ‘recipeIDs()', check that the current recipe is a member of the list(better safe than sorry), get the recipe’s name, and finally return a response using ‘string_concat(“Phrase Part 1”, “Phrase Part 2”, Txt)’.
a50recipeConfirm: Confirming a Recipe
After the user selects a recipe, the agent should confirm the user’s choice. On this page, the user would see recipe information via visual support. We foresee three potential situations for this conversation, which can be accommodated by making three a50recipeConfirm patterns. After the agent uses ‘recipeCheck’ to ask if the user can look over the recipe information to decide if they want to cook that recipe, the user could confirm (1), deny (2), or show appreciation (3).
In patterns.pl, make the a50recipeConfirm patterns for each of the three scenario’s mentioned above. Look at Dialogflow for the appropriate Intent identification naming. If the user says it does not want to choose that recipe, we need to go back a step. How would one do this?
In responses.pl fill in ‘text(recipeCheck, “”)’ response.
a21noMoreFilters
Example:
A: “What other filters would you like to add”
U: “I do not want more filters “
A: “Ok. Here is a list of recipes” / “Sorry the list is still too long to show”
a21noMoreFilters pattern handles a user request to not add more feature requests, preferences, or requirements. When filtering the recipes, the user is not shown the list of filtered recipes until there are only 15 (or fewer) recipes. It could be, though, that the user does not wish to filter recipes further. The user would then use the NoMoreFilters intent. The agent can then allow the user to see the list with the ‘grantPicture’ response, or deny with ‘pictureNotGranted’. If the agent grants the user’s request, the pattern should end with the agent updating its memory using ‘[agent, update(['show'='true'])]’. This triggers the showing of recipes by updating the agent’s memory.
Implement the ‘a21noMoreFilters’ pattern in patterns.pl.
In responses.pl we have to make two rules, for ‘grantPicture’ and ‘pictureNotGranted’. An agent can allow the list of recipe pictures to be shown if the list is less than 100 recipes long. An agent cannot grant the recipes if the list is over 99 recipes long. The ‘recipesFiltered’ predicate provides a list of the filtered recipes. Fill in the two rules with the corresponding conditions.
Pattern a21featureRequest
Pattern A2.10: Open Request Series
The open request series pattern is central to a recipe selection conversation.
Example:
U: A recipe from Japan.
A: Do you want to add another filter?
U: Recipes that use pasta (penne).
A: What recipe would you like to cook? (assuming only <6 left which are displayed on screen)
U: Curry noodle soup.
A: You're welcome!
There will be 4 variants of feature requesting:
A variant for when a user wants to add a specific feature while already checking a recipe, and there are recipes that satisfy all feature requests (i.e. the agent can acknowledge that there are recipes left).
A variant for when a user wants to add a specific filter while already checking a recipe, but there are no recipes left that satisfy all feature requests.
A variant for when there are recipes that satisfy all feature requests; automatically remove all feature requests that are conflicting with the new request(s).
A variant for the case whereby there is no recipe left that satisfies all filters.
Unlike previous patterns, this pattern will be in a rule, where the head is currently filled in as ‘_' for each of the rules (e.g.: ‘pattern(_)’). You will replace this with a proper pattern for each of the four scenario’s specified below. For all feature request pattern variations, the conversation starts with the ‘addFilter’ intent of the user. After the user adds a filter, you should have the agent use the predicate removeConflicts(Params) to remove the conflicting filters. It will look as follows: ‘pattern([a21featureRequest, [user, addFilter], [agent, removeConflicts(Params)], …])', where you will further implement what is in the dotted part for each of the four pattern scenario’s.
Variant 1: a21featureRequest
In variant 1 of a21featureRequest, while already checking a recipe in the confirmation phase, the user wishes to continue filtering or look at other recipes. This particular context is already specified in the rule body, by means of the ‘parent(…)’ command. What you need to do is further fill in the pattern in the head of the rule.
In this variant we assume that some recipes fit the new filter criteria, and the agent can acknowledge that there are recipes left. The agent should use the ‘ackFilter’ predicate (see the specification of this pattern in responses.pl). In this variant, if the user is checking a recipe and wants to look at other recipes, the agent must re-insert a50recipeSelect into its agenda.
Variant 2: a21featureRequest
This variant has the same context (e.g.: parent) as the first one. The user wants to add a specific filter while already checking a recipe, but there are no recipes left that satisfy all feature requests. In other words, after the user adds a filter, the agent removes conflicts and then finds that there are no recipes left. It should then inform the user that there are no recipes left that fit the user’s criteria, using the predefined predicate in responses.pl. Subsequently, it should ask the user to remove a filter with the predicate ‘featureRemovalRequest’. Lastly, since there are no recipes left and the user would already be past the a50recipeSelect step, the selection should go back to this step. How would one do this?
In responses.pl you have to fill in an appropriate phrase in text(featureRemovalRequest, “”).
Variant 3: a21featureRequest
This variant is for when the user is not checking a recipe and there are recipes left that could be filtered. The pattern itself is the same as variant 1, but instead of inserting the a50recipeSelect into its agenda the agent should continue its feature inquiry and ask the user for more filters. This is done with the 'featureInquiry' rules, which you should specify in responses.pl. Note that the response should be different based on the number of recipes left:
if the list of recipes is smaller than 16, your bot should show recipes.
if the list is greater than 890 (the size of the database), the recipes have not been filtered yet.
Variant 4: a21featureRequest
The user is in the a50recipeSelect step and asks for a filter that results in no recipes. This pattern is the same as variant 2, apart from one exception. What should be left out?
Add Comment