Skip to content

6.1 指令与控制

IOT 场景的关键是「指令」:用户说话 → 云端识别意图 → 下发 CALL_SKILL_EVENT → 设备端"照做"。 设备端收到指令事件无需再语义判断,直接调用对应功能模块(如红外开关/系统闹钟等)即可。 本章节重点说明:怎么建模指令、怎么配置、怎么测准确率。

下行指令事件 CALL_SKILL_EVENT 示例(点击展开)
json
{
    "code": 200,
    "msg": "Event success",
    "requestId": "1",
    "mid": "1",
    "contentType": "EVENT",
    "content": {
        "roundId": "0_1",
        "eventType": "CALL_SKILL_EVENT",
        "eventData": {
            "msg": "意图事件",
            "type": "CALL_SKILL_EVENT",
            "data": {
                "instructions": [
                    {
                        "action": "VOLUMN_SET",
                        "args": {"slotKey1": "slotValue"},
                        "desc": "音量调到XX"
                    }
                ],
                "intentClassify": "音量调到XX",
                "intentCode": "VOLUMN_SET"
            }
        }
    }
}

协议中 dataintentCode 属性值与 instructionsaction 属性值等同,为首条指令的 intentCode 编码。多条动作指令同理,intentCode 取首条。

6.1.1 自定义指令协议

输出控制协议(单指令)

json
{
    "code": 200,
    "msg": "Event success",
    "requestId": "1",
    "mid": "1",
    "contentType": "EVENT",
    "content": {
        "roundId": "0_1",
        "eventType": "CALL_SKILL_EVENT",
        "eventData": {
            "msg": "意图事件",
            "type": "CALL_SKILL_EVENT",
            "data": {
                "instructions": [
                    {
                        "action": "VOLUMN_SET",
                        "args": {
                            "slotKey1": "slotValue",
                            "slotKey2": "slotValue"
                        },
                        "desc": "音量调到XX"
                    }
                ],
                "intentClassify": "音量调到XX",
                "intentCode": "VOLUMN_SET"
            }
        }
    }
}

协议中 dataintentCode 属性值与 instructionsaction 属性值等同,为首条指令 intentCode 编码。

动作指令协议(多指令串行)

json
{
    "code": 200,
    "msg": "Event success",
    "requestId": "1",
    "mid": "1",
    "contentType": "EVENT",
    "content": {
        "roundId": "0_1",
        "eventType": "CALL_SKILL_EVENT",
        "eventData": {
            "msg": "意图事件",
            "type": "CALL_SKILL_EVENT",
            "data": {
                "instructions": [
                    {
                        "action": "ACTION_TURN_LEFT",
                        "desc": "向左转"
                    },
                    {
                        "action": "ACTION_TURN_RIGHT",
                        "desc": "向右转"
                    }
                ],
                "intentClassify": "向左转",
                "intentCode": "ACTION_TURN_LEFT"
            }
        }
    }
}

6.1.2 配置前准备:先理清三个问题

在动手配置之前,先和厂商/产品对齐以下三件事,后续每一步都建立在这三个决策之上:

问题你需要确定的内容举例
① 能力长在哪儿?设备的型号、品类、部件智能台灯 097(品类=台灯,部件=上灯/下灯)
② 能做什么?设备有哪些可控对象,每个对象支持哪些动作亮度(设置/查询/调高/调低)、开关(打开/关闭)
③ 传什么值?每个可控对象的取值形态:开关型 / 枚举型 / 数值型亮度→数值型(1~100%);模式→枚举型(白光/暖光/自然光)

这三件事互相独立——改一个不影响另外两个。把它们想清楚,配置就只是"填表"。

数据类型怎么选:问自己一句话

「能不能用一句话描述目标值?」

能不能用一句话描述目标值?
├─ 不能,只有「开 / 关 / 暂停」二元(或三元)状态 → SWITCH 开关型
│  例:制氧机开关、提示音开关

├─ 能,目标值是"数字 + 单位",有 min/max 范围 → NUMERIC 数值型
│  例:流量档位 1~5、温度 16~30℃、定时 5~120 分钟

└─ 能,目标值是"有限的标签集合",无数学大小关系 → ENUM 枚举型
   例:洗涤模式(智能洗/快洗/羊毛洗)、风量档位(强/中/弱)

ENUM vs 数值 易错点:

用户说话方式value 装什么应该选原因
"调到 3 档"标签 3(绝对目标)ENUM 或 数值取值在有限集 {1,2,3,4,5},两者都能承载
"调到最大/最小"归一后的标签 5/1ENUM 或 数值仍落在有限集
"调高 1 档/再大 2 档"1/2/…任意增量必须用 数值value 是开放正整数集,ENUM 无法列全

