AI Zone Admin Forum Add your forum
Simple ‘Expert System’ chatbot, just for fun
 
 

When I owned my first Apple ][ computer back in 1985, it came with a little program called Animals.  Just for fun this evening I rewrote it in Perl in a couple of hours… Here is a log of my conversation with it…

Basically, you think of an animal, and it tries to determine what it is.

If it fails, it learns the new animal by asking for information about it in the form of a simple Yes/No question.

does it live in the water? (y/n) : n
Ok, is the animal a moose? (y/n): n
Ok, I give up, what animal was it? dog

Ok, now please enter a question that would differentiate between ‘dog’ and ‘moose’: are they domesticated
And the correct answer to this question for ‘dog’? y
Thank you for teaching me about a new animal.

Another game? (y/n): y

does it live in the water? (y/n) : n
are they domesticated? (y/n) : y
Ok, is the animal a dog? (y/n): y
Sweet, I got it, I am so smart

Another game? (y/n): y
does it live in the water? (y/n) : n
are they domesticated? (y/n) : n
Ok, is the animal a moose? (y/n): n
Ok, I give up, what animal was it? spider

Ok, now please enter a question that would differentiate between ‘spider’ and ‘moose’: do people kill them by stepping on them
And the correct answer to this question for ‘spider’? y
Thank you for teaching me about a new animal.

Another game? (y/n): y

does it live in the water? (y/n) : n
are they domesticated? (y/n) : n
do people kill them by stepping on them? (y/n) : y
Ok, is the animal a spider? (y/n): y
Sweet, I got it, I am so smart

Another game? (y/n): y
does it live in the water? (y/n) : n
are they domesticated? (y/n) : n
do people kill them by stepping on them? (y/n) : n
Ok, is the animal a moose? (y/n): n
Ok, I give up, what animal was it? bear

Ok, now please enter a question that would differentiate between ‘bear’ and ‘moose’: does it have horns
And the correct answer to this question for ‘bear’? n
Thank you for teaching me about a new animal.

Another game? (y/n): y

does it live in the water? (y/n) : n
are they domesticated? (y/n) : n
do people kill them by stepping on them? (y/n) : n
does it have horns? (y/n) : y
Ok, is the animal a moose? (y/n): y
Sweet, I got it, I am so smart

————————————————————————————————————————-

Just for fun, the kids like it smile

Only 156 lines of Perl ....

my $another_game 1;
while(
$another_game)
{
    
if(!open(F,"<database")) print "can't open database.\n"; exit(1); }
    my 
@= <F>; close(F);
    
my $newrec 0;

    
my %= ();
    
my %= ();
    
my @= ();

    foreach 
my $L (@l)
    
{
        chomp
($L);
        
my ($rn,$str) = split(/=/,$L);
        
next unless($str);
        
$str =~ s/^\s*(.*?)\s*$/$1/;
        if(
$rn $newrec{ $newrec $rn}

        
if($str =~ m/a\((.*?)\)$/)
        
{
            $A{$rn} 
= $1;
        
}

        
if($str =~ m/q\((.*?)\):\s*(\d+),(\d+)$/)
        
{
            my $q_str 
= $1my $yes = $2my $no = $3;
            
$Q{$rn}{'qtxt'$q_str;    
            
$Q{$rn}{'yes'$yes;    
            
$Q{$rn}{'no'$no;    
        
}
    }

    my $cr 
1;
    
$newrec++;
    
my $asking 1;
    
my $next 0;
    while(
$asking)
    
{
        my $qtxt 
$Q{$cr}{'qtxt'};
        
my $r '';
        
my $yon 0;
        while(
$yon==0)
        
{
            $cmd 
"espeak -s 120 \"$qtxt\"";
            
#`$cmd`;
            
print $qtxt."? (y/n) : "
            
$r = <STDIN>;
            
chomp($r);
            
$r =~ tr/a-z/A-Z/;
            if(
$r eq 'Y'{ $yon 1}
            
if($r eq 'N'{ $yon 1}
        }

        $next 
0;
        if(
$r eq 'Y')
        
{
            $next 
$Q{$cr}{'yes'};
        
}    
        
else
        
{
            $next 
$Q{$cr}{'no'};
        
}

        
if($Q{$next})
        
{
            $cr 
$next
            
next;
        
}
        
        $asking 
0;
        
    
}
    
if($A{$next})
    
{    
        my $r 
''my $yon 0;
        
$cmd "espeak -s 120 \"Okis the animal a ".$A{$next}."?\"";
        
#`$cmd`;
        
print "Ok, is the animal a ".$A{$next}."? (y/n): ";
        
        while(
$yon==0)
        
{
            $r 
= <STDIN>;
            
chomp($r);
            
$r =~ tr/a-z/A-Z/;
            if(
$r eq 'Y'{ $yon 1}
            
if($r eq 'N'{ $yon 1}
        }
        
if($r eq 'Y')
        
{
            
print "Sweet, I got it, I am so smart\n";
            
#`espeak -s 120 \"Sweet I got it, I am so smart\"`;
            
print "\nAnother game? (y/n): "my $r = <STDIN>;
            
chomp($r);
            if(
$r eq 'n'{ $another_game 0}
            
if($r eq 'y'{ $another_game 1}
        }
        
if($r eq 'N')
        
{
            
print "Ok, I give up, what animal was it? "my $r = <STDIN>; chomp($r);
            
#$cmd = "espeak -s 120 \"Ok, now please enter a question that would differentiate between '$r' and '".$A{$next}."'\""; 
            #`$cmd`;
            
print "\nOk, now please enter a question that would differentiate between '$r' and '".$A{$next}."': "my $newq = <STDIN>;
            
chomp($newq);
            print 
"And the correct answer to this question for '".$r."'? "my $newa = <STDIN>; chomp($newa);
            
my $wrongan $A{$next};
            
my %newlines = ();
            
my $newrec2 $newrec 1;
            
$newa =~ tr/a-z/A-Z/;
            if(
$newa eq 'Y')
            
{    
                $newlines{$next} 
"$next=q(".$newq."):$newrec,$newrec2";
            
}    
            
else
            
{
                $newlines{$next} 
"$next=q(".$newq."):$newrec2,$newrec";
            
}
            $newlines{$newrec} 
"$newrec=a(".$r.")";
            
$newlines{$newrec2} "$newrec2=a(".$wrongan.")";
            
            if(!
open(F,">database")) print "can't write to database\n"next}            
            
foreach my $T (@l)    
            
{
                chomp
($T);
                
my ($rn,$str) = split(/=/,$T);
                if(
$newlines{$rn})
                
{
                    
print F $newlines{$rn}."\n";
                    
delete $newlines{$rn};
                
}
                
else
                
{
                    
print F $T."\n";
                
}
            }
            
foreach my $str (keys %newlines)
            
{
                
print F $newlines{$str}."\n";
            
}
            
print "Thank you for teaching me about a new animal.\n";
            
close(F);    
            print 
"\nAnother game? (y/n): "my $r = <STDIN>;
            
chomp($r);
            if(
$r eq 'n'exit; }
            
print "\n";
        
}
    }

The lines with “espeak” are commented out… I wrote this on my Ubuntu linux box, and ‘espeak’ is a speech synthesis program on it.

 

 
  [ # 1 ]

That’s cool, Victor! I’ll have to use the code to do a PHP port, and post it as a web page sometime soon. smile

 

 
  [ # 2 ]

Sure, please do.

Can you put sound (voice synthesis ) into it ?  You’d probably need a java applet or activeX control for that I would imagine, or perhaps HTML 5.0 has that support? I haven’t even looked much at HTML 5 yet.

create a file called ‘database’ in same directory as the script.. fill it with the following..

——————————————-

1=q(does it live in the water): 2,3
2=a(frog)
3=a(moose)
——————————————-


as you can see, it starts off by knowing only 2 animals :
            it knows a frog lives in the water, and a moose does not.

as you teach it more animals, it updates the database file.

 

 
  [ # 3 ]

When I do this project, I’ll most likely use the tools that I know best, which means using a mySQL database to store the animals in one table, and the questions that it learns to ask in another, with a third table to house the correlations. This, for me, would be far easier than trying to work out how to sift through text-based data files to derive which animals have which known attributes. Quite possibly, the table structure would look like this:

"Questions Table:"

QID  Question
1      Does it live in water
2      Does it fly
3      Does it have antlers
4      Does it live in the ocean


"Animal Table:"

AID   Animal    QID
1       Moose     3
2       Frog        1
3       Eagle       2
4       Shark      1
4


"Correlation Table:"

ID    QID    AID
1      1        2
4
2      2        3
3      3        1
4      4        4 

As for creating a TTS interface, I’ll have to find a flash interface that’s universal, since most browsers don’t use ActiveX, and like you, I haven’t explored HTML5 yet.

 

 
  [ # 4 ]

Yes, agreed, a database is much better for this, and I like mySQL, its a great free db engine.    When I wrote it, I wanted to, just for fun, see how fast I could do it lol.

I wonder, though, if you need 3 tables. 

How about :

ID   TYPE   TEXT                     YES_REF   NO_REF
——————————————————————————————————
1     Q     Does it live in the water       2         3
2     Q     Does it have legs             4         5          
3     A     Moose                       NULL       NULL
4     A     Shark                       NULL       NULL
5     A     Frog                         NULL       NULL

Those NULLs will get filled in when that record (Answer record) gets replaced by a question.

Just a suggestion, but your design is also good.
I look forward to teaching your simple ‘Yes/No Expert System’ !!

Another cool thing would be, ability to enter an animal and it would give you all the information it knows about that animal.  “What do you know about frogs?”  It would be the list of each question that relates to that animal with its Yes or No value.

Also, it could answer “What does a frog and shark have in common?”—> answer, both live in the water.  Or, “What are some differences between a frog and a shark?”—answer, frog has legs!

One thing I forgot to add, which I will add later, is , right after it learns a new animal it could say:  “Thanks, Now I know about <n> animals!”

 

 
  [ # 5 ]

I’d go so far as merging the question and correlation tables, but I would have to insist on keeping the questions an “answers” (animals) in separate tables. After all, it must be remembered that every exercise or project I work on is also designed to expand my knowledge, so I’ll want to work on “one to many”, and “many to one” relationships, and how to use them. smile Call me silly, but this is how I learn best.

 

 
  [ # 6 ]

I see, sure, if that is also part of the objective, then forsure make it 2 tables.  You can verify that your JOIN types are good then.  Cool, I look forward to seeing it online!

 

 
  [ # 7 ]

I’m with Victor on this one. Code that has to be read by others (i.e. any open source or commercial quality software) should have plenty of white space. Good layout is important for guiding the eye through the flow of the program.

I also try to avoid using abbreviations wherever possible, as the extra brain power (or time spent leafing through the company’s style manual, if there is one) that’s needed to decode all but the most common abbreviations can be a hindrance too.

If either of these practices would cause problems, it means your coders’ computer screens are too small. wink

 

 
  [ # 8 ]

I’ve heard Perl described as the “Swiss Army” chainsaw of the internet.

You can use it to massacre any given problem in ten different ways. raspberry

At the risk of painting a target on my head, I put it to you that “Perl Best Practice” is to avoid using Perl altogether.

 

 
  [ # 9 ]

This thread could do for a re-railing raspberry

I like the idea of for this ‘expert system’. It allows non-programmers to teach the system and have fun with it at the same time. Reminds me a lot of that “twenty questions” game that became popular online and was quickly bought by a toy manufacturer (http://www.20q.net/). I can see this program being extended to other objects besides animals in a similar way.

 

 
  [ # 10 ]

CR - I just wonder, if it would help to locate documents.  We have a huge, and I mean HUGE fileshare at work here with 100,000’s of docs, I wonder if this little wizard could ask the user a series of logical questions to find the doc. . .  it’s worth at least a ‘thought’ experiment !

20 questions could differentiate over one million different docs!

 

 
  [ # 11 ]

I think that would depend a lot on the contents of the documents (how subtly they differ in subject and scope) and how the types of questions were chosen. I imagine incorporating your method of letting users input a question that could be used in the future to distinguish a document from others would be very useful and allow the program to grow organically and with less oversight.

 

 
  [ # 12 ]

Last weekend my nephew was over for the weekend and I showed him the animals algorithm and just as an experiment we tried educating it on how an automobile engine works, since he has a great amount of knowledge in that field.

Our first attempt technically worked, but was a bit problematic.  A second attempt turned out much better where we rethought the problem and broke down the engine structure in a way that was much more compatible to the nature of the program.  Very interesting results for such a simple algorithm !!

 

 
  [ # 13 ]

Victor: How did you change the engine structure?

I was just thinking, it might be useful for the expert system to recognize if two test questions were actually synonymous. If they have keywords that are known to be synonyms, the program could ask if a question sentence in its database is synonymous with what the user just inputed, and if so, use the sentence from the database instead. Each object that it knows could then be associated with some subset of the database’s questions/answers and the bot could tailor its future questions based on how many question/answer sets match with a known object. This arrangement might help it decide more quickly that it doesn’t know what object you’re thinking of.

Just throwing around ideas. All in all, I agree that it’s quite cool how much versatility can be derived from such a simple bit of code.

 

 
  [ # 14 ]

CR:  Actually, we just re-structured the questions themselves.    Those are some good ideas, but actually this was just a very very ‘quick and dirty’ script I put together in around an hour.  I more or less was too tired one evening to work on CLUES, but yet felt like writing something basic… and good old ‘animals’ came to mind lol…  Yes, I am seriously addicted !!

 

 
 
  login or register to react
‹‹ AiMind      NEED HELP ››