More About Triggers
RiveScript Tutorial

More About Triggers

Types of Triggers

There are a few different "types" of triggers in RiveScript. They all look the same -- they all use the + command, for instance -- but the interpreter handles them in different ways depending on their contents. You've only seen the Atomic Trigger so far in the last chapter. The types of triggers are as follows:
Atomic Triggers
Atomic triggers contain nothing but whole words. The trigger we used in the last chapter ("hello bot") contains nothing but two words: hello, bot. The human must say this exactly for this trigger to match. There's no flexibility.
Wildcards in Triggers
A trigger containing a wildcard symbol makes it an open-ended trigger. The user can match the trigger by "filling in the blanks" - where the "blanks" are the wildcard symbols. For example the user can say "my name is Casey" without there needing to be a hundred different triggers for each possible name.
Alternations in Triggers
These triggers are similar to wildcard triggers, but they aren't open-ended -- instead, the user can use one word or phrase out of two or more available, and still match the trigger. For example the human may ask "what is your home phone number" or "what is your work phone number" and match the same trigger that allows the word "home" or "work" to be used.
Optionals in Triggers
This is a trigger that contains optional words in it. For example the user might ask "what is your home phone number", or they can ask "what is your phone number" and omit the word "home" -- and both questions can match the same trigger.
Arrays in Triggers
You can define an array of words or phrases and then use these arrays inside of triggers in place of alternations. This way you can reuse the same set of alternations among multiple triggers, for example a list of colors, and then the user can tell the bot about all kinds of things that are colorful.
Prioritized Triggers
Using the same {weight} tag used in responses, you can force a certain trigger to have higher matching priority than the others.
All of these types of triggers will be explained on this page along with examples on how they are used -- with one exception. Triggers with arrays will be explained in the next chapter when we cover the Definition command.

Matching Priority

Before we proceed, let me cover how trigger matching works in RiveScript. It's important to know how this works so you can choose the best type of trigger while writing your own RiveScript code.

The RiveScript interpreter arranges all of the available triggers into a sorted list, and when you send a message to the bot, this list is read from top to bottom until one of the triggers matches the user's message. The list is sorted as follows:

  1. Atomic Triggers First
    • Atomic triggers are sorted by the number of words. A trigger with 3 words, no matter how long or short, is sorted higher than a trigger with 2 words.
    • When there are multiple triggers that have the same number of words, they are sorted by the overall length of the triggers.
    • If multiple triggers have the same number of words AND the same length in characters, they are sorted alphabetically.
  2. Triggers with Optionals Next
    • These triggers are sorted the same way as atomic triggers are.
  3. Then Triggers Containing Wildcards
    • These triggers are sorted by the number of words that aren't wildcards. Additionally, they are sorted by the type of wildcard being used:
    • Alphabetic wildcards first: _
    • Numeric wildcards next: #
    • Global wildcards last: *
  4. Finally, Wildcards by Themselves
    • If any triggers contain only one wildcard symbol, these triggers are placed at the end of the list. They are sorted by the type of wildcard in the same way as #3 above: alphabetic, numeric, and then global.
You're already familiar with Atomic Triggers since we covered them in the last chapter. "hello bot" was an atomic trigger.

Wildcards in Triggers

One of the most useful types of triggers are ones that have wildcards in them. These triggers make for some open-ended matching on the user's message. There are three symbols used for wildcards: _, #, and *. These three wildcards symbols are meant for matching different kinds of data in the user's message:

Alphabetic wildcards use the underscore symbol, _. These wildcards will only match input that has only letters in it. This is useful for capturing the user's name, since most humans don't have numbers in their names.

Numeric wildcards will only match numbers. They use the number symbol, #. These wildcards are useful for capturing numeric values such as the user's age.

Global wildcards, using the asterisk symbol (*), will match both numbers and letters. These are used when you don't have a specific requirement on what kind of data you want to match.

Regardless of the type of wildcard used, you can use the value that the wildcard matched in the response by inserting the <star> tag. If you use more than one wildcard, you can use <star1>, <star2> etc., where the number corresponds to the position of the wildcard in the trigger, from left to right.

Here are some examples of wildcards in use:

Wildcards in Triggers
// Capture the user's name: letters only!
+ my name is _
- It's nice to meet you, <star>.
- <star>, nice to meet you.
- Pleased to meet you, <star>.

// What if the user says "my name is 5"? 5 isn't a real name!
+ my name is #
- Nobody has the name of <star>.
- <star> isn't a real name.
- Names don't have numbers in them, <star>.

// If they say their name is something that contains both numbers
// and letters, match this trigger:
+ my name is *
- Your name has a number in it?

// See how old the user is
+ i am # years old
- A lot of people are <star> years old.

// But don't let them give us their age in words!
+ i am _ years old
- Can you say that again using a number?

// Both numbers and letters?
+ i am * years old
- You told me numbers and letters? Tell me only numbers.

// Let them tell us where they're from. Numbers and letters are OK!
+ i am from *
- What is it like to live in <star>?

// This one has multiple wildcards in it
+ _ told me to say *
- So did you say "<star2>" because "<star1>" told you to?
¤ Try Online

Try this example out and tell the bot your name, age, and location, by saying things like "my name is John", "my name is 5", "I am twenty years old", "I am 100 years old", "I am from New York", etc.

