开发指南

目的

智能对话是信息检索的一种高级形式,它能用准确、简洁的自然语言回答用户用自然语言提出的问题。智能对话将积累的无序语料信息,通过知识库管理工具进行有序和科学的整理,并建立基于知识的分类模型,这些分类模型可以指导新增加的知识咨询和服务访问,提高信息处理的自动性;经过累积常见问题及其解答,整理为规范的问答库形式,以支撑各种形式问题的智能对话。智能对话包括问答管理、智能对话引擎、在线问答三大模块。问答管理模块包括问答集、自定义技能、预置技能等功能;在线问答是指构建好的知识库通过智能对话引擎能够与问答平台进行人机交互问答。 本文档对基于智能对话如何进行二次开发进行了详细说明和描述,为开发者提供开发指导。

使用对象

该文档是智能对话的开发指南。

该文档使用对象为:开发人员。

术语定义

IE11:IE浏览器11版本;

SDK:指辅助开发某一类软件的相关文档、范例和工具的集合。SDK 也包括示例代码、支持性的技术注解或者其他的为基本参考资料澄清疑点的支持文档;

状态码:HTTP状态码,是用以表示网页服务器超文本传输协议响应状态的3位数字代码;

分词:将一个汉字序列切分成一个个单独的词。

概述

智能对话是由机器人提供的专业的智能交互SaaS模式的云服务平台,包括数据中心、问答构建、自定义技能、训练测试、开发者中心、预置服务六大模块,各模块下对应着不同的子模块包括意图管理、知识词典等,为开发者提供专业简便的智能交互操作接口,并内置闲聊服务等。 开发者可以通过智能对话,创建自定义技能,进行知识建设完善知识库等后台的管理,可通过下载SDK进行二次开发,或者参考《智能对话API参考》进行二次开发等,在SDK中,预先定义智能对话开发函数,提供应用程序与开发人员基于智能对话进行二次开发的能力,无需访问源码,或理解内部工作机制的细节。 在SDK中,由顾客发起的问题首先经过文字菜单处理,如果不属于文字菜单的范畴,问题将会依次转接至智能对话相关模块,包括重复问题模块、敏感词过滤模块、自定义技能模块、机器人信息模块、问答集模块、预置技能模块、未知问题模块,在任意模块中,如果问题与模块相匹配,则直接生成答案,返回结果,流程截止。其中,预置技能模块需要进行手动配置,以开启或者关闭该功能模块,智能对话处理的流程图如图 5-1所示。

开发说明

开发环境准备

JDK安装

JDK是整个Java的核心,包括了JAVA运行环境,JAVA工具和JAVA基础的类库。智能对话JAVA版本SDK依赖JDK环境,当前对JDK的版本需求是JDK1.8及JDK1.8以上版本。 首先检查部署环境是否已安装相应版本JDK,若无,则需要参考《JDK1.8 安装部署手册》进行安装部署。 安装完成后,需要验证是否已经正确安装JDK,如果是Windows系统,需打开“命令提示符”,或者在运行窗口,输入“cmd”,打开OS窗口,分别输入命令java -version与命令javac –version,如果输出各自的版本信息,则安装成功,否则请按照《JDK1.8安装部署手册》重新安装配置。如果是linux系统,在命令窗口中输入java -version与命令javac –version

到目前为止,已完成JDK的安装,接下来对SDK下载过程进行简要介绍。

SDK下载

为了方便智能对话项目的开发,在智能对话中提供SDK,可通过登录智能对话下载。 首先,进入问答平台界面。在登录界面,输入用户账号和密码,进入智能对话。

选择设置->开发者中心,在“SDK包下载”选项下面点击“下载”,完成SDK的下载。

解压下载的java.zip,获取压缩包中的dialog-bot-sdk-2.0.jar。

SDK中封装了快速建立智能对话的接口,包括构造初始化问答参数、创建问答服务、初始化问答接口、查询并返回结果等,下面对SDK的API做详细的介绍。

SDK中API说明

初始化问答参数

功能描述

构建智能对话的请求参数,通过构造对象的方式统一问答接口的参数结构。

接口信息

