Conversation with Eliza

Top  Previous  Next

In this tutorial we will set up a script that will let a user have a conversation with the classic ELIZA program.  Eliza will appear to chat using comments in a Review.  Eliza will only respond to comments in conversations that have a Defect containing her name.

Conversation with Eliza

Conversation with Eliza

Outline

When a Defect is created in Code Collaborator the Defect Activity trigger launches a Perl script in the background.  The script polls Code Collaborator for comments using the Command Line Client.  When it finds a new comment, it passes the comment to an implementation of the ELIZA program, and then posts Eliza's response to the conversation using the Command Line Client.

The script runs indefinitely until the Defect is marked fixed or deleted, or the Review is finished.

Prerequisites

The script in this example is written in Perl, so you must have the Perl runtime installed.

The Perl script invokes the Code Collaborator Command Line Client, so that needs to be installed on your server machine.  Be sure to install the Command Line Client so that it is accessible and executable by the system user which is running the Code Collaborator server (this is especially important on Unix systems).

The script uses a clone of ELIZA written in Perl called Chatbot::Eliza which must be installed.

Script Step 1: Set up constants

The script will need to know a few values to do it's work.  These will be hard-coded in to the script:

# URL to the Code Collaborator Server

$CCOLLAB_URL = "http://localhost:8080";

 

# Login of Code Collaborator User who Eliza will use for chat

# should be a Code Collaborator administrator

$CCOLLAB_USER = "eliza";

 

# Password of Code Collaborator User who Eliza will use for chat

$CCOLLAB_PASSWORD = "eliza";

 

# Seconds to sleep before polling for new chat

$REFRESH_DELAY_SECONDS = 4;

 

Script Step 2: Read parameters from command-line

The Review ID and Defect ID will be supplied by Code Collaborator as parameters when it invokes the script from the trigger (we set that up in Step 9).  The script needs to read those parameters from the command-line:

# read parameters from command-line

$reviewId = $ARGV[0];

$defectId = $ARGV[1];

 

Script Step 3: Create XSL Transform

The script needs to extract multiple pieces of information from the Code Collaborator server.  To do that more efficiently it uses an XSL Transform to extract everything in a single call to ccollab admin review-xml (Step 6).  The XSL is inlined in the Perl script using "here-document" syntax.

#xslt file we will use to extract info from Code Collaborator

$xslt = <<XSLT;

<?xml version="1.0" encoding="UTF-8"?>

<xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='1.0'>

       

       <xsl:template match='//reviews/review'>

       

               <!--  get review phase -->

               <xsl:value-of select='general/phase'/><xsl:text>

</xsl:text>

               

               <!--  find defect -->

               <xsl:for-each select='defects/defect[\@defectId=$defectId]'>

       

                       <!--  get defect status -->

                       <xsl:value-of select='status'/><xsl:text>

</xsl:text>

       

                       <!--  get defect text-->

                       <xsl:value-of select='text'/><xsl:text>

</xsl:text>

 

               </xsl:for-each>

                       

               <!--  find the conversation we're talking on (the one with the defect) -->

               <xsl:for-each select='conversations/conversation[defects/conversation-defect/\@defect-id=$defectId]'>

               

                       <!-- find last comment in conversation -->

                       <xsl:for-each select='comments/comment[last()]'>

                       

                               <!--  get author -->

                               <xsl:value-of select='\@creator'/><xsl:text>

</xsl:text>

                               

                               <!--  get text -->

                               <xsl:value-of select='text()'/><xsl:text>

</xsl:text>

                       

                       </xsl:for-each>

 

                       <!-- get file-path (empty for overall comment) -->

                       <xsl:value-of select='\@file-path'/><xsl:text>

</xsl:text>

                       

                       <!-- get line-number (empty for overall comment or file overall comment) -->

                       <xsl:value-of select='\@line-number'/><xsl:text>

</xsl:text>

                       

               </xsl:for-each>

               

       </xsl:template>

</xsl:stylesheet>

XSLT

 

Script Step 4: Initialize Eliza

The Chatbot::Eliza program is initialized by a simple constructor.

# initialize Eliza

$eliza = new Chatbot::Eliza;

 

Script Step 5: Sleep for a few seconds

The rest of the script loops until the script decides to exit (Step 7).  Every time it starts the loop, the script first sleeps for a few seconds to make sure it doesn't put too much load on the server.

# sleep so we don't hammer the server

sleep($REFRESH_DELAY_SECONDS);

 

Script Step 6: Query Code Collaborator server for info

The script invokes the ccollab admin review-xml command, passing in the XSL created in Step 3 on STDIN.  The output is then parsed to get the Review Phase, Defect status, Defect text, comment Author, comment text, and optionally file path and line number.

# Query Code Collaborator server for info

$pid = open2(*CCOLLAB_OUTPUT, *XSL_INPUT, "ccollab $ccollabOptions admin review-xml $reviewId --xsl-file -");

print XSL_INPUT $xslt;

close(XSL_INPUT);

