密级公开
版本10D.2

AICP NLU HTTP 开发手册

1. 概述#

1.1 功能介绍#

NLU(自然语言理解)能力服务用于完成和机器人的对话流程。

目前提供 HTTP 形式的接口,对于每个HTTP请求,云端完成相应操作后一次性返回结果,但多次 HTTP 访问可以通过“会话标识”来联系在一起,以保留对话的上下文信息,完成多轮对话的功能。

AICP-10 平台中的 NLU 智能对话服务 (也称 NLU 问答服务或 NLU 能力服务) 和 NLU 资源管理服务 都支持本文档描述的对话接口, “NLU 能力服务”是为了支持实际上线的机器人的对话流程,而“NLU 资源管理服务”是为了支持对维护的机器人资源进行测试。

1.2 模型特征串#

AICP-10 提供的 NLU 能力接口中,模型特征串形式为:{lang}_{domain}{lang}表示语言编码,{domain}表示领域编码。

模型特征串的概念和语言编码,请参见 《AICP 10 开发通用规范》

目前只能使用如下模型特征串:

模型特征串说明
cn_common中文通用领域

1.3 访问认证#

访问接口所需的认证机制,请参见 《AICP 10 开发通用规范》

2. 功能描述#

客户端通过 HTTP 的 POST 请求向服务端发送启动会话命令,然后多次发送用户输入,获取机器人的应答响应。最后结束对话。

客户端客户端服务端服务端开启会话start_session (机器人ID)会话标识,可能有开场白应答对话交互dialog (会话标识+用户输入)机器人应答dialog (会话标识+用户输入)机器人应答dialog (会话标识+用户输入)机器人应答结束会话end_session (会话标识)结束

3. 接口概览#

NLU 能力服务提供如下接口:

  • 开始会话

    POST http://ip:port/v10/nlu/recog/{property}/start_session?appkey={appkey}

  • 对话

    POST http://ip:port/v10/nlu/recog/{property}/dialog?appkey={appkey}

  • 结束会话

    POST http://ip:port/v10/nlu/recog/{property}/end_session?appkey={appkey}

注意

当使用此接口访问“NLU 资源管理服务”进行机器人测试时,需要将 /nlu/recog 更换为 /nlu/resource,其余部分保持一致。

3.1 URL 参数#

URL 中携带的参数如下:

参数类型必选说明
propertyString模型特征串,服务器端利用此值来调用不同的模型
appkeyString分配给开发者的 appkey

3.2 HTTP 头域参数#

请求的 HTTP Header 参数如下:

参数类型必选说明
Content-TypeStringapplication/json
X-Hci-Access-TokenStringget-access-token 接口获取的令牌
X-Tenant-IdString租户ID

X-Hci-Access-Token 是开发者使用分配给开发者的 appkeysecret 访问系统服务接口 get-access-token 获取到的令牌,详细见《系统服务 HTTP 开发手册》。

X-Tenant-Id 是租户ID,通过管理后台创建租户后获取。需要调用者自行保证一个会话的租户 ID 都是一致的。

在不启用多租户的系统或者单机版中,可以没有 X-Tenant-Id 头,或者将租户 ID 设为空串。

3.3 包体参数#

待处理的文本连同其它参数必须放在请求正文中,并以JSON格式编码。

3.4 响应格式#

在响应消息中,HTTP 状态码表示请求的总体执行情况,正文包含一个以JSON格式编码的字符串,用于携带进一步的信息。

  • 正常响应:HTTP 状态码为 200,响应包体中不包含“error”字段,但通常会包含“result” 字段用于携带正常的结果数据。
  • 失败响应:HTTP 状态码为 200 之外的值,响应包体中包含“error”字段,包含详细错误码和错误信息。

响应的格式统一为:

参数类型说明
traceTokenString服务内部的 token 字符串,可用于日志追溯。
在某些错误情况下可能没有此令牌字符串。
errorObject发生错误时可用,如果请求成功将没有此字段
resultObject调用成功表示识别结果,调用失败时将没有此字段

error 的结构如下:

参数类型说明
codeInteger错误代码,请参见 《AICP 10 开发通用规范》
messageString详细的错误信息

result 的结构针对不同调用接口是不一样的,会在下面的每个接口描述中详细说明。

以下是一个失败响应的示例:

{
"error": {
"code": 29,
"message": "robotId is not found"
}
}

正常响应的示例:

{
"traceToken": "xxxxx",
"result": {
...
}
}

在后文中,我们将略过对错误响应的描述,而仅给出正常响应的 result 的格式和示例。

4. 开始会话#

在开始和机器人交互前,用户需要使用此接口创建一个会话。