包路径 类名 方法名 说明
qa.engine.bot.sdk.ask AskRequest public AskRequest(String appKey, String appSecret, String question, String type, String sessionId, String platform) 初始化问答请求参数对象的构造函数。

参数说明

输入参数、输出参数说明,可参考使用如下表格描述。

参数名称 说明 参数值
appKey 应用key 从“开发者中心->开发者凭证”获取
appSecret 应用秘钥 从“开发者中心->开发者凭证”获取
question 提问的问题 用户输入语句
type 问题级别 两种级别:普通用户级别Constant.PRIMARY_TYPE、高级用户级别Constant.SENIOR_TYPE
sessionId 会话id 第一次获取sessionId时,将sessionId置空,通过后台获取。
platform 会话应用的平台,用户可根据需求进行选择。 网页:Constant.CUSTOM_PLATFORM;微信:Constant. WEIXIN_PLATFORM;安卓:Constant.ANDROID_PLATFORM;苹果:Constant.IOS_PLATFORM;默认选择网页版

创建问答服务

功能描述

用于实例化问答服务。

接口信息

包路径 类名 方法名 说明
qa.engine.bot.sdk.ask CloudServiceFactory public static CloudServiceFactory getInstance() 实例化服务对象
public abstract AskService createAskService() 获得智能对话服务对象

调用服务

功能描述

对会话进行配置,调用会话服务,返回会话结果。

接口信息

包路径 类名 方法名 说明
qa.engine.bot.sdk.ask AskService public void init(CloudConfiguration config) 初始化问答服务参数
public AskResponse ask(AskRequest request) throws CloudNotInitializedException 查询问答服务,返回问答结果
public SimilarityQuestionResponse similarityQuestion(AskRequest request,int limit,double score)throws CloudNotInitializedException; 查询相似问题的返回结果
public MediaResponse getMedia(AskRequest request,String mediaId) throws CloudNotInitializedException; 查询媒体文件的返回结果

参数说明

(1)init方法中输入参数说明。

参数名称 说明 参数值
config 智能对话参数类 CloudConfiguration类中封装了talkUrl路径、similarityUrl路径、mediaUrl路径、connectionTimeout连接超时时间、readTimeout读取超时时间、answer_number获取答案数量,用户通过相应的set方法设置CloudConfiguration类中的参数值,用以配置会话。如果config设置为null(不建议),系统将调用默认参数调用智能对话服务。

(2)ask方法中输入参数说明。

参数名称 说明 参数值
request 智能对话的请求容器 详情参考6.2.1节。

(3)similarityQuestion方法中的参数

参数名称 说明 参数值
request 智能对话的请求容器 详情参考6.2.1节。
limit 相似问题最多输出的个数 int
score 相似问题最小匹配度得分 double

(4)getMedia方法中的参数

参数名称 说明 参数值
request 智能对话的请求容器 详情参考6.2.1节。
mediaId 媒体对象Id String

分类检索API

分类检索服务接口信息如下表所示:

包路径 类名 方法名 说明
qa.engine.bot.sdk.ask AskService CatalogIndexResponse indexCatalog(CatalogIndexRequest ciReq); 分类检索接口

接口实现类为qa.engine.bot.sdk.ask.AskServiceImpl,请求/响应参数属性如下表所示:

参数名称 说明 参数类型 备注
appKey 应用秘钥key String 必要参数
appSecret 引用秘钥 String 必要参数
url 分类检索api路径 String 必要参数
catalog 分类名称 String 必要参数
stdQues 是否为标准问法 Boolean 非必要参数,默认false
start 分页起始页 Integer 非必要参数,默认0
limit 分页大小 Integer 非必要参数,默认10
参数名称 说明 参数类型 备注
status 响应状态码 Integer 不为空
reminder 响应提示信息 String 不为空
catalog 查询分类的名称 String 非异常不为null
total 记录总数 Integer 非异常不为null
kbFullCat 多层级分类名称列表 List 非异常不为null
questions 问法列表 List 非异常不为null

异常响应状态码及异常信息如下表所示:

状态码 说明 备注
200 响应成功
401 未授权请求 需要正确的appKey/appSeccret
403 请求参数有误 缺失必要的请求参数
11008 未找到相关分类
500 服务器响应异常 请确保服务器可以连接

开发流程

创建工程

打开eclipse,点击桌面上的eclipse图标(如果桌面中没有eclipse图标,请到eclipse的安装路径下,找到eclipse.exe,双击打开eclipse)。

(1)创建Java项目 点击菜单栏File -> New -> JavaProject,创建Java项目,如下图所示:

(2)输入工程名称 在Project name一栏中输入“SDKExample”,然后点击Finish完成项目创建,如下图所示

(3)新建文件夹 在SDKExample项目上单击鼠标右键,选择New -> Floder,如下图所示

(4)创建lib库 在弹出的对话框Fold name一栏中输入lib,并点击Finish完成文件夹创建

(5)拷贝jar包 将实验材料中的dialog-bot-sdk-1.5.jar复制到lib目录下,如下图所示

(6)修改工程属性 在SDKExample项目上单击鼠标右键,在弹出的菜单中选择Properties选项,如下图所示

(7)添加jar包 在“Properties for SDKExample”的弹出窗中选择“Java Build Path”,在右侧的tab页中选择“Libraries”,点击“Add JARS”,如下图所示

(8) 完成jar包添加 在弹出的对话框中展开SDKExample目录下的lib文件夹,选中dialog-bot-sdk-2.0.jar,点击“OK”,完成依赖包的添加。

创建类

在SDKExample项目上单击鼠标右键,选择NewOther…,如下图所示

在弹出的界面中选择Class,然后点击next,进入类创建界面。

在Package一栏中输入包名:com.inspur.sdk.demo,在Name一栏中输入SDKDemo,然后单击Finish完成接口的创建。

点击Finish后,项目的目录结构如下图所示

编写main()方法,代码如下

package com.inspur.sdk.demo;

public class SDKDemo {
    public static void main(String args[]){

    }
}

编写流程代码

SDK开发主要包含四部分:初始化问答参数、创建问答服务、初始化问答接口、查询并返回结果,如图6-18所示。

获取开发者凭证。开发者凭证是标识用户身份的唯一标识,在登录界面,用户输入账号和密码,进入智能对话。

选择“设置->开发者中心”,获取开发者凭证。

获取开发凭证并记录下来,进入初始化参数阶段。 在初始化参数阶段,首先实例化AskRequest对象,在构造方法中需要传入appkey、appSecret、询问的问题、问题级别、会话id、使用的平台。其中,appkey、appSecret对应唯一用户,需要在开发者中心获取,会话id通过后台获取,第一次访问时置空,后台将返回sessionId的值,第二次访问时,携带获取的sessionId,问题级别一般设为普通级别即可,使用的平台分为微信、开发者、IOS安卓、网页,在Constant常量中封装了各个参数,初始AskRequest时,直接调用即可。代码如下:

//应用id
String appKey = " 1afd3097a09744dbbdd40bc091f71fa9";
//应用秘钥
String appSecret = " 14cbb0e4dc354bfdb341459f2d51c373 ";
//输入的询问内容
String question = "你叫什么名字";
//输入会话Id
String sessionId="";

//初始化智能对话接口
AskRequest askRequest = new AskRequest(appKey, appSecret, question,
                Constant.PRIMARY_TYPE, sessionId, Constant.CUSTOM_PLATFORM);

在创建问答阶段,直接实例化会话服务即可,如下:

//创建问答服务
AskService askService = CloudServiceFactory.getInstance().createAskService();

在初始化问答接口阶段,需要配置CloudConfiguration参数,包括访问的url路径、连接头信息、连接超时时间、内容读取超时时间、获取答案的数量、回答问题的主题等。在此,为了方便开发者调试SDK程序,使用系统默认的参数,将参数设为null(通常请求路径必须设置)。代码如下:

//init中设置CloudConfiguration参数,
askService.init(null);

如果设置自己的参数则可使用如下设置,其中url为智能对话的url路径,answerNumber为返回答案的数量,ConnectionTimeout为链接超时时间。

