Skip to content

提示词编写 ​

当指令配置表达不了设备能力时,用提示词补足:

  • 根据指令生成提示词:在指令生成的系统提示词基础上补充提示词,处理边界badcase等;
  • 自定义提示词:放弃结构化指令配置,整段自由编写(设备能力复杂,无法通过指令配置实现场景)。

提示词是 AIOT 指令识别与执行的「大脑」,决定了模型如何理解用户话语、如何拆解任务、如何产出下发参数。

1. 两种提示词模式 ​

在智能体的 AIOT 指令配置中,提示词支持两种生成模式:

模式说明适用
根据指令集生成提示词以当前产品的指令集为基础自动生成,用户可在此之上继续补充自定义内容。当指令集发生变更后,页面会提示同步更新提示词大多数标准场景
自定义提示词完全由用户自行编写提示词内容。选择该模式后,指令集配置将不再参与生成,以编写的提示词为准需要完全掌控提示词,或指令集无法承载的能力

💡 选择「根据指令集生成」模式时,必须先创建指令,再在系统据此生成的提示词上微调;该模式下如无任何指令则无法使用。

⚠️ 切换到「自定义提示词」后,结构化指令集不再参与提示词生成——请确保提示词已覆盖全部识别与出参逻辑。

1.1 交互流程 ​

  1. 开启 AIOT 指令开关:意味着当前产品支持指令控制功能,开启后才能进入提示词配置。
  2. 选择提示词生成模式:
    • 根据指令集生成:用户通过结构化指令说明当前设备支持哪些能力,系统据此自动生成提示词。生成的提示词直接可用,可立即调试。
    • 自定义提示词:完全不依赖指令数据,由用户自行编写设备控制提示词。
  3. 在「根据指令集生成」模式下,用户要做的第一件事是新建指令集 → 新建指令,定义设备能力(详见 结构化配置)。
  4. (可选)微调提示词:若调试中需要个性化调整,可在自动生成的提示词基础上修改,保存草稿后重新调试。

⚠️ 微调内容可能丢失:在「根据指令集生成」模式下微调后,切换提示词模式、更新指令配置、关闭AIoT指令开关等操作都可能触发提示词重新初始化,覆盖微调内容。详见 4. 提示词的初始化与保存。

2. 三层提示词含义 ​

用户说一句话后,系统会依次经过三层提示词处理,前一层的产出决定后一层能否执行,形成一条接力流水线。理解这条链路是排查问题的前提——定位时只需找最早出错的那一层:

1. 意图准入层(意图层)  →  「闸门」,负责「接不接」:是否放行进设备控制
        ↓
2. 任务规划层(规划层)  →  「调度员」,负责「怎么做」(可开关):找能力/查参数/拆任务/选路径
        ↓
3. 指令执行层(执行层)  →  「执行员」,负责「出参数」:接收任务/组装/下发/处理结果,产出 intent / args / deviceTimerBody
层角色只回答一个问题边界(不做什么)
意图层闸门这句话要不要控制候选设备?不解析具体指令、不出参数
规划层调度员怎么做:能做吗、参数够吗、拆几步、走执行还是先追问?不产出最终工具参数
执行层执行员出参数:如何把 plan 变成合规工具调用?不重新决策该不该做、要不要澄清

2.1 意图准入判断——「接不接」 ​

意图分类器:先判定用户这句话是否属于「设备控制」意图。

  • 属于 → 进入后续链路;
  • 不属于 → 不进入设备控制,交回普通对话。

这一层要写什么:一个中文二分类器提示词,基于【历史对话】【候选控制指令列表】【当前 query】输出 1(设备控制)或 0(非设备控制)。核心是把「判为 1」「判为 0」的情形和上下文判定规则讲清楚。

实例:设备控制意图二分类器
text
你是一个中文智能家居设备控制意图二分类器。
基于【历史对话】【候选控制指令列表】【当前 query】,判断用户最新一句话是否属于"设备控制意图"。

### 判为 1(设备控制)的情形
1. 用户明确要控制设备/改变状态/设置参数/切换模式/调节数值/执行场景,且该能力在候选指令列表内;
2. 多轮上下文中对上轮设备控制流程做补充/确认/补槽/指代(即使本轮很短),对应能力在候选列表内;
3. 省略主语或设备名,但明显在延续设备控制链路,最终操作能力在候选列表内;
4. 对候选列表内功能的同义/近义表达(列表含「按摩开/关」,用户说「给我按一下」→ 1);
5. 对候选列表内「查询/读取」类指令的状态问询(列表含「查询甲醛」→「甲醛浓度多少」→ 1)。

