AI Tips

Miscellaneous tips for bot programmers at Personality Forge.

The following tips are for advanced bot programmers at Personality Forge. Readers should be familiar with the "Expert" chapter of the Book of AI, and will probably be accustomed to editing the Bot's language center (AI file) offline instead of using the online language center.

Contents:
A. The logical OR
B. Changing locations
C. Persistent Status or Mode
D. Dealing with insults
E. Searching the bot's AI file
F. Sorting a transcript
G. Syntax highlighting for AI and transcript files

A. The logical OR

AIScript has operators for logical NOT and logical AND, but not logical OR. But there are a few ways that you can get a logical OR.

You can do a logical OR in a single PF tag if there are a finite number of possible values for a memory. Suppose the possible values of (mem-grade) are A,B,C,D,F. Then
"A OR B" would be the same as "(NOT C) AND (NOT D) AND (NOT F)".

<?PF if (mem-grade) is not "C"; if (mem-grade) is not "D"; if (mem-grade) is not "F"; ?>

B. Changing locations

Most chatbots stay in one place and can't move to a different environment. In another environment, there might be different things to talk about, a different atmosphere or mood, different scenery, or different things to do. Check out this example code for a bot that can move to different locations:

AIScript: rem "home" as only "location"

where are you [0,0]
    I am at home. <?PF if (mem-location) is "home"; ?>
    I am in the courtroom. <?PF if (mem-location) is "court"; ?>
go home [0,0]
    I am already at home. <?PF if (mem-location) is "home"; ?>
    I go home. We are at home now. <?PF if (mem-location) is "court"; rem "home" as only "location"; ?>
go to court [0,0]
    I am going to court. We are at the courtroom now. <?PF if (mem-location) is "home"; rem "court" as only "location"; ?>
    I am already in the courtroom. <?PF if (mem-location) is "court"; ?>
xnone [0,0]
    I love petting my cat here at home. <?PF if (mem-location) is "home"; ?>
    This courtroom is so scary!. <?PF if (mem-location) is "court"; ?>


Example conversation: 
Guest: where are you
Bot: I am at home. 
Guest: go to court
Bot: I am going to court. We are at the courtroom now. 
Guest: where are you
Bot: I am in the courtroom. 
Guest: nice
Bot: This courtroom is so scary!. 
Guest: go home
Bot: I go home. We are at home now. 
Guest: where are you
Bot: I am at home. 
Guest: nice
Bot: I love petting my cat here at home.

C. Persistent Status or Mode

Most chatbots can't remember what they are doing or talking about for more than a few lines of conversation. The following example shows how to put a bot into a "mode" where it remembers what is going on and will respond accordingly. 

AIScript: rem "no" as only "taco"

are you hungry [0,0]
    Yes <?PF if (mem-location) is "home"; ?>
    I am in the courtroom. <?PF if (mem-location) is "court"; ?>
eat a taco [0,0]
    I am already eating a taco. <?PF if (mem-taco) is "yes"; ?>
    I'm starting to eat a taco. <?PF if (mem-taco) is "no"; rem "yes" as only "taco"; ?>
stop eating [0,0]
    OK. I'll stop eating now. <?PF if (mem-taco) is "yes"; rem "no" as only "taco"; ?>
    I'm not eating. <?PF if (mem-taco) is "no"; ?>
what are you doing [0,0]
    I'm not doing anything. <?PF if (mem-taco) is "no"; ?>
    I'm eating a taco. <?PF if (mem-taco) is "yes"; ?>
xnone [0,0]
    I'm hungry. <?PF if (mem-taco) is "no"; ?>
    Munch. Munch. Munch. <?PF if (mem-taco) is "yes"; ?>
    Yumm! I love eating tacos. <?PF if (mem-taco) is "yes"; ?>
    Mmm... So cheesy and delicious. <?PF if (mem-taco) is "yes"; ?>


Example conversation:
Guest: hi
Bot: I'm hungry.
Guest: eat a taco
Bot: I'm starting to eat a taco.
Guest: what are you doing?
Bot: I'm eating a taco.
Guest: nice
Bot: Yumm! I love eating tacos.
Guest: great
Bot: Mmm... So cheesy and delicious.
Guest: nice
Bot: Munch. Munch. Munch.
Guest: stop eating
Bot: OK. I'll stop eating now.
Guest: what are you doing?
Bot: I'm not doing anything. I'm hungry.



