Unresolved directive in index.adoc - include::/root/.jenkins/workspace/deep-brain-admin(prod-104)/target/asciidoc/generated/deep-brain-api/overview.adoc[]
== DeepBrain system Introduction

1. DeepBrain简介

   DeepBrain,深度语义云大脑,是一套基于语义理解的机器人SaaS云大脑平台,整个平台包含Web管理系统、DeepBrain API服务接口以及云大脑语义理解系统、技能商店。DeepBrain API提供了平台的对外服务接口,包含平台的核心业务如意图识别、技能服务、私有对话等。本文档主要介绍API的功能列表及使用方式。

2. DeepBrain API简介

   DeepBrain API,是云大脑的对外接口,供第三方对接使用,主要的服务包含两个部分:意图识别和技能服务。意图识别提供意图识别结果,由对接程序完成后续处理;技能服务包含已完成的内容,如音乐服务返回结果包含可在线播放的音乐地址、儿童相关服务返回结果包含可使用的内容资源。接口的返回结果包含简单视图和开发者视图,简单视图及问题答案或者资源详情,开发者视图除了简单视图的内容,还包括意图识别的意图命令结果和相关参数,格式为JSON字符串。

Unresolved directive in index.adoc - include::/root/.jenkins/workspace/deep-brain-admin(prod-104)/target/asciidoc/generated/deep-brain-api/paths.adoc[]
== Interface general specification

3. 接口使用说明

DeepBrain API为Restful风格的服务,采用HTTP协议实现,接口参数使用JSON格式传递。

HTTP数据 说明

调用地址

相应接口的地址,如服务请求接口http://api.deepbrain.ai:8383/deep-brain-api/ask

调用方式

POST

数据格式

JSON

安全认证

SHA1

访问限制

N/A

请求数据

消息主体采用JSON格式定义。消息头部需要设置contentType及accept支持json数据发送和接受。消息体区分大小写。

3.1. 请求参数 ServiceRequest

字段 类型 描述 非空 默认值

requestHead

RequestHead

请求头消息,包含时间,接口账号信息等。

Y

nlpData

NlpData

请求消息体,主要为用户的文本输入

Y

simpleView

Boolean

返回简单视图

True

location

RequestLocation

请求源地址信息

extParams

List<CommonAttribute>

扩展的请求参数

functionCodes

Set<String>

指定技能代码集合

3.2. 请求参数头信息 RequestHead

字段 类型 描述 非空 默认值

accessToken

SecurityToken

接口访问安全认证信息

Y

apiAccount

ApiAccount

机器人接口账号

Y

4. 接口安全认证信息 SecurityToken

nonce String Base64 编码的16位随机安全串 Y

createdTime

String

请求发生的系统时间,yyyy-MM-dd’T’HH:mm:ss

Y

privateKey

4.1. 机器人账号信息 ApiAccount

字段 类型 描述 非空 默认值

appId

String

机器人应用或者公司Id

Y

robotId

String

机器人Id

Y

userId

String

机器人用户Id

N

deviceId

String

机器人设备唯一标识符

N

4.2. 请求消息体 NlpData

字段 类型 描述 非空 默认值

inputText

String

请求内容(文本)

Y

4.3. 请求地址参数 RequestLocation

字段 类型 描述 非空 默认值

cityName

String

城市信息(中文名,如上海、北京、广州)

location

String

longitude

String

经度信息(浮点类型字符串)

longitude

String

latitude

String

纬度信息(浮点类型字符串)

latitude

String

4.4. 响应参数 ServiceResponse

字段 类型 描述 非空 默认值

responseHead

ResponseHead

响应头消息,包含响应时间,状态等

Y

simpleViewData

Map

简单视图返回对象(JSON串)Tts非空时,直接返回tts linkResources非空时,直接返回linkResources textResources非空时,返回textResources

4.5. 响应参数头信息 ResponseHead

字段 类型 描述 非空 默认值

apiAccount

ApiAccount

机器人账户信息

Y

responseTimestamp

Long

响应返回时间戳(单位毫秒)

Y

serviceTimeInMs

Long

请求执行时长(单位毫秒)

Y

statusCode

String

状态代码,参照状态代码说明 1)OK 执行完成 2)NO_PRIVILEGE没有权限 3)BAD_REQUEST请求消息格式有误 4)SERVER_ERROR系统执行异常 5)UNKNOWN未知错误

Y

errorCode

String

错误消息代码,具体说明请参照错误代码说明

4.6. 响应消息体 CommandData

字段 类型 描述 非空 默认值

inputText