### 判为 0(非设备控制)的情形
1. 闲聊、寒暄、情绪表达、抱怨、评价、无意义字符;
2. 天气/新闻/百科/开放域问答(若候选列表含「查询」类指令且命中,按判为 1 第 5 条处理);
3. 音乐/有声书/故事点播与播放控制;
4. 明确否定上轮控制建议,且当前句不构成新指令;
5. 纯描述/纯陈述/纯感受,不构成可执行控制行为。

### 关键判定规则
1. 上下文优先:当前句是对上轮控制的补充/确认/补槽,即使很短也判 1
   (上轮「开到多少度?」当前「26度」→ 1)。
2. 陈述 vs 指令:「把卧室灯关了」→ 1;「卧室灯真亮」→ 0。
3. 指代消歧:「那个关掉」「调低一点」——有控制上下文 → 1,无 → 0。

可微调范围:

  • ✅ 可调:补充/删减「判为 1」「判为 0」的具体情形;增补业务专属的同义/近义表达词典;调整上下文判定的举例。
  • ⚠️ 谨慎:输出格式固定为 0 / 1 二分类,不要改成多分类或自由文本;不要在这一层输出 intent/参数(那是执行层的职责)。

2.2 任务规划器——「怎么做」(可开关) ​

当用户请求在意图层被判为「设备控制」并放行后,才会进入规划层。它相当于一个「调度员」:结合【设备能力清单】【当前 query】【上一轮反问对话】,判断请求能否直接执行,主要完成四件事:

职责说明
① 找能力用户诉求能否命中设备能力清单里的某项能力
② 查参数命中后,参数是否完整、合法、未超出取值范围
③ 拆任务识别是一个还是多个控制动作,以及动作之间是否存在先后关系(单任务 / 并行 / 串行)
④ 选路径决定「直接执行」还是「先反问澄清」(能力/参数齐备走 IOTAgent,缺失或模糊走 ChatAgent)

一句话:规划层只回答怎么做——能不能做、参数够不够、要拆成几步、走执行还是先追问。它不产出最终工具参数(那是执行层的职责),只输出一份可执行的 plan。

  • 何时关闭:当产品交互足够简单——只做单步控制、指令表达明确、无需澄清或串联多个动作时,可关闭规划层。关闭后链路仅走意图层 + 执行层,少一层处理,响应更快、更稳定可控;相应地会失去自动拆解与追问澄清的能力。关闭时该层不可展开。
  • 何时开启:交互越复杂越应开启规划层。开启时自动展开,支持自动拆解与追问澄清。

💡 建议按产品实际复杂度选择:交互越复杂越应开启规划层,越简单直接则越适合关闭。

这一层要写什么:一个「规划决策器」提示词,定义判定优先级(直接执行 / 反问澄清 / 交回闲聊)、Agent 边界(IOTAgent 直接执行、ChatAgent 反问或推荐)、范围校验与模糊兜底规则。核心是决定「怎么做」:能否直接执行、要不要追问、多部件如何选择。

实例:任务规划器(以多部件灯为例)
text
# Role
你是设备语音助手。根据【设备能力】清单与取值范围,判断用户当前指令能否直接执行,并给出 plan 决策。

判定优先级(按顺序检查,命中即停):
1. 命中能力 + 参数全在【设备能力】范围内 → 走 IOTAgent 直接执行;
2. 命中能力但参数超范围 / 关键参数缺失 / 模糊指代且无默认值 → 走 ChatAgent 反问澄清;
3. 不命中任何设备能力(情感/咨询/推荐/闲扯)→ 走 ChatAgent 主动推荐或普通闲聊。

# Core Rules
- 简短回复:反问/推荐话术不超过 30 字。
- 部件提示(多部件设备,含 上灯/下灯):
  ① 整机开关 target='light',无需澄清(「开灯」「关灯」);
  ② 部件级启停 target='上灯'/'下灯',必须直接走 IOTAgent,严禁走 ChatAgent;
  ③ 功能能力(模式/数值/档位):用户未指定部件按无前缀版直接执行,匹配不到才反问「上灯/下灯?」。