4.1 接口 URL#

POST http://ip:port/v10/nlu/recog/{property}/start_session?appkey={appkey}

4.2 请求消息#

参数类型必选范围&默认值说明
robotIdString-机器人 ID
publishIdString-机器人发布版本 ID
configObject of Confignull识别配置项
userVarsObjectnull外部传入的用户变量,json 格式对象,内容不限,目前只支持一级变量
extraInfoString客户端设置的信息串,服务器端制作记录,或将来作为定制版本的一些特殊信息
  • publishId

仅对发送给“NLU 资源管理服务”的请求有效。如果有此字段,将测试对应的机器人资源包,也即测试某个特定的机器人发布版本;否则将测试当前最新的机器人资源,也即对机器人进行即时测试。

“NLU 对话服务”将忽略此字段。

  • userVars

外部传入的用户变量,会自动放在上下文信息中的 user. 对象中。只支持一级变量。

Config 定义:

参数类型必选范围&默认值说明
needContextBooleanfalse在响应消息中是否包括上下文信息(context)
needSlotsBooleanfalse在响应消息中是否包括词槽信息(slots)
tagFilterArray of String使用此标签数组筛选答案
  • needSlots

由于在start_session 接口中,并没有用户输入,因此响应消息中肯定不会有词槽信息,因此 needSlots 会被忽略。

  • tagFilter

tagFilter是一个字符串数组,每一项都定义了一个标签筛选条件,用于在一个答复的多个答案中选择匹配的答案输出。

目前需要答案中打上的标签能够匹配所有这些筛选条件才会被当做候选,如果打上的标签比筛选条件多也会被当做候选。

tagFilter 的每一项都是 "tagGroup:tag" 的形式,例如:

{
"tagFilter" : [
"channel:wechat", "color:blue", "color:red"
]
}

4.3 响应消息#

正常响应中的 result 结构如下:

参数类型说明
sessionIdString创建的会话 ID
robotIdString所使用的机器人,和输入参数一致
publishIdString所使用的机器人发布版本,和输入参数一致
responsesArray of Response如果此机器人有“欢迎语”或“开场白”配置,则会输出此项
否则为空数组
contextObject of Context上下文信息,在输入配置中 needContext 项为 true时才有此项
  • sessionId

sessionId 标识所创建的会话,用户使用此 Id 和机器人进行对话,同一个 Id 上的对话会保留上下文信息,以支持多轮的对话操作。

会话的过期时间缺省为20分钟。如果20分钟中未使用此sessionId和机器人进行对话,则此 sessionId 会失效,再使用会返回错误。

  • responses

responses 是一个数组,每个元素是一个 Response 结构。

responses 的返回有如下情况:

  1. 如果没有开场白,为空数组
  2. 如果开场白定义为一个“答复”,那么就返回此答复
  3. 如果开场白定义为一个“场景技能”,那么就从此场景技能的“无条件入口”进入,并进行节点流转,会根据走过的“答复”节点来返回答复。此时有可能是0,1或多个答复。

如果一个答复经过标签筛选之后还是有多个答案,则会按照机器人的配置输出第一个答案或者任意输出一个答案,因此对一个答复来说,只会输出一个答案。

Response 定义了一条回复内容,其结构定义如下:

参数类型说明
idInteger回复的Id
answerIdInteger具体答案的Id
typeString回复类型
contentString回复的具体内容,按照回复类型不一样,有不同的含义
cmdString指示客户端完成的动作,自定义的格式,可以没有

回复类型定义:

类型说明回复的具体内容
TEXT纯文本请问你想订哪天的机票?
TTSTTS 文本,其中可能带有 SSML 标签或自定义标签请问你是〖曾志伟〗先生吗?
AUDIO音频(录音)音频URL
VIDEO视频视频URL
HTMLHTML 格式的内容<h1>标题</h1><link ref="xxxx"></link>
RECOMMEND推荐知识(菜单知识)JSON表示,Recommend 结构

Recommend 结构如下:

参数类型说明
startString答案的前置提示语
menuArray of MenuItem推荐知识列表
endString答案的后置提示语

MenuItem 结构如下:

参数类型说明
idInteger推荐知识的ID,也即标准问的ID
textString推荐知识的内容

注意:如果“推荐知识”类的回复是由于问答库命中问题的匹配度没有达到“直接回答”门限而构造出来的“推荐问题”列表,而不是直接维护的答复,Repsonse 中的 id, answerId 均为0,cmd 为空。

推荐知识类型的答案的示例如下:

