1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569
|
=head1 NAME
RiveScript::Tutorial - Learn to write RiveScript code.
=head1 INTRODUCTION
This tutorial will help you learn how to write your own chatbot personalities
using the RiveScript language.
=head2 What is RiveScript?
RiveScript is a text-based scripting language meant to aid in the development
of interactive chatbots. A chatbot is a software application that can
communicate with humans using natural languages such as English in order to
provide entertainment, services or just have a conversation.
=head2 Getting Started
To B<write> your own RiveScript code, you will only need a simple text editing
program. You can use Notepad for Windows, or gedit for Linux, or any other
text editors you have available.
A RiveScript document is a text file containing RiveScript code. These files
will have a C<.rive> extension. An example file name would be C<greetings.rive>.
If you're writing RiveScript documents on Windows, you may need to put the
file name in quotes when you save it, for example C<"greetings.rive"> to be
sure it gets saved with the file extension (and not "C<greetings.rive.txt>").
To B<execute> and test your RiveScript code, you will need a RiveScript
Interpreter, or, a program that uses a RiveScript library to read and execute
RiveScript code.
The Perl L<RiveScript> module comes with a ready-to-use interpreter that can
be used for this tutorial! If you've installed the Perl RiveScript module on
a Linux, Unix or Mac OS system, the RiveScript interpreter will probably be
installed in a place like C</usr/bin/rivescript> or
C</usr/local/bin/rivescript>. You can open a terminal window and run the
command "C<rivescript>" to use the RiveScript interpreter.
If you're using Windows, you can open a Command Prompt window and run the
command "C<rivescript>" to use the RiveScript interpreter.
If you are able to run the RiveScript interpreter that is shipped with the
Perl distribution, you will be able to continue with this tutorial. If you're
using a different RiveScript library, such as the Python version, please refer
to the documentation of the library to see if it comes with a RiveScript
interpreter that you can use.
If you need to write your own interpreter program, see
L<"Writing an Interpreter"> for an example of how to do this in Perl.
This tutorial will assume you are using the C<rivescript> command shipped
with the Perl RiveScript library.
=head2 Project Directory
For this tutorial, you should create a folder to save your RiveScript documents
to. The following are some recommended locations, but you can place them
wherever you like.
For Linux, Unix and Mac OS users, I recommend making a folder in your home
directory, like so:
Unix: /home/USER/rstut
Mac: /Users/USER/rstut
Substitute C<USER> with your username of course.
For Windows users, make a directory in the C<C:\> drive, like so:
Windows: C:\rstut
After you begin writing RiveScript documents, you can test your code at any time
by running the RiveScript interpreter and pointing it at your reply directory.
For Linux, Unix and Mac OS users, open a terminal window and run a command such
as the following:
rivescript rstut
For Windows, open a command prompt window (push the Start button, type C<cmd>
and hit Enter. For Windows XP or older, push the Windows key + R on your
keyboard, and type C<cmd> and hit enter in the Run dialog). Navigate to the
"bin" folder in the Perl RiveScript distribution by using the C<cd> command,
and then run the following command:
rivescript C:/rstut
If you're having trouble getting this to work on Windows, see
L<"Windows Troubleshooting"> for help.
=head1 FIRST STEPS
=head2 Hello, Human!
Let's write our first few lines of RiveScript code!
In your text editor, create a new file and write the following in it:
! version = 2.0
+ hello bot
- Hello, human!
Save this in your project directory as C<hello.rive>, and then run the RiveScript
interpreter on that directory (see L<"Project Directory"> for reference). You
should see something along these lines in your terminal window:
RiveScript Interpreter - Interactive Mode
-----------------------------------------
RiveScript Version: 1.30
Reply Root: rstut
You are now chatting with the RiveScript bot. Type a message and press
Return to send it.
When finished, type '/quit' to exit the program. Type '/help' for other
options.
You>
At the prompt, type "Hello bot" and press Enter. The bot should respond with
"Hello, human!"
Try saying something else to the bot, such as "how are you?" and see what
it says. The bot should respond with, "ERR: No Reply Matched". This is because
you said something that there was no RiveScript code written to handle. There
is only a handler for "hello bot", and nothing else. Later you will learn how
to write a "catch-all" response that will be used when you say something the
bot wasn't programmed to handle. But first, let's go over the code you wrote
for C<hello.rive>.
=head3 The Code, Explained
RiveScript code is really simple. Each line of the text file is a separate
entity (RiveScript is a line-based scripting language). Lines of RiveScript
code always begin with a command symbol (in this example, the symbols we see
are C<!>, C<+>, and C<->) and they always have some kind of data that follows
them. The data depends on the command used.
The line, "C<! version = 2.0>" tells the RiveScript interpreter that your code
follows version 2.0 of the RiveScript specification. This way, future versions
of the language can be backwards compatible with existing code by looking at
the version number and responding accordingly. It is a good idea to always
include the version line in your code (but it isn't the end of the world if you
leave it out -- you'll just leave the interpreter to make its best guess about
which version your code is using).
The C<+> command is how you define a B<trigger>. A trigger is a line of text
that is used to match the user's message. In this case, "hello world" is
exactly the message that we're matching. You will learn about some more
complex features of triggers later in this tutorial.
B<Important Note:> a trigger is ALWAYS lower cased, and it doesn't contain
punctuation symbols. Even if you write a trigger that contains the proper noun
"I", that "I" should be lowercased too. You may have noticed when testing your
code that the interpreter doesn't care about the capitalizations used in your
messages: you can say "Hello Bot", "HELLO BOT", or "hello bot" and it will
match the trigger all the same.
The C<-> command is how you define a response to a trigger. In this case,
when the user matches the "hello bot" trigger, the bot should respond to
the user by saying "Hello, human!"
=head2 Random Replies
Making your bot I<always> respond exactly the same way to something the user
says will get boring really quickly. For this reason, RiveScript makes it
easy to add random responses to a trigger!
Getting random responses is as easy as entering multiple Response commands
for the same trigger. To see this in action, open your C<hello.rive> file from
L<"Hello, Human!"> and add the following lines to it:
+ how are you
- I'm great, how are you?
- I'm good, you?
- Good :) you?
- Great! You?
- I'm fine, thanks for asking!
Save this and then test it with the RiveScript interpreter. Ask your bot,
"How are you?" a few times and see how it responds. It will say one of these
five things at random each time you ask!
You can also use random strings I<inside> a reply by using the C<{random}>
tag (see L<"TAGS">). Example:
+ say something random
- This {random}message|sentence{/random} has a random word.
Between the C<{random}> and C<{/random}> tags, you separate the strings
with a pipe symbol and one will be chosen randomly.
=head3 A Note About Style
To keep your RiveScript documents nice and tidy and easy to read (and
maintain!) you should follow these style guidelines:
=over 4
=item * Use blank lines to separate logical groups of code.
For example, a trigger line and its responses should be grouped together,
and a blank line should separate them from a different trigger and its
responses.
=item * Indent code inside a topic or begin block.
You'll learn about these later in this tutorial.
=back
So, our C<hello.rive> should look like this now:
! version = 2.0
+ hello bot
- Hello, human!
+ how are you
- I'm great, how are you?
- I'm good, you?
- Good :) you?
- Great! You?
- I'm fine, thanks for asking!
=head3 Let's Talk About Weight
While random responses are certainly useful, there will be times when you
would prefer that I<some> replies would be chosen more frequently than
others. For example, you might be writing a bot whose personality is that
he's secretly an alien pretending to be a human that's pretending to be a
bot, and you want the bot to respond in some unintelligible gibberish
every once in a while.
You can use the C<{weight}> tag in a reply to override how frequently that
reply will be chosen compared to the others. For our alien gibberish example,
you could write a reply like this:
+ greetings
- Hi there!{weight=20}
- Hello!{weight=25}
- Yos kyoco duckeb!
Here, we've assigned a weight to each of the English responses, and
left the gibberish one alone. The effect that this has is that "Hi there!"
will be picked 20 times out of 46, "Hello!" will be picked 25 times out of
46, and "Yos kyoco duckeb!" will be chosen only 1 time out of 46.
You can test this by saying "greetings" to your bot over and over again.
It should I<very rarely> choose the "Yos kyoco duckeb!" response compared
to the other two.
The weight value controls the probability that the reply is chosen. Replies
that don't explicitly include a weight tag automatically have a weight of 1.
The probability of each reply being chosen is the reply's weight divided by
the sum of all the weights combined (in this example, 20 + 25 + 1 = 46, so
each reply has its weight out of 46 chance of being chosen).
Weight values can't be zero and they can't be negative.
You B<can not> use weights inside a C<{random}> tag.
=head2 Line Breaking
There will be times when you're writing a really long line of RiveScript
code and you'd like to break it to span multiple lines. For these cases,
you can use the C<^> command (B<Continuation>). The C<^> command automatically
extends the data from the previous line. Here is an example:
+ tell me a poem
- Little Miss Muffit sat on her tuffet,\n
^ In a nonchalant sort of way.\n
^ With her forcefield around her,\n
^ The Spider, the bounder,\n
^ Is not in the picture today.
Note that the Continuation command doesn't automatically insert a space between
the previous line and the continuation line. Consider the following example:
// There will be no space between "programmed" and "using"!
+ what are you
- I am an artificial intelligence programmed
^ using RiveScript.
If you asked "what are you" with this reply, the bot would say, "I am an
artificial intelligence programmedusing RiveScript.", with no space between
"programmed" and "using".
To make sure there's a space between continuations, use the escape sequence
C<\s> where you want the space to appear.
// This one will have a space.
+ what are you
- I am an artificial intelligence programmed\s
^ using RiveScript.
From the "tell me a poem" example, the escape sequence C<\n> inserts a line
break instead of a space.
=head1 ANATOMY OF A RIVESCRIPT BRAIN
=head2 The Begin File
You now know some of the basics about how triggers and replies relate to
each other. Before continuing, you should know how RiveScript brains are
typically organized.
RiveScript brains (a "brain" is a set of RiveScript documents) should, by
convention, include a document named C<begin.rive> that contains some
configuration settings for your bot's brain. The most useful settings that
would be set here include B<substitutions>, which are able to make changes
to the user's message I<before> a reply is looked for.
You may have noticed that the RiveScript interpreter doesn't care about
punctuation in your messages (you can say "Hello bot!!!" and it ignores the
exclamation marks), so what does that mean for things such as the word "what's"?
By default, the word "what's" would be converted into "whats" before the
interpreter looks for a reply for it. With substitutions, you can see to it
that "what's" is expanded into "what is" instead -- allowing you better
control over how you reply to the user's message!
Let's start with our C<begin.rive> file. In your text editor, create a new
document and write the following code into it (this code will be explained
below):
! version = 2.0
// Bot variables
! var name = Tutorial
! var age = 5
// Substitutions
! sub i'm = i am
! sub i'd = i would
! sub i've = i have
! sub i'll = i will
! sub don't = do not
! sub isn't = is not
! sub you'd = you would
! sub you're = you are
! sub you've = you have
! sub you'll = you will
! sub what's = what is
! sub whats = what is
! sub what're = what are
! sub what've = what have
! sub what'll = what will
Save this as C<begin.rive> in your project directory. Now, for an explanation on
what this code is doing.
=head3 Definitions
You've already seen the C<!> command used for the version line, but what are all
these other lines? More generally, the C<!> command is used for B<Definitions>
(just like the C<+> is for B<Triggers> and the C<-> is for B<Replies>). In the
version line, we are I<defining> that the version is 2.0.
Also, you may be wondering what the C<//> characters are for. Like in most
programming languages, RiveScript allows you to include B<Comments> in your
source code. The C<//> characters denote the start of a comment. The interpreter
will ignore these comments when it reads your code; they're only there for the
humans (you!) who have to read and maintain the code.
Now let's go over these new definition types.
First, we defined a couple of B<Bot Variables>. These are pieces of information
that describe your bot, such as its name and age in this example. These will
come in handy later. With bot variables, we can write replies in which the bot
can tell the user a little something about itself.
Then, we defined a handful of B<Substitutions>. Substitutions are
I<always lowercased>. On the left side of the = sign, you write the "original
text" that may appear in the user's message, and on the right you place the
substituted text. The text on the right I<should not> contain any special
symbols or punctuation, and it should also be lowercased.
With these substitutions, if a user says to the bot, "what's up?" or
"I've been at work all day", the RiveScript interpreter will expand these
messages out to "what is up" and "i have been at work all day", respectively,
before it starts looking for a reply.
Here is some more code that you can add to your C<hello.rive> file from earlier
that demonstrates how substitutions work:
+ what is up
- Not much, you?
- nm, you?
- Not a lot, you?
+ you are a bot
- How did you know I'm a machine?
You can then ask your bot, "What's up?" or "You're a bot" and see that it
matches these replies accordingly. Notice that the substitutions didn't
apply to the bot's response to "you're a bot" -- it says "How did you know
I'm a machine?" -- substitutions only apply to the user's
incoming message. They're also used with the C<% Previous> command, but
we'll get to that later.
There are other types of definition commands available too: C<array>,
C<global>, and C<person>. These are useful for more advanced replies and
they'll be covered later in this tutorial.
B<Note:> there will be many more examples of RiveScript code in this
tutorial. You can put these in any RiveScript document you wish; you can
create a new C<.rive> file for them if you like. Now and then I'll mention
a recommended file name, though, but the names don't really matter that
much.
=head1 TRIGGERS
=head2 Open-Ended Triggers
So far, the triggers you've seen have been what I call "atomic" -- they
describe a user's message I<perfectly>. For example, the user must say
exactly "hello bot"; they can't say "hello there" or "hello robot" and
still match one of your triggers, unless you've written individual triggers
for each possible thing they could say!
This is where B<Wildcards> come into play. With wildcards, you can mark
a part of the trigger as being open-ended. The best way to demonstrate
this is with an example:
+ my name is *
- Nice to meet you, <star1>!
+ * told me to say *
- Why would <star1> tell you to say "<star2>"?
- Did you say "<star2>" after <star1> told you to?
+ i am * years old
- A lot of people are <star1> years old.
With these triggers, a user can say "My name is Noah", or "I am 24 years
old", and the bot will be able to match these messages all the same.
Wildcards are very useful to match messages that may contain "variable"
data, such as names or numbers. They're also useful for your bot to be
able to fake knowledge about a subject:
+ where is *
- Where it belongs.
- Where you left it.
- Where the heart is.
You can write triggers for common questions like "who is", "where is",
and "what is" by using wildcards; so, if the user asks your bot about
something that your bot doesn't have a special trigger to handle, it
can give a sort of "generic" response that will be at least somewhat
relevant to the question.
You may have noticed the C<E<lt>star1E<gt>> and C<E<lt>star2E<gt>>
tags that appeared in some of those replies up there. These tags can
be used in a reply in order to repeat the words matched by the wildcards.
When the user says "my name is Noah", the first wildcard in that trigger
would catch the name, and C<E<lt>star1E<gt>> would be "noah" in this
case.
If you only have a single wildcard, you may just use the C<E<lt>starE<gt>>
tag without the number "1" as a shortcut:
+ who is *
- I don't know who <star> is.
While we're on the topic of wildcards...
=head3 Catch-All Trigger
Remember back in L<"Hello, Human!"> where the bot would say "ERR: No Reply
Matched" whenever we said something it couldn't reply to? Well, we can
remedy this by writing a catch-all trigger.
A catch-all trigger is one that simply consists of a single wildcard:
+ *
- I'm not sure how to reply to that.
- Try asking your question a different way.
- Let's change the subject.
Anything the user says now that doesn't get matched by a more relevant
trigger will fall back to the C<*> trigger. This way, you can avoid letting
the bot say "ERR: No Reply Matched", and use it to try to steer the
conversation back on track.
Conventionally, your catch-all trigger should go into a file named
C<star.rive>, so that when you're looking for it later to make changes
you'll know exactly where you put it.
=head3 Specialized Wildcards
Wildcards are great, but what if you want to restrict what a wildcard is
allowed to match? For example, the trigger "i am * years old" would match
a message like "I am twenty four years old" just as well as "I am 24 years
old".
There are two other wildcard symbols you may use. The C<#> symbol is a wildcard
that will I<only> match a number. The C<_> symbol is one that will I<only> match
a word with no numbers or spaces in it.
You can have multiple triggers that look the same but use different wildcards
and they will work how you'd expect:
+ i am # years old
- A lot of people are <star> years old.
+ i am _ years old
- Tell me that again but with a number this time.
+ i am * years old
- Can you use a number instead?
Regardless of the type of wildcard you use, you can use the C<E<lt>starE<gt>>
tags to pull them into the reply.
=head2 Alternatives and Optionals
What if you want to use something like a wildcard, but you want to limit the
possible words to a select few? This is where optionals come into play.
The syntax for these is a little tricky. Let's start with some examples:
+ what is your (home|office|cell) number
- You can reach me at: 1 (800) 555-1234.
+ i am (really|very|super) tired
- I'm sorry to hear that you are <star> tired.
+ i (like|love) the color *
- What a coincidence! I <star1> that color too!
- I also have a soft spot for the color <star2>!
- Really? I <star1> the color <star2> too!
- Oh I <star1> <star2> too!
In these examples, a user can say "what is your home number", or "what is
your office number", or "what is your cell number" and match the first
trigger. Or they can say "I am really tired", "I am very tired", or "I am
super tired" and match the second one. And so on. But, if the user says
"I am extremely tired", it won't match because "extremely" wasn't listed
in the alternatives!
The alternative that the user used in their message can be captured with
a C<E<lt>starE<gt>> tag too, just like wildcards. Alternatives don't have
to be single words, either.
+ i (will|will not) *
- It doesn't matter to me whether you <star2> or not.
Optionals are like alternatives, but they don't I<need> to be present in
the user's message I<at all!> But, if the user does say them, it will help
match the reply anyway.
+ how [are] you
- I'm great, you?
+ what is your (home|office|cell) [phone] number
- You can reach me at: 1 (800) 555-1234.
+ i have a [red|green|blue] car
- I bet you like your car a lot.
Since optionals don't have to be present in the user's message, they
I<can not> be captured with C<E<lt>starE<gt>> tags. If you had a wildcard
or alternative before and after an optional, C<E<lt>star1E<gt>> would be the
first wildcard or alternative, and C<E<lt>star2E<gt>> would be the second; the
optional would be skipped.
A clever thing you can do with optionals is write "keyword" triggers: if
the user says a magic word ANYWHERE in their message, your trigger will match!
+ [*] the machine [*]
- How do you know about the machine!?
You can also use these C<[*]> optionals to ignore parts of a message by putting
it before or after your trigger instead of on both sides.
=head2 Arrays in Triggers
Consider something a human might say to a bot: "what color is my blue shirt?"
You might be able to program a reply to this using wildcards, but alternatives
would be even better, since you can limit the color to a small set.
+ what color is my (red|blue|green|yellow) *
- Your <star2> is <star1>, silly!
Wouldn't it be useful to re-use this list of colors for other triggers without
having to copy and paste it all over the place? Well, that's exactly the reason
why B<Arrays> exist! In RiveScript, you can make a list of words or phrases,
give that list a name, and then use it in a trigger (or multiple triggers!)
You define an array using the C<! array> command, which was first mentioned
in the L<"Definitions">. By convention, all definitions belong in C<begin.rive>,
so write the following code in C<begin.rive>:
! array colors = red blue green yellow
Now, you can refer to this array by name in your triggers. Here are a couple
examples you can use (you can use arrays in as many triggers as you want):
+ what color is my (@colors) *
- Your <star2> is <star1>, silly!
- Do I look dumb to you? It's <star1>!
+ i am wearing a (@colors) shirt
- Do you really like <star>?
Just like wildcards and alternatives, the word the user used out of the array
can be captured in a C<E<lt>starE<gt>> tag. If you don't want this to happen,
you can use the array without the parenthesis around it:
// Without parenthesis, the array doesn't go into a <star> tag.
+ what color is my @colors *
- I don't know what color your <star> is.
Arrays can be used in optionals too. They don't go into C<E<lt>starE<gt>> tags
though, because optionals I<never> do!
// Arrays in an optional
- i just bought a [@colors] *
- Is that your first <star>?
When defining arrays, you can either separate the array items with spaces
(useful for single words) or pipe symbols (for phrases). Examples:
// Single word array items
! array colors = red blue green yellow
// Multiple word items
! array blues = light blue|dark blue|medium blue
If you use Continuations when defining an array, you can swap between
spaces and pipes on each line. Here is a very thorough array of colors:
// A lot of colors!
! array colors = red blue green yellow orange cyan fuchsia magenta
^ light red|dark red|light blue|dark blue|light yellow|dark yellow
^ light orange|dark orange|light cyan|dark cyan|light fuchsia
^ dark fuchsia|light magenta|dark magenta
^ black gray white silver
^ light gray|dark gray
=head2 Priority Triggers
You're almost done learning about all the things that can be done to a trigger!
The last thing is weighted, or priority triggers. You've seen the C<{weight}>
tag applied to responses before. Well, the same tag can also be used in a
trigger!
A weighted trigger has a higher matching priority than others. This is useful
to "hand tune" how well a trigger matches the user's message. An example of
this would be, suppose you have the following two triggers:
+ google *
- Google search: <a href="http://google.com/search?q=<star>">Click Here</a>
+ * perl script
- You need Perl to run a Perl script.
What if somebody asked the bot, "google write perl script"? They might expect
the bot to provide them with a Google search link, but instead the bot replies
talking about needing Perl. This is because "* perl script" has more words than
"google *", and therefore would usually be a better match.
We can add a C<{weight}> tag to the Google trigger to make that trigger "more
important" than anything with a lower weight.
+ google *{weight=10}
- Google search: <a href="http://google.com/search?q=<star>">Click Here</a>
+ * perl script
- You need Perl to run a Perl script.
Now, if the user starts their message with "google", that trigger will have a
higher priority for matching than anything else. The weights on triggers are
arbitrary, and higher numbers just mean it has a higher priority than ones with
lower numbers. Triggers that don't have a C<{weight}> tag automatically have a
weight of 1.
You can't have a zero or negative weight value.
If you have multiple triggers with the same weight value, these triggers are
considered equals, and their matching order will be the same as usual (triggers
with more words are tested first). If no triggers with a given weight can
match the user's message, then triggers with a lower weight are tried.
See the "Sorting +Triggers" section of the RiveScript Working Draft for a
detailed explanation of how triggers are sorted.
=head1 MORE COMMANDS
=head2 Redirections
If a user matches a trigger, you can have that trigger simply redirect them
somewhere else, as though they had asked a different question. Example:
+ hello
- Hi there!
- Hey!
- Howdy!
+ hey
@ hello
+ hi
@ hello
In this example, if the user says "hey" or "hi", the bot redirects them to the
"hello" trigger, as though they had said hello to begin with.
Of course, with alternatives and the other advanced trigger features, redirects
like this aren't always useful. But you can also use redirects I<inside> of
replies. One of my favorite examples of this:
+ * or something{weight=100}
- Or something. {@ <star>}
If the user says, "Are you a bot or something?", the bot might reply, "Or
something. How did you know I'm a machine?"
If you just want to use C<{@ E<lt>starE<gt>}>, you can use a shortcut tag
instead: C<E<lt>@E<gt>>. Use the C<{@...}> format for everything else:
+ hello *
- {@ hello} <@>
+ hello
- Hi there!
+ are you a bot
- How did you know I'm a machine?
This trigger would reply to "Hello, are you a bot?" with a reply like
"Hi there! How did you know I'm a machine?"
=head2 Short Discussions
Suppose you want to program your bot to be able to play along with a user
who is telling a Knock-Knock joke? You can pull this off with the C<%>
command (B<Previous>):
+ knock knock
- Who's there?
+ *
% who is there
- <star> who?
+ *
% * who
- LOL! <star>! That's funny!
This example introduces the C<%> command. The C<%> command is similar to the
C<+> used for triggers, except it looks at the bot's previous response to the
user instead. In the second trigger here, if the bot's previous response was
"who is there", anything the user says (C<*>) will match, and the bot will
continue playing along with the joke.
In the C<%> command, the bot's previous response is sent through the same
substitutions as the user's messages are. Notice that the bot's reply was
"Who's there?", but the C<%> line on the next trigger says "who is there".
This is because the "Who's" was substituted for "who is" due to the
substitution defined in your C<begin.rive> file!
C<% Previous> lines need to be lowercased just like triggers do.
Here is another example:
+ i have a dog
- What color is it?
+ (@colors)
% what color is it
- That's a silly color for a dog!
Now you can say "I have a dog" and the bot will ask what color it is. If you
tell it the color, it will say "That's a silly color for a dog!" -- but, if
you ignore the bot's question and say something else, the bot will just reply
to your new message as usual.
=head2 Conditionals
=head3 Learning Things
You now know most of the RiveScript commands and how to use them. But what good
is a chatbot if it can't even remember your name?
RiveScript has the capability to store and repeat variables about users. To set
a user variable, we use the C<E<lt>setE<gt>> tag, and to retrieve the variable
we use C<E<lt>getE<gt>>. Here are some examples of how we can learn and repeat
information about the user.
+ my name is *
- <set name=<star>>It's nice to meet you, <get name>.
+ what is my name
- Your name is <get name>, silly!
+ i am # years old
- <set age=<star>>I will remember that you are <get age> years old.
+ how old am i
- You are <get age> years old.
While we're talking about variables, what about those bot variables we defined
in C<begin.rive>? You can retrieve them in a similar fashion:
// The user can ask the bot its name too!
+ what is your name
- You can call me <bot name>.
- My name is <bot name>.
+ how old are you
- I am <bot age> years old.
Now, you may notice that if you tell the bot, "My name is Noah", it will store
your name as "noah" -- lowercased. To store the name as a proper noun instead,
you can use the formal tag. See L<"TAGS">.
// Store the name with the correct casing
+ my name is *
- <set name=<formal>>Nice to meet you, <get name>!
The C<E<lt>formalE<gt>> tag is a shortcut for
C<{formal}E<lt>starE<gt>{/formal}>, so you will need to use the
C<{formal}...{/formal}> syntax to formalize other things. See L<"TAGS">.
=head3 Writing Conditionals
And with learning information about the user, conditionals let us pick replies
based on the values of those variables!
You may notice that if you asked the bot what your name was I<before> you told
the bot your name, it would say "Your name is undefined, silly!" This doesn't
look very professional and would give away that the bot is just a program.
With conditionals, you can make sure the bot knows a user's name before it
opens its big mouth, and say something else if it doesn't know.
Here is an example:
+ what is my name
* <get name> == undefined => You never told me your name.
- Your name is <get name>, silly!
- Aren't you <get name>?
Now, if you ask the bot your name, it will see if your name is "undefined", and
if so, it will say "You never told me your name." Otherwise, it will give one of
the other replies.
Conditions are used to compare variables to values. You can also compare
variables to other variables. Here is a more advanced way of telling the
bot what your name is:
+ my name is *
* <formal> == <bot name> => Wow, we have the same name!<set name=<formal>>
* <get name> == undefined => <set name=<formal>>Nice to meet you!
- <set oldname=<get name>><set name=<formal>>
^ I thought your name was <get oldname>?
If you're feeling a little bit cramped on the condition lines, using the
C<^ Continuation> command is useful to get some more room.
Conditions are checked in order from top to bottom. If no condition turns out
true, the normal C<-> replies are used. If you want to have a random response
when a condition is true, you need to use the C<{random}> tag.
With conditionals, you can use the following equality tests:
== equal to
eq equal to (alias)
!= not equal to
ne not equal to (alias)
<> not equal to (alias)
The following equality tests can be used on variables that contain numbers
only:
< less than
<= less than or equal to
> greater than
>= greater than or equal to
Here is an example using different equality tests:
+ what am i old enough to do
* <get age> > 25 => You can do anything you want.
* <get age> == 25 => You're old enough to rent a car with no extra fees.
* <get age> > 21 => You're old enough to drink, but not rent a car.
* <get age> == 21 => You're exactly old enough to drink.
* <get age> > 18 => You're old enough to gamble, but not drink.
* <get age> == 18 => You're exactly old enough to gamble.
* <get age> < 18 => You're not old enough to do much of anything yet.
- I don't know how old you are.
=head1 LABELED SECTIONS
There are three types of labeled sections. Labels are defined using the
C<E<gt>> command symbol, and they're ended with C<E<lt>>. All labeled
sections should be properly closed when done (even if it's at the end of the
file). For style purposes, you should indent the contents of a labeled section
too. Labeled sections can not be embedded inside each other.
=head2 Topics
Topics are logical groupings of triggers. When a user is in a topic, they can
only match triggers that belong to that topic. Here's an example:
+ i hate you
- You're really mean! I'm not talking again until you apologize.{topic=sorry}
> topic sorry
// This will match if the word "sorry" exists ANYWHERE in their message
+ [*] sorry [*]
- It's OK, I'll forgive you!{topic=random}
+ *
- Nope, not until you apologize.
- Say you're sorry!
- Apologize!
< topic
In this example, if the user tells the bot that they don't think very much of
it, the bot will force the user to apologize before continuing conversation.
Once the user has been put into the "sorry" topic, the ONLY triggers available
for matching are the two in that topic.
The default topic is "random", and you change the user's topic using the
C<{topic}> tag, for example C<{topic=sorry}> and C<{topic=random}>.
You might be wondering why you can't use C<E<lt>set topic=randomE<gt>> instead.
Well, you I<can>, but there is a small difference in how the two tags will
behave:
The C<E<lt>setE<gt>> tag can appear multiple times in a reply and each one is
processed in order. The C<{topic}> tag can only appear once (if there are
multiple ones, the first one wins). So, they'll both do the same job, but
C<{topic}> is a little shorter to type.
Topics are capable of inheriting and including triggers from other topics, too.
But, this is for more advanced users and is outside the scope of this tutorial
(see the file C<rpg.rive> that comes with standard RiveScript distributions for
a practical example of this).
You may be wondering what happens if you accidentally set the topic to one
that doesn't exist? Would the user be unable to chat with the bot anymore since
no replies can be matched? Fortunately, the RiveScript libraries are smart
enough to detect this and will place the user back in the "random" topic
automatically.
=head2 The Begin Block
The Begin Block is an optional feature of a RiveScript brain. The Begin Block
will typically be found in C<begin.rive>. They work in a similar fashion as
topics. Here is an example:
> begin
+ request
- {ok}
< begin
The Begin block serves as a pre-processor I<and> post-processor for fetching
a response. If the Begin Block is present, the C<request> trigger will be tried
for each message the user says. If the response to this contains the C<{ok}>
tag, then a reply is fetched for the user's message and the C<{ok}> tag is
substituted out.
Here is a longer example that use the pre-processing capabilities of the
Begin Block to introduce itself to new users and interview them:
> begin
// If we don't know their name, set the new_user topic and continue.
+ request
* <get name> == undefined => {topic=new_user}{ok}
- {ok}
< begin
> topic new_user
+ *
- Hi! I'm <bot name>! I'm a chatbot written in RiveScript.\s
^ What is your name?{topic=asked_name}
< topic
> topic asked_name
+ #
- Your name is a number?
+ *
- I only want your first name.
+ _
- <set name=<formal>>Nice to meet you, <get name>!{topic=random}
< topic
And here is another example that would use the post-processing capability for
the Begin Block:
> begin
// Change the reply formatting based on the bot's mood
+ request
* <bot mood> == happy => {sentence}{ok}{/sentence}
* <bot mood> == angry => {uppercase}{ok}{/uppercase}
* <bot mood> == sad => {lowercase}{ok}{/lowercase}...
- {ok}
< begin
With this example, the bot would change the formatting of its response based on
a "mood" variable. It will be left as an exercise for you to decide how the
mood variable would be set (you can use e.g. C<E<lt>bot mood=happyE<gt>> to
change the value of a bot variable from a reply).
=head2 Object Macros
In RiveScript, an Object Macro is a programming function written in another
programming language. Usually, a RiveScript library written in a dynamic
programming language such as Perl or Python will support Object Macros of the
same language. The RiveScript libraries will also allow you to add custom
language handlers to support other languages, but this will be up to the
programmer and is outside the scope of this tutorial.
Object macros allow you to do more powerful things with your bot's responses.
For example, you can allow the user to ask the bot questions about the current
weather or about movie ticket prices, and your bot can call an object macro that
goes out to the Internet to fetch that information.
All object macros should define the programming language they're written in,
in lowercase (e.g. "perl", "python", "javascript").
Here is an example of an object macro written in Perl (you will be able to run
this code using the Perl RiveScript interpreter).
// The object name is "hash", written in Perl
> object hash perl
my ($rs, $args) = @_;
my $method = shift @{$args};
my $string = join " ", @{$args};
# Here, $method is a hashing method (MD5 or SHA1), and $string
# is the text to hash.
if ($method eq "MD5") {
require Digest::MD5;
return Digest::MD5::md5_hex($string);
}
elsif ($method eq "SHA1") {
require Digest::SHA1;
return Digest::SHA1::sha1_hex($string);
}
< object
// You call an object using the <call> tag.
+ what is the md5 hash of *
- The hash of "<star>" is: <call>hash MD5 <star></call>
+ what is the sha1 hash of *
- The hash of "<star>" is: <call>hash SHA1 <star></call>
Here is another example of an object that would tell you the bot's public IP
address, using icanhazip.com. You'd probably want to secure this question and
only allow the bot's owner to get the IP address for obvious privacy reasons.
So, you can have an "authentication" system before the bot will allow you to
see its IP address.
// To gain botmaster power, say "I am your master"...
+ i am your master
- Then you must know the secret password:
// And then enter the botmaster password...
+ *
% then you must know the secret password
* <star> == rivescript is awesome => Correct password!<set master=true>
- That's not the right password. :-P
// And after authenticated, let them get the bot's IP address!
+ what is your ip address
* <get master> == true => My IP address is: <call>myip</call>
- You're not my master so you don't need to know! :-P
// The object macro that fetches an IP address.
> object myip perl
my ($rs, $args) = @_;
# Fetch the IP.
use LWP::Simple;
my $ip = get "http://icanhazip.com";
return $ip;
< object
As you can see from this example, you don't need to declare your object macro
before calling it with a C<E<lt>callE<gt>> tag. The RiveScript interpreter
parses I<all> of your code before you can start getting replies, so it will
find your object macro definition no matter where you put it.
You can test this code with the Perl RiveScript interpreter like so:
You> What is your IP address?
Bot> You're not my master so you don't need to know! :-P
You> I am your master.
Bot> Then you must know the secret password:
You> RiveScript is awesome
Bot> Correct password!
You> What is your IP address?
Bot> My IP address is: 67.205.20.243
See the documentation of your RiveScript library to see how to write object
macros (in particular, to see the format in which arguments are passed to your
object).
=head1 MORE DEFINITIONS
To go back to C<begin.rive> definition commands, there are two more types that
may come in handy.
=head2 Global Variables
Global variables are similar to bot variables, but they're not particularly
related to your bot as an entity. Global variables may be defined by your
RiveScript interpreter (a common example would be to make all the environment
variables of your program available as globals in RiveScript, for example
C<E<lt>env REMOTE_ADDRE<gt>> could be used to show the user's IP address in
a CGI environment). However, there are two special globals that affect the
RiveScript interpreter directly:
=over 4
=item Debug Mode
! global debug = true
! global debug = false
This global variable will turn debug mode on or off in the RiveScript
interpreter. Debug mode typically will print lines of text to the terminal
window that will thoroughly document I<what> the interpreter is doing (for
example, if debug mode is on while parsing files from disk, it will print
every line of RiveScript code it sees and a short summary of what it's doing
with it. When it's on while fetching a reply, it will print every trigger that
it's trying to compare the user's message to, etc.)
The value should be C<true> or C<false>.
=item Recursion Depth
! global depth = 50
Because RiveScript replies can redirect to each other, there is some protection
in place to avoid infinite recursion (for example, a trigger that redirects to
another one, and that trigger redirects back to the first one, forever). By
default the recursion depth limit is set to 50, meaning if RiveScript can't find
a reply after 50 redirects it will give up and say "ERR: Deep Recursion
Detected".
This value should be a positive number higher than zero.
=back
=head2 Person Substitutions
These are a special kind of substitution that is intended to swap first- and
second-person pronouns. Here is how you define the person substitutions
(usually in your C<begin.rive> file):
! person i am = you are
! person you are = i am
! person i'm = you're
! person you're = I'm
! person my = your
! person your = my
! person you = I
! person i = you
Notice in this example that each pair of substitutions works in both directions.
To invoke person substitutions, you can use the C<E<lt>personE<gt>> tag (to
substitute on the C<E<lt>starE<gt>>), or C<{person}...{/person}> to substitute
on something else. Here is a practical example to show why person substitutions
can come in handy:
+ say *
- Umm... "<person>"
Now, if the user says, "say I am the greatest", the bot will reply with
"Umm... "you are the greatest"". Without person substitutions, the bot would
repeat "i am the greatest" instead.
=head1 TAGS
By now, you've seen examples of all the different RiveScript commands. Sprinkled
here and there throughout the examples were tags. Examples of tags you've seen
are C<E<lt>starE<gt>>, C<E<lt>getE<gt>>, and C<{topic}>. There are many more
tags available! This section will teach you about all the tags and how to use
them.
In general, a tag that has E<lt>angledE<gt> brackets are tags that insert
text in their place, or tags that set a variable silently. Tags that have
{curly} brackets modify the text around them.
Tags can be used with all the RiveScript commands except where explicitly
noted.
=over 4
=item C<E<lt>starE<gt>>, C<E<lt>star1E<gt>> - C<E<lt>starNE<gt>>
The star tag is used for capturing values used in wildcards, alternatives and
arrays present in the matched trigger. You've seen many examples of this in
this tutorial. If you have multiple stars, you can use C<E<lt>star1E<gt>>,
C<E<lt>star2E<gt>>, C<E<lt>star3E<gt>>, etc. to use the stars in order from
left to right. The C<E<lt>starE<gt>> tag is an alias for C<E<lt>star1E<gt>>, so
if you only have one wildcard this tag can be useful.
These tags can not be used with C<+ Trigger>.
=item C<E<lt>botstarE<gt>>, C<E<lt>botstar1E<gt>> - C<E<lt>botstarNE<gt>>
This tag is similar to C<E<lt>starE<gt>>, but it captures wildcards present
in a C<% Previous> line. Here is an example:
+ i bought a new *
- Oh? What color is your new <star>?
+ (@colors)
% oh what color is your new *
- <star> is a pretty color for a <botstar>.
Like the C<E<lt>starE<gt>> tag, C<E<lt>botstarE<gt>> is an alias for
C<E<lt>botstar1E<gt>>.
These tags can not be used with C<+ Trigger>.
=item C<E<lt>inputE<gt>>, C<E<lt>replyE<gt>>
The input and reply tags are used for showing previous messages sent by the
user and the bot, respectively. The previous 9 messages and responses are
stored, so you can use the tags C<E<lt>input1E<gt>> through
C<E<lt>input9E<gt>>, or C<E<lt>reply1E<gt>> through C<E<lt>reply9E<gt>>
to get a particular message or reply. C<E<lt>inputE<gt>> is an alias for
C<E<lt>input1E<gt>>, and C<E<lt>replyE<gt>> is an alias for C<E<lt>reply1E<gt>>.
Here are a couple examples:
// If the user repeats the bot's previous message
+ <reply>
- Don't repeat what I say.
// If the user keeps repeating themselves over and over.
+ <input1>
* <input1> == <input2> => That's the second time you've repeated yourself.
* <input1> == <input3> => If you repeat yourself again I'll stop talking.
* <input1> == <input4> => That's it. I'm not talking.{topic=sorry}
- Please don't repeat yourself.
// An example that uses both tags
+ why did you say that
- I said, "<reply>", because you said, "<input>".
=item C<E<lt>idE<gt>>
This tag inserts the user's ID, which was passed in to the RiveScript
interpreter when fetching a reply. With the interpreter shipped with the
Perl RiveScript library, the C<E<lt>idE<gt>> is, by default, C<localuser>.
RiveScript uses user IDs to keep multiple users separate. You can use the same
RiveScript interpreter to serve responses to multiple users, and it will keep
their user variables separate based on their ID.
Here is an example of how you might distinguish the botmaster from other users
based on a screen name (for example, for an instant messenger bot, where the
user ID is set to the user's screen name).
! var master = kirsle
+ am i your master
* <id> == <bot master> => Yes, you are. Hi Kirsle!
- No, <bot master> is my master, and you are <id>.
=item C<E<lt>botE<gt>>
The C<E<lt>botE<gt>> tag is used for retrieving a bot variable. It can also
be used to set a bot variable.
Bot variables can be considered "global" to the RiveScript interpreter instance.
That is, if you set the bot's name to Aiden, its name will be Aiden for
everybody who asks, regardless of the user's ID. This is in contrast to user
variables which are tied to a specific user ID.
+ what is your name
- You can call me <bot name>.
+ tell me about yourself
- I am <bot name>, a chatterbot written by <bot master>.
// Setting a bot variable dynamically
+ i hate you
- Aww! You've just ruined my day.<bot mood=depressed>
=item C<E<lt>envE<gt>>
The C<E<lt>envE<gt>> tag is used for retrieving global variables. It can also
be used to set a global variable.
For example, if the RiveScript interpreter copies all its environment variables
into RiveScript globals, a CGI-based RiveScript bot could tell a user their
IP address.
+ what is my ip
- Your IP address is: <env REMOTE_ADDR>
And here is an example of how you can set a global using this tag. In this
example, the bot's master is able to turn debug mode on or off dynamically.
+ set debug mode (true|false)
* <id> == <bot master> => <env debug=<star>>Debug mode set to <star>.
- You're not my master.
=item C<E<lt>getE<gt>>, C<E<lt>setE<gt>>
These tags are used to get or set a user variable, respectively. User variables
are arbitrary name/value pairs. You can make up any variable name you want.
Here are some examples:
+ my name is *
- <set name=<formal>>Nice to meet you, <get name>.
+ i am # years old
- <set age=<star>>I will remember that you are <get age> years old.
+ what do you know about me
- I know your name is <get name> and you are <get age> years old.
If you attempt to C<E<lt>getE<gt>> a variable that had never been defined for
the user before, it will insert the word "undefined" in its place instead. You
can use this feature to test whether a variable has been defined:
+ do you know my name
* <get name> != undefined => Yes, your name is <get name>.
- No, you've never told me your name before.
C<E<lt>getE<gt>> can be used in a trigger, but C<E<lt>setE<gt>> can not.
=item C<E<lt>addE<gt>>, C<E<lt>subE<gt>>, C<E<lt>multE<gt>>, C<E<lt>divE<gt>>
These tags can add, subtract, multiply or divide a numeric user variable,
respectively.
+ give me 5 points
- <add points=5>You have been given 5 points. Your balance is: <get points>.
If you operate on a variable that isn't defined, it will be initialized to
zero first. If you operate on a variable that doesn't currently contain a
number, an error message will appear in the place of the tag.
These tags can not be used with C<+ Trigger>.
=item C<{topic}>
This tag changes the client's topic.
+ play hangman
- {topic=hangman}Now playing hangman. Type "quit" to quit.
> topic hangman
+ quit
- Quitting the game.{topic=random}
+ *
- <call>hangman <star></call>
< topic
This tag can not be used with C<+ Trigger>.
=item C<{weight}>
This tag applies a weight to a trigger or response. When used with a trigger,
it controls the matching priority of the trigger (a higher weight means higher
priority). When used with a reply, it controls how frequently that reply will
be randomly chosen.
+ * or something{weight=10}
- Or something. <@>
+ hello
- Hi there!{weight=20}
- Hey!{weight=10}
- Howdy!
This tag can only be used with C<+ Trigger> and C<- Reply>.
=item C<{@}, E<lt>@E<gt>>
This tag performs an inline redirection to a different trigger. C<E<lt>@E<gt>>
is an alias for C<{@ E<lt>starE<gt>}>.
+ your *
- I think you mean to say "you are" or "you're", not "your". {@you are <star>}
You don't need to include a space between the C<@> and the trigger text.
This tag can not be used with C<+ Trigger>.
=item C<{random}>
Insert a sub-set of random text. This can come in handy in conditional lines, if
you want a random reply for a condition.
Between the C<{random}> and C<{/random}> tags, separate your possible texts with
a pipe symbol. Here is an example:
+ hello
* <get name> != undefined => {random}
^ Hello there, <get name>!|
^ Nice to see you again, <get name>!|
^ Hey, <get name>!{/random}
- Hello there!
- Hi there!
- Hello!
In this example, you give a random response that includes the user's name if the
bot knows it, or a normal random response otherwise.
This tag can not be used with C<+ Trigger>.
=item C<{person}>, C<E<lt>personE<gt>>
Processes person substitutions on some text. See L<"Person Substitutions">.
+ say *
- <person>
C<E<lt>personE<gt>> is an alias for C<{person}E<lt>starE<gt>{/person}>.
This tag can not be used with C<+ Trigger>.
=item C<E<lt>formalE<gt>>, C<E<lt>sentenceE<gt>>, C<E<lt>uppercaseE<gt>>, C<E<lt>lowercaseE<gt>>
Change the case formatting on some text. C<E<lt>formalE<gt>> is an alias for
C<{formal}E<lt>starE<gt>{/formal}>. The same applies for the other tags.
B<Formal> text makes the first letter of each word uppercase. This is useful
for names and other proper nouns.
B<Sentence> text makes the first word of each sentence uppercase.
B<Uppercase> and B<lowercase> make the entire string upper or lower case.
=item C<E<lt>callE<gt>>
This tag is used to call an object macro. Example:
// Call a macro named "reverse" and give it an argument
+ say * to me in reverse
- <call>reverse <star></call>
The first word in the C<E<lt>callE<gt>> tag is the name of an object macro to
call (see L<"Object Macros">). The macros may optionally take some arguments,
and you can pass them in by placing them in the C<E<lt>callE<gt>> tag as shown
in this example.
=item C<{ok}>
This is only used in the Begin Block in response to the C<request> trigger. It
indicates that it's OK to fetch a reply for the user's message. The reply will
replace the C<{ok}> tag.
=item C<\s>
This inserts a space character. It's useful when using the C<^ Continue> command
to extend a line of RiveScript code.
=item C<\n>
This inserts a line break.
=back
=head1 CONCLUSION
This concludes the RiveScript tutorial. By now you should have a thorough
understanding of how RiveScript code is written and you should be able to
start creating replies for your own chatterbot.
For more information about RiveScript, see http://www.rivescript.com/
=head1 VERSION AND AUTHOR
This tutorial was last updated on June 8, 2012.
This tutorial was written by Noah Petherbridge, http://www.kirsle.net/
=head1 APPENDIX
=head2 Windows Troubleshooting
=head3 Command Prompt Help
If you're not familiar with DOS commands and how to change directories in a
command prompt window, you should look up a quick tutorial on how to use the
command line. One such tutorial can be found at
http://www.computerhope.com/issues/chusedos.htm
For the lazy, you can create a simple batch file and place it in the same folder
as the RiveScript interpreter that would open a command prompt window there,
without needing to C<cd> to that folder yourself.
Open Notepad and type the following code into a new file:
@echo off
cmd
Save the file as C<"cmd.bat"> (I<with> the quotation marks!) in the same folder
as the C<rivescript> file from the Perl RiveScript distribution. Now, navigate
to that folder in Windows Explorer and double-click on the C<cmd.bat> file
(the file might appear as simply "C<cmd>" if file extensions are hidden).
=head2 Writing an Interpreter
Here is an example of how to write your own RiveScript interpreter application
in Perl 5.
#!/usr/bin/perl
use strict;
use warnings;
use RiveScript;
# Create a new RiveScript interpreter object.
my $rs = RiveScript->new();
# Load a directory full of RiveScript documents.
$rs->loadDirectory("./replies");
# You must sort the replies before trying to fetch any!
$rs->sortReplies();
# Enter a loop to let the user chat with the bot using standard I/O.
while (1) {
print "You> ";
chomp(my $message = <STDIN>);
# Let the user type "/quit" to quit.
if ($message eq "/quit") {
exit(0);
}
# Fetch a reply from the bot.
my $reply = $rs->reply("user", $message);
print "Bot> $reply\n";
}
=head1 SEE ALSO
L<RiveScript>
L<RiveScript::WD> - The RiveScript Working Draft -
http://www.rivescript.com/wd/RiveScript.html
|