6.1.云端对话
对话管理(Dialog Management, DM)
对话管理控制着人机对话的过程,DM 根据对话历史信息,决定此刻用户的反应。最常见的应用还是任务驱动的多轮对话,用户带着明确的目的如订餐、订票等,用户需求比较复杂,有很多限制条件,可能需要分多轮进行陈述,一方面,用户在对话过程中可以不断修改或完善自己的需求,另一方面,当用户的陈述的需求不够具体或明确的时候,机器也可以通过询问、澄清或确认来帮助用户找到满意的结果。SDK 方案提供了云端对话管理的能力,配合DUI平台强大的在线更新能力,可以做到云端对话技能秒级更新。开发者在接入AICloudDMEngine之前需要先在DUI平台配置云端技能,则AICloudDMEngine会按照云端对话内容的配置进行对话内容的分发。
对话配置
需开发者自行前往DUI平台创建产品、申请授权、添加技能,文档参见 : https://www.duiopen.com/docs/ct_skill ,方便开发者快速对接DUI,车载团队也提供一套标准的车载技能可供开发者直接继承使用,具体使用可直接与思必驰车载技术支持联系。
内置录音机
语音识别SDK按平台内置有录音机,可完成识别过程中的音频采集任务。
音频压缩
支持符合16Khz采样率、16bit数据位宽的PCM音频识别,SDK内部会对音频进行压缩。
VAD功能
VAD (语音活动检测)功能为可选项,开启后可启用本地的语音活动检测功能。关闭后,只能通过实体按键结束语音输入。
允许设置VAD后端点检测超时时间,开启后若说话停顿时长超过阈值,则主动结束本次识别的输入。
实时反馈识别结果
支持流式返回识别结果。当用户开口说话时,部分识别结果就绪后,能立即展示该部分结果。
初始化
AICloudDMEngine mEngine = AICloudDMEngine.createInstance();
mEngine.init(new AICloudDMConfig.Builder()
.setUseVad(true)
.setVadRes(SampleConstants.VAD_RES)
.setAliasKey("test") //设置请求的产品分支
.setUseFullDuplex(true)//开启全双工,默认为false
.build(), new AICloudDMListener() {
@Override
public void onQuery(NativeApi nativeApi) { //native api 回调
}
@Override
public void onCall(Command command) { //command 回调
}
@Override
public void onPlay(Speaker speaker) { // nlg 播报内容
}
@Override
public void onDisplay(CallbackWidgetType callbackWidgetType, CallbackWidget callbackWidget) {
//控件展示
}
@Override
public void onAsr(boolean b, String s) {
//实时识别结果
}
@Override
public void onEnd(String s) {
//对话结束
}
@Override
public void onRmsChanged(float v) {
//vad 音量
}
@Override
public void onBeginningOfSpeech() {
}
@Override
public void onEndOfSpeech() {
}
@Override
public void onInit(int i) {
}
@Override
public void onError(AIError aiError) {
}
@Override
public void onReadyForSpeech() {
}
@Override
public void onResultDataReceived(byte[] bytes, int i, int i1) {
}
@Override
public void onRawDataReceived(byte[] bytes, int i) {
}
});
启动对话
mEngine.start();//创建对话,使用默认的对话配置
//自定义对话配置
// AICloudDMIntent intent = new AICloudDMIntent();
// intent.setWakeupWords(new String[]{"你好小驰","小驰你好"});
// intent.setEnableEmotion(true);
// mEngine.start(intent);
结束对话
mEngine.stop();
回复对话结果
对话下发native api 内容后,待客户端完成查询后,需将查询内容同步云端对话。
mEngine.feedback(new ListFeedbackWidget()
.addContentWidget(new ContentFeedbackWidget().setTitle("世界之窗1号").setSubTitle("世界之窗")));
主动触发意图
常见用户手动触发某个UI 页面,对话需进入对应的技能内。
SkillIntent intent = new SkillIntent();
intent.setIntentName("设置提醒");
intent.setSkillId("2018061500000026");
intent.setTaskName("提醒");
mEngine.triggerIntent(intent);
通知引擎播报完成
因为对话配置可能是多轮的,下一轮对话内容的分发之前需要等待上一轮nlg内容播报完成后,故需要外部主动通知引擎播报完成
mEngine.notifyNlgEnd()
更新词库
设备级内容词库上传接口,常见联系人、app信息上传,影响识别融合后的结果。
mEngine.updateVocabs(new AIUpdateListener() {
@Override
public void success() {
Log.d(TAG, "update success");
}
@Override
public void failed() {
Log.d(TAG, "update failed");
}
}, new Vocab.Builder()
.setContents(Arrays.asList(new String[]{"刘","关","张"}))
.setAction(Vocab.ACTION_CLEAR_AND_INSERT)
.setName("sys.联系人")
.build()
);
更新设备状态
设备状态接口同步接口,常见定位数据上报,主要用作技能内信息引用和查询使用。
mEngine.updateProductContext(new AIUpdateListener() {
@Override
public void success() {
Log.d(TAG , "update success");
}
@Override
public void failed() {
Log.d(TAG , "update failed");
}
}, new ProductContext.Builder()
.setSetting(new Setting("location", "{\"city\":\"上海市\"}"))
.setOption(ProductContext.OPTION_SET)
.build());
更新技能配置
设备级动态调整技能优先级,影响语义融合后的结果。
mEngine.updateProductContext(new AIUpdateListener() {
@Override
public void success() {
}
@Override
public void failed() {
}
} , new ProductContext.Builder()
.setSetting(new Setting( "skillPriority" , "['skillid1', 'skillid2', 'skillid3']"))
.build());
全双工,锁定技能调度列表
mEngine.updateProductContext(new AIUpdateListener() {
@Override
public void success() {
}
@Override
public void failed() {
}
} , new ProductContext.Builder()
.setOption(ProductContext.OPTION_SET)
.setSetting(new Setting(Setting.DISPATCH_SKILL_LIST , new JSONArray().put("2018112000000006")))//锁定车控技能
.build());
全双工,过滤技能列表
mEngine.updateProductContext(new AIUpdateListener() {
@Override
public void success() {
}
@Override
public void failed() {
}
} , new ProductContext.Builder()
.setOption(ProductContext.OPTION_SET)
.setSetting(new Setting(Setting.FILTER_SKILL_LIST , new JSONArray().put("2018050400000026")))//过滤闲聊技能
.build());
更新全双工超时时间
mEngine.updateProductContext(new AIUpdateListener() {
@Override
public void success() {
}
@Override
public void failed() {
}
} , new ProductContext.Builder()
.setOption(ProductContext.OPTION_SET)
.setSetting(new Setting(Setting.FULL_DUPLEX_SESSION_TIMEOUT , "5000")) //5s对话超时
.build());
全双工返回结果差异
全双工和半双工一样,都会返回dm.output消息,该消息为对话结果;全双工模式下,会增加dm.rt.output消息,该消息会携带全双工的状态和事件 给客户端,实现全双工特性。
//jsontopicdm.rt.output
//dm.command.api
{
"dm": {
"command": {
"api": "interrupt"
},
"status": 0,
"runSequence": "commandFirst",
"shouldEndSession": false
},
"topic": "dm.rt.output",
"contextId": "5b82ff0f9e4448c891a282d64dcf2500",
"recordList": {
"beginTime": 1380,
"endTime": 3000,
"expireTime": 2000,
"recordIdList": [{
"beginTime": 1380,
"recordId": "b917dd4c0fcc4fb69c2a10a25abbae12",
"endTime": 0
}]
},
"sessionId": "5b82ff0f9e4448c891a282d64dcf2500",
"requestId": "5b49fc73b81f4944b71dc63c48780629"
}
参数 | 说明 |
---|---|
topic | |
sessionId | 对话上下文ID,对话过程中,服务端会返回该ID,如果客户端没有生成,则服务端会自动生成该ID。 |
recordList | 对应recordId列表 |
command.api | interrupt:客户端收到该事件,可以打断正在播报的tts;discardResponse:说明该句输入,没有命中任何语义,被服务端拒识,当作噪声处理,客户端不需要做出响应;backchannel:服务端返回的接话响应。比如:用户说 '我想听' ... '一首歌',在‘我想听’后短暂犹豫一会,服务端会给一个短回复如‘嗯’,使对话过程更流畅自然 |