应用领域
在智能手机、手表或 PC 等终端中,AIUI 可以与手机深度结合为全局的智能语音控制系统。在单个应用(APP)中,可以帮助用户用语音完成复杂的交互,例如导航、买票、订餐等。
接入方式
AIUI 目前支持提供多种集成模式,包含 SDK、硬件接入、HTTP 协议的方式。以及微信公众号、服务号托管服务。
项目需求
接入科大讯飞语音识别,并创建环境,用户在客户端处理唤醒,实现用户无手势操作,凭语音实现操作APP进行特定页面跳转。
语音唤醒
AIUI中默认不带语音唤醒功能,可通过接入MSC库将唤醒与交互结合起来。
- 登录“科大讯飞开放平台”
- 创建应用
- 在我的应用中为刚添加的应用开通【语音唤醒】服务和【AIUI平台】服务
AIUI平台服务
SDK介绍
AIUI移动端SDK为开发者提供了简单易用的交互接口。AIUIAgent是和AIUI交互的桥梁,开发者可以发送不同的AIUIMessage来控制AIUI的运行,如发送CMD_WAKEUP使AIUI进入唤醒就绪状态,发送CMD_RESET_WAKEUP使AIUI进入休眠状态。同时通过AIUIListener监听接收AIUI抛出的AIUIEvent进行解析,如通过EVENT_RESULT解析AIUI返回的听写和语义结果,通过EVENT_SLEEP得知AIUI进入休眠状态。参考官方文档
集成步骤(参考官方文档)
参数配置
SDK中的cfg文件在AIUI初始化时会被读取,根据配置初始化各个内部模块。参考官方文档
可动态配置,配置文件中的情景模式(默认情景为main)和后台应用定义的情景模式对应,在后台可以为不同情景模式配置不同语义技能、问答库,通过本地的配置文件或者动态设置场景可使用不同情景模式下对应的业务。(目前需求暂不需要使用动态配置)
消息事件(重点)
AIUI在交互过程中依靠AIUIMessage向SDK传递指令,依靠AIUIEvent从SDK内部向外抛出事件回调。下面将罗列这些AIUIMessage与AIUIEvent的具体取值及含义。参考官方文档
AIUI交互状态(重点)
AIUI在运行过程中,在不同阶段处于不同状态,不同的状态能处理的操作也不同。参考官方文档
语音唤醒服务
唤醒词配置
- 唤醒词最多支持8个,每个为4-6个汉字或不超过2个英文单词。中英文不可同时配置。
- 语音唤醒是离线服务,而且唤醒资源和SDK包捆绑,如果您修改了唤醒词,请 前往SDK下载中心 重新下载SDK替换。
收费标准
- 语音唤醒体验版提供3个装机量,60天的免费试用;
- 语音唤醒服务按照装机量收费,购买后即获得相应数量的授权。启用一台新终端,消耗一个装机量;
- 在第一次购买成功后,需要重新下载SDK替换原项目中使用的旧版,避免报错;
唤醒SDK集成
iOS集成
- 打开SDK包,进入resource/ivw/目录,将里面的*.jet文件重命名为ivw.jet,放入工程resource/ivw/下,进入lib目录将iflyMSC.framework放入工程的framework目录中
- 语音唤醒iOSSDK集成流程
- 配置唤醒参数
self.iflyVoiceWakeuper = [IFlyVoiceWakeuper sharedInstance];
self.iflyVoiceWakeuper.delegate = self;
// 设置keyeword的阈值
// 例如,0:1450; 1:1450
// 0:第一个关键字,1450:第一个关键字的阈值
// 1:第二个关键字,1450:第二个关键字的阈值
//关键字的顺序必须与资源文件一致
NSString *thresStr = [NSString stringWithFormat:@"0:%d", 1450];
[self.iflyVoiceWakeuper setParameter:thresStr forKey:[IFlySpeechConstant IVW_THRESHOLD]];
// 设置会话类型
[self.iflyVoiceWakeuper setParameter:@"wakeup" forKey:[IFlySpeechConstant IVW_SST]];
// 设置资源文件的路径
NSString *resPath = [[NSBundle mainBundle] resourcePath];
NSString *wordPath = [[NSString alloc] initWithFormat:@"%@/ivw/ivw.jet",resPath];
NSString *ivwResourcePath = [IFlyResourceUtil generateResourcePath:wordPath];
[self.iflyVoiceWakeuper setParameter:ivwResourcePath forKey:@"ivw_res_path"];
// 在服务成功后设置会话延续状态。
// 0:一次唤醒后会话结束; 1:唤醒后会话继续
[self.iflyVoiceWakeuper setParameter:@"1" forKey:[IFlySpeechConstant KEEP_ALIVE]];
// 设置音频源
[self.iflyVoiceWakeuper setParameter:IFLY_AUDIO_SOURCE_MIC forKey:@"audio_source"];
// 设置录像机保存的音频路径
[self.iflyVoiceWakeuper setParameter:@"ivw.pcm" forKey:@"ivw_audio_path"];
- 开启唤醒监听
// 开启唤醒监听
[self.iflyVoiceWakeuper startListening];
- 唤醒结果回调
唤醒成功后,在唤醒结果回调中发送AIUI唤醒消息和开始录音消息即可进行语音交互。
/**
result callback of voice wakeup
resultDic:语音唤醒结果
**/
-(void) onResult:(NSMutableDictionary *)resultDic {
// self.aiuiState为AIUI状态
// STATE_IDLE:空闲状态,AIUI服务未开启。
// STATE_READY:就绪状态,已经开启录音,等待唤醒。
// STATE_WORKING:工作状态,已经唤醒,可以开始人机交互。
if (self.aiuiState == STATE_READY) {
// 发送CMD_WAKEUP消息至AIUI,使AIUI处于唤醒状态,再发送开始录音消息,使麦克风录入音频。
// 发送唤醒消息
IFlyAIUIMessage *msg = [[IFlyAIUIMessage alloc] init];
msg.msgType = CMD_WAKEUP;
[_aiuiAgent sendMessage:msg];
// 发送开始录音消息
IFlyAIUIMessage *msg1 = [[IFlyAIUIMessage alloc] init];
msg1.msgType = CMD_START_RECORD;
[_aiuiAgent sendMessage:msg1];
}
}
Android集成
- 打开SDK包,进入res/ivw/目录,将里面的*.jet文件重命名为ivw.jet, 放入工程src/main/assets/ivw/下,进入libs目录将Msc.jar放入工程libs/下,libmsc.so放入工程src/main/jniLibs/armeabi下;
- 修改aiui_phone.cfg配置文件,添加唤醒参数即可。在代码中创建AIUIAgent后即可开始唤醒,唤醒成功后可进行语音交互。
// 唤醒参数
"ivw":{
"res_type":"assets",
"res_path":"ivw/ivw.jet",
"ivw_threshold":"0:2000" //0为唤醒词编号,2000为唤醒阈值(范围0~3000),多个唤醒用分号隔开,如:"ivw_threshold":"0:2000;1:1500"
},
// 语音业务流程控制
"speech":{
"wakeup_mode":"ivw"
}
- 初始化,建议将初始化放在程序入口处(如Application、Activity的onCreate方法),初始化代码如下,XXXXXX为你的应用appid。
SpeechUtility.createUtility(this, String.format("engine_start=ivw,delay_init=0,appid=%s","XXXXXX"));
- 创建AIUIAgent,发送CMD_START_RECORD消息,即开始录音,等待唤醒。
//创建AIUIAgent
mAIUIAgent = AIUIAgent.createAgent( this, getAIUIParams(), mAIUIListener );
//开始录音
AIUIMessage msg = new AIUIMessage(AIUIConstant.CMD_START_RECORD, 0 ,0, "data_type=audio,sample_rate=16000", null);
mAIUIAgent.sendMessage(msg);
AIUI自定义技能平台
技能资源限制
在技能工作室中,针对用户下每种资源的创建,存在数量上的限制。详情查看官方文档
情景模式
AIUI 应用默认配置了一个语义情景模式main。目前 AIUI 一个应用支持配置最多10个情景模式。情景模式分为语义情景模式和翻译情景模式。您可以为每个语义情景模式配置不同的识别、语义、后处理,也可以选择新建翻译专用的情景模式
语义理解
在应用配置中开启语义理解,可配置关键词过滤、语义技能
- 用户表述中可能包含唤醒词,此时会影响到语义理解的结果,此种情况下可添加关键词过滤。
- 语义技能包括自定义技能、自定义问答、商店技能。技能优先级:自定义技能>自定义问答>商店技能。
自定义技能
进入IFlyOS技能工作室构建技能,可查看技能工作室官方文档
创建技能
一个技能的编写,一定来自于一个具体的产品需求。在技能开发之前,你需要定义技能,即确定这个技能能够满足用户的何种需求。
1.1 技能分为商店技能和私有技能,可查看不同类型技能的区别。根据本项目需求,使用私有技能->AIUI平台。
注意:技能类型一经创建,不可修改,暂不支持删除技能,请谨慎操作。-
意图配置
每个交互模型必须有一个入口意图,作为技能交互入口。
2.1 语料:用户的每个意图在实际中可能有很多种表述方式(以查快递意图为例)可能的表述有:- 我要查顺丰快递
- 我要查快递
- 查一下快递
- ......
这些表述统称为语料,一个技能中,每个意图下可能存在几十条到几千条不等的语料,为了保证技能语义理解的结果,我们建议开发者尽可能完善所有的语料。
2.2 关于AIUI中实体的理解静态实体、动态实体、所见即可说、通配实体
2.3 辅助词:在用户的表述中会出现的词汇,但是这些词汇开发者并不关心其具体值,其存在的意义是保证表述完整,例如常见的辅助词有:请问、查看、如何等。 技能后处理(暂未使用)
利用技能后处理,您可以通过编写代码的方式,为您的技能配置多轮对话,以及调用外部信源,为您的技能组合丰富多彩的回答话术。后处理云函数,目前AIUI技能后处理使用v2.0协议。发布构建技能
4.1 技能修改/构建完毕之后需要发布上线才可以使用。
4.2 发布之后的私有技能,开发者可在AIUI应用的语义技能处引用该技能。
4.3 当你的AIUI应用添加了商店技能时,若商店技能更新版本,你的应用默认会使用旧版本。当确认新版本不会造成已经分发给用户的客户端异常时,你可以通过移除后再次添加技能的方式,使得商店技能新版本生效。
AIUI交互事件结果解析
/*!
* 事件回调<br>
* SDK所有输出都通过event抛出。
*
@param event AIUI事件,具体参见IFlyAIUIEvent。
*/
- (void) onEvent:(IFlyAIUIEvent *) event ;
AIUI交互结果事件通过EVENT_RESULT
抛出,详细参考官方demo,结果类型包括:
- 听写结果(iat)
- 语义结果(nlp)
- 后处理服务结果(tpp)
- 云端tts结果(tts)
- 翻译结果(itrans)
AIUI交互结果事件回调中IFlyAIUIEvent
对象的info
字段所包含的接送内容格式如下:
{
"data": [{
"content": [{
"cnt_id": "0",
"dte": "utf8",
"dtf": "json"
}],
"params": {
"cmd": "iat-kc-tts",
"lrst": "1",
"rstid": "3",
"sub": "nlp",
"tts": "1"
}
}]
}
各字段含义解释
sub
的值确定对应的事件结果类型;值如果是nlp
,代表是语义结果,若cnt_id
内容id不为空,可根据cnt_id
获取event.data
中对应的语义结果json串。
dte
的值确定语义结果的数据编码;dtf
的值确定语义结果的数据格式。
其他字段暂未使用,这里暂时不做介绍
关于语义结果json串说明,可以参考AIUI语义协议
progressive 流式识别(听写结果解析)
progressive 流式识别简称 pgs,在关闭该选项时,云端 VAD 会在用户说完一句话时返回一次识别结果。 打开该选项时,云端会在识别一句话的过程中,返回多次识别结果,并不断自动修正,开发者如果希望在界面上实时展示修正结果以提高用户体验,可以打开该选项。流失识别官方文档
JSON字段 | 类型 | 说明 |
---|---|---|
sn | number | 第几句(当前结果id) |
ls | boolean | 是否为最后一条结果 |
bg | number | 开始 |
ed | number | 结束 |
pgs | string | 结果操作字段,其中apd代表结果追加,rpl代表结果替换 |
rg | array | 替换范围 |
ws | array | 词 |
cw | array | 中文分词 |
sc | number | 分数 |
w | string | 单字/词组 |
技能后处理云函数编写示例代码(帮助理解技能后处理)
AIUI.create("v2", function(aiui, err){
//打印 request 结构体
requestObject = aiui.getRequest().getObject();
console.log(requestObject);
//获取 response 对象
var response = aiui.getResponse();
// 获取当前意图名
intentName = requestObject.request.intents[0].name;
console.log("本次意图来自:"+intentName);
// 获取填槽对话状态
dialogState= requestObject.request.dialogState;
if(dialogState!=null&&dialogState!="COMPLETED"){
// 填槽对话未完成时,托管给系统管理
response.addDelegateDirective();
}else{
// 填槽对话完成时,回复用户一句 answer
updatedIntent = aiui.getUpdatedIntent();
// 获取槽值
companyValue = updatedIntent.getSlotValue("company");
// 获取槽值
numberValue = updatedIntent.getSlotValue("number");
answer="你的"+"快递单号是:"+numberValue+",已经达到北京市"
// 回答用户
response.setOutputSpeech(answer);
}
// 提交
aiui.commit();
})