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 调用流程

主要功能接口调用如下图: NLU_流程

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目录下。如下图所示: NLU

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意图领域。这两个字段,既可以同时传入,也可以只传入任意一个,视实际的应用场景决定。

results matching ""

    No results matching ""