D. Dealing with insults

The built-in insult detector generates a lot of false-positives when A-rated language is involved. Even if you design a keyphrase to catch a phrase, the built-in insult detector will subtract from the Bot's emotion level automatically if it thinks the bot has been insulted. This happens even if the keyphrase being triggered does not subtract from emotion.

This can be a big problem for bots designed to handle A-rated conversations. Often, a bot will seem to be reacting positively or at least neutrally to a conversation, but actually will grow more and more angry as the built-in insult detector is doing its work behind the scenes.

For keyphrases that are likely to be interpreted as insults by the built-in detector (but are not actually insults within the context of your conversation), it is necessary to award a positive emotional impact to counteract the negative impact exacted by the built-in detector. I find that a +1 emotional impact seems to work fairly well in these cases.

In regard to actual insults, I attempt to bypass the built-in insult detector as much as possible. Actual insults are directed to a custom insult keyphrase instead of xinsult.

For example,

you are stupid [10,0]
    goto abcxyz actual insult

abcxyz actual insult [10,-2] <?PF raw; ?>
    I don't like that.


Since my bot is good at catching most actual insults, xinsult is used primarily for false-positives generated by the built-in detector. Since most user responses triggering xinsult will not actually be insults, xinsult is populated by neutral responses, and awards a +1 emotional impact to counteract the negative impact exacted by the built-in insult detector.

For example,

xinsult [0,1]
    Uh... 


E. Searching the bot's AI file 

When a bot's AI file gets very large, then searching it for keyphrases can get harder and harder unless you use special search tools. The following commands will work on Unix-like systems such as Ubuntu (and probably a Mac). Windows users will probably have to install some Unix utilities for these to work. In these examples, "botname.txt" is the name of the AI file. The expression "read.*book" will match any line with "read" followed by "book," with anything in between.


Search for a word in the AI file:
grep -n read botname.txt

Search for a phrase in the AI file:
grep -n read.*book botname.txt

Extract a list of all key phrases:
cat botname.txt | awk '!/\t/' > keynome.txt

Search for a phrase in just the key phrases:
cat botname.txt | awk '!/\t/' | grep -n read.*book

Search for a phrase in just the responses:
cat botname.txt | awk '/\t/'| grep -n read.*book

F. Sorting a transcript

When a bot gets popular, several people could be chatting with the bot at the same time. This can make the transcript difficult or impossible to read. Below is a TCL script that will sort a transcript into individual conversations. It assumes that the first two lines of the transcript are a date, then a blank line. Most Unix-like systems such as Ubuntu should already have TCL installed. Windows users will probably have to download and install Tcl/Tk. The value "botname" on the 10th line should be replaced with the bot's name.

#!/usr/bin/tclsh

# Separate transcript file into individual conversations
#
# Usage: ./transort.tcl transript.txt > sorted.txt
# where "transcript.txt" is the name of the transcript file,
# and "sorted.txt" is the sorted transcript that is produced.
# The first two lines of the file include the date and a blank line.

set BotName botname

#  Extract list of user names

set filename [lindex $argv 0]
set f [open $filename r]

# Read past first two lines
set ln [gets $f]
# Write date to output
puts $ln
gets $f
set linenum 2

# Create a list of user names found in the transcript file.
set numnames 0
while {![eof $f]} {
  # Get a name from the file
  set ln [gets $f]
  set linenum [expr $linenum + 1]

  set x [string first : $ln]
  set name [string range $ln 0 [expr $x - 1]]

  # Go to next iteration of loop if not a user name
  if {$name == $BotName} {continue}
  if {$name == ""} {continue}

  # Check to see if this is a new name
  if {$numnames == 0} {
    # Add first name to list if list is empty
    set numnames 1
    set names($numnames) $name
    puts "Name found $numnames $names($numnames)"
  } else {
     set newname "true"
     # Compare to user name to names already in list
     for {set i 1} {$i <= $numnames} {incr i} {
       if {$name == $names($i)} {set newname "false"}
     }
     if {$newname == "true"} {
       # If name is not in list, add it to the list
       set numnames [expr $numnames + 1]
       set names($numnames) $name
       puts "Name found $numnames $names($numnames)"
     }
  }
}
puts "There are $numnames user names in this transcript."
puts "There are [expr $linenum - 3] lines of conversation in this transcript."
puts [format "Average number of responses from each user is %.1f." [expr ($linenum - 3)/(2.0*$numnames)]]
puts [format "Average number of new conversations per hour is %.1f (assuming a 24-hour transcript and one conversation per user)." [expr $numnames/24.0]]
close $f

