1. 语义理解(NLU)概述
自然语言理解 (Natural Language Understanding,简称NLU)技术,是将人类语言进行分析,让机器真正理解人类意图,成为人类伙伴的一种技术。其涵盖领域非常广泛,包括句子检测,分词,词性标注,句法分析, 文本分类/聚类,文字角度,信息抽取/自动摘要,机器翻译,自动问答,文本生成等多个领域。
灵云语义理解支持多领域,如支持天气,导航等20多个常见领域,可以直接通过语义理解的意图从第三方平台获取识别结果,并支持多轮对话,通过多轮对话确定真实意图等。捷通华声利用自然语言理解技术推出了智能客服,语音助手等产品。这些产品在市场上得到了广泛应用,业务涉及通讯、政府、电子商务、智能家电和汽车等行业。
本文档是集成捷通华声语音识别(NLU)SDK的使用指南,旨在让开发者迅速上手集成SDK。指南中介绍了语义理解的使用过程以及类和函数的基本使用。关于函数和参数更详细的说明,请参考灵云SDK开发手册。在集成过程中如有疑问,可登录灵云开发者论坛,查找答案或与其他开发者交流。
1.1 名词解释
名词 | 解释 |
---|---|
本地识别 | 在本地进行语义理解,支持基于本地字典语法文件的语言理解。 |
云端识别 | 联网情况下在云端进行语义理解,支持不同领域内的语言理解(不需要本地资源)。 |
意图识别 | 在识别完成后进行意图结果和意图相关内容获取。使用意图识别时,需要在启动回话时,指定识别选项intention,即意图识别领域。 |
多轮对话 | 当用户的需求比较复杂时,这时就需要分多轮进行陈述,用户也可能在对话过程中不断修改或完善自己的需求。此外,当用户的陈述的需求不够具体或明确的时候,机器也可以通过询问、澄清或确认来帮助用户找到满意的结果。 |
常见意图识别领域如下:
意图识别领域 | 中文描述 |
---|---|
weather | 天气 |
map | 地图 |
music | 音乐 |
joke | 笑话 |
hotel | 酒店 |
news | 新闻 |
story | 故事 |
message | 发短信 |
website | 打开网站 |
更多意图配置请咨询捷通华声或关注开发者社区。
1.2 能力定义(capkey)
capKey配置项指定了所要使用的能力,分为本地能力和云端能力。capkey在NLU能力集成时会作为配置项作为传入参数,详见3.3初始化NLU能力
和语义理解相关的capkey如下所示:
capkey | 说明 |
---|---|
nlu.local.recog | 本地语义理解 |
nlu.cloud | 云端语义理解 |
1.3 调用流程
主要功能接口调用如下图:
2. 准备工作
2.1 创建应用
在集成NLU之前,开发者需要在灵云开发者社区创建相关应用,并保存appkey,developerkey等信息。同时选择需要使用的能力定义(Capkey),具体详见灵云开发者社区使用指南。
2.2 导入SDK
2.2.1 使用 Android 版 SDK
2.2.1.1 下载SDK
在官网开发者社区下载语义理解SDK并解压缩。
2.2.1.2 导入jar包和运行库
在开发应用前,需要将灵云SDK中的Jar包文件(.jar)和相应的动态运行库(.so)引入到工程中。将在官网下载的Android SDK 压缩包中libs目录下所有子文件拷贝至Android工程的libs目录下。如下图所示:
2.2.1.3 库目录文件介绍
jar包文件
- hcicloud-5.0.jar
必选模块
- libcurl.so
- libhci_sys.so
- libhci_sys_jni.so
- libhci_nlu.so
- libhci_nlu_jni.so
- libstlport_shared.so
云端识别
- libhci_nlu_cloud_recog.so
本地识别
- libhci_nlu_local_recog.so
- libiThinkDialog.so
2.2.1.4 添加用户权限
在工程 AndroidManifest.xml 文件中添加如下权限。
<!—通常需要设置一些sd卡路径(例如日志路径)为可写,因此需要能够写外部存储 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!—以下访问网络的权限均需要打开-->
<!--连接网络权限,用于执行云端能力 -->
<uses-permission android:name="android.permission.INTERNET" />
<!--读取网络信息状态 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!--获取当前wifi状态 -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!--允许程序改变网络连接状态 -->
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<!--读取手机信息权限 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<!—以下访问权限可选-->
<!--手机定位信息-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
2.2.2 使用 C++ 版 SDK
2.2.2.1 下载SDK
下载语音识别SDK并解压缩。
2.2.2.2 库目录介绍
开发者可以根据自身需求组合所需要的库。
必选模块
- libhci_curl.dll
- hci_sys.dll
- hci_nlu.dll
云端识别
- hci_nlu_cloud_recog.dll
本地识别
- hci_nlu_local_recog.dll
- iThinkDialog.dll
2.2.3 使用ios版SDK
2.2.3.1 下载SDK
下载语音识别SDK并解压缩。
2.2.3.2 库目录介绍
开发者可以根据自身需求组合所需要的库。
必选模块
- libcurl_device_simulator_iOS5.1.1.a
- libhci_sys_device_simulator_iOS5.1.1.a
- libhci_nlu_device_simulator_iOS5.1.1.a
云端识别
- libhci_nlu_cloud_recog_device_simulator_iOS5.1.1.a
本地识别
- libhci_nlu_local_recog_device_simulator_iOS5.1.1.a
适配器选择(只选其一)
适配器静态库中包含对应能力所需的头文件文件,所以只需要选择一个需要的组合能力适配器静态库就可以了,避免引入多个适配器静态库引起的符号表冲突问题。
- *libhci_nlu_only_cloud_adapter_device_simulator_iOS5.1.1.a(只使用云端识别)*
- *libhci_nlu_only_local_adapter_device_simulator_iOS5.1.1.a(只使用本地识别)*
- *libhci_nlu_cloud_local_adapter_device_simulator_iOS5.1.1.a (既使用云端识别,又使用本地识别)*
2.2.3.3 导入静态库
在SDK解压目录下的libs文件夹中包含语义理解(NLU)能力所需要的静态库,开发者可以根据需要相应的选择集成哪些语音识别(ASR)的功能。
请在您的工程目录结构中,添加语义理解(NLU),在选项TARGETS--> Build Phases-->Link Binary With Libraries-->Add Other,选择相应静态库文件并选择确认。
添加系统依赖框架(Framework)和编译器选项 TARGETS-->Build Phases-->Link Binary With Libraries--> + -->'UIKit','Foundation','SystemConfiguration','Accelerate','CoreLocation','libstdc++'
将语义理解(NLU)的头文件引入您的工程中
- hci_sys.h
- hci_nlu.h
最后语义理解(NLU)的编译环境是stdc++,在选项TARGETS--> Build Settings-->C++ Standard Library,选择libstdc++(GNU C++ standard library)。
同时设置bitcode选项为No,在选项TARGETS--> Build Settings-->Enable Bitcode,选择No。
2.2.4 导入本地资源(仅限本地识别)
如需使用本地语义理解,就需要将资源文件导入到工程中。
2.2.4.1 所需本地资源文件
核心依赖资源文件
- tdle_cmn.bin
- tdle_bi_tag.txt
- tdle_tag.txt(可选)
领域相关资源文件
- tdlr_ptr.txt
- tdlr_ent.txt
- tdlr_tag.txt(可选)
本地语义理解可以加载多种领域资源,当需要多领域识别时,相关的领域资源文件需要加前缀进行区分。不同领域间的前缀固定为相应的intention加下划线的的形式,如传入天气和笑话领域,则需加weather和joke前缀以示区别。如下图所示:
3. NLU能力集成
本节主要讲述开发者应该如何简单通过调用SDK,使自己的应用拥有语音识别(NLU)能力。这里以云端识别为例,调用顺序参考调用流程,为开发者演示如何简单的调用SDK。至于其他使用场景的调用,如多轮对话,多领域识别,详见场景示例
3.1 初始化灵云系统
在调用语义理解能力之前,需要初始化灵云SDK的SYS通用模块,用以开启日志,获取授权等。详见灵云SDK开发手册。
Android代码
// 创建初始化参数辅助类 InitParam initparam = new InitParam(); // 授权文件所在路径,此项必填 String authDirPath = context.getFilesDir().getAbsolutePath();; initparam.addParam(InitParam.PARAM_KEY_AUTH_PATH, authDirPath); // 灵云云服务的接口地址,此项必填 initparam.addParam(InitParam.PARAM_KEY_CLOUD_URL, "http://api.hcicloud.com:8888"); // 开发者密钥,此项必填,由捷通华声提供 initparam.addParam(InitParam.PARAM_KEY_DEVELOPER_KEY, "01234567890"); // 应用程序序号,此项必填,由捷通华声提供 initparam.addParam(InitParam.PARAM_KEY_APP_KEY, "1234abcd"); // 日志的路径,可选,如果不传或者为空则不生成日志 String logDirPath = "/storage/emulated/0/sinovoice/com.sinovoice.example/log"; initparam.addParam(InitParam.PARAM_KEY_LOG_FILE_PATH, logDirPath); // 日志等级,0=无,1=错误,2=警告,3=信息,4=细节,5=调试,SDK将输出小于等于logLevel的日志信息 initparam.addParam(InitParam.PARAM_KEY_LOG_LEVEL, "5"); // 灵云系统初始化 // 第二个参数在Android平台下,必须为当前的Context int errCode = HciCloudSys.hciInit(initparam.getStringConfig(), this); if(errCode != HciErrorCode.HCI_ERR_NONE) { // "系统初始化失败" return; }
C++代码
HCI_ERR_CODE err_code = HCI_ERR_NONE; //配置串是由"字段=值"的形式给出的一个字符串,多个字段之间以','隔开。字段名不分大小写。 string init_config = ""; //灵云应用序号 init_config += "appKey=1234abcd"; //灵云开发者密钥 init_config += ",developerKey=1234567890"; //灵云云服务的接口地址 init_config += ",cloudUrl=http://api.hcicloud.com:8888"; //授权文件所在路径,保证可写 init_config += ",authpath=../../bin"; //日志的路径 init_config += ",logfilepath=../../bin"; //日志的等级 init_config += ",loglevel=5"; //日志文件的大小 init_config += ",logfilesize=512"; //其他配置使用默认值,不再添加,如果想设置可以参考开发手册 err_code = hci_init( init_config.c_str() );
iOS代码
HCI_ERR_CODE errCode = HCI_ERR_NONE; //appkey, developerKey, cloudUrl, authPath为必填项。其他可配置信息请查询灵云SDK开发手册hci_init函数说明。 NSString *appkey = @""; //开发者社区申请所得 NSString *developerKey = @""; //开发者社区申请所得 NSString *cloudUrl = @""; //开发者社区申请所得 NSString *authPath = @""; //授权文件所在路径,一般设置为沙盒Document路径 NSString *config = [NSString stringWithFormat:@"appkey=%@,developerKey=%@,cloudUrl=%@,authPath=%@", appkey, developerKey, cloudUrl, authPath]; errCode = hci_init(config.UTF8String); if (errCode != HCI_ERR_NONE && errCode != HCI_ERR_SYS_ALREADY_INIT) { NSLog(@"hci_init failed, error: %@", errCode); }else{ NSLog(@"hci_init success"); }
常见错误码(errcode)定义,详见灵云SDK开发手册
3.2 获取授权
在灵云系统初始化成功后,第一次使用各项能力之前,我们还需要调用授权检测函数去云端获取授权。
Android代码
// 获取授权 private int checkAuthAndUpdateAuth() { // 获取系统授权到期时间 int initResult; AuthExpireTime objExpireTime = new AuthExpireTime(); initResult = HciCloudSys.hciGetAuthExpireTime(objExpireTime); if (initResult == HciErrorCode.HCI_ERR_NONE) { // 显示授权日期,如用户不需要关注该值,此处代码可忽略 Date date = new Date(objExpireTime.getExpireTime() * 1000); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd",Locale.CHINA); Log.i(TAG, "expire time: " + sdf.format(date)); if (objExpireTime.getExpireTime() * 1000 > System.currentTimeMillis()) { // 已经成功获取了授权,并且距离授权到期有充足的时间(>7天) Log.i(TAG, "checkAuth success"); return initResult; } } // 获取过期时间失败或者已经过期 initResult = HciCloudSys.hciCheckAuth(); if (initResult == HciErrorCode.HCI_ERR_NONE) { Log.i(TAG, "checkAuth success"); return initResult; } else { Log.e(TAG, "checkAuth failed: " + initResult); return initResult; } }
C++代码
//获取过期时间 int64 expire_time; int64 current_time = (int64)time( NULL ); HCI_ERR_CODE err_code = hci_get_auth_expire_time( &expire_time ); if( err_code == HCI_ERR_NONE ) { //获取成功则判断是否过期 if( expire_time > current_time ) { //没有过期 printf( "auth can use continue\n" ); return true; } } //获取过期时间失败或已经过期 //手动调用更新授权 err_code = hci_check_auth(); if( err_code == HCI_ERR_NONE ) { //更新成功 printf( "check auth success \n" ); return true; } else { //更新失败 printf( "check auth return (%d:%s)\n", err_code ,hci_get_error_info(err_code)); return false; }
iOS代码
//获取过期时间 int64 expireTime; int64 currentTime = (int64)time(NULL); HCI_ERR_CODE errCode = hci_get_auth_expire_time(&expireTime); if (errCode == HCI_ERR_NONE) { if (expireTime < currentTime) { errCode = hci_check_auth(); if(errCode == HCI_ERR_NONE){ NSLog(@"check auth success"); return YES; }else{ NSLog(@"check auth failed, error: %@", errCode); return NO; } } else { //没有过期 NSLog(@"auth can use continue"); return YES; } } //读取授权文件出现错误 else if(errCode == HCI_ERR_SYS_AUTHFILE_INVALID){ errCode = hci_check_auth(); if(errCode == HCI_ERR_NONE){ NSLog(@"check auth success"); return YES; } else { NSLog(@"check auth failed, error: %@", errCode); return NO; } }else{ NSLog(@"check auth failed, error: %@", errCode); return NO; }
3.3 初始化 NLU 能力
在初始化灵云系统和获取授权成功后,我们还需要调用初始化函数初始化语义理解(NLU)能力。
Android代码
// 创建初始化参数辅助类 NluInitParam nluInitParam = new NluInitParam(); // 设置本地资源库的路径 nluInitParam.addParam(NluInitParam.PARAM_KEY_DATA_PATH, "/storage/emulated/0/sinovoice/com.sinovoice.example/data"); // 使用云端识别能力 nluInitParam.addParam(NluInitParam.PARAM_KEY_INIT_CAP_KEYS, "nlu.cloud"); // 初始化语义理解能力 errCode = HciCloudNlu.hciNluInit(nluInitParam.getStringConfig());
C++代码
string init_config = "initCapkeys=nlu.cloud";
init_config += ",dataPath=../../data";
err_code = hci_nlu_init(init_config.c_str());
if (err_code != HCI_ERR_NONE)
{
printf("hci_nlu_init return (%d:%s) \n",err_code,hci_get_error_info(err_code));
return;
}
printf( "hci_nlu_init success\n" );
iOS代码
//initCapKeys为必填项,如果为本地识别dataPath为必填项。其他可配置信息请查询开发手册hci_nlu_init函数说明。 NSString *dataPath = [[NSBundle mainBundle] pathForResource:@"data" ofType:Nil]; //本地识别所需本地资源所在路径 NSString *initCapKeys = @nlu.cloud"; NSString *config = [NSString stringWithFormat:@"dataPath =%@, initCapKeys =%@", dataPath, initCapKeys]; HCI_ERR_CODE errCode = HCI_ERR_NONE; errCode = hci_nlu_init(config.UTF8String); if (errCode != HCI_ERR_NONE){ NSLog(@"hci_nlu_init failed, error:%@", errCode); eturn NO; } NSLog(@"hci_nlu_init success"); return YES;
3.4 开启 NLU 识别会话
语义理解具体的工作是由引擎完成的,初始化 NLU 能力成功之后,我们还需要开启会话,用以实现初始化引擎,加载领域资源等。
Android代码
Session session = new Session(); NluConfig sessionConfig = new NluConfig(); // 使用意图识别能力key,此项必填。每个session只能定义一种能力 sessionConfig.addParam(NluConfig.SessionConfig.PARAM_KEY_CAP_KEY, "nlu.cloud"); // 开启会话 errCode = HciCloudHwr.hciHwrSessionStart(sessionConfig.getStringConfig(), session);
C++代码
int nSessionId = -1; string strSessionConfig = "capkey=nlu.cloud,intention=weather"; //此处也可以传入其他配置,参见开发手册,此处其他配置采用默认值 err_code = hci_nlu_session_start( strSessionConfig.c_str(), &nSessionId ); if( err_code != HCI_ERR_NONE ) { printf( "hci_nlu_session_start return (%d:%s)\n", err_code ,hci_get_error_info(err_code)); return false; }
iOS代码
//开启session HCI_ERR_CODE errCode = HCI_ERR_NONE; NSString *config = @"capKey=nlu.cloud"; int sessionID; //开启会话成功后,会返回的会话ID errCode = hci_nlu_session_start(config.UTF8String, &sessionID); if (errCode != HCI_ERR_NONE){ NSLog(@"hci_nlu_session_start failed, error:%@", errCode); return NO; } NSLog(@"hci_nlu_session_start success"); return YES;
3.5 语义理解
开启会话成功后,就可以进行语义理解了。
Android代码
NluConfig recogConfig = new NluConfig(); // 云端必须传intention recogConfig.addParam("intention", "weather"); // 开始翻译 NluRecogResult nluResult = new NluRecogResult(); // sTransText 要翻译的文本 utf-8格式, 以'\0'结束 errCode = HciCloudNlu.hciNluRecog(session, sTransText, recogConfig.getStringConfig(), nluResult);
C++代码
//以云端识别为例 NLU_RECOG_RESULT nlu_result; string recog_config = "intention=weather,context=yes"; err_code = hci_nlu_recog( nSessionId, result_line, recog_config.c_str(), &nlu_result ); if (err_code == HCI_ERR_NONE) { printf( "\nhci_nlu_recog success\n" ); // 输出识别结果 PrintNluResult( nlu_result ); // 释放识别结果 hci_nlu_free_recog_result( &nlu_result); } else { printf( "hci_nlu_recog return (%d:%s)\n", err_code ,hci_get_error_info(err_code)); }
iOS代码
//以云端识别为例 HCI_ERR_CODE errCode = HCI_ERR_NONE; NLU_RECOG_RESULT nluResult; //识别结果保存 NSString *config = @"intention = weather"; // 云端必须传intention //_sessionID:为开启会话(session)后获得的sessionID NSString *str = @"今天天气怎么样?"; //待识别文本需要以UTF-8进行编码 errCode = hci_nlu_recog(_sessionID, str.UTF8String, config.UTF8String, & nluResult); if (errCode != HCI_ERR_NONE) { NSLog(@"hci_nlu_recog failed, error:%@"errCode); }else{ NSLog("hci_nlu_recog success"); if (nluResult.pNluRecogResultCount != 0) { for (int i = 0; i < nluResult.pNluRecogResultCount; i++) { NSLog( @"index[%d]: %@", i, nluResult.pNluRecogResultList[i].pszResult); } } hci_nlu_free_recog_result(& nluResult); }
3.6 关闭 NLU 识别会话
不再需要使用NLU某个识别会话后,需要关闭识别会话
Android代码
HCI_ERR_CODE errCode = HciCloudNlu.hciNluSessionStop(session);
C++代码
HCI_ERR_CODE errCode = HCI_ERR_NONE; //关闭会话 errCode = hci_nlu_session_stop(sessionID); //sessionID:已经开启的会话的sessionID
iOS代码
HCI_ERR_CODE errCode = hci_nlu_session_stop(nSessionId);
3.7 终止NLU能力
如果所有的识别会话都已关闭,而且不需要再使用NLU能力了,我们可以终止NLU能力。
Android代码
HCI_ERR_CODE errCode = HciCloudNlu.hciNluRelease();
C++代码
HCI_ERR_CODE errcode = hci_nlu_release();
iOS代码
HCI_ERR_CODE errCode = hci_nlu_release();
3.8 关闭灵云系统
最后,需要关闭灵云系统。
Android代码
HCI_ERR_CODE errCode = HciCloudSys.hciRelease();
C++代码
HCI_ERR_CODE errCode = hci_release();
iOS代码
HCI_ERR_CODE errCode = hci_release();
4. 场景示例
4.1 多轮对话
多轮对话需要开启上下文功能,即在调用hciNluRecog接口时传入 context=yes 配置串,具体示例如下:
Android代码
NluConfig recogConfig = new NluConfig(); //云端必须传intention recogConfig.addParam("intention", "weather"); //开启上下文功能 recogConfig.addParam("context","yes"); NluRecogResult nluResult = new NluRecogResult(); int errCode = HciCloudNlu.hciNluRecog(session, "今天北京天气怎么样", recogConfig.getStringConfig(), nluResult); if (errCode == HciErrorCode.HCI_ERR_NONE) { ShowMessage("hciNluRecog success"); printNluResult(nluResult); } errCode = HciCloudNlu.hciNluRecog(session, "明天呢", recogConfig.getStringConfig(), nluResult); if (errCode == HciErrorCode.HCI_ERR_NONE) { ShowMessage("hciNluRecog success"); printNluResult(nluResult); }
C++代码
string recog_config="intention=weather,context=yes"; NLU_RECOG_RESULT nlu_result; //注意:识别的文本数据,UTF-8编码,以'\0'结束 err_code = hci_nlu_recog( nSessionId, "今天天气怎么样", recog_config.c_str(), &nlu_result ); if (err_code == HCI_ERR_NONE) { printf( "\nhci_nlu_recog success\n" ); // 输出识别结果 PrintNluResult( nlu_result ); // 释放识别结果 hci_nlu_free_recog_result( &nlu_result); } err_code = hci_nlu_recog( nSessionId, "明天呢", recog_config.c_str(), &nlu_result ); if (err_code == HCI_ERR_NONE) { printf( "\nhci_nlu_recog success\n" ); // 输出识别结果 PrintNluResult( nlu_result ); // 释放识别结果 hci_nlu_free_recog_result( &nlu_result); }
iOS代码
//以云端识别为例 HCI_ERR_CODE errCode = HCI_ERR_NONE; NLU_RECOG_RESULT nluResult; //识别结果保存 NLU_RECOG_RESULT nluResult1; //识别结果保存 NSString *config = @"intention = weather"; // 云端必须传intention //_sessionID:为开启会话(session)后获得的sessionID //待识别文本需要以UTF-8进行编码 errCode = hci_nlu_recog(_sessionID, @"今天天气怎么样?".UTF8String, config.UTF8String, & nluResult); errCode = hci_nlu_recog(_sessionID, @"明天呢?".UTF8String, config.UTF8String, & nluResult1); if (errCode != HCI_ERR_NONE) { NSLog(@"hci_nlu_recog failed, error:%@"errCode); }else{ NSLog("hci_nlu_recog success"); }
识别结果示例:
{ "answer": { "content": { "date":"2017-08-30", "description":"多云", "direction":"南风", "high":27, "location":"北京", "location_id":101010100, "low":19, "power":"<3级" }, "intention": { "action":"query", "city":"北京", "date":"20170830", "domain":"weather", "entry_score":5002700, "place":"北京" } } } { "answer": { "content": { "date":"2017-08-31", "description":"阴", "direction":"南风", "high":27, "location":"北京", "location_id":101010100, "low":18, "power":"<3级" }, "intention": { "action":"query", "city":"北京", "date":"20170831", "domain":"weather", "entry_score":5000900, "place":"北京" } } }
4.2 多领域识别
多领域识别,需要在传入intention字段添加多个领域, 以分号分割。具体示例如下:
Android代码
NluConfig recogConfig = new NluConfig(); //添加weather,joke领域 recogConfig.addParam("intention", "weather;joke"); NluRecogResult nluResult = new NluRecogResult(); int errCode = HciCloudNlu.hciNluRecog(session, "今天北京天气怎么样", recogConfig.getStringConfig(), nluResult); if (errCode == HciErrorCode.HCI_ERR_NONE) { ShowMessage("hciNluRecog success"); printNluResult(nluResult); } else{ ShowMessage("hciNluRecog error:" + HciCloudSys.hciGetErrorInfo(errCode)); } errCode = HciCloudNlu.hciNluRecog(session, "讲个笑话", recogConfig.getStringConfig(), nluResult); if (errCode == HciErrorCode.HCI_ERR_NONE) { ShowMessage("hciNluRecog success"); printNluResult(nluResult); }
C++代码
//interntion :传入多个领域,以分号分隔 string recog_config="intention=weather;joke"; NLU_RECOG_RESULT nlu_result; //注意:识别的文本数据,UTF-8编码,以'\0'结束 err_code = hci_nlu_recog( nSessionId, "今天天气怎么样", recog_config.c_str(), &nlu_result ); if (err_code == HCI_ERR_NONE) { printf( "\nhci_nlu_recog success\n" ); // 输出识别结果 PrintNluResult( nlu_result ); // 释放识别结果 hci_nlu_free_recog_result( &nlu_result); } err_code = hci_nlu_recog( nSessionId, "讲个笑话", recog_config.c_str(), &nlu_result ); if (err_code == HCI_ERR_NONE) { printf( "\nhci_nlu_recog success\n" ); // 输出识别结果 PrintNluResult( nlu_result ); // 释放识别结果 hci_nlu_free_recog_result( &nlu_result); }
iOS代码
//以云端识别为例 HCI_ERR_CODE errCode = HCI_ERR_NONE; NLU_RECOG_RESULT nluResult; //识别结果保存 NLU_RECOG_RESULT nluResult1; //识别结果保存 NSString *config = @"intention = weather; joke"; // 云端必须传intention //_sessionID:为开启会话(session)后获得的sessionID //待识别文本需要以UTF-8进行编码 errCode = hci_nlu_recog(_sessionID, @"今天天气怎么样?".UTF8String, config.UTF8String, & nluResult); errCode = hci_nlu_recog(_sessionID, @"讲个笑话".UTF8String, config.UTF8String, & nluResult1); if (errCode != HCI_ERR_NONE) { NSLog(@"hci_nlu_recog failed, error:%@"errCode); }else{ NSLog("hci_nlu_recog success"); }
识别结果示例:
{ "answer": { "content": { "date":"2017-08-30", "description":"多云", "direction":"南风", "high":27, "location":"北京", "location_id":101010100, "low":19, "power":"<3级" }, "intention": { "action":"query", "city":"北京", "date":"20170830", "domain":"weather", "entry_score":5002700, "place":"北京" } } } { "answer":{ "content": { "content": "我妈让我不要和成绩比我差的同学玩,于是我去找学习委员,学习委员说:“我妈不让我和学习比我差的同学玩。", "rating":"child", "title":"成绩", "type":"" }, "intention": { "action":"query", "domain":"joke", "entry_score":5001200 } }
4.3 客服云、意图场景混合交互
NLU SDK,既支持通过意图的方式,向内容平台请求意图识别结果。也支持以挂接客服云机器人的方式,对接客服云,实现QA问答。 要想实现对应功能,需在NLU识别接口中传入正确的配置串,示例如下:
- Android代码
recogConfig.addParam("intention", "weather;joke"); // 此处调用公有云云端意图领域,返回的是意图结果
recogConfig.addParam("needcontent","yes"); //此处设置是否仅需要意图结果,还是也需要内容平台第三方接口返回的意图答案。推荐设置为yes。
recogConfig.addParam("robotid", "37042c188c5b4885de37e9b2d7c74eb1"); //调用客服云参数,每一个robotid都对应客服云上唯一的一个逻辑机器人
recogConfig.addParam("channelid", "2"); //此处定义渠道编号,不同渠道的渠道编号值不同,通常可以设置为网页,channelid=2
recogConfig.addParam("resver", "2"); //此处定义请求云平台NLU协议版本,目前云端的协议版本为第二版,此处需设置resver=2
recogConfig.addParam("needanswer", "yes"); //此处设置是否需要客服云QA答案,如果设置为否,则不会返回问题答案,answer字段返回answerid。推荐设置为yes
C++代码
recog_config += "intention=weather;joke"; // 此处调用公有云云端意图领域,返回的是意图结果 recog_config += ",needcontent=yes"; //此处设置是否仅需要意图结果,还是也需要内容平台第三方接口返回的意图答案。推荐设置为yes。 recog_config += ",robotid=37042c188c5b4885de37e9b2d7c74eb1"; //调用客服云参数,每一个robotid都对应客服云上唯一的一个逻辑机器人 recog_config += ",channelid=2"; //此处定义渠道编号,不同渠道的渠道编号值不同,通常可以设置为网页,channelid=2 recog_config += ",resver=2"; //此处定义请求云平台NLU协议版本,目前云端的协议版本为第二版,此处需设置resver=2 recog_config += ",needanswer=yes"; //此处设置是否需要客服云QA答案,如果设置为否,则不会返回问题答案,answer字段返回answerid。推荐设置为yes
iOS代码
NSString * intention = @"weather;joke"; // 此处调用公有云云端意图领域,返回的是意图结果 NSString * needcontent = @"yes"; //此处设置是否仅需要意图结果,还是也需要内容平台第三方接口返回的意图答案。推荐设置为yes。 NSString * robotid = @"37042c188c5b4885de37e9b2d7c74eb1"; //调用客服云参数,每一个robotid都对应客服云上唯一的一个逻辑机器人 NSString * channelid = @"2"; //此处定义渠道编号,不同渠道的渠道编号值不同,通常可以设置为网页,channelid=2 NSString * resver = @"2"; //此处定义请求云平台NLU协议版本,目前云端的协议版本为第二版,此处需设置resver=2 NSString * needanswer = @"yes"; //此处设置是否需要客服云QA答案,如果设置为否,则不会返回问题答案,answer字段返回answerid。推荐设置为yes
示例运行结果,首先在content字段中,返回的intention=null,此处是由于示例输入的问题是“转账汇款5000元:,在weather,joke两个领域,没有对应的意图答案。由于没有找到对应的意图,所以content字段里也不会有内容平台返回的答案。但是”转账汇款5000元“,命中了客服云机器人的标准问(hit_question),所以会有客服云答案,此处设置needanswer=yes,获取问题答案。客服云后台各机器人有对应知识库,知识库分标准问、扩展问等,此处字段返回参照智能客服通用逻辑。
5. 配置说明
配置串是由"字段=值"的形式给出的一个字符串,多个字段之间以','隔开。字段名不分大小写。
字段 | 取值或示例 | 缺省值 | 含义 | 详细说明 |
---|---|---|---|---|
intention | 字符串,如:poi | 无 | 识别意图 | 可传入多个领域,以分号分隔。例如:intention=weather;call, 相应的添加资源文件:weather_xxxx,call_xxxx |
context | 字符串,有效字{yes,no} | yes | 是否开启上下文功能 | yes: 使用上下文,使NLU能记住对话的情景 no: 不使用上下文 |
needcontent | 字符串,有效字{yes,no} | yes | 是否返回内容 | yes: 返回内容 no: 仅返回意图结果 |
客服云配置 | ||||
robotid | 字符串 | 无 | 机器人ID | 可选,请求调用客服云时,客服云每一个逻辑机器人对应一个唯一的robotid,客服云机器人的创建,请联系技术支持 |
channelid | 字符串 | 无 | 渠道ID | 可选,用于标识渠道的ID,通过客服云后台管理系统的“机器人管理/渠道管理”配置,对应渠道类型为网站、微信或者QQ等。通常可以设置channelid=2 |
resver | 字符串 | 无 | NLU协议版本号 | SDK与客服云平台对接时,云平台使用的NLU协议版本号,当前的云平台,SDK端对应设置resver=2 |
needanswer | 字符串 | 无 | 是否需要QA答案 | 此处设置是否需要客服云QA答案,设置为yes,直接返回答案,设置为no,则返回的是答案的answerid |
关于配置参数更详细的说明,请参考灵云SDK开发手册。
5. FAQ
Q:意图领域有数量限制吗?一次性添加多个intention,添加了以后,服务器返回的json里都是null,是什么原因?这个代码该怎么写?
A:没有数量限制。采用如下方法添加参数,intention中间用分号隔开。需要注意代码添加的领域,appkey对应的应用里必须有勾选。如果添加了一个应用没有勾选的领域,则服务器会返回错误,客户端不会取得任何结果。
nluConfig.addParam(NluConfig.ResultConfig.PARAM_KEY_INTENTION, "weather;story");
Q:我希望的是,我说一句话,然后得到我说的这句话的识别内容和对应的语义结果,而不是传文本给你们去获取意图,这个应该怎么做?
A: 首先,NLU能力,实现的就是根据输入文本,返回语义结果。您说的场景,涉及语音+语义两部分,目前asr已经有一个专门的意图理解的capkey:asr.cloud.dialog,专门用来实现先进行语音识别,再根据语音识别的结果取语义结果的过程。您的场景,推荐用这种方式。
Q:我在哪里可以看到我需要的意图领域?我现在需求电话、日历、天气等领域的意图。
A: 开发者社区,创建应用或修改能力时,可以勾选应用capkey。勾选nlu.cloud和asr.cloud.dialog这两种意图识别能力时,会弹出一个窗口,您在需要用到的意图领域前面打钩,应用appkey就拥有了对应意图领域的访问权限。
Q:我用申请的公有云账号,调用你们的客服云,总是返回11号错误,service response failed,这个是什么原因?
A:客服云目前只部署在酒仙桥商用域,测试域(test.api.hcicloud.com:8888)账号无法使用,如果请求被导流到软件园商用域,也无法使用。请联系技术支持解决此问题,并尝试申请正式商用账号。
Q:NLU的返回结果个数是怎么判断的?我这边一次请求,返回了5个意图结果。
A5:NLU引擎默认支持返回多候选结果,各个候选结果的得分不同。如果想要仅返回一个NLU意图结果,云端,请设置candNum=1。candNum取值范围:[1,10]。本地,请设置candidateCount=1,candidateCount取值范围:[1,8]。
Q:我是否可以自定义NLU答案?比如我说“小娃你好”,返回“主人您也好”。
A:客服云支持自定义标准问、扩展问。公有云支持新增客户自定义的NLU意图领域,在客户定制领域内,支持自定义场景返回结果、自定义意图。通用领域,如weather领域,由于有大量用户在使用,不支持自定义。如有相关需求,请联系技术支持和商务。
Q:我的应用场景,需要和机器人做多轮问答,你们的NLU是否是支持多轮交互的?
A:支持,是否支持多轮通过context参数设置,默认参数就是context=yes,支持上下文,在下一次的NLU问答中,会将上一轮的结果带回。但是所有的多轮交互,都需要在一个session里进行,如果重新开启了sesison,则会跳出多轮交互。同时,我们的意图领域,和客服云一样,也是支持多轮交互的。但是这个需要服务端有对应的多轮意图文件,如有此方面需求,请联系技术支持和商务。
Q:我看你们的开发手册,本地领域资源文件,有tdlr_ptr.txt,tdlr_ent.txt,tdlr_tag.txt,这些txt格式的资源文件,我们是否可以自己编辑?
A:推荐不要,这个是我们的场景加工同事提供的,如有相关需求,建议协调我们的相关同事处理。如您确实希望自己编译此场景文件,请协调技术支持提供NLU场景文件加工相关的手册,参照手册进行场景意图模板加工工作。
Q:你们的公有云和客服云是什么关系?我是否可以直接发请求给你们的客服云?
A:可以,客服云就是一个智能客服系统,对外暴露了QA接口等,可以进行问答,接口接入需要参考《智能客服接口开发文档》。公有云通过一个固定的appkey访问客服云,外部用户不需要关心。以正常的方式调用NLU SDK,公有云自己就会完成寻找客服云的操作。
Q:robotid和intention字段,在调用nlu识别接口时,是否都是必传的?
A:robotid与客服云逻辑机器人绑定,intention字段则对应NLU意图领域。这两个字段,既可以同时传入,也可以只传入任意一个,视实际的应用场景决定。