String

文本输入内容

functionCode

String

技能代码

Y

functionName

String

技能名称

commandCode

String

意图代码

commandName

String

意图名称

commandSource

String

意图源 private standard

commandAttrs

List<CommonAttribute>意图参数列表,参数识别结果

dataType

String

数据类型 1) text 纯文本 2) hylink 访问地址

Y

isAsk

Boolean

是否为反问

ttsText

String

反问内容或者对话结果

ttsAudio

byte[]

TTS

音频输出

linkType

String

连接资源类型 1)video视频资源 2)audio音频资源 3)img 图片资源 4)rpc远程调用资源

textResources

List<TextResource >

tts 列表

linkReources

List<LinkResource>

数据内容如果是文本,则直接是文本内容,否则是一个json对象,该对象包含一个列表,每个元素为LinkResource

Y

4.7. 链接资源信息 LinkResource

字段 类型 描述 非空 默认值

accessURL

String

链接地址

Y

linkType

String

连接资源类型 1)video视频资源 2)audio音频资源 3)img图片资源 4)rpc远程调用资源

Y

resName

String

资源名称

Y

resAttrs

List<CommonAttribute>

资源属性列表

4.8. 文本资源信息 TextResource

字段 类型 描述 非空 默认值

ttsText

String

文本输出

ttsAudio

byte[]

TTS音频输出

4.9. 通用属性信息 CommonAttribute

字段 类型 描述 非空 默认值

attrName

String

属性名

Y

attrValue

String

属性值

Y

Unresolved directive in index.adoc - include::/root/.jenkins/workspace/deep-brain-admin(prod-104)/target/asciidoc/generated/deep-brain-api/definitions.adoc[]
== Sample of Usage

5. 接口调用Java示例

/**
 * 调用主程序示例
 */
public static void main(String[] args) {
    ApiAccount apiAccount = new ApiAccount();
    apiAccount.setAppId("6ef0f5e60d3711e79cf590b11c244b31");
    apiAccount.setRobotId("11b74db20d3c11e79cf590b11c244b31");
    apiAccount.setDeviceId("SZB0C0300BF8");
    apiAccount.setUserId("13766663333");
    RequestLocation location = new RequestLocation();
    location.setCityName("上海");
    List<CommonAttribute> extParams = new ArrayList<>();
    extParams.add(new CommonAttribute("myattr", "myval"));
    try {
        ServiceResponse response = ask(apiAccount, location, extParams, "天气");
        System.out.println(new Gson().toJson(response));
    } catch (Exception e) {
        logger.error(ExceptionUtils.getStackTrace(e));
    }
}
/**
 * ask接口调用
 * @param apiAccount
 * @param location
 * @param extParams
 * @param inputText
 * @return
 * @throws Exception
 */
public static ServiceResponse ask(ApiAccount apiAccount, RequestLocation location, List<CommonAttribute> extParams, String inputText) throws Exception {
    ServiceResponse response = null;
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    try {
        ServiceRequest request = new ServiceRequest();
        request.getRequestHead().setApiAccount(apiAccount);
        SecurityToken accessToken = new SecurityToken();
        accessToken.setNonce(generateNonceStr(32));
        accessToken.setCreatedTime(getCreated(new Date()));
        accessToken.setPrivateKey(SecurityTokenUtils.doPasswordDigest(accessToken.getNonce(), accessToken.getCreatedTime(), apiAccount.getRobotId()));
        request.getRequestHead().setAccessToken(accessToken);
        request.setNlpData(new NlpData());
        request.getNlpData().setInputText(inputText);
        request.setLocation(location);
        request.setExtParams(extParams);
        Gson gson = new Gson();
        String responseStr = httpInvoke(getConfigedURL(), gson.toJson(request));
        if (StringUtils.isNoneEmpty(responseStr)) {
            response = gson.fromJson(responseStr, ServiceResponse.class);
        }
    } catch (Exception e) {
        logger.error(ExceptionUtils.getStackTrace(e));
    } finally {
        stopWatch.stop();
        logger.info(stopWatch.getTotalTimeSeconds());
    }
    return response;
}
/**
 * http post请求示例
 * @param requestURL
 * @param jsonBody
 * @return response body的json串
 */