# 范围校验
- 相对调节(调高/调低 N档)只校验能力存在、增量为正、单位匹配,不推算当前值,不因可能越界转澄清;
- 参数超范围 → 改判 ChatAgent 反问;当前指令集未配置 min/max 时按用户给定值下发并标注。

# 模糊兜底
- 参数缺失(未指定上灯/下灯、未说调到多少)→ ChatAgent 反问澄清;
- 表达模糊(「差不多」「随便」「调一下」)→ 有 default 取默认值走 IOTAgent,无则反问。

可微调范围:

  • ✅ 可调:判定优先级的分支与举例;反问/推荐话术风格与字数上限;多部件设备的 target 命名与澄清策略;模糊兜底时的默认值策略。
  • ⚠️ 谨慎:三条 Agent 边界(IOTAgent/ChatAgent-clarify/ChatAgent-chat)的分流骨架不要打乱。
  • ⛔ 注意:本层可整体关闭;关闭后无拆解与澄清能力,复杂交互请保持开启。

2.3 垫句 ​

垫句是在任务规划器处理期间,用于填补等待时间、提升交互自然度的过渡语句(如「明白。」「稍等一下。」)。

  • 垫句最多可配置 5 条,系统会随机选用;
  • 垫句不等于执行回复。

联动矩阵:

指令集「执行反馈开关」垫句列表最终表现
开启有内容设备执行 + 播报垫句 + 播报执行回复
开启空设备执行 + 播报执行回复
关闭有内容设备执行 + 播报垫句(无执行回复)
关闭空完全静默(仅执行动作)

完全静默的配置详见 静默指令。

2.4 执行层 · 工具执行——「出参数」 ​

规划层生成可执行 plan 后,才会进入执行层。它相当于一个「执行员」:把 plan 里「要做什么」翻译成正确的工具调用,主要完成四件事:

职责说明
① 接收任务读取 plan 生成的设备、intent、参数及任务顺序,不得擅自增删或修改控制动作
② 组装指令将任务转成标准工具参数(intent / domain / value / unit 等),并选择正确的执行工具
③ 下发指令携带 bot_id / did / device_token 等设备上下文调用 IoT 平台或下发端侧;复合指令必须完整下发,不可漏发
④ 处理结果依据工具返回的 observation 判断成功 / 失败 / 需补充信息,并生成最终回复;不得把失败包装成成功,也不得遗漏查询结果(详见 § 2.5)

一句话:执行层只回答「出参数」——忠实执行规划层的决策,把动作变成合规的工具调用参数下发到设备,再据返回结果回复。它不重新做决策(该不该做、要不要澄清已由规划层定夺)。其中「组装指令」阶段的重点是把用户语言映射成参数:

对具体子任务生成符合协议的结构化输出(如 intent / args / deviceTimerBody),严格按结构化协议出参,最终下发到设备。

这一层要写什么:告诉模型怎么把用户语言映射成参数——动作动词归一(如 开启/启动/开 → '打开')、intent 拼装规则(intent = 动作 + target)、合法 intent 枚举(参数约束),以及关键的「增量 vs 目标值」区分,配一组示例锚定出参。

实例:执行层参数提取(以多部件灯为例)
text
# 语义映射
- intent 拼装:intent = <动作> + <target>(target 来自「参数约束」枚举)。
- 动作归一:打开/开启/启动/开 → '打开';关闭/关掉/停/关 → '关闭';查询/查看 → '查询';调到/设为 → '设置'。
- 增量 vs 目标值:带「到/至/为/成」标记(「调高到40」「亮度设为50」)是目标值 → intent='设置<target>',value 填目标数;
  无标记(「调高40」「调亮40」)是在当前值上增减 → intent='调高<target>'/'调低<target>',value 填增量。

# 参数约束(合法 intent 枚举;严禁臆造表外值)
- target 'light'(打开/关闭)→ '打开light' | '关闭light'
- target '上灯'|'下灯'(打开/关闭/查询)→ '打开上灯' | '关闭上灯' | '查询上灯' | ...
- target '亮度'(设置/调高/调低/查询)→ '设置亮度' | '调高亮度' | '调低亮度' | '查询亮度' | ...

