以下是视频内容文字版:
大家好,欢迎观看欧拉蜜系列教程视频,这节课要介绍的内容是 OSL 文本文件的撰写。我会从以下这两个部分来撰写:
一、OSL 文件声明的撰写规则 1、意图声明 2、slot 声明 3、modifier 声明 4、grammar 声明 |
二、OSL 文件定义的撰写规则 1、定义 rule 2、定义 grammar 3、定义语料 4、定义 template 5、定义答案 |
一、OSL 文件声明的撰写规则
1、意图声明
意图声明是必要内容,它用来定义模块的名称,以“ !intention”作为开头,且必须声明在 modifier 声明和 grammar 声明之前,写作:
!intention intention-name; 注意:“intention-name”指的是模块的名称。 |
可以看下面的例子:比如,我们这个模块的名称是“weather”,那么就这样写:!intention <weather>;
2、slot 声明
Slot 声明是非必要,也就是说如果模块中没有使用 slot 的话,可以不添加声明。 slot 声明以“!slot” 作为开头,而且必须指定数据类型,可以这样写:
!slot <slot-name:slot-type>; |
在这里,“slot-name” 指的是 slot 的名称,“slot-type”就是 slot 的类型,在声明 slot 的时候也必须要指定长度限制,可以这样写:
!slot <slot-name:slot-type(min-length|max-length)>; |
在这里“min-length” 和“ max-length” 限定了 slot 可以匹配的字符串的长度范围,它的值必须是正整数,而且 “max-length” 数值必须大于等于“min-length” ,min-length要大于等于0
例:
slot 名称:city 类型:ext slot的声明为:!slot <city:ext>; 如果需要指定最长最短字符数,比如2到12:!slot <city:ext(2|12)> |
因为 slot 的类型有很多,在这里列了一个表格,把不同类型的 slot 声明格式都写了下来,我们一起来看一下。
slot 类型 |
声名格式示例 |
说明 |
internal |
!slot <slot-name:internal>; |
如果需要引用此 slot,需定义一个同名的 rule 来列举 slot 的值 |
ext |
!slot <slot-name:ext(min-length|max-length)>; |
匹配长度在 min-length 到 max-length 个字符的ext slot。 |
numbe |
!slot <slot-name:number>; |
|
float | !slot <slot-name:float>; |
|
datetime |
!slot <slot-name:datetime>; |
时间类型,匹配各种时间说法 |
!slot <slotname:datetime.timepoint>; | 时间类型,匹配确切的时间点 | |
!slot <slot-name:datetime.duration>; |
时间类型,匹配确切的时间段,包括重复时间 |
在这里,我还要重点说一下 internal 和 ext 类型的 slot 的声明时候的一些特殊情况。
(1)如果我们要引用一个 internal 类型的 slot ,必须还要定义一个与和 slot 名称相同的 rule 后才能被引用,例如:
// 这里声明了一个 internal 类型的 slot !slot <type:internal>; // 在这里定义一个同名的 rule 来列举 slot 内容 <type>:流行|经典|儿童|摇滚|民族|古风|重金属; // 被 grammar 引用 <tingge>:我[非常|很|特别|极其]喜欢听<type>音乐 |
(2)若要替 internal 或 ext 类型的slot 设置引用类别信息时,示例如下:
// internal slot !slot <slot-name:internal.'referenceJson'>; // ext slot !slot <slot-name:ext.'referenceJson'(min-length|max-length)>; |
referenceJson 是一个 json,整体要用单引号’ ’包裹,referenceJson 格式为:{“ref”:[“type”]},ref 是关键字,type 是这个 slot 具体的引用类别,且只能有一个。看下面的例子:
// internal slot,名称: city,引用类别:地点 !slot <city:internal.'{"ref":["地点"]}'>; // ext slot,名称: place,引用类别:地点,长度: 2 – 10 !slot <place:ext.'{"ref":["地点"]}'(2|10)>; |
(3)若要替 ext 类型的 slot 设置验证类别,示例如下:
// ext slot !slot <slot-name:ext.'validateJson'(min-length|max-length)>; |
validateJson 是一个json,整体要用单引号’ ’包裹,validateJson格式为{“val”:[“type”]},val是关键字,type是这个ext slot具体的验证类别,具体的验证类别最多不超过4个,例如:
// ext slot,名称为 singer,验证类别是歌手,长度在 2 到 10 个字符 !slot <singer:ext.'{"val":["歌手"]}'(2|10)>; // ext slot,名称为 place,验证类别是国家,省,城市,区县,长度在 2 到 10 个字符 !slot <place:ext.'{"val":["国家","省","城市","区县"]}'(2|10)>; |
(4)若要替 ext 类型的 slot 同时设置引用类别和验证类别,示例如下:
// ext slot,名称为 name,引用类别是人物,验证类别是歌手,长度在 2 到 10 个字符 !slot <name:ext.'{"ref":["人物"],"val":["歌手"]}'(2|10)>; |
3、modifier 声明
Modifier 声明是非必要,以“ !modifier” 作为开头,撰写格式如下:
!modifier <intention-or-slot-name>:modifier1|modifier2|modifier3|...; |
在这里,“intention-or-slot-name ”表示模块名称或者 slot 名称。
当声明中使用模块名称时,表示这是一个 global modifier
当声明中使用 slot 名称时,表示这是一个 slot modifier
看下面的例子:
名称为 “weather” 的模块,global modifier 声明的撰写方式如下:
!modifier <weather>:query|最高温|最低温; |
名称为 “city” 的 slot,slot modifier 声明的撰写方式如下:
!modifier <city>:Chinese; |
4、grammar 声明
撰写格式如下:
<intention-name>:<grammar1>|<grammar2>|<grammar3>|...; |
“intention-name” 表示模块名称,grammar1、grammar2、grammar3 是相应的 grammar 名称。
例如,在名称为 “weather” 的模块里,有两个名称分别为 “query1”、“query2” 的 grammar,,那么声明的示例如下:
<weather>:<query1>|<query2>; |
在这里要提醒大家一点:
(1):所有的 grammar 都必须先声明,如果定义 grammar 之前没有声明就会被认为是 rule;
(2):grammar 声明不需要以 ! 字符开头,直接以模块名称作声明;
(3)、声明多个 grammar 用“| ” 隔开。
二、OSL 文件定义的撰写规则
需要定义的基本对象是 rule、template、grammar,主要内容是命名和语法描述句内容。
1、定义 rule
在 OSL 文件里定义 rule 的规则是这样的:
<rule-name>:pattern; |
“ rule-name”表示 rule 的名称,“pattern”即是一般的 OSL 语法描述句,也就是 rule 的内容。
例,在 OSL 文件中定义名称为 “like” 的 rule 就这么写:
<like >:喜欢|喜爱; |
2、定义 grammar
定义 grammar 的规则也类似:
<grammar-name>:pattern; |
例:在 OSL 文件中定义名称为 “tingge ” 的 grammar :
< tingge >:我要听<singer><{singer@=itissinger}>的歌<{@=music}>; |
3、定义 template
在 OSL 文件中定义 template 的规则如下示例:
<template-name:template>:content; |
示例里 “template-name” 表示 template 的名称,“:template”是特殊保留字,用来表达这个定义的内容是一个 template,“content” 即为 template 的内容描述。
可以看下面的例子:
<动词_重复:template>:[=动词=]$(动词)[一]$(动词)|$(动词)[[一]下]; < _帮忙_动词性短语:template>: [=动词性短语=][请][帮]我$(动词性短语); |
在这里还要注意一下:
(1):定义 template 时候没有写特殊保留字“:template”,直接写:<动词_重复>:[=动词=]$(动词)[一]$(动词)|$(动词)[[一]下];会提交失败
(2):末尾的分号不能忘记
4、定义语料
(1)方式:以 //*C: 作为开头。
(2)每一个 grammar 必须定义至少一个例句语料,而且语料必须和 grammar 匹配。
(3)例句语料必须定义在相应的 grammar 定义之前(即 grammar 定义描述的上一行)。
(4)可以定义多个例句语料,但每一行只能定义一个。
撰写格式如下:
//*C:content1 //*C:content2 //*C:content3 <grammar-name>:pattern; |
例如,在 OSL 文件中,替名称为 “tingge” 的 grammar 定义一个例句语料的示例:
//*C:我要听蔡依林的歌 //*C:我要听周杰伦的歌 <tingge>:我要听<singer><{singer@=itissinger}>的歌<{@=music}> |
需要注意的是,我们定义的语料它必须被某一个 grammar 所匹配,而且 grammar 的权重必须大于等于匹配整个 OSL 文件里其他 grammar 的权重。 也就是说这句语料只能被这一条 grammar 匹配。看下面的例子:
例: //*C:吃苹果 <grammar_apple>:吃<ext_slot_apple>; //*C:吃香蕉 <grammar_bannana>:吃(香蕉|苹果);
由于 “吃苹果” 这句语料也能被名称为 “grammar-bannana” 的 grammar 所成功匹配,且匹配的权重比 “grammar-apple ”更高,因此,提交时系统便会提示发生错误。 |
5、定义答案
规则:以 //*A: 作为开头。答案必须定义在相应的 grammar 定义之前(即 grammar 定义描述的上一行)。可以定义多个答案,但每一行只能定义一个, grammar 可以没有答案。撰写格式如下:
//*A:answer1 //*A:answer2 //*A:answer3 <grammar-name>:pattern; |
例:
在 OSL 文件中,替名称为 “query_time” 的 grammar 定义一个答案的示例: //*C:现在几点 //*A:现在是<time> <query_time>:现在几点;
定义多个答案的时候: //*C:现在几点 //*A:<time> //*A:现在是<time> <query_time>:现在几点; |
以上这些就是这节课的全部内容,感谢大家观看,我们下节课再见。