1. 概述

意图识别是在语音识别(ASR)的基础上,对识别出的语音文本信息进行语义理解,找出话者想要表达的确切意图。意图识别的结果依赖不同领域的大数据模型,针对不同的领域,需要使用不同的资源文件。综上意图识别是一种复合能力,它结合了语音识别(ASR)自由说和语义理解(NLU)两种能力。

在集成过程中如有疑问,可登录灵云开发者论坛,查找答案或与其他开发者交流。

本地意图识别

  本地意图识别即离线识别模式,加载本地模型并调用本地识别引擎进行意图识别工作。

云端意图识别

  云端识别即在线识别模式,调用云端引擎进行意图识别工作。

1.2 能力定义(Capkey)

需要说明的是本地意图识别能力(asr.local.dialog)在开发者网站并没有指定的能力可以选择,这是因为本地意图识别能力(asr.local.dialog)结合了本地自由说识别(asr.local.freetalk)和本地语音理解(nlu.local.recog)这两种能力。开发者在使用本地意图识别(asr.local.dialog)时,应该在开发者网站开通以上两种能力(asr.local.freetalk 和 nlu.local.recog)

capkey 说明 领域 所需资源文件
asr.local.dialog
(dialogMode=freetalk)
本地意图识别
(自由说+NLU)
ASR freetalk模型
NLU engine模型
NLU resource模型(根据intention选择不同领域模型,如weather)
ft_decoder.conf
ispk_dnn.dat
ispk_hclg.dat
ispk_blm.dat
ispk_slm.dat
tdle_bi_tag.txt
tdle_cmn.bin
tdlr_ent.txt
tdlr_ptr.txt
tdlr_tag.txt
asr.local.dialog
(dialogMode=grammar)
本地意图识别(语法+NLU) ASR grammar模型
NLU engine模型
NLU resource模型(根据intention选择不同领域模型,如weather)
grm_decoder.conf
ispk_aux.dat
ispk_dnn.dat
ispk_g2p.dat
tdle_bi_tag.txt
tdle_cmn.bin
tdlr_ent.txt
tdlr_ptr.txt
tdlr_tag.txt
asr.cloud.dialog 云端意图识别    

2. 准备工作

本地意图识别在不同领域所需要的资源文件存在重名情况。其中 engine 资源(tblebi_tag.txt,tble_cmn.bin)与领域无关,在不同领域间是相同的,可以只导入一份到工程目录中,而 resource 资源(tdlr_ent.txt,tdlr_ptr.txt,tdlr_tag.txt)则存在同名情况,这时导入工程目录需将文件加相应前缀,不同于 resPrefix 参数设置的是,不同领域间的前缀固定为领域的命名,如天气(weather)领域,则需要加 `weather` 前缀以示区别。

加载前缀后,导入工程目录如下图所示。

详见ASR能力集成指南

3. 意图识别能力集成

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");
      }
    

3.2 授权检测

在初始化灵云 SDK 的 SYS 通用模块后,还需要调用授权检测函数去云端获取授权。

  • 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 能力初始化

在初始化灵云 SDK 的 SYS 通用模块和授权检测成功后,需调用 ASR 初始化函数。详见灵云SDK开发手册

  • Android代码

      // 创建初始化参数辅助类
      AsrInitParam asrInitParam= new AsrInitParam ();
      // 设置本地资源库的路径
      asrInitParam.addParam(AsrInitParam .PARAM_KEY_DATA_PATH, "/storage/emulated/0/sinovoice/com.sinovoice.example/data");
      asrInitParam.addParam(AsrInitParam .PARAM_KEY_INIT_CAP_KEYS, "asr.local.dialog");
      int errCode = HciCloudAsr.hciAsrInit(asrInitParam.getStringConfig());
    
  • C++代码

      string asr_init_config = "";
      //建议在initcapkeys中添加需要使用的所有能力以提高第一次识别的效率
      asr_init_config += "initcapkeys=asr.local.dialog";
      //如果是本地能力,此处指定本地能力依赖资源路径
      asr_init_config += ",datapath=../../data";
      err_code = hci_asr_init(asr_init_config.c_str());
      if (err_code != HCI_ERR_NONE)
      {
          printf("hci_asr_init return (%d:%s) \n",err_code,hci_get_error_info(err_code));
          return;
      }
    
  • iOS代码

      //initCapKeys为必填项,如果为本地意图识别dataPath为必填项。其他可配置信息请查询开发手册hci_asr_init函数说明。
      NSString *dataPath = [[NSBundle mainBundle] pathForResource:@"data" ofType:Nil];  //本地意图识别识别所需本地资源所在路径
      NSString *initCapKeys = @"asr.local.dialog";  //语音识别(ASR)所需使用的能力列表,可以包含多种能力,用';'分号隔开
      NSString *config = [NSString stringWithFormat:@"dataPath =%@, initCapKeys =%@", dataPath, initCapKeys];
      HCI_ERR_CODE errCode = HCI_ERR_NONE;
      errCode = hci_asr_init(config.UTF8String);
      if (errCode != HCI_ERR_NONE){
          NSLog(@"hci_asr_init failed, error:%@", errCode);
          return NO;
      }
      NSLog(@"hci_asr_init success");
      return YES;
    

