<jupyter_start><jupyter_text>Using Context ItemsContext is a global memory space available to rules to store and retrieve information about items. This is a key concept which allows rules to communicate with each other during processing.Items are a generic term that represents a collection of knowledge about a single thing. A common way to use items is to store information about real-world entities, such as a person, place, or other object. Items can have attributes, and those attributes can be other nested values so that you can store hierarchical information about those items.If you are familiar with Blackboard systems, the Context is the area where all agents can write to and read from.During processing, rules can work together to contribute and add knowledge to items. For example, in a natural language processing system, you may have rules which detect noun phrases. These rules can work together to continually append information into a Context item, similiar to how we build up an image or understanding in our minds when we hear words describing an object.<jupyter_code>import os, sys
sys.path.insert(1, os.path.abspath('..\\..'))
from thoughts.rules_engine import RulesEngine
import pprint

engine = RulesEngine()
pprint.pprint(engine.context.items)<jupyter_output>{}<jupyter_text>Naming ItemsEach item has a name, starting with a "$" character. You can use this name to refer to the item, as well as attributes on the item by using "dot" syntax. For example, you can have an item representing a person, track information about a person, and refer to that information with $person.phone_number.The code below adds an item manually to the Context. This is useful if you want to preload the Context with some information from a database or file. Upcoming sections will show you how to do this within the rules themselves to read and write information during rule processing.<jupyter_code>engine.context.items["$tom"] = {"birthdate": "01/01/2005"}

pprint.pprint(engine.context.items)<jupyter_output>{'$tom': {'birthdate': '01/01/2005'}}<jupyter_text>Storing Simple ValuesThe store command will store an item into the Context, similiar to how variables are stored in memory. Note that we use the term "item" when referring to an item in the Context.Note that the local variable's name starts with "?" and the Context item's name starts with "$". This is to help mentally separate temporary variables from more the persistant items in the Context.<jupyter_code>rule = {
    "#when": "animal",
    "#then": [{ "#store": "dog", "#into": "$animal" }, { "#output": "$animal" }]
}

engine.add_rule(rule)
engine.process("animal")
pprint.pprint(engine.context.items)<jupyter_output>dog
{'$animal': 'dog', '$tom': {'birthdate': '01/01/2005'}}<jupyter_text>Storing Values Passed InYou can also store values that are passed from the when clause to the then clauses.In this example, the ?animal variable is set in the when clause and then used in the then clause to store the value into the $animal Context item.Notice here too that the previous item's value is overrwritten with the new value.<jupyter_code>rule = {
    "#when": "the animal is a ?animal",
    "#then": [{ "#store": "?animal", "#into": "$animal" }, { "#output": "$animal" }]
}

engine.add_rule(rule)
engine.process("the animal is a cat")
pprint.pprint(engine.context.items)<jupyter_output>cat
{'$animal': 'cat', '$tom': {'birthdate': '01/01/2005'}}<jupyter_text>Handling Unknown ValuesIf the local variable is not set in the when clause, then the variable's name will be used.Likewise, if an item is not found in the Context, then the item's name will be used.<jupyter_code>rules = [{
    "#when": "sport",
    "#then": [{ "#output": "?sport" }]
  },
{
    "#when": "tree",
    "#then": [{ "#output": "$tree" }]
}]

engine.add_rules(rules)
engine.process("sport")
engine.process("tree")<jupyter_output>?sport
$tree<jupyter_text>Appending ValuesBy default, the store command will replace the previous value with the new one. You can append the item to the current value by using the append option, which creates a list.<jupyter_code>rule = {
    "#when": "add ?car to the cars list",
    "#then": [{ "#store": "jeep", "#into": "$cars" }, 
             { "#store": "?car", "#append": "$cars" },
             { "#output": "cars are $cars" }]
}

engine.add_rule(rule)
engine.process("add honda to the cars list")
pprint.pprint(engine.context.items)<jupyter_output>cars are ['jeep', 'honda']
{'$animal': 'cat',
 '$cars': ['jeep', 'honda'],
 '$tom': {'birthdate': '01/01/2005'}}<jupyter_text>Appending Values to the BeginningOr, if you need to place the item at the beginning of the sequence, you can do that using the push option.<jupyter_code>rule = {
    "#when": "add ?food to the foods list",
    "#then": [{ "#store": "apple", "#into": "$foods" }, 
             { "#store": "?food", "#push": "$foods" },
             { "#output": "foods are $foods" }]
}

engine.add_rule(rule)
engine.process("add orange to the foods list")
pprint.pprint(engine.context.items)
rules = [

  {"#item": "$dog1", "breed": "havanese"},

  {
    "#when": "doggo",
    "#then": "$dog1.breed"
  },

  {
    "#when": "get dog breed",
    "#then": [
      { "#assert": "doggo", "#into": "?doginfo" },
      { "#output": "?doginfo"}
    ]
  }

]<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.12690355329949238, 'fraction_numerical': 0.008084226358338033, 'mean_word_length': 4.62962962962963, 'pattern_counts': {'":': 40, '<': 23, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '7', 'dir': 'jupyter-structured-clean-dedup', 'id': '469115', 'license': 'MIT', 'n_tokens_mistral': 1619, 'n_tokens_neox': 1549, 'n_words': 647, 'path': 'notebooks/tutorial/030_context.ipynb', 'repo_name': 'hofmanniac/thoughts', 'size': '5319'}