语法构建
语法构建是指通过本地的gram引擎构建出来用作本地识别引擎使用的语言模型资源,使用编写xbnf文件的方式,允许用户内置任意的语法到本地识别引擎。
语法构建
语法构建是指通过本地的gram引擎构建出来用作本地识别引擎使用的语言模型资源,使用编写xbnf文件的方式,允许用户内置任意的语法到本地识别引擎。
XBNF文件编写指导
xbnf文件采用ebnf语法作为基础语法,开发者通过编辑该文件用以限定识别范围同时规定输出的语义项格式。
扩展巴科斯-瑙尔范式(EBNF)是表达作为描述计算机编程语言和形式语言的正规方式的上下文无关文法的元语法(metalanguage)符号表示法
ebnf语法有两部分组成:定义变量及主执行语句;形如:
$hello=你好; (\<s\($hello) \<\/s\>)
主执行语句用于指定当前识别的语法,其定义为语法内容我们一般在前后加上"<s>"、"</s>",用于表明句子的开始及结束,实际使用中对应用户开始的静音及结束时的静音;
变量,如果ebnf语法是较为复杂的语法,且有共用的地方,可以使用变量来做为替换。变量定义语法:
$变量名=...; #以$开始标明变量名,同时以分号结束;
变量名由字母或者中文组成,如:
$hello=你好; $你好=你好|hello; (\<s\>( $hello | $你好 ) \<\/s\>)
正则标记
目前支持的正则标记有:
用途 | 符号表示 | 描述 | 举例 | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
注释 | # | 该符号之后的文本为注释文本 | #这是一段注释文本 | ||||||||||
定义 | = | 为变量定义内容 | $VAR=value; | ||||||||||
终止 | ; | 表达式的结束 | $VAR=value; | ||||||||||
分割 | \ | 列举,从中选择一个 | $人名=张学友\ | 刘德华; | |||||||||
可选 | [...] | 用于描述当前语句重复0或1次 | $国家=中[华人名共和]国; #用于标识中国,或者中华人民共和国; | ||||||||||
分组 | (...) | 描述当前内容在一个组合内,多与"\ | "搭配使用 | $DIGIT=(0\ | 1\ | 2\ | 3\ | 4\ | 5\ | 6\ | 7\ | 8\ | 9); #描述0~9数字中的一个 |
0到多的重复 | {...} | 被包含语句重复0到多次 | $NUM=12{2}; #描述若干个数的集合{12,122,1222,12222,...} | ||||||||||
1到多的重复 | <...> | 被包含语句重复1到多次 | $PENTI=<阿>嚏; | ||||||||||
指定范围的重复 | /min=a,max=b/ | 描述前一个语句重复[a,b]次 | $NUM = ( $DIGIT/min=1,max=11,k="number"/); #$DIGIT为0~9的数字,用于描述数字重复1到11次 |
语义设定
K,V项的设置
在扩展属性语法"/.../"中设置"k","v",用于识别反馈语义,如:
$digit = (1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0);
$phone_num =($digit/min=1,max=11,k="number"/);
$expr1=(打电话给)/k="action",v="call"/ $phone_num;
( \<s\> ($expr1) \<\/s\>)
如果识别结果为"打电话给123456",对应的语义输出为:
{"action":"call","number":"123456"}
说明: 如果扩展属性语法"/.../"中存在"k"值,即当前结果是要做语义输出的,如果没有指定"v",则采用对应的识别结果做为对应的键值;如果指定v,则使用"v"做为输出。如:
$phone_num =($digit/min=1,max=11,k="number"/) => 输出 "number":"123456"
(打电话给)/k="action",v="call"/ => 输出 "action":"call";
层级嵌套的设定
语法属性支持层级的设计,输出结果为json,如:
$digit = (1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0);
$phone_num =($digit/min=1,max=11,k="number"/);
$expr1=((打电话给)/k="action",v="call"/ $phone_num)/k="test"/;
( \<s\> ($expr1) \<\/s\>)
如果识别结果为"打电话给123456",对应的语义输出为:
{"test":{"action":"call","number":"123456"}}
扩展的属性
同时支持自定义扩展属性,用于json输出: 如check="hook即为自定义属性,输出为"check":"hook"
$NUM = ( $DIGIT/min=1,max=11,k="number",check="hook"/);
其对应的json输出为:
{"number":"123456","check":"hook"}
语义识别结果说明
实例语法形如:
$DIGIT = (1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0);
$NUM = ( $DIGIT/min=1,max=11,k="number"/); #number字段使用长度为1~11的数字填充
$PERSON = (小明|小华|小金)/k="person"/; #person字段使用(小明|小华|小金)中的一个填充
$PHONE_ACTION = (打[电话]给 | 电话给 | 呼叫 | 联系 | 致电 | 拨通 | 拨打)/action="call"/; #为其加上自定义的属性,以表明具体动作
$CMD = ($PHONE_ACTION ($PERSON | $NUM))/domain="phone"/; #为其加上自定义的属性domain="phone",以区分大类
( \<s\> ( $CMD ) \<\/s\> )
如果识别中设置setUseXbnfRec(true),对应的语义识别结果形如:
{
"version": "0.0.34.2014.4.3.16:19:48",
"res": "grammar.h.0.0.9",
"eof": 1,
"rec": "打电话给小明",
"conf": 0.832383,
"post": {
"sem": { //语义识别结果
"domain":"phone",
"action": "call",
"person": "小明"
}
}
}
{
"version": "0.0.34.2014.4.3.16:19:48",
"res": "grammar.h.0.0.9",
"eof": 1,
"rec": "打电话给10086",
"conf": 0.832383,
"post": {
"sem": { //语义识别结果
"domain":"phone",
"action": "call",
"number": "10086"
}
}
}
语法构建引擎示例代码
初始化
AILocalGrammarEngine mGrammarEngine;
/**
* 初始化资源编译引擎
*/
private void initGrammarEngine() {
if (mGrammarEngine != null) {
mGrammarEngine.destroy();
}
mGrammarEngine = AILocalGrammarEngine.createInstance();
mGrammarEngine.setRes("ebnfc.aicar.1.2.0.bin");
mGrammarEngine.init(new AILocalGrammarListenerImpl());
}
public class AILocalGrammarListenerImpl implements AILocalGrammarListener {
@Override
public void onError(AIError error) {
showInfo("资源生成发生错误");
}
@Override
public void onBuildCompleted(String path) {
showInfo("资源生成/更新成功\npath=" + path + "\n重新加载识别引擎...");
Log.i(TAG, "资源生成/更新成功\npath=" + path + "\n重新加载识别引擎...");
initLocalAsr();//在资源构建成功后,初始化离线识别引擎
}
@Override
public void onInit(int status) {
if (status == 0) {
showInfo("资源定制引擎加载成功");
} else {
showInfo("资源定制引擎加载失败");
}
}
}
读取语法内容,并构建语法
//设置生成的net.bin文件路径,包含文件名,路径随意。且确保路径事先存在
mGrammarEngine.setOutputPath("/sdcard/local.net.bin");
//读取语法内容文件, 并把内容赋值给string变量
BufferedReader br = null;
StringBuilder sb = new StringBuilder();
try {
br = new BufferedReader(new InputStreamReader(mContext.getAssets().open("asr.xbnf"), Charset.forName("UTF-8")));
String line = null;
while ((line = br.readLine()) != null) {
sb.append(line + "\n");
}
} catch (IOException e) {
e.printStackTrace();
Log.e("error", "Template file " + filename + " not found, Pls fix this bug!");
return null;
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Log.i(TAG, sb.toString);
// 设置ebnf语法,并启动语法编译引擎,更新资源
mGrammarEngine.buildGrammar(sb.toString());