请求数据指的是平台发送 http(s) post 请求时 body 中的数据,数据格式为 application/json 。

1. 请求数据对象结构

字段名 type 描述 是否必要
sessionId String 会话ID,session内的对话此ID相同
utterance String 进入意图时用户所说的语句
requestData Map 请求附带参数,使用天猫精灵音箱调用技能时额外携带的信息,
在线测试无此数据
token String 技能配置 OAuth2.0 授权并且用户登录授权账号后可以得到此 token,详细请查看【OAuth2.0配置文档】,
在线测试无此数据
botId Long 应用ID,标识用户所使用的的天猫精灵设备的种类
domainId Long 领域ID
skillId Long 技能ID
skillName String 技能名称
intentId Long 意图ID
intentName String 意图标识
slotEntities List 从用户语句中抽取出的 slot 参数信息
selectIndexList List 上一轮状态标识 resultType: SELECT 时,
用户所做选择的索引值。
confirmStatus String 上一轮状态标识 resultType: CONFIRM 时,
用户所进行的确定(CONFIRMED)或否定(DENIED)回答。
device Device 用户的设备信息。在线测试没有设备,不会携带设备数据
requestId String 本次请求的ID
skillSession SkillSession 技能粒度的session信息

RequestData 中包含的主要信息字段:

字段名 type 描述
userOpenId String 天猫精灵用户id和技能id混合加密,只能在当前技能中唯一标识用户
deviceOpenId String 天猫精灵设备id和技能id混合加密,只能在当前技能中唯一标识设备
city String 天猫精灵设备所处的城市
screenStatus String 用户使用带屏设备的标识: “screenStatus”: “online”
若用户使用的是无屏设备,则没有此条数据。
需要到 权限包管理 中申请“设备有无屏特性”权限包
deviceUnionIds String 如果技能挂载到组织下,设备在各个组织中的加密id。默认没有此数据,需要额外开通服务卡片账号打通功能
userUnionIds String 如果技能挂载到组织下,用户在各个组织中的加密id。默认没有此数据,需要额外开通服务卡片账号打通功能

SlotEntities 中每一个数组对象SlotEntity的具体字段:

字段名 type 描述 是否必要
intentParameterId Long 意图参数ID
intentParameterName String 意图参数名
originalValue String 原始句子中抽取出来的未做处理的 slot 值
standardValue String slot 归一化后的值
liveTime Integer 该 slot 已存在的会话轮数
createTimeStamp Long 该 slot 产生时的时间戳

SkillSession 中包含的主要信息字段:

字段名 type 描述
skillSessionId String 技能粒度session的id
newSession Boolean 用户首次进入技能时:true
用户后续在技能中对话:false
如果技能交互中用户有跳出技能,再次进入技能时:true

2. Webhook 服务请求结构样例

  1. POST http://your-webhook-service.com/skill/weather
  2. Headers:
  3. //默认已填充,规定请求体中的数据格式
  4. Content-type: application/json
  5. //开发者自定义的headers
  6. //key1: value1
  7. //key2: value2
  8. POST body:
  9. {
  10. "sessionId": "b112a091-1523-4d2d-8059-e09461dafd73",
  11. "utterance": "魔都今天天气",
  12. "token": "ozkYw9Y8*******lffDM", //技能配置OAuth2授权,并且用户登陆授权账号后会携带
  13. "requestData": {
  14. "userOpenId": "XXXXXXXX==",
  15. "deviceOpenId": "YYYYYYYYY==",
  16. "city": "上海"
  17. },
  18. "botId": 10,
  19. "domainId": 12345,
  20. "skillId": 23456,
  21. "skillName": "天气小助手",
  22. "intentId": 34567,
  23. "intentName": "weather",
  24. "slotEntities": [
  25. {
  26. "intentParameterId": 45678,
  27. "intentParameterName": "city",
  28. "originalValue": "魔都",
  29. "standardValue": "上海",
  30. "liveTime": 0,
  31. "createTimeStamp": 1564110905331,
  32. "slotName": "city:city",
  33. "slotValue": "魔都"
  34. },
  35. {
  36. "intentParameterId": 56789,
  37. "intentParameterName": "time(公共实体)",
  38. "originalValue": "今天",
  39. "standardValue": "今天",
  40. "liveTime": 0,
  41. "createTimeStamp": 1564110905331,
  42. "slotName": "time(公共实体):sys.time",
  43. "slotValue": "今天"
  44. }
  45. ],
  46. "requestId": "20190726111511958-508551760",
  47. "device": { },
  48. "skillSession": {
  49. "skillSessionId":"8d7501fe-a80a-46cf-a43f-ff8743a7ec66",
  50. "newSession":true
  51. }
  52. }