public static String httpInvoke(String requestURL, String jsonBody) {
    String responseStr = "";
    RequestConfig REQUEST_CONFIG = RequestConfig.custom().setConnectTimeout(CONNECT_TIMEOUT)
            .setConnectionRequestTimeout(CONNECT_TIMEOUT).setSocketTimeout(SOCKET_TIMEOUT).build();
    HttpClient httpClient = HttpClientBuilder.create().setDefaultRequestConfig(REQUEST_CONFIG).build();
    HttpPost httpRequest = new HttpPost(requestURL);
    httpRequest.addHeader("Accept", "application/json;charset=utf-8");
    httpRequest.addHeader("Content-Type", "application/json;charset=utf-8");
    httpRequest.addHeader("Content-Encoding", "utf-8");
    httpRequest.setEntity(new StringEntity(jsonBody, ContentType.APPLICATION_JSON));
    try {
        HttpResponse httpResponse = httpClient.execute(httpRequest);
        responseStr = EntityUtils.toString(httpResponse.getEntity(), Charset.forName("UTF-8"));
    } catch (IOException e) {
        logger.error(ExceptionUtils.getStackTrace(e));
    }
    return responseStr;
}

6. 安全认证信息生成示例

6.1. 不可重复的随机串Nonce生成示例

/**
 * ******************************************************************************************
 * ******************************** generate nonce str **************************************
 */

public static String generateNonceStr(int length)
        throws Exception {
    return Base64.encodeBase64String(generateNonce(length));
}

private static byte[] generateNonce(int length)
        throws Exception {
    try {
        SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
        byte[] temp = new byte[length];
        random.nextBytes(temp);
        return temp;
    } catch (Exception ex) {
        throw new Exception(
                "Error in generating nonce of length " + length, ex);
    }
}

6.2. 时间戳生成示例

/**
 * *****************************************************************************************
 * ****************************** generate created stamp************************************
 */

public static final String CREATED_FORMAT = "yyyy-MM-dd'T'HH:mm:ss";

public static String getCreated(Date date) {
    return getDateFormatter().format(date == null ? new Date() : date);
}

public static DateFormat getDateFormatter() {
    SimpleDateFormat dateFormat = new SimpleDateFormat(CREATED_FORMAT);
    dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
    return dateFormat;
}

6.3. 秘钥生成示例

/**
 * *****************************************************************************************
 * ******************************** generate private key ************************************
 */
public static String getPrivateKey(String nonce, String created, String privateKey) {
    String passwordDigest = null;
    try {
        byte[] b1 = nonce != null ? nonce.getBytes("UTF-8"): new byte[0];
        byte[] b2 = created != null ? created.getBytes("UTF-8") : new byte[0];
        byte[] b3 = privateKey != null ? privateKey.getBytes("UTF-8") : new byte[0];
        byte[] b4 = new byte[b1.length + b2.length + b3.length];
        int offset = 0;
        System.arraycopy(b1, 0, b4, offset, b1.length);
        offset += b1.length;
        System.arraycopy(b2, 0, b4, offset, b2.length);
        offset += b2.length;
        System.arraycopy(b3, 0, b4, offset, b3.length);
        byte[] digestBytes = generateDigest(b4);
        passwordDigest = Base64.encodeBase64String(digestBytes);
    } catch (Exception e) {
        System.out.println(e.getMessage());
    }
    return passwordDigest;
}

public static byte[] generateDigest(byte[] inputBytes) throws Exception {
    try {
        MessageDigest digest = MessageDigest.getInstance("SHA-1");
        return digest.digest(inputBytes);
    } catch (Exception e) {
        throw new Exception("Error in generating digest", e);
    }
}

6.4. Base64 示例

public class Base64Utils {
    private static final char LAST2BYTE = (char) Integer.parseInt("00000011", 2);
    private static final char LAST4BYTE = (char) Integer.parseInt("00001111", 2);
    private static final char LAST6BYTE = (char) Integer.parseInt("00111111", 2);
    private static final char LEAD6BYTE = (char) Integer.parseInt("11111100", 2);
    private static final char LEAD4BYTE = (char) Integer.parseInt("11110000", 2);
    private static final char LEAD2BYTE = (char) Integer.parseInt("11000000", 2);
    private static final char[] ENCODE_TABLE = new char[]{
            'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
            'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'};