Alternations in Triggers

Open-ended triggers are nice, but sometimes it's more useful to limit what can go into a wildcard by narrowing down the range of what will and won't match.

A common example of why this would be useful is when you have one trigger that can be asked in more than one way by the human. For example if your bot has a phone number, and only one phone number, then it doesn't matter whether the human wanted the bot's home, office, or cell number -- it will give them the same number regardless. The trigger for this would look like this:

Alternation Example
+ what is your (home|office|cell) phone number
You use alternations by enclosing them in parenthesis, and separating each option with a pipe symbol. The options can contain spaces in them. The value chosen by the user can be included in the response via a <star> tag -- just like with wildcards. In the example above, <star> might be "home", "office", or "cell", depending on which one the user said in their message. Here are more examples:
Alternations in Triggers
+ what is your (home|office|cell) phone number
- You can call my <star> number at 1 (888) 555-5555.

+ i (can not|cannot) *
- Have you tried?
- Why can't you <star2>?
- Do you really want to <star2>?

+ who (is your master|made you|created you|programmed you)
- I was developed by a RiveScript coder; you don't need to know his name!

+ (what is your name|who are you|who is this)
- My name is Aiden, I'm a chatterbot running on RiveScript!

+ (happy|merry) (christmas|xmas|valentines day|thanksgiving)
- Wow! Is it really <star2> already?
¤ Try Online

Optionals in Triggers

Similar to alternations, optionals are words or phrases that can help the user match a particular trigger, but it's OK if the user doesn't include these words or phrases in their message. They look like alternations, but they're enclosed in square brackets [, ], and they do not go into the <star> tags in the response.

Here are some examples of optionals:

Optionals in Triggers
// Now they don't even need to say the word "phone"!
+ what is your (home|office|cell) [phone] number
- My <star> number is: 1 (888) 555-5555.

+ i do not have [any] friends
- Aw. I'll be your friend!

+ am i [a] (boy|guy|male) or [a] (girl|female)
- I can't tell with any degree of certainty whether you are a <star1> or <star2>.
¤ Try Online

Notice in the last example the use of <star1> and <star2> - the two optional "a's" don't match into the <star> tags. So here, <star1> is either "boy", "guy", or "male" and <star2> is either "girl" or "female".

Prioritized Triggers

Earlier in this chapter the sorting algorithm for trigger matching was briefly discussed. It was said that triggers that contain at least one wildcard in them are sorted so that the one with the most words (that aren't wildcards) are sorted higher than ones with fewer words.

This presents an interesting dilemma when you actually want a shorter trigger to be "more important" than a longer one. For example, if you were to implement some chat-driven commands, where the user starts their message by saying a specific keyword and then the remainder of their message is to be sent to an external program, you'd want these triggers to always match if the user says the right keyword.

We'll cover the use of objects much later in the tutorial, but here is a working example of an object that creates a Google search link for something the user wants to search for:

Google Search Object
// If the user begins a message with "google" it will create
// a google search link.
+ google *
- Google Search: <call>google <star></call>

// If the user ends their message with "or something", the
// bot will simply say "Or something." and drop the topic.
+ * or something
- Or something.

// Here is the Google search object. We'll cover objects in more
// depth later in the tutorial.
> object google javascript
   var query = escape(args.join(" "));
   return "<a href=\"http://www.google.com/search?q=" + query + "\">Click Here!</a>";
< object
¤ Try Online Try this code and ask it the following questions: The bot will reply "Or something." to your first query, and provide a Google link for your second one. Why? Because of the matching order, the trigger * or something (which has two words that aren't wildcards) has a higher priority than google * (which has only one word). Therefore if the user's message begins with "google" and ends with "or something" -- no matter how long their message is -- the "or something" trigger wins because it's longer.

Now, if we add some extra priority to the Google trigger by using the {weight} tag, we can force it to be higher on the matching list than it would otherwise be. Here's an example if we give it a weight tag:

Google Search Object
// If the user begins a message with "google" it will create
// a google search link.
+ {weight=100}google *
- Google Search: <call>google <star></call>

// If the user ends their message with "or something", the
// bot will simply say "Or something." and drop the topic.
+ * or something
- Or something.

// Here is the Google search object. We'll cover objects in more
// depth later in the tutorial.
> object google javascript
   var query = escape(args.join(" "));
   return "<a href=\"http://www.google.com/search?q=" + query + "\">Click Here!</a>";
< object
¤ Try Online

Now if you say "google hello world or something", it will provide you a Google search link instead of saying "Or something."

The number in the weight tag gives the trigger special priority. If more than one trigger has the same number in their weight tags, these triggers will be sorted amongst themselves as normal, and then placed in the final sort buffer with a higher priority than other triggers that have less weights.

It is not recommended to use weight tags except when absolutely necessary, like in this example. If your bot has a Google search command, it wouldn't be good if the command would only work "some of the time", depending on how your user phrased their question. You'd want it to work "all of the time," so you'd put a weight on this trigger so that it will always be at the top of the list of triggers when the interpreter looks for a match.

In the next chapter we'll cover the Definition command, which will enable the use of arrays in triggers, as well as set up some substitutions that can modify the user's message before it reaches your RiveScript code to make coding simpler.

Up: Table of Contents
Next: Definitions and Arrays