# 离线命令词

# 概览

启动AIUI的离线命令词功能,常用语音指令可以完全在本地进行识别,可以减少响应时间,提高交互体验和减少云端交互。

AIUI在没有离线识别的情况下,对例如上一首,下一首,暂停播放这些音乐控制命令,都会将音频上传到AIUI云端,云端在处理后将听写和语义的结果再下发到客户端。

AIUI开启离线命令词识别功能后,会在音频送到AIUI云端的同时送到本地的离线识别引擎进行识别。

# 使用步骤

# 获取离线功能SDK

联系技术支持说明需求并获取离线功能SDK包。

# 接入使用

# 添加配置

aiui.cfg中增加离线命令词相关配置:

	"speech":{
		"intent_engine_type":"mixed"
	},

    "esr":{
        "engine_type": "wfst_fsa",
        "pgs_enable": "1",
        "res_type":"assets",
        "res_path":"esr/common.jet",
        "preloads": [
            {
                "id": 0,
                "res_type": "assets",
                "res_path": "esr/contact.jet"
            }
        ]
    },


# 配置文件说明

intent_engine_mode控制音频到语义结果的解析方式,取值有:

  • cloud 纯云端解析,全部使用云端语义和听写功能,只返回在线结果

  • local 纯离线命令词解析,只使用本地的离线命令词功能,只返回离线结果

  • mixed 云端本地同时解析,返回最快的有效结果

  • pipe 本地优先解析,如果有效即返回如果无效请求在线语义返回结果

esr['res_path']配置离线命令词模型通用资源。

esr['engine_type']控制离线结果的输出类型,取值有:

  • wfst 离线听写模式

  • wfst_fsa 离线听写+离线命令词匹配模式

  • fsa 离线命令词匹配模式

esr['pgs_enable']控制离线听写模式开启时是否有流式听写结果返回,取值有:

  • 1 开启

  • 0 关闭

esr['preloads']配置初始化时默认编译加载的离线语法资源,可以配置多条预加载的资源。在每一条配置中需要声明编译加载语法的ID和语法文件路径。语法ID的意义可以参考语法动态编译更新时语法ID的含义。

如上配置之后,SDK在识别时就会按照配置的离线语法进行离线命令词识别,并通过EVENT_RESULT返回离线结果,结果数据示例请参见离线结果一节的说明。

# 编写语法文件

离线命令语法是使用 FSA 描述的语法。示例离线语法如下:

#FSA 1.0;

0	1	<action>
1	2	<contact>
2	3	-
2	3	<phoneType>
;

<action>:拨打|呼叫|打电话给;
<contact>:张三|李四;
<phoneType>:移动号码|家庭号码|单位号码;

格式说明:

  • 以#开头的行表示注释行;
  • 以<开头表示slot槽定义,冒号后面是slot的值定义。slot的即可以在语法文件中定义,也可以通过下面章节介绍的方式进行更新;
  • 以数字开头行表示句式网络定义,上面示例语法网络定义可视化表示如下:

只要识别的内容能命中定义的网络,SDK就会返回离线命令词结果。比如说法打电话给张三会命中0 -> 1(action)和1 -> 2(contact)句式网络定义,那就返回如下离线命令词结果:

{
        "ws": [
            {
                "slot": "action",
                "w": "打电话给"
            },
            {
                "slot": "contact",
                "w": "张三"
            },
            {
                "slot": "",
                "w": "。"
            }
        ]
    }

# 结果解析

根据配置文件中esr的engine_type配置,离线解析时会返回离线流式听写、离线听写,离线命令词结果这几类结果类型的组合。离线流式听写和离线听写结果可以用作识别时的识别过程显示,离线命令词结果中包含识别命中离线语法定义的句式结果,所以可以用作解析交互的意图。例如engine_typewfst_fsapgs_enable处于开启状态,那一次交互会返回多次离线流式识别结果 + 一次离线识别结果 + 一次离线命令词结果

# 离线流式结果(esr_pgs)
  • info

    {
        "data": [
            {
                "params": {
                    "sub": "esr_pgs"
                },
                "content": [
                    {
                        "dte": "utf8",
                        "dtf": "json",
                        "cnt_id": "0"
                    }
                ]
            }
        ]
    }
    
  • result

    {
        "text": {
            "content": "点一"
        }
    }
    
# 离线听写结果(esr_iat)
  • info

    {
        "data": [
            {
                "params": {
                    "sub": "esr_iat"
                },
                "content": [
                    {
                        "dte": "utf8",
                        "dtf": "json",
                        "cnt_id": "0"
                    }
                ]
            }
        ]
    }
    
  • result

    {
        "text": {
            "bg": "-1",
            "ed": "-1",
            "sc": "26982",
            "ws": [
                {
                    "boundary": "68",
                    "pinyin": "xia4",
                    "sc": "0",
                    "slot": "",
                    "w": "下"
                },
                {
                    "boundary": "76",
                    "pinyin": "yi1",
                    "sc": "0",
                    "slot": "",
                    "w": "一"
                },
                {
                    "boundary": "116",
                    "pinyin": "ye4",
                    "sc": "0",
                    "slot": "",
                    "w": "页"
                },
                {
                    "sc": "0",
                    "slot": null,
                    "w": "。"
                }
            ]
        }
    }
    
