Dialogflow
Entity for number of ingredients and number of recipe steps
While implementing the previous capability we only implemented three features that can be used to filter recipes on. To make our addFilter intent more useful and allow a user to make requests about more recipe features, we need to add more training phrases that can capture what a user wants in Dialogflow. For each type of recipe feature that we want to add, however, we need to also add all of the values of such a feature as entity entries. There is, however, one relatively cheap way to add a new feature that makes use of the system entities of Dialogflow. We can use, for example, the @sys.number
entity for implementing feature requests related to the number of ingredients. For example, you can add phrases like “A recipe with less than 10 ingredients” to cater to users looking for simpler recipes. Remember to annotate the number of ingredients in each phrase with the @sys.number
system entity so Dialogflow can correctly identify and extract this parameter. And, just as important, you should specify a parameter name such as nrOfIngredients for the parameter Dialogflow should extract. Your new entry in the table in the Actions and parameters section should look as follows:
In a similar vein, you can add phrases about the number of recipe steps such as “I’m looking for a recipe with less than 8 steps”. Use a parameter name such as nrSteps. This will make sure the MARBEL agent will receive the filter nrSteps=8
and store that in the conversational memory.
Extracting multipe features from a single user expression
Another way to improve your Dialogflow agent is to enable a user to include multiple requests in a single user expression. You can achieve this simply by including many more phrases such as “I’d like a Chinese recipe with less than 8 ingredients”. This will ensure that your conversational agent can recognize multiple filter requests.
Prolog and Patterns
Retrieving the (number of) ingredients and recipe steps
As before, we will need to do some work to extract information from the database to implement new filters for requests related to the number of ingredients and recipe steps. We will start by implementing Prolog rules to extract the list of ingredients (including their quantities) and the list of recipe instruction steps for a particular recipe from the recipe database. Using those rules it will then be easy to compute their number. As the rules for
Define a rule that returns a list of ingredients
ingredients(RecipeID, IngredientList) :-
Find a built-in Prolog predicate (part of the Prolog language) that you can use for returning a set of ingredients that match a specific goal (i.e. the recipe we are looking at). This predicate should take a list, check elements in the list for compliance with a condition (goal of filtering), then return a list of the elements that comply. When you find the predicate, be sure to read what arguments it takes in the Prolog documentation. You can use Google or look here: SWI-Prolog.
In the database, find the predicate that is used to store ingredient information.
Now that we have found the necessary predicate, we need to define the “goal”, i.e. the condition an ingredient has to fulfill to be added to the set. We only want ingredients for a recipe with a certain RecipeID. We will use the predicate in Step 3(a)(i) to retrieve a set of ingredients (list without repetition). We want to output a list of ingredients ('List') by inputting all available ingredient information ('Information') where the inputted recipe ID ('RecipeID') and Information match with the arguments in a predicate with ingredient information found in the database. Those that match should be returned in a List which is outputted by the rule as ‘IngredientList’.
To simplify the condition, you can use the caret (^) in Prolog by defining your goal/ condition in the set predicate with the following syntax:
RecipeID^(databaseIngredientPredicate(RecipeID, inputted Information variable to be filtered))
TODO: add something about recipe steps here too…
In the recipe_selection.pl
file, you should create a rule to compute the number of ingredients a recipe uses.
nrOfIngredients(RecipeID, N) :-
Create a rule to return N
, the length of the list of ingredients for a certain RecipeID
.
applyFilter
applyFilter(+ParamName, +Value, +RecipeIDs, -FilteredRecipes)
Filters the recipes provided as input using the (Key) feature with associated value and returns the recipes that satisfy the feature as output.
ParamName: A parameter name referring to a feature that the recipes should have (for example: ’cuisine’).
Value: The associated value of the recipe feature (for example: ‘Chinese’).
RecipeIDs: The recipes that need to be filtered.
FilteredRecipes: The recipes that have the required feature.
Thus, you must find all recipes that fit the filter criteria and return a list of the filtered recipes. Make sure to use the naming conventions for the variables that we provided. The head of the rule can be found below.
Predicate to filter recipes on a maximum number of ingredients | applyFilter('nrOfIngredients', Value, RecipeIDsIn, RecipeIDsOut) :- |
|
Retrieving ingredients and recipe instructions from the recipe database
Visuals
Extend the recipe confirmation page
The initial version of the recipe confirmation page that we created for Capability 2: Request a Recommendation should be extended now and also show the recipe instruction and ingredient details. Use the Prolog rules you created for recipeSteps(RecipeID, StepsList)
and ingredients(RecipeID, IngredientList)
to retrieve these from the recipe database. Then add these to two new cards that you add to the page for showing these recipe details.
Retrieve the following information by putting the appropriate predicates in the places indicated in the rule by comments and by using the variable names indicated below.
We need to retrieve the chosen recipe from memory. Find the necessary predicate and name that variable ‘Recipe’.
The previous step retrieves the Recipe ID, but we also need the recipe name. Use a variable called ‘Name’ for this.
Retrieve the time needed to complete the recipe in a variable named ‘Minutes’.
Retrieve the number of servings in a variable called ‘Persons’.
To retrieve a list of the recipe steps and a list of ingredients, you will need two additional predicates in
recipe_selection.pl
.The first of the two predicates is a rule that returns a list of ingredients
ingredients(RecipeID, IngredientList) :-
Implement a rule in
recipe_selection.pl
calledrecipeSteps(RecipeID, StepsList) :-
to retrieve a list of the recipe steps without changing their order. There is no repetition, so this predicate does not need to remove duplicates. Your rule for retrieving the steps needs to use the accompanying rule given belowgetStepString
in your goal of the built-in Prolog predicate, so your goal should look as follows:RecipeID^getStepString(RecipeID, Step)
.getStepString(RecipeID, String) :- step(RecipeID, NrStep, StepSentence), to_upper_case(StepSentence, StepSentenceUpper), atomic_list_concat(['Step ', NrStep, ': ', StepSentenceUpper], String). %, '.'
Go back to
html.pl
and toa50recipeConfirm
Save the recipe steps as ‘Steps’
Save the list of ingredients as ‘Ingredients’
Ask for recipes with 5 ingredients and see if you receive the following answer.
Extend
Extend your agent to be able to filter by the maximum number of steps in a recipe, recipe duration, and number of servings in a recipe. The process is quite similar to that of the filtering by maximum number of ingredients.
Test it Out
Check if the recipe on the a50 recipe confirm page fulfills the criteria you chose for the number of steps, number of servings, and duration. Make sure all 3 filters work.