NAME
RiveScript - Rendering Intelligence Very Easily
SYNOPSIS
use RiveScript;
# Create a new RiveScript interpreter.
my $rs = new RiveScript;
# Load some replies.
$rs->loadDirectory ("./replies");
# Load in another file.
$rs->loadFile ("./more_replies.rs");
# Stream in even more RiveScript code.
$rs->stream (q~! global split_sentences = 1~);
# Sort all the loaded replies.
$rs->sortReplies;
# Grab a response.
my @reply = $rs->reply ('localscript', 'Hello RiveScript!');
print join ("\n", @reply), "\n";
DESCRIPTION
RiveScript is a simple input/response language. It has a simple, easy-to-learn syntax, yet it is more powerful even than Dr. Wallace's AIML (Artificial Intelligence Markup Language). RiveScript was created as a reply language for chatterbots, but it has been used for more complex things above and beyond that.
PERL PACKAGE
This part of the manpage documents the methods of the Perl RiveScript library. The RiveScript language specifications are below: see "RIVESCRIPT".
Public Methods
- new
-
Creates a new RiveScript instance.
- setSubroutine (OBJECT_NAME => CODEREF)
-
Define an object macro (see "Object Macros")
- loadDirectory ($DIRECTORY[, @EXTS])
-
Load a directory of RiveScript files.
@EXTS
is optionally an array of file extensions to load, in the format(.rs .txt .etc)
. Default is just ".rs" - loadFile ($FILEPATH[, $STREAM])
-
Load a single RiveScript file. Don't worry about the
$STREAM
argument, it is handled in thestream()
method. - stream ($CODE)
-
Stream RiveScript codes directly into the module.
- sortReplies
-
Sorts all the loaded replies. This is necessary for reply matching purposes. If you fail to call this method yourself, it will be called automatically with
reply()
, but not without a nasty Perl warning. It's better to always sort them yourself, for example if you load in new replies later, they won't be matchible unless a newsortReplies
is called. -
Get a reply from the bot. This will (normally) return an array. The values of the array would be all the replies to that message (i.e. if you use the
{nextreply}
tag in a response, or if you pass in multiple sentences).%TAGS
is optionally a hash of special reply tags. Each value is boolean.scalar = Forces the return value into a scalar instead of an array no_split = Don't run sentence-splitters on the message. retry = INTERNAL. Tells the module that it's on a retry run, for special cases such as ;) - winking emoticon - since ; is a default sentence-splitter.
- search ($STRING)
-
Search all loaded replies for every trigger that
$STRING
matches. Returns an array of results, containing the trigger, what topic it was under, and its file and line number where applicable. - write ([$FILEPATH])
-
Writes all the currently loaded replies into a single file. This is useful for if your application dynamically learns replies by editing the loaded hashrefs. It will write all replies to the file under their own topics. Comments and other unnessecary information is ignored.
The default path is to "written.rs" in the working directory.
Note: This method doesn't honor the
%PREVIOUS
command in RiveScript.See "Dynamic Replies".
- setGlobal (VARIABLE => VALUE, ...)
-
Set a global RiveScript variable directly from Perl (alias for
! global
) - setVariable (VARIABLE => VALUE, ...)
-
Set a botvariable (alias for
! var
) - setSubstitution (BEFORE => AFTER, ...)
-
Set a substitution setting (alias for
! sub
) - setUservar ($USER_ID, VARIABLE => VALUE, ...)
-
Set a user variable (alias for
<set var=value>
for$USER_ID
) - getUservars ([$USER_ID])
-
Get all uservars for a user. Returns a hashref of the variables. If you don't pass in a
$USER_ID
, it will return a hashref of hashrefs for each user by their ID.
Security Methods
The RiveScript interpreter can specify some security settings as far as what a RiveScript file is allowed to contain.
Note: These settings only apply to commands found in a RiveScript document while it's being loaded. It does not apply to tags within RiveScript responses (for example {! global ...}
could be used in a reply to reset a global variable. This can't be helped with these commands. For ultimate security, you should have your program manually check these things).
- denyMode ($MODE)
-
Valid modes are
deny_some
,allow_some
, andallow_all
. allow_all is the default. Use thedeny()
andallow()
methods complementary to the denyMode specified. - deny (@COMMANDS)
-
Add
@COMMANDS
to the denied commands list. These can be single commands or beginnings of command texts. Example:$rivescript->deny ( '&', '! global', '! var copyright', '> begin', '< begin', '> __begin__', '< __begin__', );
In that example,
&PERL
,!GLOBAL
, the botvariablecopyright
, and theBEGIN
statements (and its internal names) are all blocked from being accepted in any loaded RiveScript file. - allow (@COMMANDS)
-
Add
@COMMANDS
to the allowed commands list. For the highest security, it would be better toallow_some
commands rather thandeny_some
.$rivescript->allow ( '+', '-', '! var', '@', );
That example would deny every command except for triggers, responses, botvariable setters, and redirections.
Private Methods
These methods are called on internally and should not be called by you.
- debug ($MESSAGE)
-
Print a debug message (when debug mode is active).
- makeParser
-
Creates a RiveScript::Parser instance, passing in the current data held by
RiveScript
. This call is made before using the parser (to read or write replies) and destroyed when no longer needed. - intReply ($USER_ID, $MESSAGE)
-
This is the internal reply-getting routine. Call
reply()
instead. This assumes that the data is all correctly formatted before being processed. - splitSentences ($STRING)
-
Splits
$STRING
at hte sentence-splitters and returns an array. - formatMessage ($STRING)
-
Formats
$STRING
by running substitutions and removing punctuation and symbols. - mergeWildcards ($STRING, @STARS)
-
Merges the values from
@STARS
into$STRING
, where the items in@STARS
correspond to a captured value from$1
to$100+
. The first item in the array should be blank as there is no<star0>
. - stringUtil ($TYPE, $STRING)
-
Formats
$STRING
by$TYPE
(uppercase, lowercase, formal, sentence). - tagFilter ($REPLY, $ID, $MESSAGE)
-
Run tag filters on
$REPLY
. Returns the new$REPLY
. - tagShortcuts ($REPLY)
-
Runs shortcut tags on
$REPLY
. Returns the new$REPLY
.
RIVESCRIPT
The following is the RiveScript 1.00 specification.
RiveScript Format
RiveScript is a line-by-line command-driven language. The first symbol(s) of each line is a command, and the following text is its data.
In its most simple form, a valid RiveScript reply looks like this:
+ hello bot
- Hello human.
RiveScript Commands
- ! (Definition)
-
The
!
command is for definitions. These are used to define variables and arrays at load time. Their format is as follows:! $type $variable = $value
The supported types are as follows:
global - Global settings (eg. debug and sentence_splitters) var - BotVariables (eg. the bot's name, age, etc) array - An array sub - A substitution pattern person - A "person" substitution pattern addpath - Add an include path for RiveScript includibles include - Include a separate RiveScript library or package syslib - Include a Perl module into the RiveScript:: namespace.
Some examples:
// Set global variables (defaults) ! global debug = 0 ! global split_sentences = 1 ! global sentence_splitters = . ! ; ? // Setup a handler string for object failures. ! global macro_failure = <b>ERROR: Macro Failure</b> // Set bot vars ! var name = Casey Rive ! var age = 14 ! var gender = male ! var color = blue // Delete botvar "color" ! var color = undef // An array of color names ! array colors = red blue green yellow cyan fuchsia // An array of "can not" variations ! array not = can not|would not|should not|could not // A few substitutions ! sub can't = can not ! sub i'm = i am // Person substitutions (swaps 1st- and 2nd-person pronouns) ! person i = you ! person you = me ! person am = are ! person are = am // Add a path to find libraries. ! addpath C:/MyRsLibraries // Include some English verb arrays ! include English/EngVerbs.rsl // Include a package of objects. ! include DateTime.rsp
Note: For arrays with single-word items, separate entries with white spaces. For multi-word items, use pipe symbols.
Note: To delete a variable, set its value to "undef"
See also: "Environment Variables" and "Person Substitution".
- < and > (Label)
-
The
<
and>
commands are for defining labels. A label is used to treat a part of code differently. Currently there are three uses for labels:begin
,topic
, andobject
. Example:+ you are stupid - You're mean. Apologize or I'm not talking to you again.{topic=apology} > topic apology + * - No, apologize for being so mean to me. + sorry - See, that wasn't too hard. I'll forgive you.{topic=random} < topic
- + (Trigger)
-
The
+
command is the basis for all reply sets. The+
command is what the user has to say to activate the reply set. In the example,+ hello bot - Hello human.
The user would say "hello bot" and get a "Hello human." reply.
Triggers are passed through the regexp engine. They should be completely lowercase and not contain too many foreign characters (use substitutions to format the message any way you want so you don't need to use foreign characters!)
- % (Previous)
-
The
%
command is for drawing a user back to complete a thought. It's similar to the<that>
functionality in AIML.+ ask me a question - Do you have any pets? + yes % do you have any pets - What kind of pet?
The
%
command is like the+Trigger
, but for the bot's last reply. The same substitutions are run on the bot's last reply as are run on the user's messages.! sub who's = who is + knock knock - Who's there? + * % who is * - <formal> who? + * % * who - Haha! <sentence>! That's hilarious!
(see "Tags" for details on what
<formal>
and<sentence>
are) - - (Response)
-
The
-
command is the response to a trigger. The-
command has several different uses, depending on its context. One+Trigger
with one-Response
makes a one-way question-and-answer scenario. When multiple-Response
s are used, they become random replies. For more information, see "Complexities of the Response". - ^ (Continue)
-
The
^
command is to extend the data of the previous command. This is for editor-side use only and has no effect on the brain when replies have all been loaded.The following commands can be used with the
^Continue
command:! global ! var ! array + trigger % previous - response @ redirection
Here's an example of extending a very long
-Response
over multiple lines. When the brain is tested, the reply will come out as one long string. The^Continue
is only for you, the reply writer, to make it easier to read the code.+ tell me a poem - Little Miss Muffit sat on her tuffet\s ^ in a nonchalant sort of way.\s ^ With her forcefield around her,\s ^ the Spider, the bounder,\s ^ is not in the picture today.
Note that spaces are NOT assumed between breaks. You'll need the
\s
tag (see "Tags"). - @ (Redirect)
-
The
@
command is for directing one trigger to another. For example:+ my name is * - Nice to meet you, <formal>. + people call me * @ my name is <star> + i am named * @ my name is <star>
- * (Condition)
-
The
*
command is for checking conditions. The format is:* variable = value => say this
For an example, you can differentiate between male and female users:
+ am i a boy or a girl * gender = male => You're a boy. * gender = female => You're a girl. - You've never told me what you are.
You can perform the following operations on variable checks:
= equal to != not equal to < less than <= less than or equal to > greater than >= greater than or equal to ? returns true if the variable is defined
If you want to check the condition of a bot variable, prepend a
#
sign to the variable name. This isn't necessary, but if the user has a variable by the same name, the user's variable overrides the bot's.+ is your name still soandso * #name = Soandso => That's still my name. - No, I changed it.
Here's an example of the "defined" condition:
// Only use the user's name if they've defined it to us + hello bot * name ? => Hello there, <get name>, nice to see you again! - Hello there!
- & (Perl)
-
The
&
command is for executing Perl codes directly from a RiveScript reply set. Use this only as a last resort, though. RiveScript is powerful enough to handle almost anything you could want it to, and it can handle these things more securely than this command would, as this command simplyeval
s the expression.+ what is 2 plus 2 - 500 Internal Error (the eval failed for some reason!) & $reply = '2 + 2 = 4';
- // or # (Comments)
-
The comment syntax is
//
, as it is in other scripting languages. Also,/* */
comments can be used to span across multiple lines:// A one-line comment /* this comment spans across multiple lines */
Commands can be used in-line next to RiveScript commands. They need to have at least one white space before and after the comment symbols.
+ what color is my (@colors) * // "What color is my green shoe?" - Your <star2> is <star1>! // "Your shoe is green!"
The Perl comment symbol,
#
, can be used in RiveScript as well. It follows the same principals as the//
commands, but it can not span across multiple lines.
RiveScript Holds The Keys
The RiveScript engine was designed for the RiveScript brain to hold most of the control. As little programming as possible on the Perl side as possible has made it so that your RiveScript can define its own variables and handle what it wants to. See "A Good Brain" for tips on how to approach this.
Complexities of the Trigger
The +Trigger
can be used for more complex things than just simple, 100% dead-on triggers. This part is passed through a regexp, hence any regexp commands can be used in the trigger... however, don't think too much into it, you can get impressive results with simple-looking patterns.
Note: An asterisk *
is always converted into (.*?)
regardless of its context. Keep this in mind.
- Wildcards:
-
You can write open-ended triggers (called "wildcard triggers"). You can capture the output of them, in order, by using the tags
<star1>
to<star100>
+. Example:+ my name is * - Nice to meet you, <star1>.
- Alternations:
-
You can use alternations in the triggers like so:
+ what (s|is) your (home|office|cell) phone number
The values the user chose for each set of alternations are also put into the
<star>
tags like the wildcards are. - Optionals:
-
You can use optional words in a trigger. These words don't have to exist in the user's message in order to match it, but they can be. Example:
+ what is your [home] phone number - You can call me at 555-5555.
Alternations can be used inside of optionals as well:
+ what (s|is) your [home|office|cell] phone number
- Arrays:
-
This is why it's good to define arrays. Arrays can be used in any number of triggers. Here's an example of how it works:
// Make an array of color names ! array colors = red blue green yellow cyan fuchsia // Now they can tell us their favorite color! + my favorite color is (@colors) - Really?! Mine is <star> too!
If you want the array choice to be put into a
<star>
tag, enclose it in parenthesis. Without the parenthesis, it will be skipped over and not matchible. Example:// If the input is "sometimes I am a tool"... ! array be = am are is was were + * i @be * // <star1> = 'sometimes' // <star2> = 'tool' + * i (@be) * // <star1> = 'sometimes' // <star2> = 'am' // <star3> = 'a tool'
Complexities of the Response
The -Response
command has many uses depending on its context:
- One-way question/answer:
-
A single
+
and a single-
will lead to a one-way question/answer scenario. - Random Replies:
-
A single
+
with multiple-
's will yield random results from the responses.+ hello - Hey. - Hi. - Hello.
- Fallbacks:
-
When using conditionals and Perl codes, you should have at least one
-Response
to fall back on in case everything returns false. - Weighted Responses:
-
With random replies, you can apply weight to them to improve their probability of being chosen. All replies have a default weight of 1, and anything lower than 1 can not be used. Example:
+ hello - Hello, how are you?{weight=49} - Yo, wazzup dawg?{weight=1}
See "Tags".
Begin Statement
The BEGIN file is the first reply file loaded in a loadDirectory call. If a "begin.rs" file exists in the directory being loaded, it is included first. This is the best place to put your definitions and include statements.
Note: BEGIN statements are not required.
How to define a BEGIN statement
> begin
+ request
- {ok}
< begin
BEGIN statements are like topics, but are always called first on every reply. If the response contains {ok}
in it, then the module gets an actual reply to your message and substitutes it for {ok}
. In this way, the BEGIN statement could format all the replies in the same way. For an example:
> begin
// Don't give a reply if the bot is down for maintenance. Else, sentence-case
// every reply the bot gives.
+ request
* #maintenance = yes => Sorry, the bot is currently deactivated!
- {sentence}{ok}{/sentence}
< begin
Here is a more complex example using a botvariable "mood"
> begin
+ request
* mood = happy => {ok}
* mood = sad => {lowercase}{ok}{/lowercase}
* mood = angry => {uppercase}{ok}{/uppercase}
* mood = pissed => {@not talking}
- {ok}
+ not talking
- I'm not in a talkative mood.
- I don't want to talk right now.
< begin
Note: The only trigger that BEGIN receives automatically is request
.
Topics
Topics are declared in a similar way to the BEGIN statement. To declare and close a topic, the syntax is as follows:
> topic NAME
...
< topic
The topic name should be unique and only one word.
The Default Topic: The default topic name is "random
"
Setting a Topic: To set a topic, use the {topic}
tag (see "Tags" below).
+ you are stupid
- You're mean. Apologize or I'm not talking to you again.{topic=apology}
> topic apology
+ *
- No, apologize for being so mean to me.
+ sorry
- See, that wasn't too hard. I'll forgive you.{topic=random}
< topic
Always set topic back to "random" to break out of a topic.
Object Macros
Special macros (Perl routines) can be defined and then utilized in your RiveScript code.
- Inline Objects
-
You can define objects within your RiveScript code. When doing this, keep in mind that the object is included as part of the
RiveScript::
namespace. That being said, here are some basic tips to follow:1) If it uses any modules, they need to be explicitely declared with a 'use' statement. 2) If it refers to any variables global to your main script, 'main::' must be prepended. Example: '$main::hashref->{key}' 3) If it refers to any subroutine of your main program, 'main::' must be prepended. Example: '&main::reload()'
Here's a full example of an object:
+ give me a fortune cookie - Your random fortune cookie: &fortune.get() > object fortune my ($method,$msg) = @_; my @cookies = ( 'You will be rich and famous', 'You will meet a celebrity', 'You will go to the moon', ); return $cookies [ int(rand(scalar(@cookies))) ]; < object
- Define an Object from Perl
-
This is done like so:
# Define a weather lookup macro. $rivescript->setSubroutine (weather => \&weather_lookup);
- Call an Object
-
To call on an object inside of a reply, the format is:
&object_name.method_name(argument)
All objects receive
$method
(the data after the dot) and$argument
(the data inside the parenthesis). Here's another example:+ encode * in base64 - &encode.base64(<star>) + encode * in md5 - &encode.md5(<star>) > object encode my ($method,$data) = @_; use MIME::Base64 qw(encode_base64); use Digest::MD5 qw(md5_hex); if ($method eq 'base64') { return encode_base64 ($data); } else { return md5_hex ($data); } < object
Note: If an object does not exist, has faulty code, or does not return a reply, the contents of global
macro_failure
will be inserted instead. The module cannot tell you which of the three errors is the cause, though.
Tags
Special tags can be inserted into RiveScript replies. The tags are as follows:
- <star>, <star1> - <star100>+
-
These tags will insert the values of
$1
to$100
+, as matched in the trigger regexp.<star>
is an alias for<star1>
. - <input1> - <input9>, <reply1> - <reply9>
-
Inserts the last 1 to 9 things the user said, and the last 1 to 9 things the bot replied with, respectively.
- E<id>
-
Inserts the user's ID.
- E<bot>
-
Insert a bot variable (defined with
! var
).+ what is your name - I am <bot name>, created by <bot author>.
This is also the only tag that can be used in triggers.
+ my name is <bot name> - <set name=<bot name>>What a coincidence, that's my name too!
- <get>, <set>
-
Get and set a user variable. These are local variables for the current user.
+ my name is * - <set name=<formal>>Nice to meet you, <get name>! + who am i - You are <get name> aren't you?
- <add>, <sub>, <mult>, <div>
-
Add, subtract, multiple and divide numeric variables, respectively.
+ give me 5 points - <add points=5>You have receive 5 points and now have <get points> total.
If the variable is undefined, it is set to 0 before the math is done on it. If you try to modify a defined, but not numeric, variable (such as "name") then (Var=NaN) is inserted in place of this tag.
Likewise, if you modify a variable with a non-numeric value, then (Value=NaN) is inserted.
- {topic=...}
-
This will change the user's topic. See "Topics".
- {nextreply}
-
Breaks the reply into two parts here. This will cause
reply()
to return multiple responses for each side of the{nextreply}
tag. - {weight=...}
-
Add some weight to a
-Response
. See "Complexities of the Response". - {@...}, <@>
-
An inline redirection. These work like normal redirections but can be inserted into another reply.
+ * or something - Or something. {@<star>}
<@>
is an alias for{@<star>}
- {!...}
-
An inline definition.
- {random}...{/random}
-
Inserts a random bit of text. Separate single-word items with spaces or multi-word items with pipes.
+ test random - This {random}reply response{/random} has random {random}bits of text|pieces of data{/random}.
- {person}...{/person}, <person>
-
Will take the enclosed text and run person substitutions on them. See "Person Substitution".
<person>
is an alias for{person}<star>{/person}
- {formal}...{/formal}, <formal>
-
Will Make Your Text Formal.
<formal>
is an alias for{formal}<star>{/formal}
- {sentence}...{/sentence}, <sentence>
-
Will make your text sentence-cased.
<sentence>
is an alias for{sentence}<star>{/sentence}
- {uppercase}...{/uppercase}, <uppercase>
-
WILL MAKE THE TEXT UPPERCASE.
<uppercase>
is an alias for{uppercase}<star>{/uppercase}
- {lowercase}...{/lowercase}, <lowercase>
-
will make the text lowercase.
<lowercase>
is an alias for{lowercase}<star>{/lowercase}
- {ok}
-
This is used only with the "Begin Statement". It tells the interpreter that it's okay to get a reply.
- \s
-
Inserts a white space.
- \n
-
Inserts a newline.
- \/
-
Insert a forward slash. This is to include forward slashes without them being interpreted as comments.
- \#
-
Inserts a pound symbol. This is to include pound symbols without them being interpreted as comments.
Environment Variables
Environment variables are kept as "botvariables" and can be retrieved with the <bot>
tags. The variable names are all uppercase and begin with "ENV_"
- RiveScript Environment Variables
-
ENV_OS = The operating system RiveScript is running on. ENV_APPVERSION = The version of RiveScript being used. ENV_APPNAME = A user-agent style string ("RiveScript/1.00") ENV_REPLY_COUNT = The number of loaded triggers.
- Perl Environment Variables
-
All Perl variables are prepended with "ENV_SYS_", so that "ENV_SYS_REMOTE_ADDR" would contain the user's IP address if RiveScript was used via HTTP CGI.
- Setting Environment Variables
-
RiveScript's syntax prohibits the modification of environment variables through any loaded RiveScript document. However, you can call the method
setVariable()
to change environment variables from the Perl side if need-be.
Person Substitution
The {person}
tag can be used to perform substitutions between 1st- and 2nd-person pronouns.
You can define these with the !define
tag:
! person i = you
! person my = your
! person mine = yours
! person me = you
! person am = are
! person you = I
! person your = my
! person yours = mine
! person are = am
Then use the {person}
tag in a response. The enclosed text will swap these pronouns.
+ do you think *
- What if I do think {person}<star>{/person}?
"Do you think I am a bad person?"
"What if I do think you are a bad person?"
Without the person tags, it would say "What if I do think I am a bad person?" and not make very much sense.
Note: RiveScript does not assume any pre-set substitutions. You must define them in your own brains.
Dynamic Replies
Here is an overview of the internal hashref structure of the RiveScript object, for modifying replies directly.
- $rs->{replies}
-
This hashref contains all of the replies. The first keys are the topic name, then the trigger texts under that topic.
So, $rs->{replies}->{random} contains all triggers for the default topic.
$rs-{replies}->{random}->{'my favorite color is (@colors) *'}> would be the location of a specific trigger.
- Trigger Sub-Keys
-
The following keys are underneath a trigger key ($rs-{replies}->{$topic}->{$trigger}>)
1..n - The
-Responses
under the trigger, in order.redirect - The contents of the
@Redirect
if applicable.conditions-{1..n}> - The data from the
*Condition
commands, in order.system-{codes}> - The contents of any
&Perl
codes if applicable. - Examples
-
// RiveScript Code + my name is * - <star>, nice to meet you! - Nice to meet you, <star>. # Perl code. Get the value of the second reply. $rs->{replies}->{random}->{'my name is *'}->{2} // RiveScript Code > topic favorites + *(@colors)* - I like <star2> too. :-) & &main::log('<id> likes <star2>') < topic # Perl code. Get the perl data from that trigger. $rs->{replies}->{favorites}->{'*(@colors)*'}->{system}->{codes} // RiveScript Code + * % whos there - <star> who? # Perl code. Access this one's reply. $rs->{replies}->{'__that__whos there'}->{1}
Included Files
Recommended practice is to place all your !include
statements inside your begin.rs file, as this file is always loaded in first.
- RiveScript Libraries
-
RiveScript Libraries (.rsl extension) are special RiveScript documents that are generally full of arrays and substitutions. For instance, the RiveScript distribution comes with English.rsl which is full of English nouns, verbs, and adjectives.
- RiveScript Packages
-
RiveScript Packages (.rsp extension) are special RiveScript documents that are generally full of objects. The RiveScript distribution comes with DateTime.rsp, which has an object for returning time stamps.
- RiveScript Include Search Path
-
The default RiveScript Includes search path is the array of Perl's
@INC
, with "/RiveScript" tacked on to the end of it. Also, the working directory of your script is included in this.You can use the
!addpath
directive to add new search paths.
Reserved Variables
The following are all the reserved variables within RiveScript which cannot be (re)set by your reply files.
- Reserved Global Variables
-
These variables can't be overwritten with the
!global
command:reserved replies array syntax streamcache botvars uservars botarrays sort users substitutions
- Reserved Topic Names
-
The following topic names are special and should never be (re)created in your RiveScript files.
__begin__ (used for the BEGIN statement) __that__* (used for the %Previous command)
A Good Brain
Since RiveScript leaves a lot of control up to the brain and not the Perl code, here are some general tips to follow when writing your own brain:
- Make a config file.
-
This would probably be named "config.rs" and it would handle all your definitions. For example it might look like this:
// Set up globals ! global debug = 0 ! global split_sentences = 1 ! global sentence_splitters = . ! ; ? // Set a variable to say that we're active. ! var active = yes // Set up botvariables ! var botname = Rive ! var botage = 5 ! var company = AiChaos Inc. // note that "bot" isn't required in these variables, // it's only there for readibility // Set up substitutions ! sub won't = will not ! sub i'm = i am // etc // Set up arrays ! array colors = red green blue yellow cyan fuchsia ...
Here are a list of all the globals you might want to configure.
split_sentences - Whether to do sentence-splitting (1 or 0, default 1) sentence_splitters - Where to split sentences at. Separate items with a single space. The defaults are: ! . ? ; macro_failure - Text to be inserted into a bot's reply when a macro fails to run (or return a reply). debug - Debug mode (1 or 0, default 0)
- Make a begin file.
-
Create a file called "begin.rs" -- there are several reasons for doing so.
For one, you should use this file for
!include
statements if you want your brain to use some common libraries or packages. Secondly, you can use the <BEGIN statement to setup a handler for incoming messages.Your begin file could check the "active" variable we set in the config file to decide if it should give a reply.
> begin + request * active=no => Sorry but I'm deactivated right now! - {ok} < begin
These are the basic tips, just for organizational purposes.
SEE OTHER
RiveScript::Parser - Reading and Writing of RiveScript Documents.
RiveScript::Brain - The reply and search methods of RiveScript.
RiveScript::Util - String utilities for RiveScript.
CHANGES
Version 1.00
- Public stable beta release.
Version 0.21
- Added \u tag for inserting an "undefined" character (i.e. set global macro_failure
to \u to remove macro failure notifications altogether from the responses)
- The code to run objects is now run last in RiveScript::Util::tagFilter, so that other
tags such as {random}, <get>, etc. are all run before the object is executed.
- Two new standard libraries have been added:
- Colors.rsl - Arrays for color names
- Numbers.rsl - Arrays for number names
Version 0.20
- Added shortcut tags: <person>, <@>, <formal>, <sentence>, <uppercase>, <lowercase>,
for running the respective tags on <star> (i.e. <person> ==> {person}<star>{/person})
- Added environment variable ENV_REPLY_COUNT which holds the number of loaded triggers.
- Bugfix: sending scalar=>0 to reply() was returning the scalar of the array of replies,
not the array itself. This has been fixed.
Version 0.19
- Added methods for allowing or denying certain commands to be used when RiveScript
documents are loaded in.
- Bugfix: the sortThats() method of RiveScript::Parser was blanking out the current
value of $self->{thatarray} -- meaning, the last file to have %Previous commands used
would be kept in memory, previous ones would be lost. This has been fixed now.
Version 0.18
- Minor bugfix with the "%PREVIOUS" internal array.
Version 0.17
- All the "%PREVIOUS" commands found at loading time are now sorted in an internal
arrayref, in the same manner that "+TRIGGERS" are. This solves the bug with
matchability when using several %PREVIOUS commands in your replies.
- Added the # command as a "Perly" alternative to // comments.
- Comments can be used in-line next to normal RiveScript code, requiring that at
least one space exist before and after the comment symbols. You can escape the
symbols too if you need them in the reply.
- Created a new package DateTime.rsp for your timestamp-formatting needs.
Version 0.16
- Added "! syslib" directive for including Perl modules at the RiveScript:: level,
to save on memory usage when more than one object might want the same module.
- The "%PREVIOUS" directive now takes a regexp. The bot's last reply is saved as-is,
not formatted to lowercase. The % command now works like a +Trigger for the bot's
last reply.
- The "%PREVIOUS" directive check has been moved to another subroutine. In this way,
its priority is much higher. A trigger of * (catch-all) with a %PREVIOUS will always
match, for example.
- Fixed a bug with the BEGIN method. The bot's reply is no longer saved while the
topic is __begin__ - this messed up the %THAT directive.
Version 0.15
- Broke RiveScript into multiple sub-modules.
Version 0.14
- {formal} and {sentence} tags fixed. They both use regexp's now. {sentence} can
take multiple sentences with no problem.
- In a BEGIN statement, {topic} tags are handled first. In this way, the BEGIN
statement can force a topic before getting a reply under the user's current topic.
- Fixed a bug with "blank" commands while reading in a file.
- Fixed a bug with the RiveScriptLib Search Paths.
Version 0.13
- The BEGIN/request statement has been changed. The user that makes the "request"
is the actual user--no longer "__rivescript__", so user-based conditionals can
work too. Also, request tags are not processed until the reply-getting process
is completed. So tags like {uppercase} can modify the final returned reply.
Version 0.12
- Migrated to RiveScript:: namespace.
Version 0.11
- When calling loadDirectory, a "begin.rs" file is always loaded first
(provided the file exists, of course!)
- Added support for "include"ing libraries and packages (see "INCLUDED FILES")
Version 0.10
- The getUservars() method now returns a hashref of hashrefs if you want the
vars of all users. Makes it a little easier to label each set of variables
with the particular user involved. ;)
- Cleaned up some leftover print statements from my debugging in version 0.09
(sorry about that--again!)
- Made some revisions to the POD, fixed some typo's, added {weight} and {ok}
to the TAGS section.
Version 0.09
- $1 to $100+ are now done using an array rather than a hash. Theoretically
this allows any number of stars, even greater than 100.
- Arrays in triggers have been modified. An array in parenthesis (the former
requirement) will make the array matchable in <star#> tags. An array outside
of parenthesis makes it NOT matchable.
- Minor code improvements for readibility purposes.
Version 0.08
- Added <add>, <sub>, <mult>, and <div> tags.
- Added environmental variable support.
- Extended *CONDITION to support inequalities
- Botvars in conditions must be explicitely specified with # before the varname.
- Added "! person" substitutions
- Added {person} tag
Version 0.07
- Added write() method
- reply() method now can take tags to force scalar return or to ignore
sentence-splitting.
- loadDirectory() method can now take a list of specific file extensions
to look for.
- Cleaned up some leftover debug prints from last release (sorry about that!)
Version 0.06
- Extended ^CONTINUE to cover more commands
- Added \s and \n tags
- Revised POD
Version 0.05
- Fixed a bug with optionals. If they were used at the start or end
of a trigger, the trigger became unmatchable. This has been fixed
by changing ' ' into '\s*'
Version 0.04
- Added support for optional parts of the trigger.
- Begun support for inline objects to be created.
Version 0.03
- Added search() method.
- <bot> variables can be inserted into triggers now (for example having
the bot reply to its name no matter what its name is)
Version 0.02
- Fixed a regexp bug; now it stops searching when it finds a match
(it would cause errors with $1 to $100)
- Fixed an inconsistency that didn't allow uservars to work in
conditionals.
- Added <id> tag, useful for objects that need a unique user to work
with.
- Fixed bug that lets comments begin with more than one set of //
Version 0.01
- Initial Release
SPECIAL THANKS
Special thanks goes out to jeffohrt and harleypig of the AiChaos Forum for helping so much with RiveScript's development.
KEYWORDS
bot, chatbot, chatterbot, chatter bot, reply, replies, script, aiml, alpha
AUTHOR
Cerone Kirsle, kirsle --at-- f2mb.com
COPYRIGHT AND LICENSE
RiveScript - Rendering Intelligence Very Easily
Copyright (C) 2006 Cerone J. Kirsle
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2 POD Errors
The following errors were encountered while parsing the POD:
- Around line 1195:
Unknown E content in E<id>
- Around line 1199:
Unknown E content in E<bot>