请求数据指的是平台发送 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. }