DSK接入协议
一. DSK协议
1.1 概述
DSK协议为自定义开发过程中需要依赖的协议,本质上规定了开发过程中客户端与服务端数据交互的格式。
1.2 使用场景
适用于有开发运维能力或拥有自有NLP服务的开发者和第三方平台接入。
识别和语义的定制同任务型技能的定制过程一致。
二. 协议接入
2.1 接入流程
1)学习DSK协议,详细了解DSK协议各字段所表达的意思。
2)开发者开发自有服务,根据DSK协议,接收来自DUI技能平台(相当于客户端)发送过来的请求,服务端的主要功能就是解析请求的JSON数据,根据相同字段的不同内容,决定服务端返回的数据。
3)服务端开发完毕并启动,在DUI技能平台填写正确的服务地址,进行测试。参考文档《创建自定义技能》来完成控制台上的配置。
2.2 请求格式
2.2.1 请求参数
JSON格式的请求体参数如下所示,主要包括三部分: request, session, context。
request是与当前请求相关的数据,session是与当前技能会话相关的数据,context是全局共享的数据。详见《DSK协议基本概念》
参数 | 必填(Y/N) | 类型 | 说明 |
---|---|---|---|
version | Y | string | 协议版本号 |
session | Y | object | 当前会话信息 |
session.sessionId | Y | string | 会话唯一标识 |
session.new | N | boolean | 是否新创建的session,非必须,默认false。true 表示开启新会话 |
context | Y | object | 全局共享的数据 |
context.skill | Y | object | 技能信息 |
context.skill.settings | N | object | 技能级配置 |
context.user | Y | object | 用户信息 |
context.device | Y | object | 设备信息 |
context.product | Y | object | 产品信息 |
context.system.settings | N | object | 系统级配置 |
request | Y | object | 当前请求相关的信息,分三种类型start, continue |
Start Request
参数 | 必填(Y/N) | 类型 | 说明 |
---|---|---|---|
request.type | Y | string | 取值为start |
request.requestBodyType | Y | string | 请求内容类型:nluResult, triggerIntent, executeReturn, syncSession等。 以下内容以nluResult举例 |
request.requestId | Y | string | 请求的唯一标识 |
request.task | Y | string | 任务名 |
request.slots | Y | array | 合并后的slots |
request.audio | N | object | 音频(base64编码),只有配置了"透传音频"时才有此键 |
request.inputs | Y | array | 用户语义解析记录列表,按照由远到近排序 |
request.inputs[].input | Y | string | 用户输入的文本,一般是语音识别结果 |
request.inputs[].audio | N | object | 音频内容, 只有配置了"透传音频"时才有此键 |
request.inputs[].audio.content | N | base64 string | 音频(base64编码),只有配置了"透传音频"时才有此键 |
request.inputs[].slots[].name | N | string | 语义槽名称,其中intent是一种特殊的slot |
request.inputs[].slots[].value | N | string | 语义槽取值 |
request.inputs[].slots[].rawvalue | N | string | 原始value |
request.inputs[].slots[].rawpinyin | N | string | 原始value的拼音 |
request.inputs[].slots[].pos | N | array | value在文本中的位置 |
Continue Request
与Start Request基本一样, 区别是Continue Request不是第一个请求
参数 | 必填(Y/N) | 类型 | 说明 |
---|---|---|---|
request.type | Y | string | 这里取值continue |
request.requestBodyType | Y | string | 请求内容类型:nluResult, triggerIntent, executeReturn, syncSession等。 以下内容以nluResult举例 |
request.requestId | Y | string | 请求标识 |
request.task | Y | string | 任务名 |
request.slots | Y | array | 合并后的slots |
request.inputs | Y | array | 用户输入的文本, 一般是语音识别结果 |
2.2.2 HTTP请求头
POST /your-skill-path HTTP/1.1
Content-Type : application/json;charset=UTF-8
Host : your.skill.host.com
Accept : application/json
Accept-Charset : utf-8
Authorization : Bearer %BEARER TOKEN%
Content-Length : N
2.2.3 HTTP 请求体
JSON格式的请求体格式如下所示:
{
"version": "1.0",
"session": {
"new": true,
"sessionId": "this-is-session-id",
"attributes": {
"key": "this-is-value"
}
},
"context": {
"skill": {
"skillId": "this-is-skill-id",
"settings": { }
},
"user": {
"userId": "this-is-user-id"
},
"device": {
"deviceName": "this-is-device-name"
},
"product": {
"productId": "this-is-product-id",
"productVersion":"1"
},
"system": {
"settings": { }
}
},
"request": {}
}
当前request 分三种类型: start, continue:
1)请求体 : Start Request
{
"version": 1.0,
"session": {...},
"context": {...},
"request": {
"type": "start",
"requestBodyType": "nluResult",
"requestId": "this-is-request-id",
"task": "查天气",
"slots": [ // 合并后的slots
{"name": "intent", "value": "查城市天气"},
{"name": "city", "value": "北京", "rawvalue": "北京", "rawpinyin": "bei jing", "pos": [1, 2]}
],
"inputs": [
{
"input": "我要查天气",
"audio": { // 如果创建技能时,配置了透传音频选项,则请求体中会携带音频信息
"audioType": "ogg",
"sampleRate": 16000,
"channel": 1,
"sampleBytes": 2,
"content": "base64_encoded_audio_data"
},
"task": "查天气",
"timestamp": 1514882440,
"slots": [
{"name": "intent", "value": "查城市天气"}
]
},
{
"input": "北京",
"audio": { // 如果创建技能时,配置了透传音频选项,则请求体中会携带音频信息
"audioType": "ogg",
"sampleRate": 16000,
"channel": 1,
"sampleBytes": 2,
"content": "base64_encoded_audio_data"
},
"task": "查天气",
"timestamp": 1514882444,
"slots": [
{"name": "intent", "value": "查城市天气"},
{"name": "city", "value": "北京", "rawvalue": "北京", "rawpinyin": "bei jing", "pos": [1, 2]}
]
}
]
}
}
2)请求体 : Continue Request
{ "version": 1.0, "session": {...}, "context": {...}, "request": { "type": "continue",
如果创建技能时,配置了透传音频选项,则请求体中会携带音频信息
"requestBodyType": "nluResult", "requestId": "this-is-request-id", "task": "查天气", "slots": [ // 合并后的slots {"name": "intent", "value": "查城市天气"}, {"name": "city", "value": "北京", "rawvalue": "北京", "rawpinyin": "bei jing", "pos": [1, 2]} ], "inputs": [ { "input": "我要查天气", "audio": { // 如果创建技能时,配置了透传音频选项,则请求体中会携带音频信息
"audioType": "ogg", "sampleRate": 16000, "channel": 1, "sampleBytes": 2, "content": "base64_encoded_audio_data" }, "task": "查天气", "timestamp": 1514882440, "slots": [ {"name": "intent", "value": "查城市天气"} ] }, { "input": "北京", "audio": { //"audioType": "ogg", "sampleRate": 16000, "channel": 1, "sampleBytes": 2, "content": "base64_encoded_audio_data" }, "task": "查天气", "timestamp": 1514882444, "slots": [ {"name": "intent", "value": "查城市天气"}, {"name": "city", "value": "北京", "rawvalue": "北京", "rawpinyin": "bei jing", "pos": [1, 2]} ] } ] } }
2.3 响应格式
2.3.1 响应参数
第三方平台需要把数据结构化成DUI的数据格式,避免使用null标记空值字段,DUI将会校验关键字段的合法性。
参数 | 必填(Y/N) | 类型 | 说明 |
---|---|---|---|
version | Y | string | 版本号 |
session | Y | object | 上下文信息 |
response.speak | Y | object | 对话交互中语音播报的内容 |
response.speak.type | Y | string | 对话输出,音频或者语音合成;"text":纯文本;"audio":音频资源;"ssml":合成SSML标记 |
response.speak.text | N | string |
合成文本,speak.type是"text"时必须有 注意:和response.speak.ssml只能二选一,两个都填了会出现都不生效的情况 |
response.speak.audioUrl | N | string | 对话语音输出音频,speek.type为"audio"时必须有 |
response.speak.ssml | N | string |
用于合成的ssml标记文本,speek.type为"ssml"时必须有 注意:和response.speak.text只能二选一,两个都填了会出现都不生效的情况 |
response.widget | N | object | 对话交互中要显示的内容, DUI控件包含: 文本(text)、内容卡片(content)、列表(list)、多媒体(media)、内嵌网页(web)、自定义。 |
response.execute | N | object | 执行本地命令或本地查询, nativecmd没有返回值, nativeapi有返回值(nativeapi保留备用) |
shouldEndSession | Y | boolean | 对话是否结束,false:继续对话,true:结束对话 |
confidence | N | float | 置信度 |
yield | N | boolean | 是否让出调度权。默认false,如果为true将在DUI技能中再次调度。参考《示例 skill yield&re-dispatch》 |
其中widget包括文本、内容卡片、列表、多媒体、内嵌入网页等,详见文档《DUI控件介绍》 《控件数据格式》
2.3.2 正确响应
HTTP 响应头
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Content-Length: N
HTTP 响应体
第三方平台需要把数据结构化成DUI的数据格式。
JSON字符串:
{
"version": "1.0",
"session": {
"nextIntents": ["下一轮意图1","下一轮意图2"],
"attributes": {...} // 保留备用
},
"response": {
"speak": {
"type": "text",
"text": "北京晴, 26到32度"
},
"widget": {
"type": "content",
"name": "the widget name",
"title": "the title",
"subTitle": "sub-title",
"label": "label",
"imageUrl":"URL of the image to be shown",
"linkUrl":"URL of the attribute to be associated with the card",
"extra": {
"key1": "val1",
"key2": "val2"
},
"recommendations": ["推荐说法1", "推荐说法2"]
},
"execute": { // 执行本地命令或本地查询, 可以有返回值, 也可以没返回值
"url": "nativecmd://settings/openwifi", // 命令URL, nativecmd没有返回值, nativeapi有返回值
"args": { // 参数
"arg1": "val1",
"arg2": "val2"
}
}
},
"yield": false,
"shouldEndSession": false,
"confidence": 0.9
}
}
2.3.3 异常
使用标准HTTP状态来表达 API 请求的成功或是错误。以下是有可能遇到的HTTP状态:
200:表示请求成功
非200:表示请求失败
2.4 示例demo
2.4.1 下载Python示例
2.4.2 下载Java示例
2.5 其他说明
2.5.1 注意事项
1)对话回复部分为“接入服务代理”,配置时暂只支持填写web服务地址(即http://、https://),且服务地址必须为服务的公网IP地址,否则DUI网站请求将无法到达开发者的服务地址。
2)提供的Java示例是Spring Boot工程,需开发者自己创建一个工程,模仿示例可以写出一个最简单的demo。Spring Boot基础教程:https://gitee.com/didispace/SpringBoot-Learning
3)Java示例中用到了Redis数据库、fastjson等工具,开发者需要在pom.xml中提供相关依赖:
4)Java示例中的端口、数据库设置通过application.properties文件设置,开发者可根据实际情况自行设置:
5) 使用python示例需要安装python3和python3-flask模块,重启脚本,计数会清零。
2.5.2 常见问题
Q1:使用Python示例后,在线测试时,输入调用名,回复出错,查看json时,"nlg" 为 "xxx服务有故障,暂时不能为你提供服务" (XXX为技能名称)
A1:请检查下代码中定制的调用名是否和网站上配置的一致。如果改动了调用名,代码中也同样需要改变。
Q2: 使用Java示例后,在线测试时,回复提示SSM错误
A2: 如果开发者使用的是windows系统,当出现SSM错误时,可以查看是否是因为防火防设置导致无法ping通。
Q3: 使用Java示例后,在线测试时,用调用名唤醒技能成功,但是后续回复为“error”。
A3: 请检查eclipse的报错信息,如果报错信息为“Exception thrown :org.springframework.data.redis.RedisConnectionFailureException: Cannot get Jedis connection; nested exception is redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool”, 开发者需要检查是否已安装java redis。