CloudConfiguration cloudConfigration = new CloudConfiguration();
//设置问答路径
cloudConfig.setTalkUrl("http://10.111.25.27:8080/dialog/service/qa/bot/sdk/talk");
//设置相似问题路径
cloudConfig.setSimilarityUrl("http://10.111.25.27:8080/dialog/service/qa/bot/sdk/similarities");
//设置媒体文件路径
cloudConfig.setMediaUrl("http://10.111.25.27:8080/dialog/service/qa/bot/sdk/media");
//设置回答问题的数量
cloudConfigration.setAnswer_number("1");
//连接超时时间
cloudConfigration.setConnectionTimeout(1000);

在查询阶段,将初始化的参数传入问答服务中,获取类型为AskResponse的对象。在AskResponse中,封存了返回的状态码、结果的答案、分词等信息。注意,sessionId在第一次请求时置空,通过后台获取。代码如下:

//询问返回的结果
AskResponse askResponse = null;
askResponse = askService.ask(askRequest);
//获取第一次询问的产生的sessionId
String sessionId = askResponse.getResponseAnswer().getSessionid();
//返回所有结果的json
System.out.println(askResponse.getContent());
//返回指向的状态码
System.out.println(askResponse.getStatus());

为了进行多轮对话,在代码的末尾处添加循环输入,可以实现多轮会话功能。(当对话返回结果为音频、视频、图片、图文时,通过调用媒体文件的接口获取相应的素材文件)。

// 循环输入
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNext()) {
            question = scanner.nextLine();
            askRequest = new AskRequest(appKey, appSecret, question, Constant.PRIMARY_TYPE, sessionId,
                    Constant.CUSTOM_PLATFORM);

            try {

                //获取问题答案
                askResponse = askService.ask(askRequest);
                //获取相似列表
                simiRes = askService.similarityQuestion(askRequest, 4, 0.5);
                String answer = askResponse.getAnswer();
                if (askResponse.getResponseAnswer().getAnsType().equals("TM") && askResponse.getResponseAnswer().getTextMenu() != null) {
                    System.out.println("    文字菜单内容,请调用文字菜单接口解析:");
                    System.out.println(askResponse.getResponseAnswer().getTextMenu());
                }
                if(askResponse.getResponseAnswer().getAnsType().equals("T")){
                    System.out.print("    文本类型的答案:");
                    System.out.println(answer);
                    System.out.println(askResponse.getContent());
                }
                //素材类型(GT:图文 IMG:图片 AU:语音 VI:视频),可以对每种类型的文件分别检测,这里只列举其中一种
                if(askResponse.getResponseAnswer().getAnsType().equals("AU")){
                    //获取媒体文件
                    MediaResponse mediaR = askService.getMedia(askRequest,askResponse.getResponseAnswer().getMediaId());
                    System.out.print("    音频文件:");
                    System.out.println(mediaR.getMedia().getMediaName());
                }
                System.out.print("    相似问题列表:");
                System.out.println(simiRes.getSimilarityQuestionAll().getAnswers());

            } catch (CloudNotInitializedException e) {
                if (logger.isErrorEnabled()) {
                    logger.error(e);
                }
            }
        }

完整的示例代码如下

package qa.engine.bot.sdk.example;

import java.util.Scanner;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import qa.engine.bot.sdk.ask.AskRequest;
import qa.engine.bot.sdk.ask.AskResponse;
import qa.engine.bot.sdk.ask.AskService;
import qa.engine.bot.sdk.ask.CloudConfiguration;
import qa.engine.bot.sdk.ask.CloudNotInitializedException;
import qa.engine.bot.sdk.ask.CloudServiceFactory;
import qa.engine.bot.sdk.ask.MediaResponse;
import qa.engine.bot.sdk.ask.SimilarityQuestionResponse;
import qa.engine.bot.sdk.ask.util.Constant;

/**
 * SDK调用的示例代码
 */
