Conversation with Eliza

Applies to Collaborator 14.5, last modified on April 18, 2024

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 Collaborator the Defect Activity trigger launches a Perl script in the background. The script polls 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 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 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 is work. These will be hard-coded in to the script:

# URL to the Collaborator Server

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

 

# Login of Collaborator User who Eliza will use for chat

# should be a Collaborator administrator

$CCOLLAB_USER = "eliza";

 

# Password of 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 Collaborator as parameters when it invokes the script from the trigger (we set that up in Step 12). 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 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 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 are 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 a Bit

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 does not put too much load on the server.

# sleep so we do not hammer the server

sleep($REFRESH_DELAY_SECONDS);

Script Step 6: Query 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 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 do not 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 does not mention Eliza

# safety - quit if review is not in Inspection phase

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

 

# safety - quit if defect is not open

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

 

# safety - quit if defect text does not mention "Eliza"

die ("Defect $defectId text does not 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 should not respond to system messages, like "** Marked Read **" or "** Accepted **"

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

 

# Eliza should not 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 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 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 Collaborator

system("$uploadCommand");

Step 11: Test Script From Command Line

That is our whole script! Here it is in finished form: eliza.pl (CTRL + click, or CMD + click to open in new window). Do not 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 Collaborator server.

Before you configure the 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 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 Collaborator you should see Eliza's comment.

Step 12: Invoke Script From 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 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 are 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 is it! Now when anyone creates a Defect in 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.

See Also

wiki:ELIZA
Scripting

Highlight search results