Skip to content

SA 设备查询:Agent 设计方案 (Semantic/AI Layer)

文档目的:描述设备查询专家(Query Specialist)在 intent_type=QUERY 场景下的独立推理链路。与设备控制(CONTROL)共享 Stage 1 槽位提取和 Stage 2 工程化检索,但从 Stage 3 开始分叉:LLM 跳过 L3 注入、仅做属性选择输出、Engine 按需拉取值绑定。

关联文档


1. 核心业务流程 (Happy Path Sequence)

与 CONTROL 的核心差异:CONTROL 的 L3(current_values[])在 LLM 推理前注入,LLM 需计算目标值;QUERY 的 L3 在 LLM 输出后由 Engine 按需拉取,LLM 仅做属性选择。


2. 第一阶段:槽位提取 (Stage 1: Slot Filling)

与 CONTROL 共享同一套槽位定义和提取逻辑,intent_typeQUERY。详见 SA_设备控制_Agent设计.md §2

QUERY 判定规则:包含"多少/状态/查/看/显示/告警/有没有/是否/监测/情况"等查询动词。


与 CONTROL 共享同一套 search_entities() 函数,详见 SA_设备控制_Agent设计.md §3

差异点:QUERY 场景下 device 为空时返回该空间全部设备(不限 CONTROL 能力标签),以覆盖用户"所有设备状态"等宽泛查询。


4. 信息注入策略

层级CONTROLQUERY
L2(复合实体骨架)注入 cap_tags + llm_desc相同,LLM 依赖 llm_desc 理解属性语义做映射
L3(产品级聚合描述)Step 1 默认不注入,Step 2 按需注入 current_values[] + mapping跳过,LLM 无需消费

QUERY 跳过 L3 的理由:L2 已注入 llm_desc(MCP 标准语义描述),LLM 仅需理解每个 capability 的语义含义以完成属性选择,不需要 current_values[] 具体数值来辅助决策。Engine 在拿到 selected_attrs 后,按需调用 get_product_caps() 获取实际值用于绑定和渲染。


5. LLM 输出结构

QUERY 场景 LLM 仅输出用户关心的属性 key 数组,不含 scenelabel 等冗余字段,最小化 token 开销。Engine 负责将 key 匹配到设备并补充 label。

LLM 输出(纯 key 数组):

json
{
  "selected_attrs": ["hvac_target_temp", "hvac_mode"]
}

用户明确指定属性时(如"305空调多少度"),仅含一个 key:

json
{
  "selected_attrs": ["hvac_target_temp"]
}

与 CONTROL 的区别:CONTROL 需要按 product_id 分别输出目标值(因枚举兼容性因产品而异),QUERY 只读值没有兼容性问题,所以 LLM 统一输出 key 数组即可,Engine 自动匹配到所有设备。label 由 Engine 查标准语义库补充,LLM 无需输出。

5.1 Prompt 约束

LLM 输出 selected_attrs 时需遵循以下约束:

数量上限selected_attrs 元素个数 不超过 10 个(含)。大部分 IoT 设备的可读 capability 总数在此范围内;超过此上限时,LLM 需结合用户 query 语境剔除明显无关的属性(如定时参数、关联设备地址等低频/非核心字段),保留与用户意图最相关的属性。

不负责排序:LLM 只做属性选择筛选,不负责决定属性展示顺序。渲染时 Engine 按设备分组,组内按 L3 capabilities 的原始排列顺序展示。

示例:某设备有 12 个 capability,用户问"看看这台空调的状态":

  • LLM 剔除 timer_configlinked_device_addrfirmware_version 等低频/非核心字段
  • ✅ 输出 9 个核心属性:["light_power","hvac_target_temp","hvac_mode","hvac_fan_speed","room_temp","alarm_status","energy_consumption","filter_life","defrost_status"]

5.2 典型场景示例

以下示例基于设备的可用 capability 集:

  • 空调light_power(开关)、hvac_target_temp(设定温度)、hvac_mode(运行模式)、hvac_fan_speed(风速)、room_temp(回风温度/RO)、alarm_status(故障状态)
  • 灯具light_power(开关)

示例 1 — 用户精确指定设备+属性 → compact

User: "305空调多少度"

LLM 推理:用户明确要查"多少度",只关心温度属性。空调的 temperature 相关 capability 有 hvac_target_temp(设定温度、RW)和 room_temp(回风温度、RO)。此处用户说的"多少度"更接近设定温度,因此仅输出 hvac_target_temp

json
{ "selected_attrs": ["hvac_target_temp"] }

→ Engine 装配后所有设备均为 1 个 attr → compact


示例 2 — 用户问设备综合状态 → detail

User: "305空调什么状态"

LLM 推理:"什么状态"未明确指定属性,LLM 推断用户想了解设备的核心运行状态,选择开关+设定温度+运行模式。

json
{ "selected_attrs": ["light_power", "hvac_target_temp", "hvac_mode"] }

→ 任一设备 ≥2 个 attr → detail


示例 3 — 用户问制冷效果(传感器对比)→ detail

User: "305空调制冷效果怎么样"

LLM 推理:"制冷效果"隐含了设定值与实际值的对比意图,选择 hvac_target_temp(设定值)+ room_temp(传感器回风温度、RO 只读)来呈现温差,同时带 hvac_mode 确认当前模式。

json
{ "selected_attrs": ["hvac_target_temp", "room_temp", "hvac_mode"] }

detail,前端展示"设定 24℃ vs 回风 26℃"对比。


示例 4 — 用户查故障 → compact

User: "查一下305空调有没有故障"

LLM 推理:用户明确关心故障状态,仅需输出 alarm_status

json
{ "selected_attrs": ["alarm_status"] }

compact,值显示为"正常"、"通信异常"等枚举中文标签。


