客户端动作(command)编写

一、 command介绍

部分意图下,除了文字/语音的回复外,还需要客户端/本地执行对应的操作才能完成用户指令,此时就需要配置【客户端动作】以向客户端发出对应指令。

例如拨打电话的技能,用户说「给XXX打电话」,要输出指令给本地执行【拨打电话】这个操作。

【客户端动作】在DUI也称为command。

 

1.1 command作用

command,即DUI直接向设备端下发指定的操作指令,以满足用户在该意图下的操作设备诉求。

1.2 command适用场景

command和nativeapi的作用不同,故其适用场景也不同:

  • nativeapi,是向设备端获取内容源数据,是双向的,对话的中间一环。
  • command,是向设备端下发指定的操作指令,是单向的,一般是对话的最后一环。如增大音量、打开爱奇艺。

注:由于nativeapi是双向传输的,会让对话延时增加约100ms,所以请避免将nativeapi当做command使用。

关于nativeapi的介绍和使用说明,参见nativeAPI编写说明

1.3 command命名规范

基于command的作用,建议命名规范如下(以dui.deviceController.setVolume为例):

  • command的名称由三部分组成,由"."相连。
  • 每个部分的命名,遵循“纯英文+小驼峰”规则。
  • 第一部分,用来标识该技能所属的公司或者组织,如dui|AIspeech。
  • 第二部分,用来标识本地模块名称,一般为名词,如phone|deviceController。
  • 第三部分,用来标识意图指令,一般为动词+名词,如dialNumber|setVolume。

如下图:

    

1.4 command参数规范

当客户端开发者明确了command所对应的意图指令后,就需要提取参数部分,用以辅助指令的执行。建议规范如下:

  • 参数名称,应为纯英文,且为明确含义的名词,如number|volume。
  • 参数名称,需要是确定的、有限个数的。
  • 参数值,应为纯英文|纯中文。可引用语义槽的值(#联系人#),可引用cinfo的值($context.xx.yy$),也可传入固定值。
  • 参数值,需要是有单一含义的、无歧义的。

如下图:

   

二、 典型场景的推荐做法

1.1 场景1:音量控制

场景分析: 该场景意图下,用户核心诉求是操作设备音量,次要诉求是听到反馈。

方案

  1. 使用command来实现指令
  2. command命名:dui.deviceController.setVolume
  3. command参数:

参数名称

必须

类型

说明

type Y string 设置音量的类型。取值范围:relativeIncrease、relativeDecrease、absoluteValue、absoluteMax、absoluteMin
volume N int 音量值。取值范围:0-100。

客户端开发实现

  1. 收到command消息:dui.deviceController.setVolume
  2. 解析command参数:type
    1. 若type == relativeIncrease,表示增大相对音量(到某个值)。
    2. 若type == relativeDecrease,表示减小相对音量(到某个值)。
    3. 若type == absoluteValue,表示调整绝对音量(到某个值)。
    4. 若type == absoluteMax,表示调整音量到最大。
    5. 若type == absoluteMin,表示调整音量到最小。
  3. 解析command参数:volume,获取具体数值。
  4. 调用操作系统的设置音量的接口,完成command指令

类似场景: 播放控制、APP控制、导航、模拟点击

1.2 场景2:这是哪首歌

场景分析: 该场景意图下,用户核心诉求是能够知道(看到|听到)设备端正在播放的音乐信息

方案

  1. 使用nativeapi来实现
  2. nativeapi命名:dui.music.querySongInfo
  3. nativeapi参数:无
  4. nativeapi返回数据:contentWidget
  5. nlg播报:这首歌的歌名是$title$,演唱者是$extra.singer$。

属性

取值

type content
name default
title 忘情水
subTitle 演唱:刘德华;作词:李安修。
imageUrl https://www.qqmusic.com/pic/fdahfahsjdasd
label 流行,刘德华,90年代
linkUrl
buttons
recommendations
extra {"song":"忘情水","singer":"刘德华"}

客户端开发实现

  1. 收到nativeapi消息:sys.music.querySongInfo
  2. (跳过)解析nativeapi参数
  3. 调用QQ音乐的查询当前播放的接口,获取到歌曲信息
  4. 将该信息格式化为contentWidget,返回给DUI,完成nativeapi响应
  5. 收到contentWidget控件消息,展示UI

类似场景:查备忘提醒、查微信好友列表、查支付宝账单余额

三、 典型场景中长尾case的推荐做法

目标:技能开发者若期望增加对长尾case的处理,需力图保证:

  • 不影响正常case时的流程
  • 不增加正常case时的耗时
  • 有长尾case需求的客户端开发者才需处理,无此需求的无需关注和处理。

1.1 场景1:音量控制

长尾case:期望有一些异常情况下的nlg播报,反馈给用户。如音量已调到最大。

方案一(推荐)

  • 技能开发者不输出nlg播报。
  • 客户端开发者在原有逻辑的基础上,增加步骤5:判断异常情况,并调用TTS播放异常文案。

方案二

  • 技能开发者在设计中通过$context.skill.curVol$增加对话条件判断。异常情况下,仅输出异常nlg。正常情况下,输出command和正常nlg。
  • 客户端开发者在原有逻辑的基础上,增加步骤0:监听系统音量变化,当音量发生变化时,将音量值curVol通过skill.settings接口上传给DUI。

1.2 场景2:这是哪首歌

长尾case:期望要区分一些异常情况下的nlg播报,反馈给用户。如当前未安装QQ音乐、QQ音乐没在播放。

方案

    • 技能开发者对nativeapi返回的contentWidget数据,通过$extra.error$增加对话条件判断。不同异常情况下,输出不同的异常nlg。
    • 客户端开发者在原有逻辑的基础上,增加步骤3.1:检查QQ音乐APP状态,若APP不存在则返回{"error":1};若APP未运行,则返回{"error":2}。

属性

取值

type content
name noQQMusic、noPlay
title 当前未安装QQ音乐、当前未在播放
subTitle
imageUrl
label
linkUrl
buttons
recommendations
extra {"error":1}、{"error":2}