    public static String base64Encode(byte[] from) {
        StringBuffer to = new StringBuffer((int) (from.length * 1.34) + 3);
        int num = 0;
        char currentByte = 0;
        for (int i = 0; i < from.length; i++) {
            num = num % 8;
            while (num < 8) {
                switch (num) {
                    case 0:
                        currentByte = (char) (from[i] & LEAD6BYTE);
                        currentByte = (char) (currentByte >>> 2);
                        break;
                    case 2:
                        currentByte = (char) (from[i] & LAST6BYTE);
                        break;
                    case 4:
                        currentByte = (char) (from[i] & LAST4BYTE);
                        currentByte = (char) (currentByte << 2);
                        if ((i + 1) < from.length) {
                            currentByte |= (from[i + 1] & LEAD2BYTE) >>> 6;
                        }
                        break;
                    case 6:
                        currentByte = (char) (from[i] & LAST2BYTE);
                        currentByte = (char) (currentByte << 4);
                        if ((i + 1) < from.length) {
                            currentByte |= (from[i + 1] & LEAD4BYTE) >>> 4;
                        }
                        break;
                }
                to.append(ENCODE_TABLE[currentByte]);
                num += 6;
            }
        }
        if (to.length() % 4 != 0) {
            for (int i = 4 - to.length() % 4; i > 0; i--) {
                to.append("=");
            }
        }
        return to.toString();
    }

    public static String base64Encode(String from) throws UnsupportedEncodingException {
        return base64Encode(from.getBytes(DEFAULT_ENCODING));
    }
}

7. 接口消息示例

7.1. 请求消息示例

{
    "requestHead":{
        "accessToken":{
            "nonce":"Zr9pSlFhNv0YBFTpM3wK4N1HOjG1Cc7KWfPgA+cIsYk=",
            "privateKey":"RRKArrhTJAbELNk1oC4GTpWuc/A=",
            "createdTime":"2017-04-11T11:31:00"
        },
        "apiAccount":{
            "appId":"6ef0f5e60d3711e79cf590b11c244b31",
            "robotId":"11b74db20d3c11e79cf590b11c244b31",
            "userId":"13766663333",
            "deviceId":"SZB0C0300BF8"
        }
    },
    "nlpData":{
        "inputText":"你好"
    },
    "simpleView":true
}

7.2. 链接型响应示例

{
  "inputText": "播放刘德华的冰雨",
  "command": "CommandMusic",
  "commandAttrs": [
    {
      "attrName": "FavoriteList",
      "attrValue": ""
    },
    {
      "attrName": "SongType",
      "attrValue": ""
    },
    {
      "attrName": "Singers",
      "attrValue": "刘德华"
    },
    {
      "attrName": "Album",
      "attrValue": ""
    },
    {
      "attrName": "Songs",
      "attrValue": "冰雨"
    }
  ],

  "ttsText": null,
   ttsAudio": null,

  "dataType": "hylink",
  "linkType": "audio",
  "textResources": null,
  "linkResources": [
    {
      "accessURL": "http://cdnmusic.hezi.360iii.net/hezimusic/7556.mp3",
      "linkType": "audio",
      "resName": "冰雨",
      "resAttrs": [
        {
          "attrName": "artist",
          "attrValue": "刘德华"
        },
        {
          "attrName": "album_name",
          "attrValue": "幻影中国巡回演唱会Live"
        },
        {
          "attrName": "duration",
          "attrValue": ""
        },
        {
          "attrName": "bitRate",
          "attrValue": ""
        },
        {
          "attrName": "streamSize",
          "attrValue": ""
        },
        {
          "attrName": "format",
          "attrValue": "mp3"
        }
      ]
    }
  ],
  "ask": false
}

7.3. 文本型响应示例

{
  "inputText": "你好朋友",
  "command": "commandChat",
  "commandAttrs": null,
  "ttsText": "那个有写短信。",
  "ttsAudio": null,
  "dataType": "text",
  "linkType": null,
  "textResources": null,
  "linkResources": null,
  "ask": false
}

1. Status Code

1.1. 状态及错误代码说明

1.1.1. 返回状态说明

状态代码 代码描述 备注

OK

执行完成

NO_PRIVILEGE

没有权限

BAD_REQUEST

请求消息格式有误

SERVER_ERROR

系统执行异常

UNKNOWN

未知错误

1.1.2. 错误代码说明

错误代码 错误描述 备注

MSG_BAD_REQUEST_NO_HEAD

无效请求,请求头为空

MSG_BAD_REQUEST_NO_ACCOUNT

无效请求,账号信息为空

MSG_BAD_REQUEST_INVALID_ACCOUNT

无效请求,账号信息无效

MSG_BAD_REQUEST_INVALID_TOKEN

无效请求,请求Token信息无效

MSG_BAD_REQUEST_NO_TOKEN

无效请求,请求Token为空

MSG_BAD_REQUEST_NO_NLPDATA

无效请求,输入数据为空

MSG_UNKNOWN_NLP_RESULT

无效请求,未知的语义识别结果

2. SDK下载

2.1. Java版本

2.2. C语言版本