HarmonyOS应用《民族图鉴》开发第72篇:Skill技能开发——小艺技能接入与语音交互

📖 引言
想象一下这样的场景:
你正在做饭,手上沾着面粉,突然想了解一下傣族的泼水节。你不用擦干手、解锁手机、打开App、搜索……只需要对着手机说一声:"小艺小艺,傣族的传统节日是什么?"小艺就会直接告诉你答案,甚至还能打开「民族图鉴」的傣族详情页。
这就是语音交互的魅力——解放双手,自然便捷。
在鸿蒙系统中,语音交互是通过**Skill(技能)**来实现的。小艺助手是系统级的语音入口,第三方应用可以通过开发Skill,让自己的服务被用户用语音唤起。
你可能会问:
- 什么是Skill?它和普通的App有什么区别?
- Skill有哪些类型?「民族图鉴」适合做什么样的Skill?
- Skill的开发流程是怎样的?需要哪些技术栈?
- 语音交互的核心概念有哪些?意图、槽位、对话流是什么?
- 怎么让Skill和App联动?语音怎么打开App的特定页面?
- 识别不准、意图匹配错误怎么办?怎么提升对话体验?
这些问题非常重要。语音交互是AI时代的重要交互方式,掌握Skill开发,能让你的应用拥有"语音入口",降低用户使用门槛,提升用户体验。
本文将系统讲解鸿蒙Skill技能开发的完整知识体系。我们会从基础概念讲起,逐步深入到Skill的设计、开发、测试、上架全流程,并结合「民族图鉴」项目,设计并实现一个民族查询技能。
🎯 学习目标
完成本文后,你将能够:
- ✅ 理解什么是Skill,以及Skill的类型和价值
- ✅ 掌握Skill开发的完整流程:注册→开发→测试→上架
- ✅ 理解语音交互的核心概念:意图、槽位、对话流
- ✅ 学会设计「民族图鉴」的Skill技能
- ✅ 掌握Skill与App的联动方式
- ✅ 理解多轮对话设计的要点
- ✅ 具备实战开发Skill的能力
- ✅ 了解常见问题及解决方案
💡 需求分析
为什么要做Skill?
在讲技术之前,我们先回答一个最根本的问题:为什么要花时间做Skill?它能给「民族图鉴」带来什么价值?
1. 降低使用门槛:说一句话就能用
很多用户下载了App,但可能很久才打开一次。而语音是最自然的交互方式——用户不需要找到App图标、不需要点击、不需要打字,说一句话就能获取信息。
场景举例:
- “小艺,今天推荐哪个民族?” → 直接获取今日推荐
- “小艺,藏族的人口有多少?” → 快速查询民族信息
- “小艺,打开民族图鉴看傣族” → 直接跳转到详情页
对于「民族图鉴」这样的工具类/内容类应用,Skill可以:
- 大幅降低使用门槛
- 提高功能使用率
- 增加用户触达渠道
2. 系统级入口:无处不在
小艺是鸿蒙系统的级助手,用户在任何界面都可以唤起:
- 桌面:长按Home键、说"小艺小艺"
- 锁屏:熄屏状态下也能唤起(支持的设备)
- 任何App内:通过小艺悬浮球或手势
这意味着,你的Skill可以无处不在——用户不需要打开你的App,就能使用你的服务。
3. 先发优势:流量红利
新的平台往往意味着新的流量红利。先入驻的Skill往往能获得:
- 更多的推荐曝光
- 更早的用户积累
- 更好的搜索排名
4. 技术储备:拥抱AI时代
语音交互是AI时代的重要交互方式。掌握Skill开发:
- 是对AI交互的实践和探索
- 为后续更复杂的Agent开发打基础
- 提升团队的技术竞争力
Skill和App的关系
很多人会混淆Skill和App的关系。它们不是替代关系,而是互补关系。
| 维度 | App | Skill |
|---|---|---|
| 交互方式 | 触控为主 | 语音为主 |
| 使用场景 | 深度使用、复杂操作 | 快速查询、简单操作 |
| 入口 | 桌面图标、应用市场 | 小艺助手、系统搜索 |
| 内容展示 | 丰富的视觉界面 | 语音回复 + 简单卡片 |
| 开发技术 | ArkUI/ArkTS | 技能平台 + 后端服务 |
| 优势 | 体验丰富、功能完整 | 使用便捷、触达方便 |
最佳实践:
- Skill做轻量功能:快速查询、简单操作、语音播报
- App做深度体验:详细内容、丰富交互、复杂功能
- 两者联动:Skill引导用户打开App,App内也可以用语音操作
对于「民族图鉴」来说:
- Skill:快速查询民族基本信息、今日推荐、节日问答
- App:详细介绍、图片展示、音乐播放、知识答题、地图分布
- 联动:Skill回复后,提供"查看详情"按钮,点击跳转到App对应页面
🛠️ 核心实现
步骤1:什么是Skill——鸿蒙的技能系统
在深入开发之前,我们先建立对Skill的基本认知。
1.1 Skill的定义
Skill(技能) 是鸿蒙系统中,第三方应用向小艺助手提供的服务能力。简单说,Skill就是"小艺能帮你做的事情"。
比如:
- 天气Skill:“今天天气怎么样?”
- 音乐Skill:“播放一首周杰伦的歌”
- 闹钟Skill:“明天早上7点叫我起床”
- 民族图鉴Skill:“傣族的传统节日是什么?”
1.2 Skill的类型
鸿蒙的Skill分为三大类:
Skill类型
├── 官方技能
│ ├── 系统内置(打电话、发短信、设闹钟等)
│ ├── 华为自有服务(天气、音乐、视频等)
│ └── 深度集成,体验最好
├── 第三方技能
│ ├── 第三方开发者开发
│ ├── 在技能市场上架
│ └── 用户可以选择启用/禁用
└── 自定义技能
├── 用户自己创建的简单技能
├── 比如"回家模式"(开空调+开灯+放音乐)
└── 面向普通用户,不是开发者
我们作为应用开发者,主要关注第三方技能。
1.3 Skill的形态
Skill有几种不同的形态,适用于不同场景:
| 形态 | 说明 | 适用场景 | 示例 |
|---|---|---|---|
| 语音播报 | 只用语音回复 | 简单信息查询 | “傣族的人口有多少” |
| 语音+卡片 | 语音回复 + 屏幕上显示卡片 | 需要展示信息的 | 民族介绍 + 封面图 |
| 语音+跳转 | 语音回复 + 点击跳转到App | 需要深度操作的 | “查看详情” → 打开App |
| 多轮对话 | 多轮问答,逐步澄清 | 复杂需求、需要补充信息 | “我想了解一个民族” → 追问"哪个民族?" |
对于「民族图鉴」,我们会用到:
- 语音播报:简单的问答(人口、节日等)
- 语音+卡片:民族简介 + 封面图
- 语音+跳转:提供"查看详情"按钮
- 多轮对话:用户没说清楚时追问
步骤1.5:AI原生应用的完整架构
在深入Skill开发之前,我们先从更高的视角来看一下AI原生应用的整体架构。理解了这个架构,你就能明白Skill处在什么位置,以及它和Agent、模型、数据之间的关系。
四层架构模型
AI原生应用采用四层架构设计,从下到上依次是:
┌─────────────────────────────────────────────────────┐
│ Agent层(智能体层) │
│ 民族文化Agent / 学习助手Agent / 旅游规划Agent... │
│ 意图理解 · 任务规划 · 工具调用 · 多轮对话 │
├─────────────────────────────────────────────────────┤
│ Skill层(技能层) │
│ 问答Skill / 翻译Skill / 推荐Skill / 讲解Skill... │
│ 单一职责 · 可组合 · 可发现 · 可复用 │
├─────────────────────────────────────────────────────┤
│ 模型层(Model层) │
│ 端侧大模型 / 云端大模型 / 垂直领域模型 / 小模型 │
│ NLU · NLG · 多模态理解 · 推理能力 │
├─────────────────────────────────────────────────────┤
│ 数据层(Data层) │
│ 民族知识库 / 用户数据 / 对话日志 / 知识图谱 │
│ 数据采集 · 数据清洗 · 知识表示 · 数据安全 │
└─────────────────────────────────────────────────────┘
下面我们逐层讲解。
第一层:数据层(Data Layer)
数据是AI的"粮食",没有好的数据,再强的模型也没用。
数据层的核心组成:
| 组成 | 说明 | 「民族图鉴」示例 |
|---|---|---|
| 领域知识库 | 垂直领域的结构化知识 | 56个民族的百科知识、历史文化、风俗民情 |
| 用户数据 | 用户的个人数据和行为 | 收藏列表、阅读历史、学习记录、偏好标签 |
| 对话日志 | 用户与AI的对话记录 | 历史对话、用户提问、AI回复、用户反馈 |
| 知识图谱 | 实体和关系的网络结构 | 民族-节日关系、民族-服饰关系、民族-地区关系 |
| 素材库 | 图片、音频、视频等 | 民族图片、民族音乐、介绍视频 |
数据层的关键工作:
- 数据采集:从各种渠道收集数据
- 数据清洗:去重、纠错、补全、标准化
- 知识表示:把数据组织成AI能理解的形式
- 数据安全:脱敏、加密、权限控制
对「民族图鉴」的意义:
- 我们现有的56个民族数据,就是AI技能的"知识源泉"
- 数据越丰富、越准确,AI回答的质量就越高
- 后续可以不断扩充数据,让AI越来越"聪明"
第二层:模型层(Model Layer)
模型是AI的"大脑",负责理解和生成。
模型层的核心组成:
模型层
├── 端侧模型
│ ├── 轻量级大模型(On-device LLM)
│ ├── 小模型(NLU、TTS、图像识别等)
│ └── 特点:隐私好、延迟低、离线可用
├── 云端模型
│ ├── 通用大模型(如盘古大模型)
│ ├── 垂直领域微调模型
│ └── 特点:能力强、更新快
└── 模型调度
├── 端云协同(简单端侧做,复杂云端做)
├── 智能路由(根据任务选最合适的模型)
└── 模型热更新(不用发版就能更新模型)
模型层的关键能力:
- 自然语言理解(NLU):听懂用户在说什么
- 自然语言生成(NLG):生成自然的回复
- 多模态理解:理解图片、语音、文字等多种模态
- 推理能力:逻辑推理、知识推理、数学计算
对「民族图鉴」的意义:
- 简单问题(如"傣族人口多少")用端侧模型,快且保护隐私
- 复杂问题(如"比较傣族和泰国泰族的文化异同")用云端模型,效果好
- 端云协同,兼顾体验和成本
第三层:Skill层(Skill Layer)
Skill是AI的"手和脚",是具体的能力单元。我们这篇文章讲的就是这一层。
Skill层的核心特点:
- 单一职责:一个Skill只做一件事,做好一件事
- 可组合:多个Skill可以组合起来完成复杂任务
- 可发现:系统能自动发现和调用Skill
- 可复用:同一个Skill可以被多个Agent调用
Skill的分类:
| 类型 | 说明 | 「民族图鉴」示例 |
|---|---|---|
| 信息查询类 | 查询和获取信息 | 民族问答Skill、节日查询Skill |
| 内容生成类 | 生成文本、图片等 | 民族讲解Skill、推荐Skill |
| 工具操作类 | 操作设备或应用 | 打开App Skill、分享Skill |
| 服务调用类 | 调用后端服务 | 翻译Skill、知识库查询Skill |
Skill和模型的关系:
- 模型是"通用能力",Skill是"场景化能力"
- 模型负责"理解和生成",Skill负责"具体做事"
- 一个模型可以支撑很多个Skill
- Skill可以调用模型,也可以不调用(如纯逻辑的Skill)
第四层:Agent层(Agent Layer)
Agent是AI的"总指挥",负责理解用户意图、规划任务、调用工具、生成结果。
Agent和Skill的关系:
- Agent是"项目经理":理解需求、拆解任务、协调资源
- Skill是"专家":专注做好某一件具体的事
- Agent可以调用多个Skill来完成复杂任务
- 一个Skill可以被多个Agent调用
Agent的核心能力:
- 意图理解:准确理解用户想做什么
- 任务规划:把复杂任务拆解成多个步骤
- 工具调用:选择和调用合适的Skill/工具
- 结果整合:把多个工具的结果整合起来
- 多轮对话:和用户多轮交互,澄清需求
「民族图鉴」Agent示例:
假设用户说:“我下个月去云南旅游,帮我介绍一下当地的少数民族文化,再推荐几个必体验的。”
Agent的工作流程:
用户需求:云南旅游 + 少数民族文化介绍 + 体验推荐
│
▼
意图理解:用户要去云南旅游,想了解当地少数民族
│
▼
任务规划:
1. 查询云南主要的少数民族(调用民族查询Skill)
2. 介绍这些民族的文化特色(调用民族讲解Skill)
3. 推荐可体验的文化活动(调用推荐Skill)
4. 整理成旅游攻略形式(调用内容生成Skill)
│
▼
工具调用 → 依次调用各个Skill
│
▼
结果整合 → 把各Skill的结果整合成一篇完整的攻略
│
▼
用户反馈 → 根据用户反馈调整
四层架构的协同工作
这四层不是孤立的,而是协同工作的:
用户提问:"傣族的泼水节是怎么来的?"
│
├───────────────────────────────────────────┐
│ ▼
│ Agent层:理解意图,规划任务 │
│ 意图:查询民族节日起源 │
│ 规划:调用问答Skill查询 │
│ │
├───────────────────────────────────────────┤
│ ▼
│ Skill层:执行具体任务 │
│ 问答Skill处理节日查询请求 │
│ │
├───────────────────────────────────────────┤
│ ▼
│ 模型层:理解和生成 │
│ NLU理解问题语义 │
│ NLG生成自然回答 │
│ │
├───────────────────────────────────────────┤
│ ▼
└─────── 数据层:提供知识素材 │
从民族知识库中查找傣族节日数据 │
返回结构化的节日信息 │
可以这样理解:
- 数据层是"知识库":AI的知识来源
- 模型层是"大脑":负责思考和理解
- Skill层是"手脚":负责具体做事
- Agent层是"指挥":负责协调和决策
四层协同,构成了完整的AI原生应用体系。
步骤2:Skill开发流程
开发一个Skill,大致分为四个阶段:注册 → 开发 → 测试 → 上架。
Skill开发流程
├── 1. 注册
│ ├── 注册华为开发者账号
│ ├── 登录技能开发平台
│ ├── 创建技能,填写基本信息
│ └── 配置技能的基本属性
├── 2. 开发
│ ├── 定义意图(Intent)
│ ├── 定义槽位(Slot)
│ ├── 设计对话流
│ ├── 开发后端服务( fulfillment )
│ └── 配置语音交互模型
├── 3. 测试
│ ├── 在线测试(平台模拟器)
│ ├── 真机测试(小艺助手)
│ ├── 功能测试(所有意图都能正确触发)
│ └── 体验测试(对话是否自然流畅)
└── 4. 上架
├── 提交审核
├── 审核通过
├── 上架技能市场
└── 用户可以启用
下面我们逐一讲解每个阶段的要点。
2.1 注册阶段
1. 注册华为开发者账号
- 访问华为开发者联盟官网
- 注册企业开发者账号(个人也可以,但企业权限更多)
- 完成实名认证
2. 创建技能
- 登录小艺技能开放平台
- 点击"创建技能"
- 填写技能名称、调用名、技能简介
- 选择技能分类(如:工具、教育、生活服务等)
3. 技能的基本属性
| 属性 | 说明 | 注意事项 |
|---|---|---|
| 技能名称 | 技能的显示名称 | 简洁明了,不超过10个字 |
| 调用名 | 用户用语音唤起技能的词 | 容易发音、不容易混淆 |
| 技能简介 | 一句话描述技能能做什么 | 清晰说明技能价值 |
| 详细描述 | 详细介绍技能功能 | 列出主要功能和使用示例 |
| 图标 | 技能的图标 | 符合设计规范 |
「民族图鉴」技能的基本信息示例:
- 技能名称:民族图鉴
- 调用名:民族图鉴
- 技能简介:查询中国56个民族的文化知识
- 分类:教育 / 文化
2.2 开发阶段
这是最核心的阶段,我们后面会详细讲。核心工作:
- 定义用户可能会说的话(意图)
- 定义需要抽取的信息(槽位)
- 设计对话流程
- 开发后端服务来处理请求
2.3 测试阶段
开发完成后,需要充分测试:
1. 在线测试
- 平台提供的测试工具
- 输入文字,看能否正确识别意图和槽位
- 看回复是否正确
2. 真机测试
- 在手机上用小艺助手测试
- 用真实语音测试,看识别效果
- 测试不同的说法、不同的口音
3. 测试要点
- 每个意图都要覆盖到
- 测试边界情况(用户说的话不在预期内)
- 测试多轮对话的连贯性
- 测试错误处理(服务异常时的兜底回复)
2.4 上架阶段
测试通过后,就可以提交审核了:
1. 提交审核
- 填写审核信息
- 上传测试说明(告诉审核员怎么测)
- 提交审核
2. 审核周期
- 通常几个工作日
- 如果被驳回,根据反馈修改后重新提交
3. 上架后
- 用户可以在技能市场找到你的技能
- 可以查看使用数据(调用次数、用户数等)
- 持续优化迭代
步骤3:语音交互的核心概念
要开发Skill,必须理解几个核心概念:意图(Intent)、槽位(Slot)、对话流(Dialog Flow)。
这些是语音交互的基石,理解了它们,你就理解了语音交互的本质。
3.1 意图(Intent)
意图就是"用户想做什么"。每一种用户需求对应一个意图。
比如用户说:
- “傣族的传统节日是什么?” → 意图:查询民族节日
- “藏族的人口有多少?” → 意图:查询民族人口
- “今天推荐哪个民族?” → 意图:今日民族推荐
意图的组成:
意图(Intent)
├── 意图名称:唯一标识,如 query_ethnic_festival
├── 用户说法(Utterance):
│ ├── "傣族的传统节日是什么?"
│ ├── "藏族有什么节日?"
│ ├── "苗族过什么节?"
│ └── (越多越好,覆盖各种说法)
└── 槽位(Slot):需要从用户话里抽取的信息
└── 民族名称:傣族 / 藏族 / 苗族
设计意图的原则:
-
一个意图对应一个用户目标
- 不要把多个不同的目标混在一个意图里
- 比如"查询节日"和"查询人口"是两个意图,不要合并
-
意图粒度要适中
- 太粗:一个意图处理太多情况,逻辑复杂
- 太细:意图太多,维护困难
- 经验:按"用户要做什么事"来划分
-
用户说法要足够多
- 每个意图至少准备10~20条用户说法
- 覆盖不同的表达方式:书面语、口语、简略说法
- 覆盖不同的提问方式:疑问句、陈述句、祈使句
「民族图鉴」的意图设计:
| 意图名称 | 说明 | 用户说法示例 |
|---|---|---|
query_ethnic_info |
查询民族基本信息 | “介绍一下傣族”、“我想了解藏族” |
query_ethnic_population |
查询民族人口 | “壮族有多少人”、“回族人口是多少” |
query_ethnic_festival |
查询民族节日 | “傣族有什么传统节日”、“苗族的节日” |
query_ethnic_custom |
查询民族习俗 | “蒙古族有什么风俗习惯” |
daily_recommendation |
今日民族推荐 | “今天推荐哪个民族”、“每日推荐” |
ethnic_quiz |
知识问答 | “考考我民族知识” |
open_app_page |
打开App页面 | “打开民族图鉴的傣族页面” |
3.2 槽位(Slot)
槽位就是"需要从用户话里抽取的关键信息"。
比如用户说"傣族的传统节日是什么?",我们需要抽取的信息是:
- 民族名称:傣族
这个"民族名称"就是一个槽位。
槽位的类型:
| 类型 | 说明 | 示例 |
|---|---|---|
| 系统槽位 | 平台内置的通用槽位 | 时间、地点、数字、人名等 |
| 自定义槽位 | 开发者自己定义的 | 民族名称、节日名称等 |
槽位的属性:
| 属性 | 说明 | 示例 |
|---|---|---|
| 槽位名称 | 唯一标识 | ethnic_name |
| 槽位类型 | 系统/自定义 | 自定义槽位:民族名称 |
| 是否必填 | 用户必须提供吗 | 是(查询哪个民族的信息,必须知道民族名) |
| 追问话术 | 用户没说时怎么问 | “你想了解哪个民族呢?” |
| 槽位值列表 | 可能的取值列表 | 汉族、壮族、回族、苗族、维吾尔族…… |
「民族图鉴」的槽位设计:
| 槽位名称 | 类型 | 是否必填 | 追问话术 | 槽位值示例 |
|---|---|---|---|---|
ethnic_name |
自定义 | 是 | “你想了解哪个民族呢?” | 汉族、壮族、回族、藏族、苗族…… |
info_type |
自定义 | 否 | - | 节日、习俗、人口、饮食、服饰…… |
quiz_category |
自定义 | 否 | - | 历史、文化、习俗、节日…… |
槽位填充的两种方式:
-
用户直接说出
- 用户:“傣族的传统节日是什么?”
- 槽位
ethnic_name= “傣族”(从用户话里直接抽取)
-
系统追问获取
- 用户:“传统节日有哪些?”
- 系统:“你想了解哪个民族的传统节日呢?”(追问)
- 用户:“傣族的”
- 槽位
ethnic_name= “傣族”(通过追问获取)
这就是多轮对话的基本原理——当必要的槽位没填时,系统会主动追问。
3.3 对话流(Dialog Flow)
对话流就是"用户和系统对话的流程"。简单的单轮问答不需要对话流,但复杂的多轮对话就需要设计。
单轮对话 vs 多轮对话:
| 类型 | 说明 | 示例 |
|---|---|---|
| 单轮对话 | 一问一答,一次交互完成 | 用户:“傣族的人口有多少?” → 系统回答 |
| 多轮对话 | 多轮交互,逐步澄清需求 | 用户:“我想了解一个民族” → 系统:“哪个民族?” → 用户:“傣族” → 系统回答 |
多轮对话的触发场景:
-
槽位缺失:必要的信息用户没说,需要追问
- 用户:“查一下节日” → 缺"民族名称" → 追问"哪个民族的节日?"
-
确认信息:重要操作前需要用户确认
- 用户:“清空收藏” → 确认"确定要清空所有收藏吗?"
-
选项澄清:用户需求模糊,需要用户选择
- 用户:“我想了解傣族” → “你想了解傣族的哪方面?节日/习俗/饮食/服饰?”
对话流设计的原则:
-
最少轮次原则:尽量用最少的对话轮次满足需求
- 能一轮解决的,不要用两轮
- 追问太多,用户会不耐烦
-
自然流畅原则:对话要像人与人聊天,不要太机械
- 追问话术要自然
- 可以有一些"语气词",不要太生硬
-
容错原则:用户说的话可能不在预期内,要能优雅处理
- 没听懂时,换个方式问
- 连续听不懂时,给出选项
- 实在不行,引导用户打开App操作
步骤4:「民族图鉴」Skill设计
讲完了理论,我们来实际设计「民族图鉴」的Skill。
4.1 技能定位
首先明确技能的定位:
- 定位:民族文化知识查询助手
- 目标用户:对民族文化感兴趣的用户
- 核心价值:快速查询56个民族的文化知识
- 与App的关系:Skill做轻量查询,App做深度体验
4.2 意图设计
我们设计8个核心意图:
民族图鉴Skill意图设计
├── 1. 查询民族基本信息(query_ethnic_info)
│ ├── 说法:"介绍一下傣族"、"我想了解藏族"、"回族是什么样的民族"
│ ├── 槽位:ethnic_name(必填)
│ └── 回复:语音播报简介 + 显示卡片 + "查看详情"按钮
│
├── 2. 查询民族人口(query_ethnic_population)
│ ├── 说法:"壮族有多少人口"、"苗族有多少人"
│ ├── 槽位:ethnic_name(必填)
│ └── 回复:语音播报人口数据
│
├── 3. 查询民族节日(query_ethnic_festival)
│ ├── 说法:"傣族有什么传统节日"、"藏族的节日"
│ ├── 槽位:ethnic_name(必填)
│ └── 回复:语音播报主要节日 + 简单介绍
│
├── 4. 查询民族习俗(query_ethnic_custom)
│ ├── 说法:"蒙古族有什么风俗习惯"、"彝族的习俗"
│ ├── 槽位:ethnic_name(必填)
│ └── 回复:语音播报主要习俗
│
├── 5. 今日民族推荐(daily_recommendation)
│ ├── 说法:"今天推荐哪个民族"、"今日民族"、"每天一个民族"
│ ├── 槽位:无
│ └── 回复:推荐一个民族 + 简介 + "查看详情"按钮
│
├── 6. 知识问答(ethnic_quiz)
│ ├── 说法:"考我一个民族知识题"、"民族知识问答"
│ ├── 槽位:quiz_category(可选)
│ └── 回复:出题 + 用户回答后判断对错
│
├── 7. 打开App页面(open_app_page)
│ ├── 说法:"打开民族图鉴看傣族"、"在民族图鉴里搜索藏族"
│ ├── 槽位:ethnic_name(必填)
│ └── 回复:"好的,正在为你打开" → 跳转到App对应页面
│
└── 8. 帮助(help)
├── 说法:"你能做什么"、"帮助"、"怎么用"
├── 槽位:无
└── 回复:介绍技能功能,给出示例说法
4.3 槽位设计
自定义槽位:民族名称(ethnic_name)
槽位值:56个民族的名称,以及常见的别名/简称。
| 槽位值 | 别名/同义词 |
|---|---|
| 汉族 | 汉人、华夏族 |
| 壮族 | 壮族 |
| 回族 | 回民、回族 |
| 苗族 | 苗族 |
| 维吾尔族 | 维吾尔、维族 |
| 藏族 | 藏、藏族 |
| …… | …… |
自定义槽位:信息类型(info_type)
| 槽位值 | 同义词 |
|---|---|
| 节日 | 传统节日、节日有哪些 |
| 习俗 | 风俗习惯、习俗是什么 |
| 人口 | 人口数量、有多少人 |
| 饮食 | 吃什么、特色美食 |
| 服饰 | 穿什么、传统服装 |
| 建筑 | 住什么、传统民居 |
4.4 对话流设计
我们以"查询民族信息"为例,设计对话流:
用户发起查询
│
├─► 用户说了民族名称?
│ ├─ 是 ──► 直接回答
│ └─ 否 ──► 追问:"你想了解哪个民族呢?"
│ │
│ └─► 用户回答民族名 ──► 回答
│
└─► 用户指定了信息类型?
├─ 是 ──► 回答该类型的信息
└─ 否 ──► 回答基本简介 + 询问"还想了解哪方面?"
示例对话1(完整信息,单轮):
用户:“傣族的传统节日是什么?”
系统:“傣族的传统节日有泼水节、关门节、开门节等。其中最著名的是泼水节,一般在公历4月中旬举行,人们通过泼水来祈福。”
示例对话2(缺民族,多轮):
用户:“传统节日有哪些?”
系统:“你想了解哪个民族的传统节日呢?”
用户:“傣族的”
系统:“傣族的传统节日有泼水节、关门节、开门节等……”
示例对话3(模糊查询,多轮澄清):
用户:“我想了解一个少数民族”
系统:“中国有55个少数民族,你想了解哪一个呢?可以告诉我民族名称,或者我给你推荐一个?”
用户:“你推荐一个吧”
系统:“好的,今天给你推荐傣族……”
步骤5:Skill与App的联动
Skill不是孤立的,它应该和App形成联动。Skill做轻量入口,App做深度体验。
5.1 联动的方式
Skill和App的联动主要有几种方式:
| 联动方式 | 说明 | 适用场景 |
|---|---|---|
| deeplink跳转 | Skill回复中带链接,点击跳转到App指定页面 | 查看详情、深度操作 |
| 语音打开App | 用户语音指令直接打开App | “打开民族图鉴” |
| 语音操作App | App内集成语音,用语音操作App内部功能 | App内的语音控制 |
| 数据互通 | Skill和App共享用户数据 | 收藏、历史记录同步 |
5.2 deeplink跳转实现
deeplink是最常用的联动方式。
原理:
- App配置deeplink scheme,如
ethnicbook:// - Skill的回复卡片中携带deeplink链接,如
ethnicbook://detail?ethnic=dai - 用户点击卡片,系统根据deeplink打开App的指定页面
App端配置deeplink:
在 module.json5 中配置:
{
"module": {
"abilities": [
{
"name": "EntryAbility",
"skills": [
{
"entities": ["entity.system.home"],
"actions": ["action.system.home"]
},
{
"entities": ["entity.system.browsable"],
"actions": ["action.system.view"],
"uris": [
{
"scheme": "ethnicbook",
"host": "detail",
"path": ""
}
]
}
]
}
]
}
}
App端接收deeplink参数:
在Ability中接收参数并跳转:
// EntryAbility.ets
import AbilityConstant from '@ohos.app.ability.AbilityConstant';
import UIAbility from '@ohos.app.ability.UIAbility';
import Want from '@ohos.app.ability.Want';
export default class EntryAbility extends UIAbility {
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
// 检查是否是deeplink唤起
if (want.uri) {
this.handleDeepLink(want.uri);
}
}
private handleDeepLink(uri: string): void {
// 解析uri,如 ethnicbook://detail?ethnic=dai
const url = new URL(uri);
const path = url.pathname;
const params = url.searchParams;
if (path === '/detail' || path === 'detail') {
const ethnicName = params.get('ethnic');
if (ethnicName) {
// 保存参数,等页面加载后跳转
AppStorage.setOrCreate('deepLinkEthnic', ethnicName);
}
}
}
}
首页检查deeplink并跳转:
// Index.ets
@Entry
@Component
struct Index {
@StorageLink('deepLinkEthnic') deepLinkEthnic: string = '';
aboutToAppear(): void {
if (this.deepLinkEthnic) {
// 跳转到对应民族详情页
this.navigateToDetail(this.deepLinkEthnic);
// 清空,避免重复跳转
AppStorage.setOrCreate('deepLinkEthnic', '');
}
}
}
5.3 语音打开App
用户可以直接说"打开民族图鉴"来启动App。这个是系统默认支持的,只要App安装了就能用。
但如果想让语音指令更丰富,比如:
- “打开民族图鉴看傣族” → 直接跳转到傣族详情页
- “打开民族图鉴的音乐页面” → 直接跳转到音乐页
就需要配置deeplink + Skill意图来实现。
5.4 App内集成语音
除了通过小艺助手使用Skill,还可以在App内部集成语音交互能力。这样用户在App内也能用语音操作。
App内集成语音的场景:
- 搜索页面:语音搜索民族
- 详情页面:语音播报介绍
- 问答页面:语音提问
实现方式:
- 使用HarmonyOS的语音识别API(ASR)
- 使用TTS API做语音合成
- 可以接入小艺的语音能力,也可以用第三方SDK
对于「民族图鉴」,我们已经有了TTS语音播报功能(第22篇)。后续可以增加语音搜索功能——用户点击搜索框的麦克风按钮,说话就能搜索民族。
步骤5.5:Skill技能的设计原则与开发规范
在开始动手开发之前,我们需要先明确Skill的设计原则和开发规范。好的设计是成功的一半。
设计原则
原则1:单一职责原则(Single Responsibility)
一个Skill只做一件事,把这件事做好。
- ❌ 不好:一个Skill既做问答,又做翻译,还做推荐
- ✅ 好:问答Skill专注问答,翻译Skill专注翻译,推荐Skill专注推荐
为什么?
- 职责单一,更容易理解和维护
- 更容易被系统发现和调用
- 可以灵活组合,完成复杂任务
- 出问题时更容易定位和修复
原则2:可组合原则(Composable)
Skill要设计成可以组合使用的"积木块"。
可组合的设计要点:
- 输入输出标准化:统一的接口格式,方便互相调用
- 无状态或状态可控:不依赖外部状态,或者状态可以传入
- 粒度适中:太大不好组合,太小组合成本高
- 错误处理完善:失败了能优雅降级,不影响整体
「民族图鉴」的Skill组合示例:
用户:"用傣语说一句泼水节快乐,再翻译给我听"
│
├─ 第一步:翻译Skill(中文 → 傣语)
├─ 第二步:TTS Skill(文字 → 语音播报)
└─ 第三步:讲解Skill(解释泼水节的含义)
原则3:用户价值优先(User Value First)
做Skill不是为了"炫技",而是为了给用户创造价值。
判断一个Skill值不值得做的三个问题:
- 用户真的需要这个功能吗?(需求真实吗?)
- 用语音/AI方式做,比传统方式更好吗?(体验提升了吗?)
- 成本和收益成正比吗?(ROI合理吗?)
「民族图鉴」的Skill优先级判断:
- ✅ 民族问答:需求真实,语音方式更便捷,ROI高 → 优先做
- ⚠️ 民族翻译:需求有,但使用频率可能不高 → 其次做
- ❌ 民族服饰3D试穿:听起来酷,但技术难度大、使用场景少 → 暂缓
原则4:渐进式增强(Progressive Enhancement)
从简单的开始,逐步增强能力,不要追求一步到位。
渐进式路线:
- MVP版本:只做最核心的1~2个功能
- 迭代优化:根据用户反馈,逐步增加功能
- 能力扩展:从单轮对话到多轮对话,从语音到多模态
- 智能化升级:从规则匹配到模型驱动
「民族图鉴」的Skill演进路线:
- V1.0:固定问答(FAQ),只能问预设的问题
- V2.0:单轮对话,支持槽位填充和追问
- V3.0:多轮对话,支持上下文理解
- V4.0:Agent化,能理解复杂需求、调用多个Skill
开发规范
规范1:命名规范
| 类型 | 命名规则 | 示例 |
|---|---|---|
| Skill名称 | 产品名 + 功能 + Skill | 民族图鉴问答Skill |
| 意图名称 | 动词_名词 | query_ethnic_info |
| 槽位名称 | 名词_属性 | ethnic_name |
| 调用名 | 简短、易发音 | 民族图鉴 |
规范2:话术规范
- 语音回复控制在30秒以内
- 口语化,避免书面语和专业术语
- 重要信息放在前面
- 结尾可以引导用户下一步操作
规范3:错误处理规范
- 必须有兜底回复,不能让用户听到"错误"、"异常"之类的话
- 听不懂时,先换个方式问,再引导到App
- 服务异常时,礼貌告知"稍后再试"
规范4:安全与隐私规范
- 不收集不必要的用户数据
- 敏感数据必须脱敏处理
- 对话日志加密存储
- 遵守相关法律法规
步骤5.7:Agent智能体的工作原理
前面我们多次提到Agent,现在来深入了解一下Agent的工作原理。理解了Agent,你就能理解AI原生应用的未来方向。
Agent是什么?
Agent(智能体) 是一个具有自主决策能力的智能实体,它能理解用户意图、规划任务、调用工具、并最终完成用户交给它的任务。
Agent vs 传统App vs Skill:
| 维度 | 传统App | Skill | Agent |
|---|---|---|---|
| 交互方式 | 触控操作 | 语音问答 | 自然语言对话 |
| 主动性 | 被动等待用户操作 | 被动响应提问 | 主动提供服务 |
| 任务复杂度 | 简单、固定 | 单一任务 | 复杂、多变 |
| 学习能力 | 没有 | 弱 | 强,能持续学习 |
| 扩展性 | 需要发版 | 需要配置 | 可以自主学习新技能 |
简单理解:
- App:工具,你用它做事
- Skill:技能,它帮你做一件事
- Agent:助手,它理解你的需求,帮你把事情做好
Agent的工作流程
Agent的工作流程可以概括为四步循环:
┌─────────────────────────────────────────────────┐
│ │
│ ① 意图识别 ──► ② 任务规划 ──► ③ 工具调用 │
│ ▲ │
│ │ │
│ └────────── ④ 结果生成 ◄─────────┘ │
│ │
│ ↕ 反馈循环 │
│ 用户反馈 │
└─────────────────────────────────────────────────┘
下面我们详细讲解每一步。
第一步:意图识别(Intent Recognition)
目标:理解用户到底想做什么。
输入:用户的自然语言(语音、文字、图片等)
输出:结构化的意图 + 关键信息(槽位)
意图识别的过程:
- 预处理:语音转文字、纠错、标准化
- 分类:判断属于哪个意图类别
- 槽位填充:抽取关键信息
- 置信度评估:判断识别结果有多靠谱
示例:
用户说:“我想了解一下傣族的传统节日”
- 意图:查询民族节日(query_ethnic_festival)
- 槽位:ethnic_name = “傣族”
- 置信度:0.95(很有把握)
第二步:任务规划(Task Planning)
目标:把用户的需求拆解成可执行的步骤。
什么时候需要规划?
- 简单任务:不需要规划,直接调用对应的Skill
- 复杂任务:需要拆解成多个步骤,依次执行
规划的方法:
- 基于规则的规划:预定义好的流程,适合固定场景
- 基于模型的规划:大模型自己规划,适合复杂场景
- 混合模式:简单的用规则,复杂的用模型
「民族图鉴」Agent规划示例:
用户需求:“我要做一个关于傣族文化的PPT,帮我收集一下资料”
Agent的规划:
任务:收集傣族文化资料,用于PPT
│
├─ 步骤1:收集傣族基本信息(调用:民族问答Skill)
├─ 步骤2:收集傣族节日资料(调用:节日查询Skill)
├─ 步骤3:收集傣族服饰资料(调用:服饰查询Skill)
├─ 步骤4:收集傣族美食资料(调用:美食查询Skill)
├─ 步骤5:查找相关图片(调用:图片搜索Skill)
└─ 步骤6:整理成PPT大纲格式(调用:内容生成Skill)
第三步:工具调用(Tool Use)
目标:调用合适的工具/Skill,执行具体的任务。
工具调用的关键问题:
- 选哪个工具?:根据任务选择最合适的Skill
- 怎么传参数?:把槽位和上下文整理成工具需要的格式
- 失败了怎么办?:重试?换个工具?告诉用户?
- 结果怎么处理?:直接返回?还是再加工一下?
工具调用的过程:
选择工具 → 准备参数 → 调用工具 → 处理结果 → 判断是否需要更多工具
↑ │
└──────────────── 循环直到任务完成 ───────────────────┘
「民族图鉴」工具调用示例:
任务:查询傣族的节日
│
├─ 选择工具:节日查询Skill
├─ 传入参数:ethnic_name = "傣族"
├─ 调用Skill,获取结果
├─ 结果处理:整理成自然语言
└─ 判断:信息足够了,不需要再调用其他工具
第四步:结果生成(Result Generation)
目标:把工具返回的结果,整理成用户能理解的自然语言。
结果生成的原则:
- 准确:信息要准确,不能出错
- 简洁:不要太啰嗦,重点突出
- 自然:像人说话一样,不要太机械
- 有用:给出的信息对用户有价值
- 引导:可以引导用户下一步操作
不好的回复 vs 好的回复:
| 不好的回复 | 好的回复 |
|---|---|
| “查询结果:傣族节日有泼水节、关门节、开门节。” | “傣族的传统节日可多啦~ 最有名的是泼水节,每年4月中旬举行,大家通过泼水来祈福。还有关门节、开门节等佛教节日。想了解哪个节日的详细介绍吗?” |
Agent的记忆系统
要让Agent"聪明",它需要有记忆。记不住之前说过什么,就没法进行连贯的多轮对话。
记忆的三个层次:
| 层次 | 说明 | 作用 | 「民族图鉴」示例 |
|---|---|---|---|
| 短期记忆 | 当前对话的上下文 | 多轮对话理解 | 上一轮聊的是傣族,这一轮说"他们的节日"能理解是傣族的节日 |
| 中期记忆 | 用户的偏好和习惯 | 个性化推荐 | 用户经常看西南地区的民族,就多推荐相关内容 |
| 长期记忆 | 用户的历史数据 | 持续学习和优化 | 用户的收藏、学习记录、历史对话 |
记忆管理的要点:
- 记忆不是越多越好:有用的才记,没用的忘了也没关系
- 记忆有时效性:太久远的记忆优先级降低
- 记忆可更新:用户的偏好会变,记忆也要跟着更新
- 记忆要安全:用户的隐私数据要保护好
步骤5.8:多模态交互
语音只是AI交互的一种方式。真正的AI原生应用,应该支持多模态交互——语音、文字、图像、手势,用户想用哪种就用哪种。
什么是多模态交互?
模态(Modality) 就是信息的传递方式。多模态,就是多种信息传递方式一起用。
常见的交互模态:
| 模态 | 说明 | 输入/输出 | 「民族图鉴」场景 |
|---|---|---|---|
| 语音 | 说话和听 | 输入+输出 | 语音提问、语音播报 |
| 文字 | 打字和阅读 | 输入+输出 | 文字搜索、文字介绍 |
| 图像 | 拍照和看图 | 输入+输出 | 拍照识服饰、图片展示 |
| 手势 | 手势操作 | 输入 | 手势翻页、手势控制 |
| 视频 | 视频通话/录制 | 输入+输出 | 视频讲解、AR体验 |
多模态的核心思想:
- 用户选择:用户想用什么方式就用什么方式
- 场景适配:不同场景用最合适的模态
- 无缝切换:各种模态之间可以无缝切换
- 互相补充:一种模态说不清楚的,用另一种补充
多模态交互的应用场景
场景1:早上起床,眼睛还睁不开
- 语音交互最方便:“小艺,今天推荐哪个民族?”
- 不用看手机,听就行了
场景2:在公交车上,太吵了听不清
- 文字交互更合适:打开App,文字搜索
- 或者看卡片展示的内容
场景3:看到一件漂亮的民族服饰,想知道是哪个民族的
- 图像交互最直接:拍张照,AI识别
- 比打字描述方便多了
场景4:做饭,手上沾着面
- 语音+手势:语音提问,手势翻页
- 不用碰手机
「民族图鉴」的多模态设计
输入侧(用户→AI):
| 模态 | 功能 | 实现方式 |
|---|---|---|
| 语音 | 语音提问、语音搜索 | 小艺Skill + App内语音识别 |
| 文字 | 文字搜索、文字对话 | 搜索框 + 聊天页面 |
| 图像 | 拍照识别民族服饰 | 调用视觉AI能力 |
| 扫码 | 扫码看民族介绍 | 扫描民族文化卡片上的二维码 |
输出侧(AI→用户):
| 模态 | 功能 | 实现方式 |
|---|---|---|
| 语音 | 语音播报、语音回答 | TTS语音合成 |
| 文字 | 文字介绍、文字回答 | 文本展示 |
| 图片 | 民族图片、文物图片 | 图片展示 + 图片超分 |
| 音频 | 民族音乐、歌曲 | 音乐播放器 |
| 视频 | 民族纪录片、介绍视频 | 视频播放器 |
多模态协同的例子:
用户用语音问:“傣族的泼水节是什么样的?”
- 语音输出:“泼水节是傣族最隆重的节日,一般在4月中旬举行……”
- 文字输出:同步显示文字介绍
- 图片输出:展示泼水节的精美图片
- 视频输出:如果有相关视频,也可以推荐
用户用图片问:“这件衣服是哪个民族的?”(拍照上传)
- 图像识别:识别出是苗族服饰
- 语音输出:“这是苗族的传统服饰哦~ 苗族服饰非常精美,以银饰和刺绣闻名……”
- 文字+图片:展示更多苗族服饰的图片和介绍
步骤5.9:对话管理与上下文理解
多轮对话是AI交互的高级形式。要让对话自然流畅,对话管理和上下文理解是关键。
什么是对话管理?
对话管理(Dialog Management) 就是控制对话流程的技术——决定什么时候说什么、什么时候追问、什么时候结束。
对话管理的核心任务:
- 状态跟踪:记住对话进行到哪一步了
- 行为决策:决定下一步该做什么(回答?追问?确认?)
- 错误恢复:用户说的话听不懂时,怎么拉回来
- 策略优化:怎么说用户体验最好
上下文理解的难点
上下文理解说起来简单,做起来难。难在哪呢?
难点1:指代消解
“它”、“他”、“她”、“这个”、“那个”、“他们”……这些指代词,人很容易理解,但AI不一定。
示例:
用户:“介绍一下傣族”
AI:“傣族是中国的少数民族之一……”
用户:“他们的传统节日有哪些?”
👉 难点:"他们"指谁?—— 傣族
难点2:省略理解
人说话经常会省略,AI要能"脑补"出省略的部分。
示例:
用户:“藏族的人口有多少?”
AI:“藏族约有706万人……”
用户:“蒙古族呢?”
👉 难点:“蒙古族呢?” = “蒙古族的人口有多少呢?”
难点3:话题切换
用户可能聊着聊着就换话题了,AI要能跟上。
示例:
用户:“傣族的泼水节是什么时候?”
AI:“一般在公历4月中旬……”
用户:“对了,蒙古族的那达慕大会呢?”
👉 难点:用户从傣族跳到蒙古族了,要能跟上
上下文理解的实现方法
方法1:基于规则的方法
人工定义各种规则,比如:
- 如果用户说"他/她/它/他们",就指代上一轮提到的实体
- 如果用户说"XX呢?",就用上一轮的问题模板替换实体
- 如果用户说"对了/话说回来",可能是要换话题
优点:简单、可控、准确
缺点:不够灵活,覆盖不了所有情况
方法2:基于模型的方法
用大模型来理解上下文,把整个对话历史都传给模型,让模型自己判断。
优点:灵活、智能、覆盖广
缺点:有时候会"脑补"错,不够可控,成本高
方法3:混合方法(推荐)
简单的用规则,复杂的用模型,两者结合。
- 规则处理常见情况,保证准确性
- 模型处理复杂情况,保证灵活性
- 规则兜底,模型增强
对话管理的最佳实践
实践1:设定清晰的对话目标
每一段对话都要有明确的目标,不要东拉西扯。
- 目标明确:用户想查傣族的节日 → 查到就结束
- 目标模糊:用户说"随便聊聊" → 引导到具体功能
实践2:控制对话长度
能一轮解决的,不要用两轮;能三轮解决的,不要用五轮。
- 对话太长,用户会不耐烦
- 每多一轮,用户流失率就增加一分
实践3:给出明确的引导
用户不知道该说什么的时候,给点提示。
- “你可以问我节日、习俗、人口等问题哦~”
- “想了解哪个民族?傣族、藏族、还是蒙古族?”
实践4:优雅地处理失败
听不懂的时候,不要说"我听不懂",要说:
- “抱歉,我没太听清,能再说一遍吗?”
- “你可以试试问XX、XX或XX”
- “这个问题我暂时回答不了,你可以打开App查看更多内容”
步骤6:多轮对话设计
多轮对话是提升语音交互体验的关键。设计好多轮对话,能让用户感觉"这个助手很聪明"。
6.1 上下文理解
多轮对话的核心是上下文理解——系统要记得之前的对话内容。
示例:
用户:“傣族的传统节日是什么?”
系统:“傣族的传统节日有泼水节、关门节、开门节……”
用户:“那他们的习俗呢?” → 这里的"他们"指傣族,系统要能理解
系统:“傣族的主要习俗有……”
上下文管理的要点:
- 记住关键槽位:上一轮提到的民族名称,下一轮可以继续用
- 支持指代消解:"他/她/它/这个/那个/他们"等指代,要能正确理解
- 支持省略说法:“那习俗呢?” = “那傣族的习俗呢?”
- 上下文有有效期:太久远的上下文就不要了,避免混淆
6.2 追问澄清的艺术
追问是门艺术——问得好,用户觉得贴心;问得不好,用户觉得麻烦。
追问设计的原则:
-
能不问就不问
- 能从上下文推断的,就不要问
- 能给默认值的,就不要问
- 能猜的,先猜,猜错了再纠正
-
一次只问一个问题
- 不要同时问多个问题,用户记不住
- “你想了解哪个民族的哪方面信息?” → 不好,两个问题
- 先问"你想了解哪个民族?“,再问"你想了解哪方面?” → 好,分步来
-
给出选项
- 开放式问题用户不知道怎么答
- 给出选项,用户更容易回答
- “你想了解哪个民族?傣族、藏族、还是其他?” → 比开放式好
-
追问话术要自然
- 不要太机械、太生硬
- 可以有一些变化,不要每次都一模一样
不好的追问 vs 好的追问:
| 不好的追问 | 好的追问 |
|---|---|
| “请输入民族名称” | “你想了解哪个民族呢?” |
| “参数缺失:ethnic_name” | “我没听清是哪个民族,能再说一遍吗?” |
| “你想了解什么信息?” | “你想了解这个民族的哪方面?节日、习俗、还是饮食?” |
6.3 错误处理与兜底
用户不会总是按照我们设计的来说话。当系统听不懂的时候,怎么处理?
错误处理的层级:
用户说话
│
├─► 能匹配到意图?
│ ├─ 是 ──► 正常处理
│ └─ 否 ──► 尝试模糊匹配
│ │
│ ├─ 模糊匹配成功?
│ │ ├─ 是 ──► 确认:"你是想了解XX吗?"
│ │ └─ 否 ──► 换个方式问
│ │
│ └─ 还是不懂?
│ ├─ 第一次:"没太听懂,能换个说法吗?"
│ ├─ 第二次:"你可以试试问XX、XX或XX"
│ └─ 第三次:"抱歉,这个我还不太会。你可以打开App查看更多内容。"
│
└─► 服务异常?
└─ 是 ──► "抱歉,服务暂时不可用,请稍后再试。"
兜底策略:
- 引导到App:Skill处理不了的,引导用户打开App
- 给出示例:告诉用户可以问什么
- 保持礼貌:即使听不懂,也要友好
- 不要死循环:连续几次听不懂,就不要追问了
步骤7:实战——接入小艺技能
讲了这么多理论,我们来看看实际怎么开发。由于Skill开发主要是在华为的技能开发平台上操作(拖拽式配置 + 后端服务),我们重点讲思路和架构。
7.1 技术架构
「民族图鉴」Skill的技术架构:
用户 → 小艺助手 → 技能平台 → 我们的后端服务
│
├─ 意图处理逻辑
├─ 民族数据查询
├─ 回复内容生成
└─ 返回给技能平台
两种开发模式:
| 模式 | 说明 | 适用场景 |
|---|---|---|
| 问答式(FAQ) | 平台内置的问答功能,配置问题和答案 | 简单的固定问答 |
| 自定义服务 | 自己开发后端服务,处理请求并返回回复 | 复杂的逻辑、动态数据 |
对于「民族图鉴」,因为有56个民族的数据,而且回复内容需要动态生成,所以应该用自定义服务模式。
7.2 后端服务开发
后端服务的核心工作:
- 接收技能平台的请求(JSON格式)
- 解析意图和槽位
- 查询民族数据
- 生成回复内容(语音文本 + 卡片信息)
- 返回给技能平台
请求示例(简化版):
{
"intent": "query_ethnic_festival",
"slots": {
"ethnic_name": {
"value": "傣族",
"confidence": 0.95
}
},
"session_id": "xxx",
"request_id": "yyy"
}
回复示例(简化版):
{
"reply": "傣族的传统节日有泼水节、关门节、开门节等。其中最著名的是泼水节,一般在公历4月中旬举行,人们通过泼水来祈福。",
"card": {
"title": "傣族 · 传统节日",
"subtitle": "泼水节、关门节、开门节",
"image_url": "https://xxx/dai.jpg",
"buttons": [
{
"text": "查看详情",
"url": "ethnicbook://detail?ethnic=dai"
}
]
}
}
7.3 民族数据接口
我们需要提供几个API接口:
// 民族数据服务
interface EthnicSkillService {
// 查询民族基本信息
getEthnicInfo(ethnicName: string): EthnicInfo;
// 查询民族人口
getEthnicPopulation(ethnicName: string): PopulationData;
// 查询民族节日
getEthnicFestivals(ethnicName: string): FestivalData[];
// 查询民族习俗
getEthnicCustoms(ethnicName: string): CustomData[];
// 获取今日推荐
getDailyRecommendation(): EthnicInfo;
// 获取一道问答题
getQuizQuestion(category?: string): QuizQuestion;
}
数据来源:
- 可以复用「民族图鉴」App已有的数据源
- 如果App的数据是本地的,需要在后端也部署一份
- 或者让后端调用App的服务端接口(如果有的话)
对于「民族图鉴」目前的Mock数据,可以:
- 把Mock数据部署到后端
- 或者把Mock数据转换为FAQ形式,直接在技能平台配置(初期可以用这种方式快速验证)
7.4 回复内容设计
回复内容的设计很重要,直接影响用户体验。
语音回复的设计原则:
-
简洁:语音是线性的,太长用户记不住
- 控制在30秒以内
- 重点信息放在前面
- 复杂信息引导用户看卡片或打开App
-
口语化:像人说话一样,不要太书面
- “傣族的人口约有1329万人” → 好
- “根据第六次人口普查数据显示,傣族人口数量为1329985人” → 太书面
-
有温度:适当加入一些语气词
- “好的"、"没错”
- 但不要太多,显得不专业
卡片回复的设计原则:
- 信息精炼:卡片空间有限,只放最核心的信息
- 视觉美观:配图 + 清晰的排版
- 行动按钮:提供"查看详情"等按钮,引导用户到App
步骤8:「民族图鉴」AI技能设计全景
前面我们讲了很多理论,现在来系统地设计一下「民族图鉴」的AI技能体系。我们要做哪些Skill?每个Skill做什么?怎么做?
技能体系总览
「民族图鉴」的AI技能分为四大类,共8个核心Skill:
「民族图鉴」AI技能体系
├── 问答类Skill
│ ├── 民族问答Skill:回答民族文化相关问题
│ └── 知识问答Skill:民族知识答题、考试
│
├── 工具类Skill
│ ├── 民族翻译Skill:少数民族语言翻译
│ └── 民族讲解Skill:语音讲解、导览
│
├── 推荐类Skill
│ ├── 今日民族Skill:每日推荐一个民族
│ └── 个性化推荐Skill:根据用户兴趣推荐
│
└── 操作类Skill
├── 打开App Skill:语音打开App指定页面
└── 分享Skill:分享民族内容
下面我们详细设计其中最重要的4个Skill。
8.1 民族问答Skill
定位:最核心的Skill,回答用户关于民族文化的各种问题。
核心能力:
- 支持56个民族的基本信息查询
- 支持节日、习俗、饮食、服饰、建筑等分类查询
- 支持多轮对话和上下文理解
- 支持模糊查询和纠错
意图设计(12个核心意图):
| 意图名称 | 说明 | 核心槽位 |
|---|---|---|
| query_ethnic_info | 查询民族基本信息 | ethnic_name(必填) |
| query_ethnic_population | 查询民族人口 | ethnic_name(必填) |
| query_ethnic_festival | 查询民族节日 | ethnic_name(必填) |
| query_ethnic_custom | 查询民族习俗 | ethnic_name(必填) |
| query_ethnic_food | 查询民族饮食 | ethnic_name(必填) |
| query_ethnic_clothing | 查询民族服饰 | ethnic_name(必填) |
| query_ethnic_architecture | 查询民族建筑 | ethnic_name(必填) |
| query_ethnic_history | 查询民族历史 | ethnic_name(必填) |
| query_ethnic_language | 查询民族语言 | ethnic_name(必填) |
| query_ethnic_region | 查询民族分布地区 | ethnic_name(必填) |
| search_ethnic | 搜索民族(模糊) | keyword(必填) |
| help | 帮助/你能做什么 | 无 |
典型对话示例:
用户:傣族的传统节日有哪些?
AI:傣族的传统节日可丰富了~ 最有名的是泼水节,每年4月中旬举行,人们通过泼水来祈福。还有关门节、开门节、花街节等。想详细了解哪个节日呢?
用户:泼水节是怎么来的?
AI:关于泼水节的由来,有一个美丽的传说……(讲述传说)想了解更多傣族文化吗?
用户:他们平时吃什么?
(系统理解"他们"指傣族)
AI:傣族的饮食很有特色,主食是大米,喜欢吃糯米。特色美食有菠萝饭、竹筒饭、酸笋、香茅草烤鱼…… 要不要打开App看看详细的美食介绍?
8.2 民族翻译Skill
定位:少数民族语言翻译工具,帮助用户了解和学习少数民族语言。
核心能力:
- 支持常用少数民族语言和汉语的互译
- 支持语音翻译(说汉语,翻成民族语;说民族语,翻成汉语)
- 支持常用语、日常对话翻译
- 可以朗读翻译结果
支持的语言(初期):
- 藏语、维吾尔语、蒙古语、壮语、朝鲜语
- 后续逐步增加更多民族语言
意图设计:
| 意图名称 | 说明 | 槽位 |
|---|---|---|
| translate_text | 翻译文字 | source_lang, target_lang, text |
| translate_voice | 语音翻译 | source_lang, target_lang |
| daily_phrases | 常用语/日常对话 | language, category |
| learn_language | 学习语言 | language, level |
典型对话示例:
用户:用藏语说"你好"怎么说?
AI:藏语的"你好"读作"扎西德勒"(Tashi Delek),也是吉祥如意的意思~ 要听发音吗?
用户:"谢谢"用蒙古语怎么说?
AI:蒙古语的"谢谢"是"bayarllaa",读作"巴亚尔拉拉"。还有什么想翻译的吗?
用户:我想学几句维吾尔语日常对话
AI:好呀~ 我教你几句常用的维吾尔语对话。第一句:"你好"——"亚克西姆塞斯"……
8.3 民族推荐Skill
定位:个性化推荐引擎,根据用户兴趣推荐民族文化内容。
核心能力:
- 每日推荐一个民族(今日民族)
- 根据用户阅读历史推荐
- 根据用户收藏推荐
- 根据用户所在地区推荐当地民族
- 可以按类别推荐(节日、美食、服饰等)
意图设计:
| 意图名称 | 说明 | 槽位 |
|---|---|---|
| daily_recommendation | 今日民族推荐 | 无 |
| recommend_ethnic | 推荐民族 | category(可选) |
| recommend_similar | 推荐相似的 | ethnic_name(可选) |
| surprise_me | 随便推荐一个 | 无 |
推荐策略:
- 冷启动:新用户先推荐知名度高的(汉族、壮族、藏族、蒙古族等)
- 基于内容:根据用户看过的民族,推荐相似的(如同地区、同语系)
- 基于行为:根据用户的收藏、分享、阅读时长判断兴趣
- 多样性:不要总是推荐同一类,保持新鲜感
典型对话示例:
用户:今天推荐哪个民族?
AI:今天给你推荐「纳西族」~ 纳西族主要分布在云南丽江,有着古老的东巴文化和美丽的丽江古城。想了解更多吗?
用户:再推荐一个
AI:那给你推荐「朝鲜族」吧~ 朝鲜族能歌善舞,美食也很多,比如冷面、泡菜、打糕…… 你之前收藏过朝鲜族的服饰,应该会感兴趣吧?
用户:有没有什么比较小众的民族?
AI:那我推荐一个你可能没怎么听说过的——「独龙族」。独龙族是中国人口最少的民族之一,主要生活在云南独龙江流域,有着独特的纹面文化……
8.4 民族讲解Skill
定位:语音讲解助手,像导游一样为用户讲解民族文化知识。
核心能力:
- 语音讲解民族介绍
- 支持不同长度的讲解(简版/详版)
- 支持专题讲解(节日专题、服饰专题等)
- 可以随时暂停、继续、提问
意图设计:
| 意图名称 | 说明 | 槽位 |
|---|---|---|
| tell_me_about | 给我讲讲XX | ethnic_name(必填) |
| explain_topic | 讲解某个主题 | topic(必填) |
| continue | 继续讲 | 无 |
| go_deeper | 详细讲讲 | 无 |
| skip | 跳过/下一个 | 无 |
讲解模式:
- 故事模式:像讲故事一样讲,生动有趣
- 知识模式:系统化讲解,信息量大
- 问答模式:边讲边问,互动性强
- 快速模式:简要介绍,30秒搞定
典型对话示例:
用户:给我讲讲藏族吧
AI:好的~ 藏族是中国一个古老而神秘的民族,主要分布在西藏、青海、四川等地。藏族有着灿烂的文化,比如藏传佛教、唐卡、藏戏……(简短介绍)
要详细了解藏族的文化吗?还是想了解某个方面?
用户:详细讲讲他们的文化
AI:好的~ 藏族文化非常丰富,主要包括这几个方面:
第一,宗教文化。藏传佛教对藏族影响深远……
第二,艺术文化。唐卡、藏戏、锅庄舞……
第三,建筑文化。布达拉宫、大昭寺……
(边讲边问)对哪方面最感兴趣呀?
用户:唐卡
AI:你真有眼光~ 唐卡是藏族特有的绘画艺术,被称为"藏文化的百科全书"。唐卡的题材很广泛,有宗教故事、历史人物、医学、天文……
想知道唐卡是怎么画出来的吗?
步骤9:Skill的发布与上架
Skill开发完成后,需要发布和上架,用户才能用。让我们来了解一下完整的发布流程。
发布前的检查清单
在提交审核之前,先对照这个清单检查一遍:
功能检查:
- 所有意图都能正确触发
- 所有槽位都能正确填充
- 多轮对话流程顺畅
- 错误处理和兜底回复正常
- deeplink跳转正常
- 卡片展示正常
体验检查:
- 语音回复自然流畅,不机械
- 回复长度合适(30秒以内)
- 追问话术自然,不生硬
- 错误回复友好
- 有引导用户下一步操作
合规检查:
- 内容合规,没有违法违规内容
- 隐私政策完善
- 没有收集不必要的用户数据
- 符合相关法律法规
- 图标、名称符合设计规范
提交流程
第一步:完善技能信息
在技能开发平台填写完整的技能信息:
- 技能名称、调用名、图标
- 技能简介、详细描述
- 功能列表、使用示例
- 分类、标签
- 隐私政策、服务协议
第二步:提交测试报告
- 测试用例和测试结果
- 典型对话示例
- 边界情况处理说明
- 兼容性说明
第三步:提交审核
- 选择审核版本
- 填写审核说明
- 上传测试账号(如果需要)
- 提交审核
第四步:等待审核结果
- 审核周期:通常3~5个工作日
- 如果通过:恭喜,可以上架了
- 如果被驳回:根据反馈修改,重新提交
常见拒审原因与对策
| 拒审原因 | 说明 | 对策 |
|---|---|---|
| 功能无法使用 | 提交的Skill无法正常工作 | 上线前充分测试,确保所有功能正常 |
| 内容违规 | 包含违法违规或敏感内容 | 严格审核内容,遵守相关规定 |
| 描述不符 | 实际功能和描述不一样 | 如实描述,不夸大、不误导 |
| 体验太差 | 经常听不懂、答非所问 | 优化模型,增加训练数据,完善兜底 |
| 隐私问题 | 违规收集用户数据 | 遵守隐私政策,只收集必要的数据 |
| 稳定性差 | 经常出错、崩溃 | 完善错误处理,保证服务稳定 |
上架后的运营
上架不是结束,而是开始。上架后还需要持续运营和优化。
数据监控:
- 调用次数:多少人在用
- 用户留存:用户会不会回来用
- 意图分布:用户最喜欢问什么
- 错误率:多少时候答不上来
- 用户反馈:好评还是差评
持续优化:
- 分析错误案例,持续优化意图识别
- 收集用户反馈,增加用户需要的功能
- 优化话术,让对话更自然
- 扩充知识库,让AI越来越聪明
版本迭代:
- 小版本:修复Bug、优化体验
- 中版本:增加新功能、新意图
- 大版本:架构升级、能力跃升
步骤10:AI应用的安全与隐私保护
AI在带来便利的同时,也带来了新的安全和隐私问题。我们必须高度重视。
安全风险与防范
风险1:数据泄露
AI应用会收集和处理大量用户数据,如果保护不好,就可能泄露。
防范措施:
- 数据最小化:只收集必要的数据,能不收集就不收集
- 数据加密:存储加密、传输加密
- 访问控制:严格的权限管理
- 安全审计:记录所有数据访问,便于追溯
「民族图鉴」的做法:
- 对话日志只保留必要的时间(如30天)
- 用户数据匿名化处理
- 不收集用户的真实身份信息
- 敏感数据(如语音)本地处理,不上传
风险2:内容安全
AI生成的内容可能有问题——虚假信息、有害内容、偏见等。
防范措施:
- 内容审核:AI生成的内容要经过审核
- 敏感词过滤:过滤违法违规内容
- 知识库校验:确保知识库的内容准确可靠
- 用户举报:提供举报渠道,及时处理
「民族图鉴」的做法:
- 民族知识来自权威来源,确保准确
- 敏感问题有预设的安全回复
- 不回答与民族文化无关的敏感问题
- 引导用户通过正规渠道获取信息
风险3:越权操作
AI可能会被诱导去做一些它不该做的事情。
防范措施:
- 权限控制:Skill能做什么、不能做什么,严格限制
- 操作确认:重要操作需要用户确认
- 边界清晰:明确Skill的能力边界,不越界
- 异常检测:检测异常行为,及时干预
「民族图鉴」的做法:
- Skill只能查询民族文化内容,不能做其他操作
- 不访问用户的个人数据(通讯录、位置等)
- 不执行系统级操作(打电话、发短信等)
- 严格限制Skill的权限范围
隐私保护原则
原则1:透明原则
- 明确告诉用户收集了什么数据、用来做什么
- 隐私政策清晰易懂,不要用法律文书式的语言
- 用户有权知道自己的数据被如何使用
原则2:用户控制原则
- 用户可以选择是否开启AI功能
- 用户可以查看、导出、删除自己的数据
- 用户可以随时关闭数据收集
原则3:数据最小化原则
- 只收集实现功能所必需的数据
- 能在本地处理的,就不上传到云端
- 数据保留时间越短越好
原则4:安全保障原则
- 采取一切合理的安全措施保护用户数据
- 定期进行安全审计和漏洞扫描
- 发生数据泄露时及时通知用户
「民族图鉴」的隐私保护实践
1. 数据收集清单
| 数据类型 | 是否收集 | 用途 | 保留时间 |
|---|---|---|---|
| 对话内容 | 是(可选) | 优化AI回答质量 | 30天 |
| 语音数据 | 否 | - | - |
| 用户ID | 是(匿名) | 统计使用情况 | 永久(可删除) |
| 设备信息 | 是 | 兼容性优化 | 永久(匿名) |
| 位置信息 | 否 | - | - |
| 联系方式 | 否 | - | - |
2. 用户权利
- 用户可以在设置中关闭AI功能
- 用户可以申请删除自己的所有数据
- 用户可以导出自己的对话历史
- 用户可以选择是否参与数据收集
3. 技术保障
- 端到端加密传输
- 数据存储加密
- 严格的内部访问权限
- 定期安全审计
⚠️ 常见问题与解答
Q1:语音识别不准怎么办?
A:语音识别不准是语音交互的常见问题,可以从几个方面优化:
1. 优化用户说法
- 收集更多的用户说法,覆盖不同的表达方式
- 考虑方言口音、常见的发音错误
- 加入同音词、近音词的匹配
2. 设计容错机制
- 识别置信度低时,主动确认:“你是想说傣族吗?”
- 提供纠错入口:“不对,我是说XX”
- 连续识别失败时,引导用户用文字输入或打开App
3. 选择好的调用名
- 调用名要容易发音,不容易和其他词混淆
- 避免用生僻字、多音字
- 比如"民族图鉴"就比"靺鞨文化"好识别得多
4. 提示用户怎么说
- 在帮助信息里给出示例说法
- 用户第一次使用时,给出引导
- “你可以问:傣族的传统节日是什么”
Q2:意图匹配错误怎么办?
A:意图匹配错误也是常见问题。可以从这几个方面优化:
1. 增加训练数据
- 每个意图的用户说法越多,识别越准
- 覆盖不同的句式、不同的用词
- 可以找人帮忙"众包"测试,收集真实说法
2. 优化意图设计
- 意图之间的边界要清晰,不要重叠
- 如果两个意图容易混淆,考虑合并或拆分
- 定期分析错误案例,持续优化
3. 加入确认机制
- 对于重要操作,即使置信度高,也可以确认
- 置信度低时,一定要确认
- “你是想了解傣族的节日吗?”
4. 提供反馈渠道
- 用户可以纠正错误
- 收集错误数据,持续优化模型
Q3:对话体验差,感觉很机械怎么办?
A:对话体验是个精细活,需要不断打磨。几个提升建议:
1. 话术多样化
- 同一个意思,准备几种不同的说法
- 随机选择一种,避免每次都一样
- 比如"好的"、“没问题”、“来啦~”
2. 加入语气词
- 适当使用"嗯"、“哦”、“呀”、"呢"等语气词
- 但要适度,太多会显得不专业
- 根据技能定位调整:偏活泼的可以多些,偏专业的少些
3. 控制对话轮次
- 能一轮解决的,不要用两轮
- 追问太多,用户会不耐烦
- 实在搞不定,引导用户打开App
4. 有"人情味"
- 用户说"谢谢",要回复"不客气~"
- 用户说"你好",要打招呼
- 一些基本的寒暄要有
Q4:Skill开发需要服务器吗?
A:看情况:
不需要服务器的情况:
- 简单的FAQ问答(固定的问题和答案)
- 技能平台内置的功能足够用
- 数据量小,直接在平台配置
需要服务器的情况:
- 数据量大,动态变化
- 需要复杂的业务逻辑
- 需要和App的后端打通
- 需要用户系统、数据存储等
对于「民族图鉴」:
- 初期:可以先用FAQ模式,把常见问题配置好
- 中期:开发简单的后端服务,提供动态查询
- 长期:和App后端打通,数据同步
Q5:用户不用小艺怎么办?怎么推广Skill?
A:这是个好问题。Skill做出来了,没人用也不行。几个推广思路:
1. App内引导
- 在App的设置页、关于页介绍Skill功能
- 弹窗提示用户"试试语音查询:小艺,傣族的节日是什么?"
- 首次进入相关页面时提示
2. 分享传播
- 用户觉得好用,可以分享给朋友
- “你可以对小艺说’问民族图鉴,傣族的节日’”
3. 应用市场描述
- 在应用商店的描述里提到Skill功能
- 截图展示语音交互的效果
4. 技能市场优化
- 好的图标、名称、描述
- 鼓励用户好评
- 争取官方推荐
📝 本章小结
核心知识点
本文系统讲解了鸿蒙Skill技能开发的知识体系:
1. 什么是Skill
- Skill是小艺助手的技能,第三方应用可以开发
- Skill和App是互补关系,不是替代关系
- Skill做轻量查询,App做深度体验
2. Skill的类型
- 官方技能、第三方技能、自定义技能
- 形态:语音播报、语音+卡片、语音+跳转、多轮对话
3. Skill开发流程
- 注册:开发者账号、创建技能、基本信息
- 开发:定义意图、槽位、对话流、后端服务
- 测试:在线测试、真机测试、功能测试、体验测试
- 上架:提交审核、审核通过、上架运营
4. 核心概念
- 意图(Intent):用户想做什么
- 槽位(Slot):需要抽取的关键信息
- 对话流(Dialog Flow):多轮对话的流程设计
5. 「民族图鉴」Skill设计
- 8个核心意图:查询信息、人口、节日、习俗、今日推荐、知识问答、打开App、帮助
- 自定义槽位:民族名称、信息类型
- 多轮对话:缺槽位追问、模糊澄清、错误兜底
6. Skill与App联动
- deeplink跳转:点击卡片跳转到App指定页面
- 语音打开App:直接语音指令启动App
- App内集成语音:App内的语音操作
7. 多轮对话设计
- 上下文理解:记住之前的对话内容
- 追问艺术:能不问就不问、一次问一个、给出选项
- 错误兜底:听不懂时的处理策略
最佳实践总结
✅ Skill定位:做轻量,不做重型
Skill的核心价值:快速、便捷、低门槛
- 查询类:快速获取信息
- 操作类:简单快捷操作
- 入口类:引导用户打开App
复杂的、深度的功能,交给App来做
✅ 对话设计:像人一样聊天
简洁:控制在30秒以内
自然:口语化,有温度
容错:听不懂也友好
最少轮次:能一轮解决,不要用两轮
✅ Skill与App联动:形成闭环
Skill做入口:让用户快速触达
App做深度:提供完整的体验
互相导流:Skill → App → Skill
数据互通:用户数据、使用记录同步
下一步预告
在下一篇文章(第73篇)中,我们将:
- 🤖 了解什么是Agent智能体,以及它和传统App的区别
- 🔗 学习A2A(App to App Agent)协议,应用间如何智能协作
- 🧠 理解Agent的核心能力:自然语言理解、任务规划、工具调用、多轮对话
- 🏗️ 掌握Agent开发框架:元能力、意图描述、服务注册
- 🎯 为「民族图鉴」设计几个Agent:文化问答、旅游规划、学习助手
- 💻 实战:开发一个民族文化问答Agent
- 💡 探讨Agent的能力边界、数据安全、用户信任等问题
Agent是比Skill更高级的智能形态,也是未来应用的发展方向。让我们一起探索AI原生应用的新世界!
🔗 相关链接
- 小艺技能开放平台: https://developer.huawei.com/consumer/cn/hiai/
- HarmonyOS 语音服务: https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ai-overview-0000001097382406
- 语音交互设计指南: 官方文档
💡 提示:Skill开发不仅仅是技术问题,更是产品问题和设计问题。好的语音交互,应该让用户感觉"自然"、“流畅”、“聪明”。技术是基础,对话设计和体验打磨才是关键。多站在用户的角度思考,多测试、多迭代,才能做出好用的Skill。
更多推荐

所有评论(0)