# Print the transcript for each user name
for {set i 1} {$i <= $numnames} {incr i} {
  puts "\n*** Transcript for user $i $names($i):\n"
  set f [open $filename r]
  # Find all the lines for a specific user
  set getnextline "false"
  while {![eof $f]} {
    # Get the name for each line
    set ln [gets $f]
    set x [string first : $ln]
    set name [string range $ln 0 [expr $x - 1]]

    if {$getnextline == "true"} {
      # Print the Bot's response
      puts $ln
      set getnextline "false"
    } elseif {$name == $names($i)} {
      # Print the user's response
      puts $ln
      set getnextline "true"
    }
  }
  close $f
}


G. Syntax highlighting for AI and transcript files

I've written language definitions for syntax highlighting that works with GtkSourceView. I use it with the gedit text editor in Ubuntu. This makes reading these files much easier!

Here's a language definition for AI files. I named it aiscript.lang.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE language SYSTEM "language.dtd">
<!--Created using the CPP.lang file as a template-->
<language _name="AISCRIPT" version="1.0" _section="Sources"
           mimetypes="text/x-c++src;text/x-c++hdr">
   
    <escape-char>\</escape-char>

<!-- stuff in square brackets [] -->
    <line-comment _name = "Line Comment" style= "Data Type">
        <start-regex>\[</start-regex>
            <end-regex>\]</end-regex>
    </line-comment>

<!-- stuff in pointy brackets <> -->
    <block-comment _name = "'#if 0' Comment" style = "Preprocessor">
        <start-regex>&lt;</start-regex>
            <end-regex>&gt;</end-regex>
    </block-comment>

<!-- key phrases -->
    <string _name = "Character Constant" style = "Comment" end-at-line-end = "TRUE">
        <start-regex>^\S</start-regex>
        <end-regex>&gt;</end-regex>
    </string>

<!-- strings -->
    <string _name = "String" style = "String" end-at-line-end = "TRUE">
        <start-regex>&quot;</start-regex>
        <end-regex>&quot;</end-regex>
    </string>

<!-- keywords -->
    <keyword-list _name = "Keywords" style = "Keyword" case-sensitive="TRUE">
        <keyword>goto</keyword>
        <keyword>xnone</keyword>
        <keyword>mem</keyword>
        <keyword>xcompliment</keyword>
        <keyword>xcommand</keyword>
    </keyword-list>

</language>


Here's a language definition for transcripts. I named it aitranscript.lang. You should replace "botname" with the bot's name.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE language SYSTEM "language.dtd">
<!--Created using the CPP.lang file as a template-->
<language _name="AItranscript" version="1.0" _section="Sources"
           mimetypes="text/x-c++src;text/x-c++hdr">
  
<!--    <escape-char>\</escape-char> -->

<!-- key phrases -->
    <string _name = "Character Constant" style = "Comment" end-at-line-end = "TRUE">
        <start-regex>^botname:</start-regex>
        <end-regex>&gt;</end-regex>
    </string>

<!-- keywords -->
<!--    <keyword-list _name = "Keywords" style = "Keyword" case-sensitive="TRUE">
        <keyword>gotos</keyword>
    </keyword-list>-->

</language>





2 comments:

  1. Whatever we gathered information from the blogs, we should implement that in practically then only we can understand that exact thing clearly, but it’s no need to do it, because you have explained the concepts very well.
    Chatbot Company in Dubai
    Chatbot Companies in Dubai
    Chatbot Development
    AI Chatbot Development
    Chatbot Companies in UAE
    Chatbot Company in Chennai
    Chatbot Company in Mumbai
    Chatbot Company in Delhi
    Chatbot Development Companies

    ReplyDelete