Table of Contents | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
Dialogflow
Ingredient (type) and cuisine entities
We now want to move on to providing our recipe recommendation agent with some more serious capabilities for filtering the recipe database in search of a recipe that meets the features that the user has requested. We will begin with developing a capability for filtering recipes in the database using an ingredient or ingredient type. The idea is that a user then can indicate to the agent that they would like to cook a recipe which uses carrots, fish, or something else as ingredient. Before you can create an intent to match user expressions such as “do you have recipes that use fish as ingredient”, you have to create ingredient entities. These entities are needed to be able to specify which parts of these user expressions should be extracted as ingredient (type) entity entries. This is done as part of the intent specification, and the presence of an entity type is used as a feature by the Dialogflow classifier model to recognize intents.
We begin with the creation of an @ingredientType entity in your Dialogflow agent. The idea behind introducing this entity is that a user may often want to ask for a specific type of ingredient such as cheese (or, e.g., meat, beef, fruit) instead of a specific instance such as taleggio, a kind of cheese from the Lombardy in Italy. For example, a user could say something like “I’d like to cook something with cheese”. We have precompiled a list of ingredient types for you that you can upload as a CSV file to your Dialogflow agent. For more information on how to upload and create entities in Dialogflow, please read the Dialogflow: Creating Intents and Entities page. Create the @ingredientType entity using the following CSV file:
View file | ||
---|---|---|
|
The CSV file for the ingredientType
entity consists of more ingredient types than the recipe database currently supports.
A more challenging entity to create is the @ingredient entity that consists of all ingredients that are used in the recipe database. You should extract all of these ingredients from the recipe_database.pl
file. You should be able to find them and automatically extract them by matching with the ingredient(..., <ingredient name>)
. In other words, using some clever data parsing techniques that you apply to the recipe_database.pl
file. Create a CSV file with all the ingredients that you extract from the database that you name ingredient and upload this file to your Dialogflow agent to create an @ingredient entity.
Note |
---|
Note that by extracting ingredients only from the recipe database, your Dialogflow agent will only be able to recognize ingredients that appear in that database. If a user would ask for an ingredient that is not in the database, this means the agent will not be able to understand the user! To deal with that issue, you might want to add more ingredients from elsewhere. One place to get more ingredients from is here. |
Finally, to be able to filter on cuisine extend your Dialogflow agent an @cuisine entity. Here is a CSV file you can use to upload the @cuisine entity into your Dialogflow agent:
View file | ||
---|---|---|
|
Note |
---|
A similar issue as for the ingredients also applies to the @cuisine entity. Only some countries are included, while others are not. To address that issue, you might want to think about a solution that uses the @sys.geo-country entity of Dialogflow instead of the csv file. |
Request for recipe features intent
The intent that allows a user to ask for specific recipe features is one of the most important intents for our recipe recommendation agent. The agent will use these features for filtering recipes to narrow down the choices that a user still has from the remaining recipes from the database. These features will include a variety of criteria, such as specifying an ingredient (type) that is used in the recipe. As we will use the features that a user will ask for as filters on the recipe database, we will name the intent addFilter. Its main purpose is to add filters of the form featureName=featureInstance
, for example, ingredient=taleggio
.
Go to the Dialogflow Console and create a new intent. Name the intent addFilter to indicate its purpose of filtering recipes based on user preferences.
Add Training Phrases: Add a large variety of phrases that users might say when they want to filter recipes by ingredient, ingredient type or cuisine, such as "I want my recipe to include taleggio" or "Something with garlic" or “Do you have something with cheese?” or “I’d like a recipe from Japan”. We recommend adding many training phrases as there are infinitely many variations of asking for some recipe feature. You should try to cover as many of those as possible to ensure broad coverage, but you do not need to craft them by hand…. You can use any tool you can think of to create as many training phrases as possible.
Note that when you add these phrases, Dialogflow will automatically detect entities like @ingredient. If it does not do that, select the ingredient word(s) and manually tag it with these as an @ingredient entity.Don’t forget to make sure the box above the table in the Action and parameters section is filled in with the name of your intent! If this is not already the case, link the ingredient parameter in this section to the @ingredient entity. Make sure that the parameter name is exactly as expected. Do the same for the @ingredientType entity. For both of these parameters, also check the box in the IS LIST column. This should look like:
...
Note |
---|
Don’t forget to press SAVE! |
Info |
---|
Checking the box in the IS LIST column enables Dialogflow to extract multiple ingredients from a user request and return a list of these ingredients. Your Dialogflow agent then will be able to extract all ingredients from an expression such as “Something with peas, onion and cheese please”. Note that we did not check the box in the REQUIRED column as a user does not have to mention an ingredient but could also provide other recipe features for selecting a recipe. |
...
|
Prolog and Patterns
We need to refine our logic now for retrieving only those recipes that satisfy specific filters. We already introduced a recipeFiltered/3
predicate for Capability 2: Request a Recommendation https://socialrobotics.atlassian.net/wiki/pages/createpage.action?spaceKey=PM2&title=2025%20Capability%202%3A%20Request%20a%20Recommendation but there it did not have to do any serious work yet. We only introduced the base case without any filters (an empty list of filters) but now need to deal with the case where we have some filters that a user provided. The basic idea to define a recursive clause for recipeFiltered/3
is simple: apply the first filter in the list to the recipes and recursively filter the remaining recipes using the remaining filters. We provide you below with the recursive clause that you should add below the base clause that we added earlier in the recipe_selection.pl
file:
...
Let’s inspect this interaction in more detail and analyse how it is organized. In Moore and Arar’s taxonomy, the parts of the dialog in this example where the user adds a feature request in the second and fourth move can be classified as Pattern A2.1: Open Request. We will use the a21featureRequest
label for this pattern and define different variants of it below. The agent initiates with an inquiry about what the user is looking for. This move is part of the a50recipeSelect
pattern, a top level pattern that we added to the agent’s agenda. We previously defined variants for that pattern for Capability 2: Request a Recommendation and Capability 3: Select Recipes by Namefor that pattern for https://socialrobotics.atlassian.net/wiki/pages/createpage.action?spaceKey=PM2&title=2025%20Capability%202%3A%20Request%20a%20Recommendation and https://socialrobotics.atlassian.net/wiki/pages/createpage.action?spaceKey=PM2&title=2025%20Capability%203%3A%20Select%20Recipes%20by%20Name. The user responds by informing the agent that they are interested in a particular cuisine (Japanese). This is a feature request that we want the agent to manage by means of a new a21featureRequest
pattern. The idea is that this pattern is inserted while the user and agent are still performing the top level a50recipeSelect
pattern. The a21featureRequest
pattern is inserted as a subdialog, which we indicated in the example above by adding indentation. The response of the agent is an acknowledgement move combined with a renewal of the question whether the user wants to add any other feature. We’ll take it that this move is also part of the a21featureRequest
pattern and ends this pattern. The fourth user move (a second feature request for the an ingredient type pasta) and the fifth agent move repeats the same a21featureRequest
pattern. The interaction concludes with a move of the user mentioning a specific recipe title (Teriyaki salmon). That last move and the agent move following it are both part of the a50recipeSelect
pattern we specified for Capability 3: Select Recipes by Name https://socialrobotics.atlassian.net/wiki/pages/createpage.action?spaceKey=PM2&title=2025%20Capability%203%3A%20Select%20Recipes%20by%20Name. That pattern added the a50recipeConfirm
pattern into the current session of the agent. This pattern asks the user to check the recipe (while showing all relevant details). You still need to add this pattern to implement the capability we are working on right now below.
...
Concluding, either way, when a user makes a feature request, we make a design choice to move the conversation to go back to (option 1) or stay (option 2) in the recipe selection stage (i.e., the a50recipeSelect
top level context). Implicitly, we are also saying here that making a feature request dialog move is an out of context intent (see Capability 4: Handling Unexpected Intents https://socialrobotics.atlassian.net/wiki/pages/createpage.action?spaceKey=PM2&title=2025%20Capability%204%3A%20Handling%20Unexpected%20Intents) when the conversation is neither in the recipe selection nor confirmation stage.
...
First, we want the pattern to be available only when either the
a50recipeSelect
or thea50recipeConfirm
is the top level pattern. We should add this as a condition to the rule defining the pattern similar to how we added the agent name condition to the greeting pattern (see Capability 1: Greet, and Self https://socialrobotics.atlassian.net/wiki/pages/createpage.action?spaceKey=PM2&title=2025%20Capability%201%3A%20Greet%2C%20and%20Self-Identify).Second, we want to remove any conflicting feature requests. You can use the special action
removeConflicts(Params)
and insert it in the pattern as a move of the agent. This action is defined in thedialog_update.mod2g
file; check it out to better understand what happens. Of course, we need to collect the parametersParams
somehow to tell the agent which feature requests (called parameters here) should be checked for conflicts. Use thegetParamsPatternInitiatingIntent(user, addFilter, Params)
query for this and add it to the condition of each of the rules you implement for thea21featureRequest
pattern variants. The predicate is defined in thedialog.pl
file; check it out to better understand how it works.Third, we need agent intent labels for the two cases that we can end up: we suggest using
ackFilter
for acknowledging there are still recipes that meet all requests, andnoRecipesLeft
when there are no recipes left. The logic that we need to implement to make these moves work differently will be implemented in theresponses.pl
file below.
...
For the featureRemovalRequest
intent, you should add a simple text/2
fact. Use as response text, for example, "Can you have a look again and remove one of your recipe requirements?".
Visuals
We want to differentiate what we show to a user depending on the number of recipes that still meet the user’s requests. The basic idea is that we should not show a large number of recipes to a user but we can show recipe details when the number of remaining recipes becomes sufficiently small (we chose <16, see also above). As a consequence, we want to create two different versions of the a50recipeSelect
page that we created for Capability 2: Request a Recommendation https://socialrobotics.atlassian.net/wiki/pages/createpage.action?spaceKey=PM2&title=2025%20Capability%202%3A%20Request%20a%20Recommendation: one that just shows the feature requests made when there are more than 15 recipes that meet these requests, and another for when there are less that 16 which shows the recipe details (titles and pictures) for all of the remaining recipes.
...
You should also add more information to this first a50recipeSelect
page. The main requirement is that the page shows all the user’s feature requests or filters. You can collect these from the agent’s memory and use the predicate filters_to_strings/1
for this that has already been defined in the dialogflow.pl
file. For styling the layout of the page, use rules defined in the html.pl
file or add new ones (see also the 2025 Visual Support Guide).
Add a second recipe recommendation page
...
Continue with changing the layout. The main requirement is that an overview of the remaining recipe titles and pictures should be shown. Check out https://www.w3schools.com/bootstrap4/bootstrap_cards.asp and how we already used a card for the recipe confirmation page for Capability 2: Request a Recommendation https://socialrobotics.atlassian.net/wiki/pages/createpage.action?spaceKey=PM2&title=2025%20Capability%202%3A%20Request%20a%20Recommendation.
Your final page should look something like this (just an example, you should be able to easily improve!).
...
Info |
---|
All done? |