Versions Compared

Key

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

The next thing we want to add is the capability to filter on dietary restrictions. This will require extensions to your Dialogflow agent for NLU but also require the implementation of new logic in Prolog for filtering the recipe database on these restrictions.

Dialogflow

As a first step, use the following CSV file to upload the dietaryRestiction entity:

View file
namedietaryRestriction.csv
.

...

To make your Dialogflow agent extract this entity, you again need to add more training phrases, and annotate these phrases for the dietaryRestrction entity, and extend the addFilter intent with these phrases. You can use the test console of your agent to verify that it is able to recognize addFilter intents with dietary restrictions and extract the entity entries you just added.

Prolog and Patterns

In the previous capabilities that we implemented for filtering the recipe database, we often could simply use the facts that are part of that database to implement the filtering process (the applyFilter/4 rules). For example, for Capability 5: Filter Recipes by Ingredients and Cuisine we could use the ingredient/2 and cuisine/2 facts, and for Capability 6: Filter by Number of Ingredients & Recipe Steps, we could use time/2 for the cooking duration of a recipe and servings/2 for the number of servings. For computing the number of ingredients and recipe instructions steps, we had to do a bit more work, but these could also be computed quite straightforwardly from these basic facts.

We have only seen one other example so far of a feature request that could not be implemented by “simply” using basic facts from the recipe database: the ingredient type for Capability 5: Filter Recipes by Ingredients and Cuisine. We used the typeIngredient/2 facts in the ingredient_hierarchies.pl file to implement a filter for ingredient type. When you inspect the recipe_database.pl file, you will see that there are also no facts in the database that suggest that a recipe is vegan or spicy, for example (two restrictions that are included in the dietaryRestrction entity in the Dialogflow agent). As for the ingredientType entity, we need to add some logic to enable the agent to conclude from the basic knowledge stored in the database about a recipe that is satisfies a dietary restriction. We will use the typeIngredient/2 predicate for this too, again.

Filtering on dietary restrictions

First, begin by adding some supporting predicates to the recipe_selection.pl file.

diet

Code Block
diet(RecipeID, DietaryRestriction) :-

In the diet rule, we need to find all the ingredients that a certain recipe has and then input them into a new function we shall create below diet, called ‘ingredientsMeetDiet’. diet should work if the list of ingredients of the inputted RecipeID fits the dietary restriction inputted DietaryRestriction.The basic idea to implement the logic for checking a dietary restriction is to check whether each ingredient of a recipe meets that dietary restriction. It is clear, for example, that a recipe that uses chicken, is not a vegetarian recipe. The reasoning is simple: Vegetarians do not eat any kind of meat, chicken is a kind of meat, so any recipe that uses chicken is not a vegetarian recipe. If we can retrieve this information about chicken somehow, then we can implement this logic for our agent too. When you inspect the ingredient_hierarchies.pl file, you will see that it includes facts that say exactly that. We find, for example, typeIngredient('chicken drumsticks', 'meat'). We can use these facts to conclude that various kinds of chicken and other ingredients are meat. There are no facts, however, to conclude that an ingredient fits in a vegetarian or vegan diet. Instead, you will find facts indicating that certain ingredients are non-vegetarian and non-vegan. Of course, assuming that these lists of facts are complete (we give no guarantees, you might want to check that), we can then also conclude that all ingredients that are not explicitly listed as non-vegetarian should be vegetarian. Let’s first add some rules that implement this logic so that the agent can conclude that an ingredient is vegetarian, too. In the ingredient_hierarchies.pl file, at the designated location, add, for example:

Code Block
typeIngredient(Ingredient, 'vegetarian') :-
	not(typeIngredient(Ingredient, 'non-vegetarian')), !.

Also add rules for the pescatarian and vegan dietary restriction. That enables our agent to handle at least three of the six dietary restrictions that we added to the dietaryRestriction entity of the Dialogflow agent. We will get back to the other three later. For now, you should assume that we can use the predicate typeIngredient/2 to check if an ingredient meets a dietary restriction. We want to implement a rule now that checks that all the ingredients in a list meet a dietary restriction, such as 'meat' or 'vegan'. You should implement an ingredientsMeetDiet/2 predicate in the recipe_selection.pl file that for any given list of ingredients checks that each one of these ingredients meets a dietary restriction. In other words, write code for the body of the recursive clause for the following rule:

Code Block
ingredientsMeetDiet([ Ingredient | Rest ], DietaryRestriction) :-

The ingredientsMeetDiet predicate should take a list of ingredients and check if each one Of course, you will also need to add a base clause for this predicate with the empty list as first argument. Should this base clause succeed or fail for a dietary restriction?

Next, we introduce one more helper predicate to check that a recipe meets a dietary restriction. It has a stop clause that is in the file already and will recursively check each ingredient and return ‘false’ when an ingredient does not meet the given dietary restriction. The predicate ‘typeIngredient’ can be used to check if an ingredient meets a dietary restriction. Fill in the body of the rule for ingredientsMeetDiet. 

Make an applyFilter function for it

...

Predicate to filter recipes that meet the dietary restrictions (such as ‘vegan’).

The idea is to find all the ingredients of a certain recipe with identifier RecipeID and feed the resulting list in the ingredientsMeetDiet/2 predicate that we just defined to check that all these ingredients satisfy a DietaryRestriction. In the recipe_selection.pl file, add code for the body of the following rule:

Code Block
diet(RecipeID, DietaryRestriction) :-

