Animals

artificial-intelligencernnganmicrosoft-for-beginnerslessonsAImicrosoft-AI-For-Beginnersmachine-learningdeep-learningcomputer-visioncnn2-SymbolicNLP

Implementing an Animal Expert System

An example from AI for Beginners Curriculum.

In this sample, we will implement a simple knowledge-based system to determine an animal based on some physical characteristics. The system can be represented by the following AND-OR tree (this is a part of the whole tree, we can easily add some more rules):

Our own expert systems shell with backward inference

Let's try to define a simple language for knowledge representation based on production rules. We will use Python classes as keywords to define rules. There would be essentially 3 types of classes:

  • Ask represents a question that needs to be asked to the user. It contains the set of possible answers.
  • If represents a rule, and it is just a syntactic sugar to store the content of the rule
  • AND/OR are classes to represent AND/OR branches of the tree. They just store the list of arguments inside. To simplify code, all functionality is defined in the parent class Content
[1]

In our system, working memory would contain the list of facts as attribute-value pairs. The knowledgebase can be defined as one big dictionary that maps actions (new facts that should be inserted into working memory) to conditions, expressed as AND-OR expressions. Also, some facts can be Ask-ed.

[2]

To perform the backward inference, we will define Knowledgebase class. It will contain:

  • Working memory - a dictionary that maps attributes to values
  • Knowledgebase rules in the format as defined above

Two main methods are:

  • get to obtain the value of an attribute, performing inference if necessary. For example, get('color') would get the value of a color slot (it will ask if necessary, and store the value for later usage in the working memory). If we ask get('color:blue'), it will ask for a color, and then return y/n value depending on the color.
  • eval performs the actual inference, i.e. traverses AND/OR tree, evaluates sub-goals, etc.
[3]

Now let's define our animal knowledgebase and perform the consultation. Note that this call will ask you questions. You can answer by typing y/n for yes-no questions, or by specifying number (0..N) for questions with longer multiple-choice answers.

[4]
hair
y/n
sharp teeth
y/n
claws
y/n
forward-looking eyes
y/n
color
0. red-brown
1. black and white
2. other
has hooves
y/n
long neck
y/n
long legs
y/n
pattern
0. dark stripes
1. dark spots
'giraffe'

Using Experta for Forward Inference

In the next example, we will try to implement forward inference using one of the libraries for knowledge representation, Experta. Experta is a library for creating forward inference systems in Python, which is designed to be similar to classical old system CLIPS.

We could have also implemented forward chaining ourselves without many problems, but naive implementations are usually not very efficient. For more effective rule matching a special algorithm Rete is used.

[5]
Collecting git+https://github.com/nilp0inter/experta
  Cloning https://github.com/nilp0inter/experta to /tmp/pip-req-build-7qurtwk3
  Running command git clone --filter=blob:none --quiet https://github.com/nilp0inter/experta /tmp/pip-req-build-7qurtwk3
  Resolved https://github.com/nilp0inter/experta to commit c6d5834b123861f5ae09e7d07027dc98bec58741
  Installing build dependencies ... done
  Getting requirements to build wheel ... done
  Preparing metadata (pyproject.toml) ... done
Requirement already satisfied: frozendict~=2.4.6 in /opt/conda/envs/ai4beg/lib/python3.12/site-packages (from experta==1.9.5.dev1) (2.4.7)
Collecting schema~=0.6.7 (from experta==1.9.5.dev1)
  Downloading schema-0.6.8-py2.py3-none-any.whl.metadata (14 kB)
Downloading schema-0.6.8-py2.py3-none-any.whl (14 kB)
Building wheels for collected packages: experta
  Building wheel for experta (pyproject.toml) ... done
  Created wheel for experta: filename=experta-1.9.5.dev1-py3-none-any.whl size=34804 sha256=888c459512a5e713f4b674caa9a0f96cfdf07ec0d6eb56cc318ce0653d218014
  Stored in directory: /tmp/pip-ephem-wheel-cache-1eeii9zy/wheels/3d/e8/bb/22d7956359603fa8dd679aa09f5b8efb3f29991c3986fdc787
Successfully built experta
Installing collected packages: schema, experta
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 2/2 [experta]
Successfully installed experta-1.9.5.dev1 schema-0.6.8
[13]

We will define our system as a class that subclasses KnowledgeEngine. Each rule is defined by a separate function with @Rule annotation, which specifies when the rule should fire. Inside the rule, we can add new facts using declare function, and adding those facts will result in some more rules being called by forward inference engine.

[14]

Once we have defined a knowledgebase, we populate our working memory with some initial facts, and then call run() method to perform the inference. You can see as a result that new inferred facts are added to the working memory, including the final fact about the animal (if we set up all the initial facts correctly).

[15]
Animal is tiger
FactList([(0, InitialFact()),
,          (1, Fact(color='red-brown')),
,          (2, Fact(pattern='dark stripes')),
,          (3, Fact('sharp teeth')),
,          (4, Fact('claws')),
,          (5, Fact('forward looking eyes')),
,          (6, Fact('gives milk')),
,          (7, Fact('mammal')),
,          (8, Fact('carnivor')),
,          (9, Fact(animal='tiger'))])
[ ]