# 示例
- '亮度设置为40'   -> intent='设置亮度', domain='light', value='40'
- '亮度调高10'     -> intent='调高亮度', domain='light', value='10'
- '亮度调高到40'   -> intent='设置亮度', domain='light', value='40'
- '现在亮度多少'   -> intent='查询亮度', domain='light'
- '打开灯'         -> intent='打开灯',   domain='light'

可微调范围:

  • ✅ 可调:动作动词归一词典(补充设备特有的同义动词);示例的增删(尤其针对易错 badcase 补 few-shot);domain / 单位等业务字段的取值说明。
  • ⚠️ 谨慎:intent / args / deviceTimerBody 等字段名与出参结构必须与设备协议严格对齐,不可自造。
  • ⛔ 禁止:输出参数约束枚举之外的 intent 值(臆造表外值会导致下发失败)。

2.5 执行层 · 处理结果——「据返回自定义回复」 ​

执行层「出参数」下发到 IoT 平台或端侧,:执行完会把结果回写到 observation,系统再依据它调用 FinalAnswerTool 生成给用户的最终回复。这一步决定了「用户最终听到什么」,也是回复话术可自定义的地方。

执行层出参 → 下发 IoT 平台 → 平台返回写入 observation
        ↓
FinalAnswerTool 依据 observation 生成最终回复(answer)
        ↓
用户听到的播报

这一层要写什么:告诉模型如何把 observation 转成最终回复——是直接透传、精简改写,还是套固定话术模板;并针对特定意图(如定时查询)约束「回复必须完整包含返回内容,不得摘要省略」。

实例:据 observation.intent_result 自定义回复
text
# 最终回复生成规则
FinalAnswerTool 的 answer 必须依据本轮 Observation.intent_result 生成,严禁凭空编造成功/失败。

- 控制类(设置/打开/关闭):intent_result 表示已执行成功时,回复精简确认话术(≤15字),
  例如 intent_result='已成功把空调模式调到制冷模式' → answer='已设置为制冷模式'。
- 查询类(尤其定时查询):answer 必须完整包含 intent_result 中的全部内容,
  严禁只回「已查询到定时任务」、严禁省略具体时间/动作/设备、严禁自行摘要或只报条数,
  本规则不受「回复不超过15字」限制。
- 失败时(intent_result 含 error / success=false):如实告知未执行成功,不谎报成功。

正确示例:
Observation: { "intent_result": "为您查询到以下定时任务:今天21点24分关闭空调的定时;今天22点24分关闭空调的定时;" }
FinalAnswerTool: { "answer": "为您查询到以下定时任务:今天21点24分关闭空调的定时;今天22点24分关闭空调的定时;", "success": true }

可微调范围:

  • ✅ 可调:回复话术风格(精简确认 / 完整播报 / 固定模板);不同意图类型的回复策略;成功/失败话术。
  • ⚠️ 谨慎:answer 必须忠于 observation,不得凭空谎报成功或失败;查询类(尤其定时查询)不得摘要省略,须完整播报返回内容。
  • 💡 该字段在端到端调试日志中的排查方法,详见 测试与调优 § 3.4。

3. 微调提示词的场景和示例 ​

在指令配置的基础上补充提示词,用于处理结构化指令表达不了的逻辑。本章分两部分:§ 3.1 把实战中最典型的 badcase 汇总成一份问题—根因—修复清单,方便按现象快速定位;§ 3.2 专门讲复合指令(一句话多个动作)的拆分与合并写法。

通用方法论:这些 badcase 大多可通过「先补通用映射规则,再加正/负向 few-shot」纠正。多数需要在规划层(plan)与执行层(Executor)同时补规则——plan 负责「想清楚做什么」,Executor 负责「真正怎么做」,两层同源才不会前后打架。

配置方式:保持「根据指令集生成」模式,在自动生成的提示词后追加自定义补充说明。

3.1 实战 Badcase 清单 ​

case 1:查询与设置控制项相近导致意图串扰——用 few-shot 明确分流 ​

  • 现象:枚举类指令的枚举值与其他指令的控制项名称相近,意图容易串。例如,「查询息屏时间」意图对应控制项为状态、枚举值为息屏时间;而「设置息屏时间」对应控制项为熄屏时间。两者同时配置时,进入的意图可能相互影响、误判。
  • 根因:枚举类指令的枚举值与其他指令的控制项名称相近,模型难以区分「读状态」还是「改参数」。
  • 修复:在plan与执行中补一段 few-shot 明确分流,把查询意图与设置意图各自锚定到正确的 intent / value。