一句话判断法:有没有"调高/调低 相对调节任意值"?有 → 数值;没有 → 都可以。

三种类型敲定后,平台自动派生配置:

  • SWITCH → 配 on/off或者0/1 协议值,可选「打开/关闭」行为
  • ENUM → 必须列枚举清单,可选「设置/查询」行为
  • NUMERIC → 必须填 min/max/单位/步长,可选「设置/查询/调高/调低」行为

6.1.3 配置流程总览

Step 5 批量测试是上线前必做的质量关卡,详见 6.1.6 批量测试

6.1.4 分步操作指南

Step 1:在型号库登记型号

菜单路径:「资源管理 > 型号库 > 新建型号」

这一步把设备的物理属性沉淀下来,后续所有指令都挂在型号之下。

字段说明示例
产品型号名称自定义智能台灯 097
产品品类一类产品的统称,不确定时选「通用」台灯
产品部件型号内部可独立控制的子结构;无需求可不填上灯 / 下灯
IoT 平台指令需经 IOT 平台转发则选对应平台;直达设备可不选小家 / 集贤
指令描述描述产品型号的主要能力和属性支持亮度调节、色温切换

创建型号

实操要点:先把"型号 / 品类 / 部件"在型号库中沉淀清楚,再去建指令集。一旦部件清单变化,下游所有指令的"作用部件"配置都可能受影响。

Step 2:创建指令集并绑定型号

菜单路径:「资源管理 > 指令库」,点击【新建】

指令集就是"这台型号能听懂的命令清单"。

