技能生态与运行方式

智能音箱的"技能"(Skill)本质上是一个可被语音触发的应用:用户说一句话,音箱完成语音识别与语义理解,把结构化请求转发给技能的后端服务,服务返回应答文本,音箱再语音播报。整个链路对开发者只暴露两部分:意图模型与后端接口。

主流平台的技能开发大同小异:在开发者平台定义意图(Intent)与槽位(Slot),配置调用词,然后提供一个 HTTPS 接口接收请求。平台负责语音识别(ASR)与自然语言理解(NLU),开发者专注业务逻辑,不用自己碰语音。

本文核心知识点
  • 意图一句话映射到哪个业务动作。
  • 槽位从话里抽出设备、参数等变量。
  • 会话多轮对话的状态保持机制。
  • 回退本地技能与断网兜底设计。

对智能家居场景,技能的价值是把"控制设备"从 App 点按升级成自然语言:"把客厅灯调到最暗""明早七点叫我""空调设成二十六度"。这些都能拆成意图加槽位:意图是控制,槽位是设备、动作、数值。

音箱技能开发配图:深蓝渐变背景上中央圆润智能音箱轮廓向四周扩散声波弧线,周围悬浮灯泡、时钟与设备节点的扁平科技插画
一个技能 = 意图模型 + 后端服务,语音只是入口。

意图与槽位设计

意图设计是技能体验的分水岭。原则是"意图要少而准":把同一种操作归为一个意图,靠槽位区分细节,而不是为每句话单独建意图。比如"开灯""关灯""调亮度"可以是一个 SetLight 意图加 action 槽位,也可以拆成三个意图——拆太多会让 NLU 训练样本分散,识别率下降。

// 意图与槽位定义(JSON 示意)
{
  "intent": "SetLight",
  "slots": {
    "device": ["客厅灯", "卧室灯", "走廊灯"],
    "action": ["开", "关", "调亮", "调暗"],
    "level":  ["最暗", "最亮", "百分之五十"]
  }
}
// 示例话术:把{device}给{action}{level}

槽位类型尽量用平台内置的(设备名、数字、百分比),自定义词表要给足同义词:"客厅灯"要有"客厅的灯""客厅照明"等变体。训练话术准备几十条覆盖各种说法,比追求话术数量更重要。

后端服务开发

后端服务收到平台请求后,核心任务是三件事:校验签名、解析意图槽位、执行并返回应答。应答文本要短而自然,最好带上确认信息:"好的,客厅灯已调到百分之五十"。执行失败时返回明确的兜底话术,而不是让用户干等。

// 技能后端处理(伪代码)
def handle_skill(request):
    verify_signature(request)         # 1. 校验来源
    intent = request.intent_name      # 2. 解析意图
    slots  = request.slots
    if intent == "SetLight":
        ok = device_api.set(
            device=slots["device"],
            action=slots["action"],
            level=slots.get("level"))
        if ok:
            return speak(f"好的,已{slots['action']}")  # 3. 应答
        return speak("操作失败了,请检查设备状态")
    return speak("我还不会这个操作")

接口的响应时限通常在几秒内,超时会被视为失败。凡是可能慢的操作(查设备状态、调云平台接口)要么提前缓存,要么先回"好的,正在处理"再用异步通知补齐结果,避免用户听到"网络好像出问题了"。

本地技能与私有设备

很多家庭场景希望语音指令不绕云端:音箱直接控制局域网内的设备,断网也能用。这就是本地技能(Local Skill)的价值。实现方式通常是音箱局域网内发现设备,通过本地协议(MQTT 本地通道、HTTP API、厂商私有协议)下发指令。

  • 设备发现:通过 mDNS / UDP 广播发现局域网设备,维护在线列表。
  • 本地通道:优先走局域网,云端只是配置下发与远程兜底。
  • 权限校验:本地接口也要校验来源,防止局域网内任意设备冒充音箱。
  • 断网兜底:云端不可达时,纯本地指令仍可执行,体验不中断。

本地技能的开发难点在协议适配:不同厂商的设备协议各异,需要做统一抽象层,把"调亮度"映射到各家的私有命令。抽象层做得好,接入新设备就是加一个适配器的事。