Versions Compared

Key

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

Dialogflow

Entity for number of ingredients and number of recipe steps

...

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 nrOfSteps. This will make sure the MARBEL agent will receive the filter nrStepsnrOfSteps=8 and store that in the conversational memory.

...

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. We will define a rule for extracting ingredients including their quantities, which will be useful also later again when we revisit and extend the recipe confirmation page; see Visuals section below. Using those rules it will then be easy to compute their number. As the rules for extracting the ingredients and recipe instructions from the database are very similar, we will only guide you through the one for

...

ingredients and leave the other up to you. You should add both rules in the recipe_selection.pl file at the designated locations in that file.

  • Add a Prolog rule for ingredients(RecipeID, IngredientList) that returns the list of ingredients with their quantities for the recipe with identifier RecipeID in the output argument IngredientList:

    1. Find a built-in Prolog predicate

...

    1. that you can use for returning a set of ingredients that match a specific goal (i.e., they are associated with the given recipe

...

    1. RecipeID). Be sure to read the Prolog documentation (check here: SWI-Prolog) to make sure you understand what kind of arguments the predicate expects.

    2. In the recipe_database.pl file, 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’.

  1. 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.

Code Block
nrOfIngredients(RecipeID, N) :-

Create a rule to return N, the length of the list of ingredients for a certain RecipeID.

applyFilter

Code Block
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) :-

  • Value inputs are an atom/string, check utils.pl

...

    1. including the quantities needed. You should use this predicate as the “goal” that the built-in predicate expects as its second argument. Note that we only want to retrieve the ingredients for the recipe with identifier RecipeID. As we are only interested in the IngredientAndQuantity argument, you should abstract away the other argument. You can do this by using the caret ^ operator in Prolog and put the “goal” of the operator inside the template RecipeID^(...).

    2. Those ingredients with their quantities that match the “goal” should be returned as a list in the output argument IngredientList.

  • Add a Prolog rule for steps(RecipeID, StepList) that returns the list of instruction steps for the recipe with identifier RecipeID in the output argument StepList.

Using the rules for ingredients/2 and steps/2, you should now be able to define rules for nrOfIngredients(RecipeID, N) and nrOfSteps(RecipeID, N) that return the number of ingredients and instruction steps, respectively, by computing the length of the list of ingredients and steps.

Applying filters: Number of ingredients and recipe steps

As we did before for ingredient (types) and cuisine, to enable filtering the recipe database for recipes with fewer than a specified number of ingredients, we want to define a rule for (the head) in the recipe_selection.pl file:

Code Block
applyFilter('nrOfIngredients', Value, RecipeIDsIn, RecipeIDsOut)

Here Value is the number specified by the user for the maximal number of ingredients that a recipe should have. To make sure that Value is an integer value, we first apply the convert_to_int/2 predefined predicate in utils.pl. In the body of the rule, use the query convert_to_int(Value, MaxInt) first and than add a findall/3 query similar to the ones that we used before but now for evaluating the condition that the number of ingredients for a recipe are less than MaxInt.

Note

It is very important to make sure that values are of the right type. The values that Dialogflow returns are often atoms or strings. Comparing strings to numbers using the < operator, for example, will result in a Type error in SWI Prolog that will terminate the MARBEL agent.

To avoid such issues, we therefore always need to make sure that values that must be numbers (because they match with @sys.number entity type in Dialogflow) are converted to numbers again in Prolog. There are predicates defined for this purpose in the utils.pl file.

  • Now add a similar rule that applies a filter for the nrOfSteps feature; your Training phrases should dictate how to read the constraint. I.e., if your phrase says “less than N recipe steps” than you should write code that implements the filter to mean exactly that.

Visuals

Extend the recipe confirmation page

...

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.

...