字段说明
指令集名称自定义(如"台灯标准指令集")
产品型号选择唯一产品型号(一个指令集只能绑定一个型号;多型号复用用"复制指令集")
指令集描述30 字以内
是否需要执行反馈开启→执行完有语音/文字回复;关闭→静默执行(详见 6.1.5 垫句机制

创建指令集

Step 3:新建指令(核心步骤)

在指令集详情页点击【新建指令】,首先选择指令类型:

类型适用场景操作行为
控制项指令标准功能点(开关/亮度/音量/温度/模式/风速/档位)设置/查询/调高/调低/自定义(一条指令可多行为)
非控制项指令非标准功能(机器人动作/机械臂操作等私有协议)仅支持「设置」一种 + 槽位提取参数

创建指令

3a. 控制项指令配置

适用于设备的标准功能点——能被抽象为"开关切换 / 档位选择 / 数值调节"的通用场景。平台将自然语言解析为统一格式下发到设备。

字段说明
控制项名称 / 别名 / 编码编码全英文可含 -/_同型号下不可重复
指令下发方式端侧(不经云端直达设备) / IOT 平台(经 IOT 平台转发)
作用部件指定仅作用于某些部件;无部件或全作用可不选
数据类型SWITCH / ENUM / NUMERIC(详见 6.1.1 数据类型选择
操作行为设置/查询/调高/调低,一条指令可多个
参数配置开关型:状态映射;枚举型:枚举清单;数值型:min/max/step/unit/default

操作行为需与设备物模型/IOT 接口定义的动词完全一致。例如设备物模型为"开始测量",则填写"开始"。名称不一致将导致设备无法识别指令

⚠ 数据类型为开关时,系统「设置」即等于「打开」「关闭」,无需重复设置自定义操作行为。

💡 当预设的 4 种操作行为无法满足业务需求时(如"开始""暂停""切换""重置"),可点击「+ 添加自定义操作行为」动态添加。

操作行为与业务意图的映射关系:

业务意图描述对应操作行为是否需要 value 入参
XX - 固定数值(设置为/调到/设置成…)设置需要 value
调高XX - 无数值调高不带 value
调低XX - 无数值调低不带 value
调高XX - 相对数值(调高 N)调高带 delta
调低XX - 相对数值(调低 N)调低带 delta
XX 最大 / XX 最小设置(value=上限/下限)复用设置

3b. 非控制项指令配置

适用于非标准功能(机器人动作、机械臂操作等私有协议指令)。用户可自定义指令名称、识别规则和参数槽位。

字段说明
指令名称 / 编码编码全英文
识别提示词定义指令含义+触发规则("什么时候触发" + "什么时候不触发")
槽位用户输入中需提取的关键参数(如"前进 30 厘米"的 30)
槽值类型数值 / 文本 / 枚举
槽值提取提示词引导系统提取槽值的关键词或规则

示例:机器人前进指令

  • 识别提示词:"当用户希望机器人向前移动一定距离时触发,常见表述如'往前走'、'前进 N 米'"
  • 槽位 distance = 数值,提示词:"提取移动距离,单位换算为厘米"

Step 4:应用配置

菜单路径:「应用管理 > 创建/编辑应用」

  1. 创建应用,绑定产品型号——该型号下的所有指令集会自动带入应用
  2. ⚠️ 必须在技能列表中勾选「AIot 设备控制」,才能启用设备控制链路

技能中勾选AIoT指令控制

系统指令集与自定义指令集冲突:若两者控制项相同,优先使用系统指令,自定义指令集中与之不同的指令无法生效。解决方案:将系统指令集中的指令在自定义指令集中创建,并取消选择系统指令集。

系统内置指令

平台提供系统内置指令(音量控制、电量查询、退出对话等),在应用编辑页点击【添加指令】即可选择。

系统内置指令

Step 5:批量测试验证准确率 ⭐

这是上线前最关键的一步,详见 6.1.6 批量测试

配置完指令后,用批量测试回答:例句够不够?换种说法还能识别吗?整体准确率多少?哪几条拖后腿?

千万不要跳过这一步直接发布——没有量化验证的指令集,上线后必然出现"用户说了但没反应"或"识别成另一条指令"的问题。

6.1.5 任务规划器(并行 vs 串行下发)

任务规划器是 AIot 设备控制链路上的"前置思考层"。指令真正下发前,规划器先调用 LLM 对用户输入做一次额外理解与拆分,判断:

  • 意图是否完整、是否需要反问澄清
  • 是否包含多个并行子指令、是否需要按 SOP 顺序补全参数
  • 是否需要根据上下文做多轮对话改写

核心差异

配置指令下发形式是否调用规划模型适用特征
开启任务规划器并行下发:多指令拆分为多个独立协议,分别下发需澄清/SOP/主动推荐/多设备多意图并行
关闭任务规划器串行下发:多指令打包为一个协议,按顺序在 instructions[] 数组中下发否(走精准指令链路)一句话能说清楚、明确不需澄清的简单/连续动作

何时开启

  • 需要主动推荐 / SOP 约束的场景
  • 用户表达不完整、需要反问澄清
  • 需要根据上下文做多轮意图延续与改写
  • 多设备 / 多意图并行执行,希望规划器自动拆分

何时关闭

  • 简单指令场景(如"音量调高一点"、"灯光调亮一点"),避免不必要的模型调用,降低延迟与成本
  • 简单多指令 + 端侧事件下发(如"先左翻再右翻,然后打个招呼"),端侧期望收到一个 instructions[] 数组按序执行,关闭规划器一次性串行下发
  • 对响应速度敏感、且不需 LLM 额外推理

6.1.6 垫句机制(避免等待感)

AIot 流程多次调用模型,IOT 指令下发链路较长。垫句的作用:指令真正执行前,先给用户一个即时的语音/文字回复,让用户感受到"已经收到、正在处理",避免长时间静默等待。

触发条件:只有当规划器识别到"可执行的 IOT 任务"时,平台才从垫句列表中随机选一条输出。

与任务规划器的联动

任务规划器垫句列表实际表现
开启不为空AIot 指令先回垫句;多指令并行下发,每条一个协议
开启为空不垫句,但多指令仍并行下发
关闭(列表隐藏,不可编辑)不垫句,多指令打包为单协议串行下发

何时配置垫句

  • 需给用户即时反馈,避免等待感(指令链路长、需走 IOT 平台转发的设备)
  • 希望通过差异化垫句话术强化人设、提升交互温度

何时清空垫句

  • 需要完全静默执行:不希望服务端下发任何 TTS(既不希望有执行后回复,也不希望有执行前垫句)
  • 此时需配合"指令集 → 是否需要执行反馈 = 关闭"一起使用
静默执行的两层关闭配置位置
关闭执行后回复指令集 → 是否需要执行反馈 = 关闭
关闭执行前垫句AIot 技能 → 垫句列表 = 清空

6.1.7 批量测试(量化识别准确率) ⭐⭐⭐

⚠ 这是上线前最关键的一步,切勿跳过!

配置完指令集不测就发布 = 闭着眼睛上线。批量测试是唯一能告诉你"整体准确率多少、哪几条拖后腿"的量化工具。

为什么必须做批量测试

配置完指令集后,你可能会有这些疑问:

  • 我配的例句够不够?真实用户换种说法还能不能识别?
  • 这个指令集整体识别准确率到底是多少?
  • 改了一版例句之后,到底是变好了还是变差了?
  • 哪几条指令是"拖后腿"的?我应该重点优化哪几条?

批量测试回答这些问题。平台基于已配置的 target + action 自动泛化出大量"用户可能这么说的同义表达",逐条丢给指令集识别,最后告诉你:

  • 整体准确率——这个指令集"听懂用户话"的能力有多强
  • 每一句泛化口令的预期输出 vs 实际输出——具体是哪句话被识别错了、错成了什么

操作流程

Step 1:进入批量测试入口

进入【资源管理 > 指令库】,点击目标指令集进入详情页,右上角点击【批量测试】。

Step 2:新建测试任务

点击【新建测试任务】,填写两项:

配置项说明
任务名称带版本号(如"台灯指令集-v1 首测"),方便日后对比
泛化倍数小倍数跑得快覆盖窄(首次建议 5 倍);大倍数跑得慢覆盖广(发布前全量回归)

提交后任务进入"进行中"状态,可以关闭页面去做别的事,跑完再回来查看。

Step 3:查看任务详情(两层信息)

第一层:整体卡片(一眼看清全貌)

指标说明
指令-操作行为数这次测了多少个"指令 × 操作行为"组合
泛化口令数量平台一共泛化出了多少条用户口令
符合预期 / 不符合预期数识别正确 / 识别错误的口令数
整体准确率符合预期 / 总数

第二层:明细列表(定位到底是哪句话错了)

  • 在"是否符合预期"列筛选"不符合预期",一次性看到所有识别错的口令
  • 点击【Excel 下载】可拿完整结果离线分析或同步给团队

Step 4:根据结果反向优化指令

测试不是终点,根据结果反向优化指令配置才是目的

你看到的现象大概率原因怎么改
某条指令的单指令准确率明显偏低例句太少、表达方式太单一;或例句和实际用户说法差距大进入该指令,给"操作行为"补充更多口语化、不同句式的例句
某些口令识别成了"另一条指令"两条指令的语义边界模糊、例句重叠检查两条指令的例句是否互相"撞车"
操作行为识别错(如"调高"被识别成"设置")不同操作行为之间的例句区分度不够在每个操作行为的例句里强化方向性词语("调高/再大/增加"对应调高,"设置为/调到 N"对应设置)
槽位提取错误(非控制项指令)槽值提取提示词不清晰、例句没覆盖典型槽值优化"槽值提取提示词",并在例句中包含典型槽值(如"前进 30 厘米"、"前进 1 米")
整体准确率 OK,少数边缘表达失败长尾用户表达,本来就难全部覆盖评估真实使用频次,决定是否值得专门加例句

优化标准动作(闭环)

跑一次批量测试,记录基线整体准确率

筛选"不符合预期",挑出 3~5 条典型失败案例

定位到对应指令,按上表思路修改例句/提示词/槽位

重新跑一次批量测试,对比准确率是否提升

准确率达标后发布上线

💡 任务名称带版本号(v1、v2…),形成"修改 → 回归 → 修改"闭环,避免改一版又改坏另一版。

6.1.8 配置示例

示例 A:控制项指令——智能台灯·亮度

配置项
型号智能台灯 097(品类=台灯,部件=上灯/下灯,IOT 平台=已选)
指令集台灯标准指令集(绑定 智能台灯 097)
控制项亮度 / 别名:明暗、亮度值 / 编码:brightness
下发方式IOT 平台
作用部件上灯
数据类型数值
操作行为设置 / 查询 / 调高 / 调低(全勾)/自定义
参数配置min=1, max=100, step=10, unit=%, default=50
例句-设置把上灯亮度调到 40、把上灯调到最亮
例句-调高把上灯亮度调高一点、上灯太暗了
例句-调低把上灯亮度调低一点、上灯太亮了
测试例句"把上灯调亮一点"、"亮度调到 80"、"亮度调到最暗"

示例 B:非控制项指令——机器人前进

配置项
型号陪伴机器人 R1(品类=机器人,无部件,IOT 平台留空)
指令集机器人动作指令集(绑定 陪伴机器人 R1)
指令名称机器人前进 / 编码:robot_move_forward
识别提示词"当用户希望机器人向前移动一定距离时触发,常见表述如'往前走'、'前进 N 米'"
操作行为设置(默认)
例句"往前走 30 厘米"、"前进一点"、"机器人前进 1 米"
槽位字段名=distance,槽值类型=数值,槽值提取提示词="提取移动距离的数值,单位统一换算为厘米"

下一步