Finally, using the diet/2 predicate, we can define a rule for applying a dietary restriction filter. You are asked to define applyFilter('dietaryrestriction', Value, RecipeIDsIn, RecipeIDsOut)

...

  • This rule should filter recipes based on their membership to dietary restriction. To check if a recipe is a member of a dietary restriction you can use the built-in Prolog member/2 predicate.

  • (member(Recipe, List of Recipes),

  • diet(Recipe, Dietary Restriction))

, similar to how rules for other filters have been defined.

Extending the logic of ingredient hierarchies

Add the following predicate above hasIngredient in ingredient_hierarchies.pl file.

Code Block
typeIngredient(Ingredient, 'vegan') :-
	not(typeIngredient(Ingredient, 'non-vegan')), !.

Add to the ingredient hierarchy by adding ingredient type functions and type ingredient lists to include vegetarian, lactose-free, gluten-free, and pescatarian dietary restrictions

Here is an example of a typeIngredient ruleAs we mentioned above, there is still information missing to implement the logic for all dietary restrictions, and also for food categories (you were already asked to add the pasta food category, but what about noodles, for example?). For the dietary restrictions, you should add typeIngredient/2 facts that can facilitate the processing of filters for lactose-free (no dairy), gluten-free (no gluten), and spicy recipes. For all three, use a simple approach that only looks at the individual ingredients that are used in a recipe. That is, for a lactose-free recipe, no dairy products should be used; for a gluten-free recipe, no products with gluten should be used; and, for a spicy recipe, the recipe should have (at least) one ingredient that is spicy (the hasIngredient/2 predicate should come to mind here). As before, we can use one fact to deduce the other, and, deduce, for example, that if an ingredient has no gluten it must be gluten-free. We can define such relations using the same type of rule as we have seen above:

Code Block
typeIngredient(Ingredient, 'gluten-free') :-
	not(typeIngredient(Ingredient, 'gluten')), !.

Here is This rule, however, still assumes that the typeIngredient(Ingredient, ‘gluten') facts are given somehow. We provide an example of the type of ingredient lists what that should look like for the 'gluten' facts:

Expand
titletypeIngredient(Ingredient, 'gluten').

typeIngredient('barley squashes', 'gluten').
typeIngredient('beer', 'gluten').
typeIngredient('lager', 'gluten').
typeIngredient('stout', 'gluten').
typeIngredient('stout', 'gluten').
typeIngredient('barley', 'gluten').
typeIngredient('couscous', 'gluten').
typeIngredient('bulgar wheat', 'gluten').
typeIngredient('dinkel', 'gluten').
typeIngredient('einkorn', 'gluten').
typeIngredient('emmer wheat', 'gluten').
typeIngredient('farro', 'gluten').
typeIngredient('freekeh', 'gluten').
typeIngredient('khorasan wheat', 'gluten').
typeIngredient('pearl barley', 'gluten').
typeIngredient('rye', 'gluten').
typeIngredient('semolina', 'gluten').
typeIngredient('spelt', 'gluten').
typeIngredient('triticale', 'gluten').
typeIngredient('wheat', 'gluten').
typeIngredient('wheat flour', 'gluten').
typeIngredient('rye flour', 'gluten').
typeIngredient('barley flour', 'gluten').
typeIngredient('plain flour', 'gluten').
typeIngredient('self raising flour', 'gluten').
typeIngredient('flour', 'gluten').
typeIngredient('oats', 'gluten').
typeIngredient('oat milk', 'gluten').
typeIngredient('biscuits', 'gluten').
typeIngredient('bread', 'gluten').
typeIngredient('cake', 'gluten').
typeIngredient('chapattis', 'gluten').
typeIngredient('crackers', 'gluten').
typeIngredient('muffins', 'gluten').
typeIngredient('pastry', 'gluten').
typeIngredient('pizza', 'gluten').
typeIngredient('muesli', 'gluten').
typeIngredient('pasta', 'gluten').
typeIngredient('noodles', 'gluten').
typeIngredient('batter', 'gluten').
typeIngredient('soy sauce', 'gluten').
typeIngredient('liquorice', 'gluten').
typeIngredient('bread crumbs', 'gluten').

For the lactose-free and spicy features, you should add the relevant facts. We recommend using automated approaches to compile these lists.

Visuals

Nothing we ask you to do here for this capability. It’s up to youinformation that you can find online and tools to automate your approach to compiling these lists.

Even though some of the recipe features that we have looked at require careful analysis, those that require more work than simply inspecting basic facts in the recipe database were all based on reasoning about individual ingredients. That is, we verified whether an ingredient is of a particular type, either a type of food or a type of dietary restriction. If you like a challenge, you can also consider other recipe features that consider more global features of a recipe, such as a recipe being low-carb or cheap. How would you define the logic for such filters? What kind of information would you need to add to the database to be able to define features like these?

Visuals

You can update the visuals based on what you think will help the user the most. Think about how you can support the implemented capability visually.

Test it Out

Try to ask your conversational agent to add dietary restrictions for, for example, vegan recipes. Try various types of restrictions to see how that works. What can you say about how consistent the logic that is defined for these restrictions is? You may want to think about how to improve that (and, if you have any ideas that you did not implement, reflect on that in your report, for example).

Info

All done?

Proceed with https://socialrobotics.atlassian.net/wiki/spaces/PM2/pages/2216001572/Designing+and+Developing+Your+Agent#Agent-Capability-8%3A-Filter-Recipes-by-Exclusion-Recipe-Categorical-CharacteristicExcluding-Features