示例 5 — 用户问空间下所有设备 → compact(多设备异构属性)

User: "305所有设备状态"

LLM 推理:空间下有灯和空调两种设备。从 Stage 2 的 cap_tags 可知灯只有 light_power、空调有多个属性。为了覆盖所有设备类型,LLM 选择 light_power(公共属性)和 hvac_target_temp(空调特有属性)。Engine 匹配时各设备仅 1 个 attr。

json
{ "selected_attrs": ["light_power", "hvac_target_temp"] }

→ Engine 装配结果:

设备匹配属性attrs.length
305主灯light_power → 已开启1
305筒灯light_power → 已关闭1
305空调hvac_target_temp → 24℃1

→ 所有设备均为 1 个 attr → compact


示例 6 — 模糊输入,LLM 推断多属性 + 混合设备 → detail

User: "看看305的设备情况"

LLM 推理:用户意图模糊,未指定具体属性,LLM 推断选择覆盖空间内主要设备的关键属性。

json
{ "selected_attrs": ["light_power", "hvac_target_temp", "hvac_mode", "alarm_status"] }

→ Engine 装配结果(mix 场景):

设备匹配属性attrs.length
305主灯light_power → 已开启1
305筒灯light_power → 已关闭1
305空调light_power + hvac_target_temp + hvac_mode + alarm_status4

→ 空调 attr.length = 4 ≥ 2 → detail。灯在 detail 中仅展示 1 行(开关),空调展示 4 行。


6. Engine 组装与渲染模式判断

Engine 收到 LLM 输出后,执行以下组装逻辑:

Step 1 — 遍历设备:遍历 Stage 2 返回的设备骨架(已按空间和设备名过滤),对每台设备获取其 product_id

Step 2 — 拉取当前值:收集命中的 product_id + selected_attrs[] 组合,调用 get_product_caps() 拉取 L3 数据(current_values[]mapping 等)用于值绑定。

L3 数据在此阶段由 Engine 按需拉取,而非注入给 LLM。LLM 全程不消费 L3 数据。

Step 3 — 属性匹配与值绑定:对每台设备,检查其所属产品的 L3 capabilities 的 key 是否命中 selected_attrs[] 中的任一元素。命中则从 current_values[] 中按设备索引提取当前值,并通过标准语义库查 key 对应的 label,组成 { label, value }。未命中的 capability 跳过。若设备没有任何命中的属性,则排除该设备。

json
{
  "devices": [
    {
      "device_id": "dev_ac_01",
      "device_name": "305空调(左)",
      "product": "大金空调",
      "attrs": [
        { "label": "设定温度", "value": "24℃" },
        { "label": "运行模式", "value": "制冷" }
      ]
    },
    {
      "device_id": "dev_ac_02",
      "device_name": "305空调(右)",
      "product": "大金空调",
      "attrs": [
        { "label": "设定温度", "value": "26℃" },
        { "label": "运行模式", "value": "制冷" }
      ]
    }
  ]
}

Step 4 — 渲染模式判断:根据所有设备的 attrs.length 决定渲染模式:

模式触发条件卡头标题
compact所有设备 attrs.length === 1复用 selected_attrs[0] 对应的标准语义名
detail任一设备 attrs.length ≥ 2固定为 "{space} · 设备详情"

mix 场景说明:不同设备的 attrs.length 可以不同(如设备 A 有 2 个属性、设备 B 有 1 个属性)。只要任一设备 ≥2 即触发 detail 模式;单属性设备在 detail 卡片中仍只展示 1 行,无需补齐。

Step 5 — 前端渲染:组装 renderQueryResult JSON 下发前端:

json
// compact 模式
{
  "display_mode": "compact",
  "semantic_label": "设定温度",
  "devices": [
    { "device_name": "305空调", "attrs": [{ "label": "设定温度", "value": "24℃" }] }
  ]
}

// detail 模式(含 mix 场景)
{
  "display_mode": "detail",
  "devices": [
    {
      "device_name": "大金空调",
      "attrs": [
        { "label": "设定温度", "value": "24℃" },
        { "label": "运行模式", "value": "制冷" }
      ]
    },
    {
      "device_name": "美的空调",
      "attrs": [
        { "label": "设定温度", "value": "26℃" }
      ]
    }
  ]
}

7. 前端渲染协议

场景协议前端表现
CONTROLrenderSAControl(含语义目标值 + product_id + 共享量程)HITL 控制卡片(滑块/开关/确认按钮)
QUERYrenderQueryResult(含设备状态集合)纯信息卡片(无交互组件)

两者均通过 Engine 组装后下发前端,不直接由 LLM 输出。


8. 异常处理

8.1 检索异常

与设备控制共享 Stage 2 检索管道,Space 404 / Device 404 异常处理逻辑完全一致,详见 SA_设备控制_Agent设计.md §6.1。QUERY 场景的 Device 404 话术为"该空间下目前暂无可查询的设备"。

8.2 设备状态异常

场景反馈逻辑
空间无设备Agent 回复"该空间下暂无可查询的设备。"
设备离线在状态卡片中该设备行标注"⛔ 离线",状态值显示为"--"

8.3 告警等特殊点位

设备告警状态作为普通逻辑点位处理(如 alarm_status 作为 enum 类型),纳入产品级映射后在 current_values[] 中一并注入。前端根据该点位的值展示对应色阶。

若为 BI 类告警统计(如告警率、历史趋势、排名),Master Agent 应路由至 Data_Query 子 Agent,不经过本管道。


9. TODO

  • [ ] 告警状态前端色阶渲染:enum 值映射色阶(正常→绿、告警→红)
  • [ ] 多设备离线状态:部分离线时卡片展示策略

10. 相关设计参考

Released under the Private License.