chomp(($spacer, $reviewPhase, $defectStatus, $defectText, $author, $inputChat, $filePath, $lineNumber) = <CCOLLAB_OUTPUT>);

close(CCOLLAB_OUTPUT);

waitpid($pid,0);

 

#cleanup filePath and lineNumber

chop($filePath);

chop($lineNumber);

 

#debug

print "reviewPhase = $reviewPhase\n";

print "defectStatus = $defectStatus\n";

print "defectText = $defectText\n";

print "author = $author\n";

print "inputChat = $inputChat\n";

print "filePath = \"$filePath\"\n";

print "lineNumber = \"$lineNumber\"\n";

print "\n";

Script Step 7: Stop script if appropriate

The script runs in an infinite loop, but we don't really want it to go forever!  The script exits if any of the following conditions are true:

The Review finishes (no longer in inspection phase)
The Defect is fixed or deleted (no longer open)
The Defect text doesn't mention Eliza

# safety -  quit if review isn't in Inspection phase

die ("Review is no longer in Inspection phase") if ($reviewPhase !~ /Inspection/);

               

# safety - quit if defect isn't open

die ("Defect $defectId is no longer open") if ($defectStatus !~ /open/);        

       

# safety - quit if defect text doesn't mention "Eliza"

die ("Defect $defectId text doesn't mention Eliza") if ($defectText !~ /Eliza/);                

 

Script Step 8: Ignore comment if appropriate

The script checks whether the comment is a "system" comment like "** Marked Read**" or if the last comment in the conversation was made by Eliza herself.  In both of these cases the script skips back to the top of the loop.

# Eliza shouldn't respond to system messages, like "** Marked Read **" or "** Accepted **"

next if ($inputChat =~ /^\*\*/);

 

# Eliza shouldn't talk to herself

next if ($author =~ /$CCOLLAB_USER/);

 

Script Step 9: Get response from ELIZA

The script passes the user's comment to the ELIZA program and gets back her response.

# Get response from Eliza

$outputChat = $eliza->transform($inputChat);

 

#debug

print "$outputChat\n"; 

print "\n";

 

Script Step 10: Upload Eliza's response to Code Collaborator

The script uploads Eliza's response to the conversation using the ccollab admin review comment create command.

# build command to upload Eliza's comment to Code Collaborator

$uploadCommand = "ccollab $ccollabOptions admin review comment create $reviewId \"$outputChat\"";

 

# file path is optional (no file path for overall review chat)

if ($filePath) {

       $uploadCommand .= " --file \"$filePath\"";

}

 

# line number is optional (no line number for overall review chat or overall file chat)

if ($lineNumber) {

       $uploadCommand .= " --line-number $lineNumber";

}

 

#debug

print "Running $uploadCommand\n";

       

# upload Eliza's comment to Code Collaborator

system("$uploadCommand");

Step 11: Test the script from the command-line

That's our whole script!  Here it is in finished form: eliza.pl.  Don't forget to replace the constants in the script (url, user, password) with the appropriate values for your environment, then copy the script to an accessible place on your server.  The script needs to be readable by the system user which is running the Code Collaborator server.

Before you configure the Code Collaborator server to invoke the script automatically, test it manually by opening a console on your server machine running it on the command-line. Be sure to log in to your server machine as the user which is running the Code Collaborator server.  First create a Review and create a Defect in the Review with the word "Eliza" in it, then run the script.

For example, if you created Review 1234 with Defect D5678, then run the script with this command:

/usr/bin/perl /home/rpaterson/eliza.pl 1234 5678

 

You should see output similar to this:

reviewPhase =   Inspection

defectStatus = open

defectText = Hello Eliza?

author = rpaterson

inputChat = Created Defect D11: Hello Eliza?

filePath = "SymlinkTest.java"

lineNumber = "73"

 

How do you do. Please state your problem.

 

Running ccollab --url http://localhost:8080 --user eliza --password "eliza"

 --quiet --non-interactive admin review comment create 1234 

"How do you do. Please state your problem." --file "SymlinkTest.java" --line-number 73

 

The script will loop until you mark the Defect fixed or deleted, or finish the Review.  When you refresh your browser in Code Collaborator you should see Eliza's comment.

Step 12: Invoke Script from a trigger

Make sure you have Step 11 working before you move on to this step.  The last thing we need to do is tell the Code Collaborator server to automatically invoke the eliza.pl script when a Defect is created.  We do this with the Defect Activity trigger.  We will use these values:

Executable: /usr/bin/perl

Parameters: -e "exit unless fork; system('/usr/bin/perl /home/rpaterson/eliza.pl ${review.id} ${defect.id} ');""

Defect Activity Trigger

Defect Activity Trigger

Note that it is important to use the FULL PATH of both the Perl runtime and the eliza.pl script.  Also note the quotes and spaces - they're important.  The Review id, and Defect id come from substitution variables.  The Perl snippet included in the Parameters field causes the script to be launched in a background process.

Finished

That's it!  Now when anyone creates a Defect in Code Collaborator the script will be invoked.  If the Defect has the word "Eliza" in it then the script will monitor that conversation for comments and have Eliza respond to them.