AI Zone Admin Forum Add your forum

NEWS: Chatbots.org survey on 3000 US and UK consumers shows it is time for chatbot integration in customer service!read more..

Accessing bot variables in objects?
 
 

Is it possible to access a bot variable in an object?

For example, if I did something like <bot mood = happy>, assuming the var ‘mood’ is setup, could this be accessed from a perl object?

 

 
  [ # 1 ]

There’s not an officially supported way yet, but that sounds like a good idea for something to add!

Like, currently you can set a bot variable by using the setVariable() method on the RS object that you get, but there’s no equivalent getVariable() in any of the libraries yet. wink

Which programming language are you using? I can probably get this added pretty quickly.

 

 
  [ # 2 ]

I’m using the httpd Perl version (as cgi), being run on a local server at present, with the intention to be online.

It would be great to experiment with the possibilities if you could. smile

The reason I initially thought about this was because I challenged myself to create a RS version of a bot inferring something based on two other bits of info, because I thought I could do it using arrays.

 

 
  [ # 3 ]

Actually, setting the variable may be enough as the bot variable can be sent in the call to the RS object (I think).

I’m not sure how to use the setVariable within an RS object. I’m new to Perl (since last week when I got into RiveScript).

 

 

 
  [ # 4 ]

So, the object macros get two variables from RiveScript: a reference to the main RiveScript object (usually in a $rs variable), and then the array reference of words sent to your code (usually called $args).

Just use that $rs variable to call setVariable from.

object setmood perl
   my 
($rs$args) = @_;
   
$rs->setVariable("mood"$args->[0]);
object 
 

 
  [ # 5 ]

Also, I just double checked the Perl source code, and you can actually use the <bot> tag to set variables (I don’t think this is yet documented on the Working Draft).

It’s a feature I programmed into the Python version originally. The {!...} syntax for dynamically streaming in new RiveScript code… its biggest use was only ever to reset bot variables and things (the syntax for trying to stream in new trigger/reply pairs would’ve been extremely messy, and would be better served using object macros like the previous example), so I made it so <bot> and <env> can be used to set the variables instead… then I ported this over to the Perl version. smile It’s been there since v1.24 (we’re on v1.28 now).

set mood (happy|angry|sad)
- <
bot mood=<star>>Mood has been updated
 

 
  [ # 6 ]

Yes, I’ve used this. Sorry, probably should have made the original post clearer. The reason for wanting to access them in the object was to manipulate them there.

Couple of things. I can’t get setVariable to work (it works as far as the object returns, but the bot variable is not updated).

Is there another way, perhaps same idea but with regular variables? (<set, <get ones)

I thought intially I could use the <call tag like this: {@otherrule <call….</call>}. This works, and I can access the returned value in the <star>, but if in that rule I try to use <set moodvar=<star>> or <bot mood=<star>>, it doesn’t work.

The idea is to be able to manipulate a varible and then store it.

 

 
  [ # 7 ]

What version of the RiveScript module are you using? This test script worked for me.

use RiveScript;

my $bot RiveScript->new();
$bot->stream('
    > object setmood perl
        my ($rs, $mood) = @_;
        $rs->setVariable(mood => $mood);
        return "done";
    < object

    + getmood
    - Mood: <bot mood>

    + setmood *
    - <call>setmood <star></call>

    + setmood2 *
    - <bot mood=<star>>Set.
'
);
$bot->sortReplies;

print 
$bot->reply('u','getmood'), "\n";
print 
$bot->reply('u','setmood happy'), "\n";
print 
$bot->reply('u','getmood'), "\n";
print 
$bot->reply('u','setmood2 angry'), "\n";
print 
$bot->reply('u','getmood'), "\n"
perl test.pl 
Mood
undefined
done
Mood
happy
Set
.
Moodangry 
 

 
  [ # 8 ]

The rivescript.pm file shows version 1.28. However, see later comment.

I’m wondering if I’ve done something wrong in the setup then?

When I copy your script into an .rs file, and call the commands in the same order, the final getmood shows undefined. I’ve tried it both with a ! var set up and without.

One thing that may make a difference. When I intially added the httpd version to my hosting, I couldn’t get it to work. The hosting company (an extremely helpful and knowledable one) havd a look at it, and added the rivescript.pm file to the same folder as the rivescript.pl file (in my case, the cgi-bin folder), which wasn’t in the original httpd download.

This may just show my lack of Perl knowledge. It’s the rivescript.pm file that shows version 1.28.

 

 
  [ # 9 ]

I’m not sure what could be wrong with it. It might help to try to debug it a bit, like make a CGI script with code like this…

#!/usr/bin/perl

use RiveScript;
use 
Data::Dumper;

my $rs RiveScript->new();
$rs->loadDirectory("./brain"); # or where your RS files are
$rs->sortReplies();

# do w/e you need to do to trigger the condition you see, i.e.
$rs->reply('user''set mood happy');

# If you see (from the Dumper line below) that the bot variable
# isn't being set properly, uncomment out this line and try again,
# to see if the problem might just be in your object macros
#$rs->setVariable('mood', 'testing');

# dump the whole data structure to the web browser
print "Content-Type: text/plain\n\n";
print 
Dumper($rs); 
 

 
  [ # 10 ]

Thanks for looking into this. I think I need to learn more about CGI and Perl….. (something for today)

I get the 500 error on any new Perl file I create (even if, as a test, I copy the contents of rivescript.pl into that file and try to access it directly - which I can do no problem with rivescript.pl).

So I am now thinking this might be to do with some more general CGI / Perl issue I’m having. I will ask the host about that also. (I’m a php / c# person, so I’ve got a lot to learn here).

 

 
  [ # 11 ]

Ok, so my 500 error was something to do with not having headers…. Anyway the error was solved by using cpanel’s Perl (which apparently may put host headers). Don’t really know what I’m talking about, but I need to look through a few Perl turtorials on this.

Now I can run this script, however I think i should have tested better first.

I just thought I ought to test this from different angles, and I see the problem is probably nothing to do with the object macro. I think it is a more general problem because the bot variable isn’t updating even within RS script.

To make sure the test was effected by anything else, I also did this with just one short .rs file:

version 2.0

begin
 
request // This trigger is tested first.
 
{ok} // An {ok} in the response means it's okay to get a real reply
begin

test
test was ok

object setmood perl
 my 
($rs$mood) = @_;
 
$rs->setVariable(mood => $mood);
 return 
"done";
object

getmood
Mood: <bot mood>

setmood *
- <
call>setmood <star></call>

setmood2 *
- <
bot mood=<star>> Set.

setmood3 *
{! var mood=<star>} Set3

Calling setmood, setmood2 or setmood3 didn’t update the bot variable. I also tried it with both the variable defined and not defined before the test.

 

 
  [ # 12 ]

One more post….. thought it best you know everything. And some success.

Tested it in the js version and all works fine (not that I want to use this, but at least it confirms the rs file and object macros are ok).

I did manage to set the user variable in an object macro, so I can do what I want this way. The idea wasn’t to use it for bot moods, but this did make a good example. Of course I’d still like to figure out why the <bot mood = ####> isn’t working in my system. I tried it also with globals, and I notced <env somevar = #####> wasn’t working wither.

But for now this covers what I need, because I can put the variable in a user var and manipulate it.

 

 
  [ # 13 ]

Looking again at setting the user variable in objects…. and now I’m using Python.

For Perl objects, this approach worked:

object setmood perl
   my 
($rs$args) = @_;
   
$rs->setVariable("mood"$args->[0]);
object 

Is there a way to do this in Python objects?

(I see in the python code there is set_uservar. In Perl I notice $rs is sent to and accessed in the object, so I’m guessing that is needed to be available in a Python object)

 

 

 

 
  [ # 14 ]

I just thought of something while re-reading through your replies. You were using the Perl version as a CGI script on the web? It might have simply been the problem that you weren’t actually saving the variables somewhere and then recalling them for the next request to your CGI script.

i.e., in theory, this should’ve worked from within one single run-through of the CGI script:

#!/usr/bin/perl

use RiveScript;
my $bot RiveScript->new();
$bot->stream(qq{
   
set mood to *
   - <
bot mood=<star>>Set mood.

   + 
what is your mood
   
I am <bot mood>.
});
$bot->sortReplies();

print 
"Content-Type: text/html\n\n";

# should print "I am undefined."
print $bot->reply("user""what is your mood"), "<p>";

# should then print "Set mood."
print $bot->reply("user""set mood to happy"), "<p>";

# should then print "I am happy."
print $bot->reply("user""what is your mood"), "<p>"

The root problem being that HTTP is a stateless protocol. For each request to a web resource, the web browser opens a new network connection to the server, requests the URL, possibly sending some form values to it if you’re posting to the URL, downloads the response from the server, and then closes the connection. Between two subsequent HTTP requests, the web server has no way of knowing that the two requests are from the same person. All the server knows is, “this IP address connected, and it wanted this resource and possibly sent me this data”

HTTP cookies were invented to at least address the problem of the server having no way to tell that one HTTP request is from the same user as the other one.

So basically, for the bot to be able to maintain state from one request to another (i.e. if the user tells the bot their name, and the bot should remember that name on the next HTTP request), you’d need to store the data somewhere in a way that it can be reloaded “from scratch” on the next request. Usually, you’ll store the user variables in a database on the server side, and give the browser an HTTP cookie with an identifier to their database record (a session cookie).

The JavaScript version of RiveScript was “better” at remembering variables because JavaScript was stateful. It was like a local program running on your PC that can keep track of data in memory. If you refresh the page, though, all is lost, and the JS RiveScript won’t remember who you are or what its mood is. wink

If you run the Perl or Python RiveScript modules locally, i.e. by running “python -m rivescript” or the rivescript app that comes with the Perl version (usually at /usr/bin/rivescript), the bot would remember variables and such during your chat session because the program is stateful. It doesn’t start up, answer your request, and shut down just to do it all over again for your next message. This is what HTTP servers do, though.

To answer your last question about the Python version, the object macros in Python receive the variables “rs” and “args”, so you use them just like in Perl. wink

object setmood python
   rs
.set_variable("mood"args[0])
object 
 

 
  [ # 15 ]

Thanks for the detailed reply.

Actually, you very last piece of code sent me doen the right path it seems. I checked the Python source and found this and the uservar function, and this seems to work:

rs.set_uservar(userid"mood"args[0]

Plus the user variables seem to carry over on page refresh, although I guess not once cache / cookies cleared. But that’s ok for me at the moment.

And as you said before, a database should cover what will be needed here, and all I need to do is port the perl object to python (I decided I’d be better off long-term sticking to one language for this).

 

 

 
  login or register to react