public class SdkExample {
    public static void main(String[] args) throws Exception {
        final Log logger = LogFactory.getLog(SdkExample.class);
        // TODO Auto-generated method stub
        // 应用id
        String appKey = "wRb7bVjf+Gs=";
        // 应用秘钥
        String appSecret = "BA3CZOMmV50=";
        // 输入的询问内容
        String question = "你叫什么名字";

        // 初始化智能问答接口
        AskRequest askRequest = new AskRequest(appKey, appSecret, question, Constant.PRIMARY_TYPE, "",
                Constant.CUSTOM_PLATFORM);

        // 创建问答服务
        AskService askService = CloudServiceFactory.getInstance().createAskService();

        // init中设置CloudConfiguration参数
        CloudConfiguration cloudConfig = new CloudConfiguration();
        cloudConfig.setTalkUrl("http://10.111.25.27:8080/dialog/service/qa/bot/sdk/talk");
        cloudConfig.setSimilarityUrl("http://10.111.25.27:8080/dialog/service/qa/bot/sdk/similarities");
        cloudConfig.setMediaUrl("http://10.111.25.27:8080/dialog/service/qa/bot/sdk/media");
        askService.init(cloudConfig);

        // 获取第一次询问的产生的sessionId
        AskResponse askResponse = null;
        SimilarityQuestionResponse simiRes = null;
        askResponse = askService.ask(askRequest);
        String sessionId = askResponse.getResponseAnswer().getSessionid();
        System.out.println("获取的sessionId:"+sessionId);

        // 循环输入
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNext()) {
            question = scanner.nextLine();
            askRequest = new AskRequest(appKey, appSecret, question, Constant.PRIMARY_TYPE, sessionId,
                    Constant.CUSTOM_PLATFORM);
            try {

                //获取问题答案
                askResponse = askService.ask(askRequest);
                //获取相似列表
                simiRes = askService.similarityQuestion(askRequest, 4, 0.5);
                String answer = askResponse.getAnswer();
                if (askResponse.getResponseAnswer().getAnsType().equals("TM") && askResponse.getResponseAnswer().getTextMenu() != null) {
                    System.out.println("    文字菜单内容,请调用文字菜单接口解析:");
                    System.out.println(askResponse.getResponseAnswer().getTextMenu());
                }
                if(askResponse.getResponseAnswer().getAnsType().equals("T")){
                    System.out.print("    文本类型的答案:");
                    System.out.println(answer);
                }
                //素材类型(GT:图文 IMG:图片 AU:语音 VI:视频),可以对每种类型的文件分别检测,这里只列举其中一种
                if(askResponse.getResponseAnswer().getAnsType().equals("AU")){
                    //获取媒体文件
                    MediaResponse mediaR = askService.getMedia(askRequest,askResponse.getResponseAnswer().getMediaId());
                    System.out.print("    音频文件:");
                    System.out.println(mediaR.getMedia().getMediaName());
                }
                System.out.print("    相似问题列表:");
                System.out.println(simiRes.getSimilarityQuestionAll().getAnswers());

            } catch (CloudNotInitializedException e) {
                if (logger.isErrorEnabled()) {
                    logger.error(e);
                }
            }
        }
    }
}

至此,完成智能对话SDK项目的代码研发。接下来,运行项目,查看返回结果。

运行并查看结果

在SDKDemo类上单击鼠标右键,选择Run As->Java Application,如下图所示。

运行结果如下图所示:

在AskResponse.getContent中的json返回结果为:

{
  "question":"你叫什么名字",
  "topic":"",
  "format":"json",
  "lang":"zh",
  "app_id":"APPID-1",
  "sessionid":"null",
  "status":"200",
  "reminder":"",
  "answers":[
    {
      "id":"1",
      "title":"",
      "answer":"我的名字是小L",
      "url":"",
      "type":"",
      "resolution":{
        "values":null
      },
      "score":"0.0"
    }
  ],
  "segment":[
    "你",
    "叫",
    "什么",
    "名字"
  ],
  "similarSentence":"",
  "bestSimilarityScore":""
}

注意事项

初始化问答接口时,为了开发方便,SDK中的Constant设置了默认的初始化参数,实际使用时,可自行通过CloudConfiguration进行配置。 sessionId通过第一次访问获取,随后的会话将依附于当前的会话id。 答案中包含媒体文件时,某些字段的值可能会发生变话,比如为空等。