{
"id": 0,
"answerId": 0,
"type": "RECOMMEND",
"content": {
"start": "前置提示语",
"end": "后置提示语",
"menu": [
{
"id": 1233,
"text": "推荐问题1"
},
{
"id": 1239,
"text": "推荐问题2"
}
]
},
"cmd": ""
}
  • context

context 是一个 Context 对象,表示上下文信息,通常只为了调试使用。

Context 对象的结构定义如下:

参数类型说明
skillObject此轮对话实际命中问题所处的技能。
如果当前并未命中任何问题,而是其他原因的回复(例如开场白)
则无此项
skill.idInteger技能Id
skill.typeString技能类型 (QABASE, KG, INTENT, SCENE, CHAT)
skill.nameString技能名称
enterSkillObject此轮对话进入时的技能,结构和 skill 一致。
如果进入时不处在某个技能,则无此项
如果是开场白指定的是技能,则是开场白技能
waitSkillObject此轮对话完成后等待时的技能,结构和 skill 一致。
如果当前意图或场景技能中已结束,那么无此项
如果命中是问答型技能又没有自动跳回任务型技能,那么也无此项
qaObject如果当前命中问题是“问答库技能”,有此项
qa.dirObject当前命中问题所在的问答库目录
qa.dir.idInteger问答库目录Id
qa.dir.nameString问答目录的名称
qa.pairIdInteger当前命中问题所在的问答对Id
kgObject如果是“知识图谱技能”,有此项
kg.nameString当前知识图谱的名称
intentObject如果当前命中问题是“意图对话技能”,有此项
intent.idString当前命中的意图
intent.nameString当前命中的意图
intent.stateString当前状态,参见下面的表
sceneObject如果是“对话流技能”,有此项
scene.nodeNamesArray本轮流经的节点
scene.nodeNames[#]String节点名称
varsObject所有的变量和值,json格式对象

intent.state 表示意图技能当前的状态,可取值如下:

取值含义
ELICIT_SLOT追问词槽
CONFIRM_SLOT确认词槽
CONFIRM_INTENT确认整体意图
FINSIH此意图已完成

start_session 接口中,context 只会有 enterSkill(如果开场白是技能)以及 vars 项,不会有其它项。

如果是经历了当前任务型技能跳转到问答型技能,那么会同时存在任务型技能、问答型技能相关的字段。

4.4 示例#

  • 请求示例
{
"robotId": "c22ff7f6-d91b-4aa1-9803-6c2d76e216eb",
"userVars": {
"var1": "blahblah",
"var2": 9,
"var3": ["abcd", "ssds", "ssds"],
},
"config" : {
"needContext": false,
"tagFilter": ["channel:wechat"]
}
}
  • 成功响应示例(无开场白)
{
"sessionId": "12345678",
}
  • 成功响应示例(有开场白)
{
"sessionId": "12345678",
"responses": [
{
"id": 2939,
"answerId": 23433,
"type": "TEXT",
"content": "你好,请问有什么可以帮您的?"
}
],
"vars"{
"global": {
},
"user": {
"var1": "blahblah",
"var2": 9,
...
}
}
}

5. 对话#

用户调用此接口与机器人进行对话。

5.1 接口 URL#

POST http://ip:port/v10/nlu/recog/{property}/dialog?appkey={appkey}

5.2 请求消息#

参数类型必选范围&默认值说明
sessionIdString 对话 ID,由 start_session 接口返回
userQueryString 用户输入
configObject of Config 对话配置
userVarsObjectnull外部传入的用户变量,json 格式对象,内容不限,只支持一级变量

configuserVars 含义都和 start_session 接口一致。

5.3 响应消息#

正常响应中的 result 结构如下:

参数类型说明
sessionIdString和输入的 sessionId 一致
robotIdString所使用的机器人
publishIdString所使用的机器人发布版本
responsesArray of Response此轮对话的回复内容,是一个数组,每一项是一个“回复”,
如果没有任何回复,返回空数组
slotsArray of Slot此轮对话的填槽结果,输入配置中 needSlots 项为 true时才有此项
contextObject of Context上下文信息,在输入配置中 needContext 项为 true时才有此项
  • responses

responses 是一个数组,每个元素是一个 Response 结构, 其定义同 start_session 接口。

一轮对话的回复可能有多个“回复”,因此定义为一个“回复”的数组。在下面这些情况下,都有可能输出多个“回复”:

  • 问答技能中,进行 “多意图” 判断,如果一个用户输入中有多个提问内容,则会输出各个提问的响应答复
  • 场景技能中,可能会经过多个“回复节点”,每个“回复节点”都会有相应的回复内容
  • 意图或场景技能中,如果跳转到问答技能后又自动恢复,那么除了要输出问答技能中的回复,还可能会追问意图或场景技能的上次问题

因此,在这些情况下,都会输出多个“回复”。而每个“回复”中,如果一个答复经过标签筛选之后还是有多个答案,则会按照机器人的配置输出第一个答案输出或者随机输出一个答案,因此对一个答复来说,只会输出一个答案。

  • slots

slots 是一个 Slot 对象,定义了本轮对话的填槽结果。注意,这里只是本轮对话的结果,如果需要之前的填槽结果,需要在 contextvars 中查找。

Slot 对象接口定义如下:

参数类型说明
namestring词槽名称
dictstring绑定的词典名称
valuestring实际词
normValuestring标准词,或者归一化后的标准结果
  • context

contextContext 对象,定义同 start_session 接口。

5.4 示例#

  • 请求示例
{
"sessionId" : "1293949",
"userQuery": "我想订一张从上海到呼市的机票",
"config" : {
"needContext": true
}
}
  • 成功响应示例
{
"result" {
"sessionId" : "1293949",
"robotId": "c22ff7f6-d91b-4aa1-9803-6c2d76e216eb",
"responses": [
{
"id": 2939,
"answerId": 22344,
"type": "TEXT",
"content": "请问您要订哪一天的?",
}
],
"slots": [
{
"name": "fromCity",
"dict": "SYS.city",
"value": "上海",
"normValue": "上海",
},
{
"name": "toCity",
"dict": "SYS.city",
"value": "呼市",
"normValue": "呼和浩特",
}
],
"context" : {
"skill": {
"id": 2333,
"type": "INTENT",
"name": "airline"
},
"waitSkill" : {
"id": 2333,
"type": "INTENT",
"name": "airline",
},
"intent": {
"id": 1233,
"name": "book_ticket",
"state": "ELICIT_SLOT",
},
"vars": {
"global": {
...
},
"slots": { // 所有词槽自动提取出来的变量
"fromCity": {
"value": "上海",
"normValue": "上海"
},
"toCity": {
"value": "呼市",
"normValue": "呼和浩特"
}
},
"user": {
...
},
"hitQuestion": {
"id": 2993,
"text": "订{fromCity@SYS.city}到{toCity@SYS.city}的机票",
"score": 0.929,
"ext": {
"id": 2295,
"text": "我想订一张{fromCity@SYS.city}到{toCity@SYS.city}的机票",
}
},
"tempVar": "abcd" // 本轮临时变量
}
}
}
}

6. 结束会话#

智能语义理解对话接口,用户可调用该接口结束一个会话。

6.1 接口 URL#

POST http://ip:port/v10/nlu/recog/end_session?appkey={appkey}

6.2 请求消息#

参数类型必选范围&默认值说明
sessionIdString对话 ID,由 start_session 接口返回

6.3 响应消息#

正常响应中的 result 结构如下:

参数类型说明
sessionIdString和输入的 sessionId 一致
robotIdString所使用的机器人
publishIdString所使用的机器人发布版本

6.4 示例#

  • 请求示例
{
"sessionId" : "1234567"
}
  • 成功响应示例
{
"result": {
"sessionId": "1234567",
"robotId": "c22ff7f6-d91b-4aa1-9803-6c2d76e216eb",
}
}

7. 其它说明#

关于 Contextskill, enterSkill, waitSkill 的说明如下。

当开始会话时:

当前条件流转enterSkillskillwaitSkill
无开场白---
开场白是回复---
开场白是技能A流转到“理解节点”A-A
流转到A技能完成A--
分派到其它技能B并流转到“理解节点”A-B
分派到其它技能B并流转到技能结束A--

会话中:

当前条件命中流转enterSkillskillwaitSkill
不处在某个技能中问答型技能 Q-Q-
任务型技能 A流转到“理解节点”-AA
流转到技能完成-A-
未命中任何问题---
处于任务型技能A 中仍命中当前技能A流转到“理解节点”AAA
流转到技能A完成AA-
仍命中当前技能A
但被分派到任务型技能B
流转到B的“理解节点”AAB
流转到技能B完成AA-
命中并跳转到问答型技能Q不自动恢复AQ-
自动恢复AQA
命中并跳转到任务型技能B流转到“理解节点”ABB
流转到技能B结束AB-
未命中任何问题重试A-A
超过重试次数退出A--
  • 会话结束时永远不会处于某个问答型技能中,因此 enterSkillwaitSkill 永远不会是一个问答型技能
  • 除首轮外,本轮对话的 enterSkill 一般就是上轮对话的 waitSkill

8. 版本记录#

接口版本平台支持版本组件及支持版本修改内容
10.0.010D.0aicp_nlu/aicp_nlu_res 10.0.0初始版本