text
# 查询/设置息屏时长分流
用户问“查询息屏时间 / 息屏时间是多少 / 当前息屏时长”时,必须输出 intent='查询状态', value='息屏时长'。
用户说“设置息屏时间为10秒 / 息屏时长改成10秒”时,才输出 intent='设置熄屏时长', value='10', unit='秒'。
严禁把“查询息屏时间”输出成 intent='查询熄屏时长' 或 intent='设置熄屏时长'。

case 2:模糊指令(不带具体值)漏出 value——用提示词强约束补齐 ​

  • 现象:query 为「调高亮度」时,亮度未返回 value 值。「亮度调高 10」可正常出参,但「调高亮度」属于不带具体值的模糊指令,模型未按指令配置在间距中带上 value,产生 badcase。
  • 根因:模糊指令缺少显式数值,模型未按指令配置以默认步长补齐 value,直接漏出参。
  • 修复:在plan与执行提示词中对这类模糊指令场景做强约束,明确要求带 value(如按默认步长补齐),避免模型漏出参。
text
# 模糊调节指令补 value 规则
当用户话术为「调高/调低 + <target>」但未给出具体数值(如「调高亮度」「调低亮度」)时,
必须按该 target 的默认步长补齐 value,严禁漏出参。
- 「调高亮度」→ intent='调高亮度', value=<默认步长>
- 「调低亮度」→ intent='调低亮度', value=<默认步长>
严禁输出不含 value 的 step。

case 3:「加一度 / 升一度」被误判为音量、风速——省略 target 致单位归属猜错 ​

  • 现象:「加一度」「升一度」这类省略控制对象的短语,模型误识别为音量调节或风速调节。
  • 根因:省略了控制对象,「度」的归属被模型猜错。
  • 修复:plan与执行提示词中补「温度单位优先级最高」规则——只要设备能力中存在 target='温度',「加/升/降/减/调高/调低 + 数字 + 度」一律判温度。
text
# 温度单位优先级最高规则
当用户话术包含「加/升/降/减/调高/调低 + 数字或中文数字 + 度」,
且设备能力中存在 target='温度' 时,必须优先判定为温度控制意图,走 AIOT 设备控制。
- 「加一度」→ 调高温度, value=1, unit=度
- 「升一度」→ 调高温度, value=1, unit=度
- 「降一度」→ 调低温度, value=1, unit=度
- 「减一度」→ 调低温度, value=1, unit=度
强约束:「度」是温度单位,不是音量单位。
严禁将「加一度 / 升一度」识别为「音量调大」或 VOLUME_UP;
严禁将「降一度 / 减一度」识别为「音量调小」或 VOLUME_DOWN。

case 4:「停止 / 关闭扫风」输出非法能力——开关型能力被当「设置」或臆造枚举外 intent ​

  • 现象:「左右扫风关闭」错输出 intent='暂停左右扫风'、「停止左右扫风」错输出 intent='关闭扫风',未准确命中控制对象与动作。
  • 根因:开关型能力被当成「设置」或臆造出枚举外 intent。
  • 修复:plan与执行都补「开关型能力 intent 输出规则」,「停止/暂停」统一归一为「关闭<target>」,不输出 value。
text
# IOT平台开关型能力 intent 输出规则
对数据类型为「开关」且操作行为为「打开 / 关闭」的能力:
- 打开 / 开启 / 启动 / 开 → intent='打开<target>'
- 关闭 / 关掉 / 关 / 取消 / 停止 / 暂停 / 停 → intent='关闭<target>'
- 严禁输出成 intent='设置<target>',严禁输出 value='1' / value='0'(开关语义由 intent 承载)
示例:「上下扫风停止」→ intent='关闭上下扫风';「停止左右扫风」→ intent='关闭左右扫风'

case 5:「灯光 / 显示 / 数显」需别名归一化——别名未归一到标准 target ​

  • 现象:「打开灯光」预期intent='打开数显',错输出 intent='打开灯光'、「关闭灯光」错输出 intent='设置数显', value='0'。
  • 根因:「灯 / 灯光 / 显示 / 屏显」是别名,未归一到标准 target「数显」。
  • 修复:补「数显/灯光开关映射规则」,别名一律归一为 数显,只输出 打开数显 / 关闭数显。