3.4 开启会话(session)

ASR 是通过会话(session)来管理识别过程的。在ASR能力初始化成功之后,需要通过开启识别会话来完成识别。详见灵云SDK开发手册

  • Android代码

      AsrConfig config = new AsrConfig();
      // 启动 ASR Session
      int errCode = -1;
      //系统初始化可以添加多个能力,但每次对话session开启只能指定一个能力
      config.addParam(AsrConfig.SessionConfig.PARAM_KEY_CAP_KEY, "asr.local.dialog");
      config.addParam("intention", "weather");
      //会话开启的字符串配置
      String sSessionConfig = config.getStringConfig();
    
      Session nSessionId = new Session();
      errCode = HciCloudAsr.hciAsrSessionStart(sSessionConfig, nSessionId);
    
  • C++代码

      int nSessionId = -1;
      string strSessionConfig = "capkey=asr.local.dialog,intention=weather";
      //此处也可以传入其他配置,参见开发手册,此处其他配置采用默认值
      err_code = hci_asr_session_start( strSessionConfig.c_str(), &nSessionId );
      if( err_code != HCI_ERR_NONE )
      {
          printf( "hci_asr_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=asr.cloud.dialog,intention=weather";
      int sessionID;            //开启会话成功后,会返回的会话ID
      errCode = hci_asr_session_start(config.UTF8String, &sessionID);
      if (errCode != HCI_ERR_NONE){
              NSLog(@"hci_asr_session_start failed, error:%@", errCode);
              return NO;
      }
      NSLog(@"hci_asr_session_start success");
      return YES;
    

3.5 语音识别

在启动会话(session)成功后,即可可以进行 ASR 识别过程。识别功能通过调用识别函数完成,如果是流式识别/实时反馈,则需要多次调用识别函数将语音数据送入 SDK。。配置参数详见灵云SDK开发手册

  • Android代码

      String audioFile = "sinovoice.pcm";
      // 从assets资源目录获取sinovoice.pcm 语音数据文件
      byte[] voiceData = Tools.getAssetFileData(this,audioFile);
      if (null == voiceData) {
          // ShowMessage("Open input voice file" + audioFile + " error!");
          return;
      }
    
      if (HciErrorCode.HCI_ERR_NONE != errCode) {
          //    ShowMessage("hciAsrSessionStart error:" + HciCloudSys.hciGetErrorInfo(errCode));
          return;
      }
      ShowMessage("hciAsrSessionStart Success");
    
      // 识别结果
      AsrRecogResult asrResult = new AsrRecogResult();
    
      // 识别方法 此处的两个参数( 语音识别配置串,识别语法数据)在SessionStart的时候已经传入了,此处省略
      errCode = HciCloudAsr.hciAsrRecog(nSessionId, voiceData, null, null, asrResult);
      if (HciErrorCode.HCI_ERR_NONE == errCode) {
          // 输出识别结果
          printAsrResult(asrResult);
      }
    
      // 输出识别结果的方法
      private  void printAsrResult(AsrRecogResult recogResult) {
          if (recogResult.getRecogItemList().size() < 1) {
              ShowMessage("recognize result is null");
          }
          for (int i = 0; i < recogResult.getRecogItemList().size(); i++) {
              if (recogResult.getRecogItemList().get(i).getRecogResult() != null) {
                  String utf8 = recogResult.getRecogItemList().get(i).getRecogResult();
                  ShowMessage("result index:" + String.valueOf(i) + " result:" + utf8);
              } else {
                  ShowMessage("result index:" + String.valueOf(i) + " result: null");
              }
          }
      }
    
  • C++代码

      ASR_RECOG_RESULT asrResult;
      string  recog_config = "audioFormat=pcm16k16bit,encode=none";
      err_code = hci_asr_recog( nSessionId, voiceData.buff_, voiceData.buff_len_, recog_config.c_str(), NULL, &asrResult );
      if( err_code == HCI_ERR_NONE )
      {
          printf( "hci_asr_recog success\n" );
          // 输出识别结果
          PrintAsrResult( asrResult );
          // 释放识别结果
          hci_asr_free_recog_result( &asrResult );
      }
      else
      {
          printf( "hci_asr_recog return (%d:%s)\n", err_code ,hci_get_error_info(err_code));
      }
    
  • iOS代码

      HCI_ERR_CODE errCode = HCI_ERR_NONE;
      ASR_RECOG_RESULT asrResult;  //识别结果保存
      NSString *config = @"audioFormat=pcm16k16bit,encode=none";
      //_sessionID:为开启会话(session)后获得的sessionID
      //_voiceData:为音频数据文件,数据类型为NSData
      errCode = hci_asr_recog(_sessionID, (void *)_voiceData.bytes, (unsigned int)_voiceData.length, config.UTF8String, NULL, &asrResult);
      if (errCode != HCI_ERR_NONE) {
          NSLog(@"hci_asr_recog failed, error:%@"errCode);
      }else{
          NSLog("hci_asr_recog success");
          NSString *strResult = nil;
          if (asrResult.psResultItemList > 0) {
              if (asrResult.psResultItemList[0].pszResult!= NULL){
                  strResult = [NSString stringWithUTF8String:asrResult.psResultItemList[0].pszResult];
              }
          }
          if (strResult && strResult.length) {
          //识别结果
          }else{
          }
          hci_asr_free_recog_result(&asrResult);
      }
    

    识别完成结果示例:

      {
          "result": "今天天气怎么样",
          "answer": {
              "content": {
                  "date": "2017-08-28",
                  "description": "晴",
                  "direction": "北风",
                  "high": 28,
                  "location": "北京",
                  "location_id": 101010100,
                  "low": 17,
                  "power": "3-4级"
              },
              "intention": {
                  "action": "query",
                  "date": "20170828",
                  "domain": "weather",
                  "entry_score": 5002100
              }
          }
      }
    

3.6 结束识别

最后我们需要反初始化,依次关闭会话,终止 ASR 能力,关闭灵云系统。

  • Android代码

      // 终止session
      HciCloudAsr.hciAsrSessionStop(nSessionId);
      //反初始化ASR
      HciCloudAsr.hciAsrRelease();
      //ShowMessage("hciAsrRelease");
      HciCloudSys.hciRelease();
    
  • C++代码

      HCI_ERR_CODE errCode = HCI_ERR_NONE;
      //关闭会话
      errCode = hci_asr_session_stop(sessionID);  //sessionID:已经开启的会话的sessionID
      //终止ASR能力
      errCode  = hci_asr_release();
      //关闭灵云系统
      errCode  = hci_release();
    
  • iOS代码

      //结束session后,调用hci_asr_release和hci_release函数结束能力调用
      HCI_ERR_CODE errCode = HCI_ERR_NONE;
      errCode = hci_asr_session_stop(sessionID);  //sessionID:已经开启的会话的sessionID
      if (errCode != HCI_ERR_NONE){
              NSLog(@"hci_asr_session_stop failed, error:%@", errCode);
              return NO;
      }
      NSLog(@"hci_asr_session_stop success");
      errCode  = hci_asr_release();
      if (errCode != HCI_ERR_NONE){
              NSLog(@"hci_asr_release failed, error:%@", errCode);
              return NO;
      }
      NSLog(@"hci_asr_release success");
      errCode  = hci_release();
      if (errCode != HCI_ERR_NONE){
              NSLog(@"hci_release failed, error:%@", errCode);
              return NO;
      }
      NSLog(@"hci_release success");
      return YES;
    

4. FAQ

results matching ""

    No results matching ""