一段能完整描述一个客服机器人的脚本被定义为scripts,一个scripts由多个function组成, 整个客服机器人的逻辑行为由function共同规约组成
描述客服机器人某种行为的一个集合,类似于编程语言中的函数。function主要有以下几种类型
常量,用于描述客服机器人的一些基本信息,如机器人的名字,机器人的头像等 此处的常量声明后提供给全局使用,其语法如下
constance {
const_name1 := <expression>
}
如果存在hello function,机器人会在初始化时自动执行hello function中的逻辑, hello function的语法为
hello {
command1
command2
...
commandN
}
客服机器人的入口。在用户第一次同机器人对话时,或者用户在其它地方给出了非预期输出,脚本又没有对应的处理逻辑时,机器人都会选择chatbox中的逻辑进行处理。 chatbox语法为
chatbox {
pattern1 => {
command1
command2
...
commandN
}
pattern2 => {
command1
command2
...
commandN
}
...
default => {
command1
command2
...
commandN
}
}
示例如下:
chatbox {
"你的性别是什么?" => {
say "我是一个男孩子"
}
"你的名字是什么?" => {
say "我叫小明"
}
default => {
say "我不知道你在说什么,请你问我其它问题"
}
}
chatbox本质上为一个分支选择语句,当用户输入的内容与某个分支的匹配时,机器人会执行该分支的逻辑,如果没有匹配的分支,机器人会执行default分支的逻辑,此处的default必须存在,且default为最后一个分支。如果default不为最后一个分支,则会报错。
topic用于描述客服机器人谈论的一个话题,里面包含一系列指令序列,语法为
topic ID {
command1
command2
...
commandN
}
示意如下
topic introduction {
say "你好,我是小明"
say "我是一个机器人"
say "我可以回答你的问题"
goto question
}
topic后需要跟随一个主题名,命名要求为字母开头,字母数字下划线组成,topic的主题名不能重复,否则会报错。topic的主题名可以在其它地方被引用,如上面的示例中,goto后跟随的就是一个topic的主题名。topic中的指令序列可以是任意的command,如say,goto,set等。
command是客服机器人的最小执行单元,command包含以下几种类型
客服机器人最基本的功能,表示机器人向用户输出一段文字,其语法如下
say <expression>
expression为一个表达式,程序会计算表达式的值,并将其结果对应的字符串输出 示例如下
say "你好,我是小明"
say 3+5
say hello_string
say `当前你的余额为${balance}元`
此处的"表达式"不仅仅是数学表达式,还可以是字符串,变量等,具体见表达式介绍
goto用于跳转到某个topic,其语法如下
goto <topic_name>
如,我们想跳转到名为introduction的topic,可以这样写
goto introduction
goto后跟随的topic_name必须为在同一script出现过的topic名称,否则会报错
menu用于向用户展示一个菜单,用户可以从菜单中选择一个选项,其语法如下
menu {
"option1" => {
command1
command2
...
commandN
}
"option2" => {
command1
command2
...
commandN
}
}
其中,选项显示的名称需要用双引号括起来,选项的内容为一个command序列,用户选择某个选项后,机器人会执行该选项对应的command序列。示例如下
menu {
"我想要充值" => {
say "请问你想充值多少钱?"
goto recharge
}
"我想要提现" => {
say "请问你想提现多少钱?"
goto withdraw
}
}
fetch用于向对应的url发送GET请求,其语法如下
fetch <url> => <variable_name>
其中,url为一个字符串,variable_name为一个变量名,fetch会将url对应的内容保存到variable_name对应的变量中,示例如下
fetch "http://api.myweb.com/info" => person_info
url支持模板,如
fetch `http://api.myweb.com/info?name=${name}&age=${age}` => person_info
如果获取到的结果为json格式,可以用.操作符获取对应的字段,如
fetch "http://api.myweb.com/info" => person_info
say `你的名字是${person_info.name}`
当然,也可以直接输出person_info,此时会将person_info转换为字符串后输出
post用于向对应的url发送POST请求,其语法如下
post <variable_name> => <url>
其中,variable_name
会被转换为字符串发送
POST的响应结果会被返回存到 variable_name
中,作用域为本地。
需要注意的是,回传结果作用域仅限于本花括号作用域。
set用于设置变量的值,其语法如下
# 声明并赋值
set <variable_name> := <expression>
# 仅赋值
set <variable_name> = <expression>
变量的作用域在对应的花括号包裹范围内,示例如下
{
set name := "小明"
say `你好,${name}`
set name = "小红"
say `你好,${name}`
}
只有在变量设置之后才能访问对应变量 你也可以加global关键字,将变量设置为全局变量,示例如下
{
set global name := "小明"
say `你好,${name}`
set global name = "小红"
say `你好,${name}`
}
这样子变量的作用域就变成了整个script
input用于获取用户输入,其语法如下
input <variable_name> <assertion> <when_silence>
其中,variable_name为变量名,assertion为断言,when_silence为用户长时间不说话时执行的操作 除了variable_name外,其它两个参数都可以省略
assertion为一个表达式,用于判断用户输入是否合法,如果用户输入不合法,机器人会一直要求用户重新输入,直到用户输入合法为止。示例如下
input name assert name <> ""
如果用户输入为空,则会一直要求用户重新输入,直到用户输入不为空为止 assert语句可以不存在,assert后跟着的表达式需要为逻辑表达式,如果表达式的值为true,则表示用户输入合法,否则表示用户输入不合法,不存在assert时默认所有输入均合法
when silence子句的对应语法如下
when silence <expression> => {
command1
command2
...
commandN
}
当用户一段时间不说话时,机器人会执行when silence子句中的逻辑 用户说话的时间长短由expression计算得来,单位是秒,示例如下
input name when silence 10 => {
say "你好像不想说话了"
goto end
}
match用于匹配用户输入,并决定下一步行为,其语法如下
match input {
pattern1 => {
command1
command2
...
commandN
}
pattern2 => {
command1
command2
...
commandN
}
...
default => {
command1
command2
...
commandN
}
}
其中, pattern表示一个正则表达式,当用户输入匹配时,机器人会执行对应的command序列,如果没有匹配的pattern,机器人会执行default分支的command序列,此处的default必须存在,且default为最后一个分支。如果default不为最后一个分支,则会报错。 同理,这里的input后还可以跟上when silence子句,示例如下
match input {
"你的性别是什么?" => {
say "我是一个男孩子"
}
"你的名字是什么?" => {
say "我叫小明"
}
default => {
say "我不知道你在说什么,请你问我其它问题"
continue
}
} when silence 10 => {
say "你好像不想说话了"
goto end
}
在match中,还可以同上使用continue,这会让机器人重新进入match的匹配流程,同时将计时器置零。
if用于判断某个条件是否成立,其语法如下
if <expression> => {
command1
command2
...
commandN
}
当然,if也可以加else分支和elif分支,示例如下
if <expression> => {
command1
command2
...
commandN
} elif <expression> => {
command1
command2
...
commandN
} else => {
command1
command2
...
commandN
}
loop用于循环执行某个指令序列,其语法如下
loop {
command1
command2
...
commandN
}
此时loop会进入死循环,如果想要跳出循环,可以使用break指令,示例如下
loop {
say "你好"
break
}
如果想要跳过本次循环,可以使用continue指令,示例如下
loop {
say "你好"
continue
say "我不好"
}
在这种情况下,say "我不好"永远不会被执行
loop可以加条件,示例如下
loop when <expression> {
command1
command2
...
commandN
}
此时,当expression为true时,会执行command序列,否则不会执行
在该脚本语言中,表达式被分为以下几种类型
同其它编程语言一样,变量名与常量名也是一种表达式,他们对应了一个值,示例如下
name
age
balance
你可以用set命令为变量赋值,示例如下
set name := "小明"
set age := 18
set balance := 100
常量表达式为一个常量,常量可以是字符串,数字,布尔值,null等,示例如下
"hello world"
3.14
true
null
只要是合法的javascript常量,都可以作为常量表达式 当然,同样可以为json对象,示例如下
{
"name": "小明",
"age": 18
}
同时,常量表达式也可以是一个数组,示例如下
[1,2,3,4,5]
算术表达式为一个算术运算,示例如下
1+2
3-4
5*6
7/8
9%10
算术表达式中可以使用括号,示例如下
(1+2)*3
逻辑表达式为一个逻辑运算,主要有关键字AND,OR和NOT示例如下
true and false
true or false
not true
同样,逻辑表达式可以使用括号,AND为与运算,OR为或运算,NOT为非运算 其计算结果为一个bool类型变量
比较表达式为一个比较运算,示例如下
1 == 2
1 != 2
1 > 2
1 < 2
1 >= 2
1 <= 2
比较表达式的计算结果为一个bool类型变量
后缀表达式主要包括下标表达式和成员访问表达式。
下标表达式主要用于访问数组成员,示例如下
set arr := [1,2,3,4,5]
say arr[0]
成员访问表达式主要用于访问对象成员,示例如下
set obj := {
"name": "小明",
"age": 18
}
say obj.name
需要注意的是,目前的表达式不支持链式访问,如obj.name.age这种形式,故只能如下访问
set tmp := result.lives
set info := tmp[0]
set temp := info.temperature
say `现在的温度为${temp}`
同时,也不支持后缀表达式作为左值。如
set obj := {
"name": "小明",
"age": 18
}
set obj.name = "小红"
这种形式是不支持的。
模板字符串为一个字符串,其中可以包含变量,示例如下
`你好,${name}`
模板字符串中的变量会被替换为对应的值,示例如下
set name := "小明"
say `你好,${name}`
这时候的输出为"你好,小明"