text
# 数显/灯光开关映射规则
「数显」是开关型能力,别名包括「灯 / 灯光 / 显示 / 屏显」。
- 打开 / 开启 / 启动 / 开 → intent='打开数显'
- 关闭 / 关掉 / 关 / 取消 / 停止 / 暂停 → intent='关闭数显'
- 别名只是话术,最终 intent 的 target 必须归一为「数显」
严禁输出:intent='设置数显' / intent='打开灯光' / intent='关闭灯光' / value='1' / value='0'
示例:「打开灯光」→ intent='打开数显';「显示关」→ intent='关闭数显'

case 6:「中风 / 最大风 / 静音档」枚举值直达——合法枚举值被当参数缺失误反问 ​

  • 现象:用户只说风速枚举值(中风/最大风/静音档/自动风),未说枚举项名称「风速」二字,模型判为模糊表达,误进 ChatAgent-clarify 反问。
  • 根因:合法枚举值被当成参数缺失。
  • 修复:补「风速省略 target 判定规则」,枚举值唯一命中一个 target 时直接执行;value 必须输出标准枚举值,不能输出 alias。
text
# 风速省略 target 判定规则
空调类设备,用户只说风速枚举值或别名(即使未说「风速」),默认 target='风速',走 IOTAgent 直接执行:
- 「中风」/「中风档」→ intent='设置风速', value='中风'
- 「最大风」→ intent='设置风速', value='max'
- 「静音档」→ intent='设置风速', value='静音风'
- 「自动风」→ intent='设置风速', value='自动'
严禁因用户未说「风速」而走 ChatAgent-clarify;value 必须输出标准枚举值,不能输出 alias。

case 7:「制冷模式」枚举项直达——命中枚举项却被判参数缺失而无意义反问 ​

  • 现象:用户说「制冷模式」,模型反问「请明确是设置制冷模式,还是开启制冷模式?」。
  • 根因:直接命中枚举项却被判为参数缺失。
  • 修复:补「枚举项直达规则」,命中枚举项即视为参数完整,默认执行「设置」动作,严禁反问。
text
# 枚举项直达规则
当用户输入直接命中某枚举项编号 / 名称 / 别名时,视为已给出完整参数,
即使没说「设置/切换/调到」,也默认执行该枚举项对应 target 的「设置」动作。
- 「制冷模式」命中 target='模式' 的枚举值 → agent='IOTAgent', intent='设置模式'
- 严禁判为参数缺失,严禁反问「设置还是开启/关闭」

case 8:查询结果回复不完整 + domain 写错——回复只摘要且外层 domain 未固定 ​

  • 现象:定时任务查询结果不完整,状态、数量与实际不同步;或外层 domain 被写成设备品类(如「空调」)。
  • 根因:回复端只摘要不透传;查询定时的外层 domain 未固定为「设备定时」。
  • 修复:Executor 补两段规则——① 回复必须完整包含 Observation.intent_result 的全部定时任务(不受「≤15字」限制);② 查询定时时 intent='查询设备定时'、外层 domain 固定为 '设备定时'。
text
# 定时查询回复完整性规则
当 intents 含 intent='查询设备定时' 时:
- FinalAnswerTool.answer 必须完整包含 Observation.intent_result 中的所有定时任务
- 本规则不受「回复不超过15字」限制
- 严禁只回「已查询到定时任务」、严禁省略具体时间/动作/设备、严禁自行摘要或只报条数

# 设备定时管理执行规则(最高优先级)
当用户意图为设置/查询/取消设备定时任务时,外层 domain 固定为 '设备定时',严禁写成设备品类。
查询定时:intent='查询设备定时', domain='设备定时', deviceTimerBody='【domain:空调】'
严禁输出 intent='查询定时任务' 或 domain='空调'。

💡 case 8 的 Observation.intent_result → 完整回复 属于执行层「处理结果」环节,机制详见 § 2.5 执行结果与回复自定义。

3.2 复合指令(一句话多个动作) ​