3.java方式的处理范例

  1. @RequestMapping(value = "/skill/weather", method = RequestMethod.POST)
  2. public @ResponseBody ResultModel<TaskResult> getResponse(@RequestBody String taskQuery) {
  3. /**
  4. * 将开发者平台识别到的语义理解的结果(json字符串格式)转换成TaskQuery
  5. */
  6. logger.info("TaskQuery:{}", taskQuery.toString());
  7. TaskQuery query = MetaFormat.parseToQuery(taskQuery);
  8. /**
  9. * 构建服务返回结果
  10. */
  11. ResultModel<TaskResult> resultModel = new ResultModel<TaskResult>();
  12. try {
  13. TaskResult result = weatherHandle.execute(query);
  14. resultModel.setReturnCode("0");
  15. resultModel.setReturnValue(result);
  16. } catch (Exception e) {
  17. }
  18. /**
  19. * 直接返回ResultModel<TaskResult>对象就ok
  20. */
  21. return resultModel;
  22. }
  23. // 天气服务执行,根据NLU理解的结果做相应处理并返回回复语句
  24. @Component
  25. public class WeatherHandleImpl implements WeatherHandle {
  26. @Override
  27. public TaskResult execute(TaskQuery taskQuery) {
  28. logger.info("WeatherHandleImpl execute...");
  29. //从请求中获取意图参数以及参数值
  30. Map<String, String> paramMap = taskQuery
  31. .getSlotEntities()
  32. .stream()
  33. .collect(
  34. Collectors.toMap(slotItem -> slotItem.getIntentParameterName(),
  35. slotItem -> slotItem.getOriginalValue()));
  36. logger.info("paramMap :" + paramMap.toString());
  37. //如果意图是询问空气质量,则执行空气质量逻辑
  38. if ("air_quality".equals(taskQuery.getIntentName())) {
  39. return aqiQuery(taskQuery, paramMap);
  40. //如果意图是询问天气情况,则执行天气查询逻辑
  41. } else if ("weather".equals(taskQuery.getIntentName())) {
  42. return baseQuery(taskQuery, paramMap);
  43. } else {
  44. return reply("请检查意图名称是否正确,或者新增的意图没有在代码里添加对应的处理分支。");
  45. }
  46. }
  47. //空气质量查询方法
  48. private TaskResult aqiQuery(TaskQuery taskQuery, Map<String, String> paramMap) {
  49. TaskResult result = new TaskResult();
  50. //TODO 根据参数获取空气质量信息
  51. reply = paramMap.get("city") + paramMap.get("date") + "空气质量 优";
  52. return reply(reply);
  53. }
  54. //天气查询方法
  55. private TaskResult baseQuery(TaskQuery taskQuery, Map<String, String> paramMap) {
  56. TaskResult result = new TaskResult();
  57. //TODO 根据参数获取空气质量信息
  58. reply = paramMap.get("city") + paramMap.get("date") + "天气 晴";
  59. return reply(reply);
  60. }
  61. private TaskResult reply(String reply) {
  62. TaskResult taskResult = new TaskResult();
  63. taskResult.setReply(reply);
  64. taskResult.setExecuteCode(ExecuteCode.SUCCESS);
  65. taskResult.setResultType(ResultType.RESULT);
  66. return taskResult;
  67. }
  68. }