# 离线命令词结果(esr_fsa)
  • info

    {
        "data": [
            {
                "params": {
                    "sub": "esr_fsa"
                },
                "content": [
                    {
                        "dte": "utf8",
                        "dtf": "json",
                        "cnt_id": "0"
                    }
                ]
            }
        ]
    }
    
  • result

    {
            "bg": "-1",
            "ed": "-1",
            "sc": "30267",
            "ws": [
                {
                    "boundary": "92",
                    "pinyin": "dian3yi1shou3",
                    "sc": "0",
                    "slot": "play",
                    "w": "点一首"
                },
                {
                    "boundary": "144",
                    "pinyin": "liu2de2hua2",
                    "sc": "0",
                    "slot": "singer",
                    "w": "刘德华"
                },
                {
                    "boundary": "156",
                    "pinyin": "de4",
                    "sc": "0",
                    "slot": "de",
                    "w": "的"
                },
                {
                    "boundary": "200",
                    "pinyin": "ge1",
                    "sc": "0",
                    "slot": "musicSuf",
                    "w": "歌"
                },
                {
                    "sc": "0",
                    "slot": null,
                    "w": "。"
                }
            ]
        }
    

# 进阶使用

# 默认语法槽更新

我们可以通过配置文件中esr下的preloads指明初始化时需要加载使用的离线命令词语法,同时离线语法文件中的槽也是可以更新的,如上面contact的slot,我需要更新成我们设备上对应的联系人,那我们可以在配置中为preloads资源增加如下的配置:

"esr":{
    "engine_type": "wfst_fsa",
    "pgs_enable": "1",
    "res_type":"assets",
    "res_path":"esr/common.jet",
    "preloads": [
            {
                "id": 0,
                "res_type": "assets",
                "res_path": "esr/contact.jet",
                "update_slots": [
                    {
                        "slot": "contact",
                        "res_type": "assets",
                        "res_path": "esr/contact_update.jet"
                    }
                ]
            },
     ]
}

contact_update.jet中内容是|分割扩展联系人列表,示例内容如下:

王二|张海洋

如上的配置加载完成后,我们直接说打电话给张海洋就可以如上面一样返回命中的esr_fsa结果

# 语法动态编译更新

除了通过上面的静态的配置文件指明需要更新扩展的槽。我们还可以通过下面介绍的命令在程序运行时动态更新槽内容,以下操作都需要在AIUI SDK的working状态下运行。

# 离线语法编译
String grammarContent = FucUtil.readAssetsFile(this, "esr/contact.jet","utf-8");
AIUIMessage buildMessage = new AIUIMessage(AIUIConstant.CMD_BUILD_GRAMMAR, 1, 0, grammarContent, null);

arg1字段指明编译语法的ID,后面更新语法槽时通过指定相同的语法ID来更新这个语法文件中槽;

arg2字段指明是否禁用语法编译自动加载下次识别生效,取值如下:

  • 1 只编译语法,编译完成后不自动加载生效(可以通过后面的CMD_LOAD_GRAMMAR手动加载编译好的语法)
  • 0 编译语法后自动加载生效

params字段指明编译的语法内容。

编译结果及下面操作都会通过EVENT_CMD_RETURN返回,示例处理如下:

    //AIUI事件监听器
    private AIUIListener mAIUIListener = new AIUIListener() {

        @Override
        public void onEvent(AIUIEvent event) {
            switch (event.eventType) {
                /**
                 * arg1 表示操作的CMD
                 * arg2 表示操作成功(0)失败(错误码)
                 * info 结果信息
                 */
                case AIUIConstant.EVENT_CMD_RETURN: {
                    switch (event.arg1) {
                        case AIUIConstant.CMD_BUILD_GRAMMAR:
                        case AIUIConstant.CMD_UPDATE_LOCAL_LEXICON: {
                            Log.d(TAG, "arg1 " + event.arg1 + " ret " + event.arg2 + " info " + event.info);
                        }
                    }
                }
                break;

                default:
                    break;
            }
        }

    };

# 离线语法槽更新
String updateContent = String.format("{\"name\": \"%s\", \"content\": \"%s\"}", "contact", "黄莺莺|窦唯|鲍家街四十三号");
AIUIMessage updateMessage = new AIUIMessage(AIUIConstant.CMD_UPDATE_LOCAL_LEXICON, 1, 0, updateContent,null);

arg1字段指明槽更新目标的语法ID,语法ID和语法内容的对应在CMD_BUILD_GRAMMAR时建立。

arg2字段指明槽更新内容模式是否为追加,取值如下:

  • 0 替换(replace)模式,更新的内容会替换当前槽内容;

  • 1 追加(append)模式,更新的内容会追加到当前槽内容的后面。

params 字段指明槽更新的内容。

# 离线语法加载
AIUIMessage loadMessage = new AIUIMessage(AIUIConstant.CMD_LOAD_GRAMMAR, 1, 0, "", null);

arg1字段指明需要加载的语法ID,语法ID需要之前通过CMD_BUILD_GRAMMAR完成编译。

# 离线语法卸载
AIUIMessage loadMessage = new AIUIMessage(AIUIConstant.CMD_UNLOAD_GRAMMAR, 1, 0, "", null)

arg1字段指明需要卸载的语法ID,语法ID需要之前通过CMD_BUILD_GRAMMARCMD_LOAD_GRAMMAR完成对应语法的加载。