一句话里包含多个控制动作(如「制冷模式16度最大风」),就是复合指令。它是最容易「发一半、漏一半」的场景——本质是规划层拆几个任务与执行层发几个意图必须一致。提示词要在两层同时约束:规划层判对 taskType,执行层合并进一个 intents 数组。

3.2.1 判定规则:taskType 决定拆几个任务 ​

规划层的 taskType 是复合指令的「因」,直接决定 tasks 数量与执行方式:

taskType条件tasks 数量
single单一动作,或同一设备的多个独立参数(走同一 iot_do_batch_domain_intent)必须且只能 1 个
parallel≥2 个任务且无先后依赖≥2 个
sequential≥2 个任务且用户明确表达「先/后/然后/再/接着/随后/之后」≥2 个

⚠️ 最易错点:「制冷模式16度最大风」是同一台空调的三个独立参数,应判 taskType='single' 且 tasks 只保留 1 个(intent 合并为「设置模式,设置温度,设置风速」),而不是拆成 3 个 task。

处理方式:在规划层与执行层同时补规则——规划层按上表判 taskType;执行层对多参数复合指令一次调用 iot_do_batch_domain_intent,把多个意图合并进 intents 数组,严禁只发首/末个意图,严禁拆成多次 tool_call。

text
# 复合指令拆分与合并规则(规划层 + 执行层同源)
【规划层】同一设备的多个独立参数(如模式+温度+风速)→ taskType='single',tasks 只保留 1 个,
  intent 合并为「设置模式,设置温度,设置风速」;有明确先后词(先/再/然后)才判 sequential。
【执行层】必须一次调用 iot_do_batch_domain_intent,把全部意图合并进 arguments.kw.intents 数组:
  - 严禁只输出首个或末个意图(发一半);
  - 严禁拆成多个 tool_call 分别下发;
  - value 必须输出标准枚举值,禁用 alias。
示例 query=「制冷模式16度最大风」→ intents=[
  {intent:'设置模式', domain:'空调', value:'制冷模式'},
  {intent:'设置温度', domain:'空调', value:'16'},
  {intent:'设置风速', domain:'空调', value:'max'} ]

3.2.2 真实调试窗示例:一眼看懂 taskType 与 intents 数组 ​

下面是 query=「制冷模式 十六度 最大风」在调试窗打出的真实 Debug Info(已精简无关字段)。对照它就能看清:规划层判 taskType='single' + 只生成 1 个 task,执行层把 3 个动作合并进一个 intents 数组——这就是复合指令「拆几个任务」和「发几个意图」必须对齐的样子。

jsonc
{
  "intent": "设备控制",
 // ① 规划层:taskType=single,tasks 只有 1 个,intent 用逗号拼接全部动作
  "AIOT_TASK_PLAN": {
    "data": {
      "agent": "IoTAgent",
      "taskType": "single",
      "reasoning": "「制冷模式十六度最大风」→ 设置模式/温度/风速,同设备三参数可合并为单任务",
      "tasks": [
        {
          "id": "task_1",
          "description": "设置模式为制冷模式,设置温度为16度,设置风速为最大",
          "intent": "设置模式,设置温度,设置风速",   // 三个动作合并,不拆成 3 个 task
          "device": "空调室内机网关"
        }
      ]
    },
    "type": "AIOT_TASK_PLAN"
  },
  // ② 执行层:一次 iot_do_batch_domain_intent 调用,intents 数组一次发全 3 个意图
  "AIOT_TASK_COMPLETED": {
    "data": {
      "result": {
        "react_steps": [
          {
            "iteration": 1,
            "tool_calls": [
              {
                "name": "iot_do_batch_domain_intent",
                "args": {
                  "kw": {
                    "intents": [
                      { "intent": "设置模式", "domain": "空调", "value": "制冷模式" },
                      { "intent": "设置温度", "domain": "空调", "value": "16", "unit": "度" },
                      { "intent": "设置风速", "domain": "空调", "value": "max" }
                    ]
                  }
                }
              }
            ],
            // ③ 平台回执:intent_result 决定最终回复
            "observation": { "intent_result": "已成功把空调设置为制冷模式、16度、最大风" }
          },
          {
            "iteration": 2,
            "tool_calls": [
              { "name": "FinalAnswerTool", "args": { "answer": "已设置为制冷模式", "success": true } }
            ]
          }
        ]
      },
      "taskId": "task_1",
      "status": "completed"
    },
    "type": "AIOT_TASK_COMPLETED"
  }
}

