共计 2478 个字符,预计需要花费 7 分钟才能阅读完成。
技术选型对比
开发语音技能的第一步是选择合适的平台。目前主流的语音平台包括 Alexa Skills Kit(ASK)、Google Actions 和百度 DuerOS。以下是它们的核心参数对比:

| 平台名称 | 开发复杂度 | API 丰富度 | 部署流程 | 适用场景 |
|---|---|---|---|---|
| Alexa Skills Kit | 中等 | 高 | 复杂 | 亚马逊生态设备 |
| Google Actions | 低 | 中 | 简单 | Google Assistant 生态 |
| 百度 DuerOS | 中等 | 中 | 中等 | 中文场景优先 |
交互设计规范
VUI 设计原则
- 避免开放式提问:语音交互应当提供明确的选项,而不是让用户自由发挥。例如,不要问 ” 你想了解什么?”,而应该问 ” 你想了解天气、新闻还是交通?”
- 提供明确的调用语句:技能的调用语句(Invocation Name)应当简短易记,例如 ” 打开天气查询 ”。
对话状态管理
对话状态管理是语音技能开发中的核心问题。推荐使用有限状态机(Finite State Machine)来管理对话流程。以下是一个简单的状态机示意图:
stateDiagram
[*] --> 欢迎状态
欢迎状态 --> 天气查询: 用户说 "查询天气"
天气查询 --> 结果展示: 提供城市名称
结果展示 --> 欢迎状态: 用户说 "谢谢"
代码实战环节
下面是一个使用 Node.js 实现的天气查询 Skill 示例,基于 Alexa Skills Kit 开发。
1. 意图识别处理
const WeatherHandler = {canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'IntentRequest'
&& handlerInput.requestEnvelope.request.intent.name === 'WeatherIntent';
},
async handle(handlerInput) {
// 获取用户输入的城市名称
const citySlot = handlerInput.requestEnvelope.request.intent.slots.city;
const cityName = citySlot && citySlot.value;
if (!cityName) {
return handlerInput.responseBuilder
.speak('请问您想查询哪个城市的天气?')
.reprompt('请告诉我城市名称,例如北京或上海')
.getResponse();}
// 调用天气 API
const weatherData = await getWeatherData(cityName);
return handlerInput.responseBuilder
.speak(` 今天 ${cityName}的天气是 ${weatherData.condition}, 气温 ${weatherData.temperature}度。`)
.withSimpleCard(`${cityName}天气 `, ` 天气状况: ${weatherData.condition}\n 温度: ${weatherData.temperature}℃`)
.getResponse();}
};
2. 外部 API 调用封装
const axios = require('axios');
async function getWeatherData(city) {
try {
// 这里应该替换为真实的天气 API
const response = await axios.get(`https://api.weather.com/v1/city/${encodeURIComponent(city)}`);
// 安全校验:验证 API 返回的数据结构
if (!response.data || !response.data.condition || !response.data.temperature) {throw new Error('Invalid weather API response');
}
return {
condition: response.data.condition,
temperature: response.data.temperature
};
} catch (error) {console.error('Weather API error:', error);
throw new Error('获取天气信息失败');
}
}
3. 响应卡片生成
在上面的代码示例中,我们使用了 withSimpleCard 方法来生成响应卡片。这是一个简单的卡片,包含城市名称和天气信息。对于更复杂的卡片,可以使用 withStandardCard 方法。
生产环境要点
冷启动优化方案
- 预加载策略:在用户首次调用技能前,预先加载必要的资源
- 代码优化:尽量减少 Lambda 函数的初始化时间
- 缓存机制:对频繁访问的数据进行缓存
对话超时处理的 3 种模式对比
- 立即结束:超时后直接结束会话,适用于一次性查询类技能
- 重新提示:超时后重新提示用户,适用于需要确认的场景
- 上下文保持:超时后保留上下文,适用于多轮对话
技能认证被拒的常见原因清单
- 调用语句(Invocation Name)不符合规范
- 隐私政策缺失或不完整
- 响应时间过长(超过 8 秒)
- 错误处理不完善
延伸思考
多轮对话的上下文保持机制
实现多轮对话的关键是维护对话上下文。可以通过以下方式实现:
- 在 sessionAttributes 中存储对话状态
- 使用持久化存储(如 DynamoDB)记录长期对话状态
- 设计清晰的对话状态转移逻辑
非预期指令的优雅降级
当用户说出非预期指令时,可以采取以下策略:
- 提供帮助:告诉用户当前可用的指令
- 确认理解:” 您是想查询天气吗?”
- 引导选项:” 您可以说 ’ 查询天气 ’ 或 ’ 查询新闻 '”
总结
开发语音技能是一个涉及多个环节的复杂过程。从平台选择到交互设计,从代码实现到生产部署,每个环节都需要仔细考虑。本文介绍了开发语音技能的全流程,并提供了实用的代码示例和优化建议。希望这些内容能帮助你顺利开发出第一个语音技能。
在实际开发中,建议先从简单的技能开始,逐步增加复杂性。同时,多进行用户测试,收集反馈并持续优化。记住,一个好的语音技能应该是自然、高效且易于使用的。
正文完
发表至: 技术开发
近一天内