怎么读这段日志:先看 AIOT_TASK_PLAN.taskType——是 single 且 tasks 只有 1 个,说明规划层判对了;再看 iot_do_batch_domain_intent 的 intents——里面有 3 个意图对象,说明执行层没「发一半」;最后看 observation.intent_result——回复完整才算真正成功。三处任一环节数量对不上,就按下面的排查顺序回溯。

3.2.3 排查顺序:核对三个数字对不对得上 ​

复合指令出问题时,按顺序数三个数字,不一致即定位到对应层:

  1. 先数 tasks(该合的合了没):taskType='single' 却拆出多个 task → 规划层错,须合并为 1 个;
  2. 再数 intents(该发的发全没):intents 数量少于动作数 → 执行层「发一半」,须合并进一个数组;
  3. 最后看 observation.intent_result(设备回没回、回复对不对):回复不完整 → 回到 § 2.5 处理结果。

💡 复合指令的全链路日志实例与逐字段校验方法,详见 测试与调优 § 3.5。

4. 提示词的初始化与保存(常见 QA) ​

提示词在「根据指令集生成」与「自定义」两种模式间切换、以及指令集变更时,会触发重新初始化,容易导致微调内容丢失。以下用实际使用场景 + QA 的形式说明,操作前请对照。

Q1:选了「根据指令集生成」,怎么让系统把提示词生成出来?

新建指令集 → 新建指令后,页面会出现**「更新提示词」的提示。点击 更新提示词,系统就会根据当前指令初始化生成一版系统提示词**,生成后即可直接调试。

Q2:什么时候该用「完全自定义提示词」?怎么用?

当设备能力完全套不进结构化指令时,切换到「自定义提示词」模式,整段自由编写提示词。注意:

  • 不可跑批测试(无结构化基准),需依赖 端到端调试 验证;
  • 建议在提示词中显式定义:角色 Role、意图边界、参数出参格式(与设备协议对齐);
  • 该模式的保存与初始化风险见下方 Q4、Q6。

Q3:我在系统生成的提示词上做了微调,什么情况下这些自定义改动会丢?

在「根据指令集生成」模式下微调后,只要触发了提示词重新初始化,微调内容就会被覆盖消失,但是指令数据及其生成的系统提示词不受影响。以下操作都会触发系统提示词初始化:

  • 把提示词切换成「自定义提示词」再切回来;
  • 关闭 AIOT 开关再重新打开;
  • 指令发生修改后点击更新提示词(见 Q5)。

💡 因此,请谨慎做出以上调整。

Q4:我用的是「自定义提示词」,会不会也丢?

会。自定义提示词后,若切换为「根据指令集生成」,或关闭开关再打开,自定义的内容同样不会保存。做相关调整前请先复制保存当前自定义提示词。

Q5:提示词微调后我又改了指令,会怎样?

页面会提示**「指令发生修改,是否更新提示词」。注意:此时若点击更新提示词**,系统会根据最新指令重新初始化提示词,此前的自定义微调内容不会保留。

💡 建议:更新前先复制一份当前提示词留档,更新完成后再把微调内容重新写回新提示词中。

Q6:我改了指令,但没点「更新提示词」就直接保存了,会怎样?

指令的修改不会自动同步到提示词。如果更新指令后没有点击「更新提示词」就直接保存,系统实际执行的仍是指令更新前的旧提示词,本次指令更新不会生效。

⚠️ 因此改完指令后,务必点击**「更新提示词」**让提示词与最新指令对齐(如需保留微调,请先按 Q5 复制留档),再保存。

Q7:微调改乱了,想恢复成系统初始化的样子怎么办?

在「根据指令集生成」模式下,切换到「自定义提示词」再切回来,系统会自动重新初始化提示词,即回到根据当前指令生成的初始版本。

Q8:为什么智能体保存不了?

以下两种情况下智能体无法保存:

  • 自定义提示词模式下,提示词内容为空;
  • 根据指令集生成模式下,指令为空(未创建任何指令)。

补齐对应内容后即可保存。

⚠️ 一句话记忆:任何会触发「重新初始化」的操作(切模式、开关重启、指令更新)都可能覆盖你的改动——动手前先存草稿/复制留档。

5. 相关链接 ​