天猫精灵技能开发实战:从零构建“欧皇之堡”语音应用

发布时间:2026/9/2 21:43:37
天猫精灵技能开发实战:从零构建“欧皇之堡”语音应用 立秋刚过朋友圈满屏都是“秋天的第一杯奶茶”。不过咱们程序员要玩就玩点不一样的——别人喝奶茶我们来写一个“秋天的第一个堡堡”这篇文章要分享的不是奶茶而是天猫精灵上的一个智能语音技能——“欧皇之堡”的完整开发实战。从账号申请、技能创建、意图配置到后端代码编写再到真机调试和发布上架整个过程都会拆开揉碎讲清楚。即使你之前没有接触过语音技能开发跟着这篇文章走一遍也能拥有一个属于自己的“欧皇之堡”。1. 天猫精灵技能开发到底是什么1.1 从“堡堡”说起什么是智能语音技能我们先从用户视角理解一下“技能”这个概念。早上你对天猫精灵说“天猫精灵打开欧皇之堡”然后它回你一句“今天也是欧气满满的一天来抽个签吧堡堡给你带来了好运”这时候你就在使用一个语音技能。所谓“技能”可以理解为天猫精灵的“ App ”。天猫精灵本身是一个语音助手能完成闹钟、天气、音乐等基础操作但更多个性化的玩法比如抽签、答题、故事接龙、家庭留言板都需要通过技能来扩展。每个技能本质上是一个云端服务接收用户语音指令处理后返回播报内容。官方叫法是 Tmall Genie Skills开发者可以通过天猫精灵开放平台阿里云 IoT 智能生活开放平台创建和发布技能。技能一旦发布用户就可以在天猫精灵 App 的技能商店里找到它并直接通过语音调用。1.2 为什么值得动手做一个技能这两年语音交互设备已经非常普及智能音箱、带屏音箱、车机、电视盒子都内置了语音助手。对于开发者来说语音技能是一个门槛不高、反馈直接的实践方向语法简单核心是 JSON 和 HTTP 请求不需要客户端开发经验。后端可以用 Java、Python、Node.js 等任何你熟悉的语言实现。一个创意想法从构思到上线最快几天就能完成。技能发布后真实用户可以直接使用非常有成就感。对物联网、智能家居、语音交互感兴趣的开发者这是很好的入门练手项目。“欧皇之堡”这个技能的设计思路很简单用户每天可以来“堡堡”抽一次签获得一句鼓励语或运势播报主打一个“秋天欧气满满”的仪式感。技术上会涉及语音交互设计、意图槽位解析、后端接口开发三个部分。1.3 技能开发的整体流程天猫精灵技能开发通常包括以下步骤阶段主要工作产出物概念设计定义技能用途、交互话术技能描述文档开发准备注册开发者账号、创建技能、配置后端技能基础信息语音交互模型配置意图、语句、槽位语音交互模型 JSON后端服务开发编写技能逻辑处理请求Web 服务接口在线测试在开发者平台模拟对话测试通过对话记录真机调试绑定设备进行语音验证调试日志发布上线提交审核后上架技能商店正式技能应用下面我们就按这个流程完整走一遍。2. 环境准备与账号申请2.1 需要准备的材料做一个天猫精灵技能不需要太复杂的本地环境。基础准备如下项目说明天猫精灵开放平台账号使用淘宝或天猫账号登录后端服务器一台可被公网访问的服务器也可以使用阿里云函数计算开发语言环境Java 8 或 Python 3.6本文以 Python 为例HTTPS 证书平台要求后端接口必须支持 HTTPS天猫精灵设备用于真机调试可用 App 内置模拟器代替代码编辑器VS Code 或任何你习惯的工具版本说明一下天猫精灵开放平台的功能和界面会不定期调整本文以实际使用的常见流程为例重点是讲解开发思路和核心配置。如果你打开平台后发现界面有变化按当前平台文档对照操作即可。2.2 创建开发者账号与技能应用打开天猫精灵开放平台使用淘宝账号登录。如果是第一次使用需要完成开发者认证。认证过程中的企业信息和个人信息按真实情况填写个人开发者也可以完成认证。登录后进入控制台选择“创建技能”。创建时需要填写以下信息技能名称例如“欧皇之堡”。技能类型选择“自定义技能”。调用词这是用户唤起技能时说的话例如“欧皇之堡”。技能描述用一两句话说明技能能做什么。创建完成后系统会分配一个技能 ID这个 ID 后面在请求链接中会用到。在技能详情页我们需要重点关注三个区域语音交互模型、后端服务配置、在线测试。2.3 公网 HTTPS 接口的准备天猫精灵技能的后端需要接收平台的请求并且平台要求接口必须是 HTTPS。本地开发阶段可以使用内网穿透工具把本地服务临时映射到公网但正式发布时建议部署到云服务器或函数计算。如果使用阿里云服务器最简单的方式是申请一个免费 HTTPS 证书然后配置到 Nginx 上。如果是个人开发者临时测试也可以使用 ngrok 之类工具做 HTTPS 映射但免费版域名不稳定接口地址每次会变所以只适合开发调试。本文的代码示例会同时给出本地运行的版本和部署到服务器的部署建议。你只需要有一个能访问的 HTTPS 地址就能完成测试流程。3. 语音交互模型与意图设计3.1 理解技能交互模型语音技能和普通网页应用最大的区别在于交互入口。网页用户能看到按钮、菜单而语音用户只能用说话来表达意图。因此我们需要预先定义好用户可能说的话以及话里面包含的关键信息这就是语音交互模型。天猫精灵的语音交互模型主要由三部分组成组成部分作用类比意图Intent用户想做什么接口名称语句Utterances用户可能说的话请求参数示例槽位Slots话里面具体的信息点请求参数拿“欧皇之堡”来说核心意图只有一个“抽签”。用户可能会说“打开欧皇之堡”“今天运势怎么样”“帮我抽个签”“来一签欧皇签”这些句子其实都指向同一个意图我们把它命名为“DailyDraw”。每次抽签还可以传入一个可选的“运势类型”槽位比如“事业签”“爱情签”“财运签”。3.2 定义意图与语句打开技能详情页的“语音交互模型”创建一个名为“DailyDraw”的意图。在意图下添加用户语句语句写得越丰富语音识别越准确。这里建议把用户可能的表达方式都列出来包括口语化表达。推荐语句示例我要抽签 今天什么运势 帮我求一签 来一个欧皇签 看看今天的堡堡运势再创建一个可选槽位“签文类型”枚举值包括枚举值含义prosperity财运career事业love爱情health健康配置完成后把意图和语句保存。平台会自动生成一个语音交互模型 JSON你也可以手动编辑后上传。这个模型本质上是描述“哪些话对应哪个意图、哪些词对应哪个槽位”的映射规则。3.3 理解请求与响应格式当用户对天猫精灵说“我要抽签”时语音识别服务会解析出对应的意图然后平台会将一段标准格式的 JSON 请求发送到你的后端接口。这个 JSON 里包含了会话信息、意图名称、槽位值等关键数据。后端返回的响应也必须是固定格式的 JSON包含要播报的文本内容等字段。由于天猫精灵开放平台的请求/响应格式会随版本调整开发时要严格按照当前平台文档来解析和组装。核心思路是接收平台 POST 请求。从请求体中取出意图名称。根据意图名称进入不同处理逻辑。组装播报文案返回 JSON。下面我们用一个具体例子说明。4. 完整实战开发“欧皇之堡”语音技能4.1 创建项目结构我们使用 Python Flask 来实现后端服务。先创建项目目录结构ouhuang-burg/ ├── app.py # 主入口Flask 应用 ├── draw.py # 抽签逻辑 ├── data.py # 签文数据 ├── requirements.txt # 依赖 └── deploy/ └── nginx.conf # 部署用 Nginx 配置示例创建虚拟环境并安装依赖mkdir ouhuang-burg cd ouhuang-burg python3 -m venv venv source venv/bin/activate pip install flaskrequirements.txt 内容如下flask2.2.5 gunicorn20.1.0这里 Flask 版本不需要刻意选最新稳定即可。未来安装时如果出现版本不兼容可以根据 pip 提示调整。4.2 编写签文数据模块签文是整个技能的灵魂。“欧皇之堡”要给人“欧气满满”的感觉签文必须正面、有趣、有画面感。我们先用一个模块存放签文数据。文件路径data.py# -*- coding: utf-8 -*- 签文数据模块 每一条签文包含 - text: 播报内容 - level: 运势等级 SIGNS { daily: [ { text: 堡堡掐指一算今天你适合吃个汉堡好运藏在番茄酱里, level: 欧皇 }, { text: 堡堡检测到你的欧气值正在飙升今天出门可能捡到宝藏, level: 欧皇 }, { text: 今天的你像堡堡的芝麻面包胚看着普通其实香气逼人, level: 小欧 }, { text: 堡堡说别着急好运正在排队进场你要做的只是耐心等待。, level: 平稳 }, { text: 堡堡偷偷告诉你把烦恼夹进生菜里一口吃掉明天就是晴天。, level: 小欧 } ], career: [ { text: 事业签老板今天会多看你一眼因为你努力的样子在发光, level: 欧皇 }, { text: 事业签方案可能会被驳回但别慌第二版才是真正的王炸。, level: 小欧 } ], love: [ { text: 爱情签今天的你自带滤镜桃花可能会在转角出现。, level: 欧皇 }, { text: 爱情签别急着表白先请对方吃个堡成功率提升百分之五十。, level: 小欧 } ], prosperity: [ { text: 财运签财神爷今天路过你的工位记得保持微笑迎接。, level: 欧皇 }, { text: 财运签适合整理账单你会发现自己原来这么富有。, level: 平稳 } ] } DEFAULT_SIGN { text: 堡堡祝你今天也是欧气满满的一天, level: 欧皇 }这里的签文数据设计成“通用签 分类签”的结构目的是方便后续扩展更多签文分类。4.3 编写抽签逻辑模块抽签逻辑模块负责从签文数据中选择一条签文。我们使用 random 模块随机选取让每次抽签都有新鲜感。文件路径draw.py# -*- coding: utf-8 -*- 抽签逻辑模块 根据槽位类型返回签文 import random from data import SIGNS, DEFAULT_SIGN def draw_sign(slot_valueNone): 抽取签文 :param slot_value: 槽位值可能为 career/love/prosperity 等 :return: 签文字典包含 text 和 level if slot_value and slot_value in SIGNS: sign_list SIGNS[slot_value] else: sign_list SIGNS[daily] # 使用 random.choice 从列表中随机选择一条 return random.choice(sign_list) def build_skill_response(sign): 构建天猫精灵技能响应 JSON :param sign: 签文字典 :return: 响应字典 output_text f{sign[text]} 今日运势等级{sign[level]}。 response { returnCode: 0, returnErrorSolution: , returnMessage: , returnValue: { reply: output_text, resultType: RESULT, executeCode: SUCCESS } } return response这里说明一下build_skill_response中组装的是常见的天猫精灵技能响应格式。实际字段名称和结构要以开放平台当前版本的协议为准代码里的核心思路——把播报文本放到reply字段——在多数版本中是一致的。4.4 编写 Flask 主程序现在编写 Flask 主程序接收天猫精灵平台发来的 POST 请求解析 JSON调用抽签逻辑最后返回响应。文件路径app.py# -*- coding: utf-8 -*- 欧皇之堡 - 天猫精灵技能后端服务 import json from flask import Flask, request, jsonify from draw import draw_sign, build_skill_response app Flask(__name__) app.route(/, methods[POST]) def skill_entry(): 技能请求入口 天猫精灵平台会 POST JSON 到该接口 # 获取请求体 req_body request.get_data(as_textTrue) print(收到请求:, req_body) try: req json.loads(req_body) except json.JSONDecodeError: # 返回默认兜底回复 return jsonify(build_skill_response_from_text(堡堡刚才走神了再说一次好不好)) # 解析意图名称 intent_name get_intent_name(req) # 解析槽位值 slot_value get_slot_value(req, sign_type) # 根据意图处理 if intent_name DailyDraw: sign draw_sign(slot_value) response build_skill_response(sign) else: # 兜底处理 response build_skill_response_from_text(堡堡还不认识这个指令试试“我要抽签”吧。) return jsonify(response) def get_intent_name(req): 从请求体中解析意图名称 不同版本协议里字段位置可能不同这里做了兼容处理 intent req.get(intentName, ) if not intent: intent req.get(request, {}).get(intentName, ) if not intent: intent req.get(query, {}).get(intentName, ) return intent def get_slot_value(req, slot_name): 从请求体中解析槽位值 slots req.get(slotEntities, []) if not slots: slots req.get(request, {}).get(slotEntities, []) if not slots: slots req.get(query, {}).get(slotEntities, []) for slot in slots: if slot.get(slotName) slot_name: values slot.get(slotValue, ) if isinstance(values, list): return values[0] if values else None return values return None def build_skill_response_from_text(text): 根据文本直接构造响应 response { returnCode: 0, returnErrorSolution: , returnMessage: , returnValue: { reply: text, resultType: RESULT, executeCode: SUCCESS } } return response app.route(/health, methods[GET]) def health(): 健康检查接口方便服务器运维 return jsonify({status: ok}), 200 if __name__ __main__: # 本地开发时使用 # 生产环境建议使用 gunicorn 启动 app.run(host0.0.0.0, port5000, debugFalse)这里分几个函数做了解析目的是尽量兼容不同版本的请求体结构。实际开发中请以开放平台文档中的请求示例为准对号入座调整字段名。4.5 本地运行与接口验证启动服务python app.py服务默认监听 5000 端口。我们用 curl 模拟一次平台请求curl -X POST http://127.0.0.1:5000/ \ -H Content-Type: application/json \ -d { intentName: DailyDraw, slotEntities: [ { slotName: sign_type, slotValue: love } ] }预期返回{ returnCode: 0, returnValue: { reply: 爱情签今天的你自带滤镜桃花可能会在转角出现。 今日运势等级小欧。, resultType: RESULT, executeCode: SUCCESS } }这个接口能通说明后端逻辑没问题。4.6 配置后端服务地址回到天猫精灵开放平台控制台在技能详情页找到“后端服务”配置将接口地址填写为你的 HTTPS 地址路径指向 Flask 应用部署的主路径。配置项说明配置项填写内容服务地址https://你的域名/请求方式POST超时时间建议 3 秒以上避免签文处理耗时导致超时填写后保存。平台通常提供“连通性测试”按钮可以一键验证接口是否可达。4.7 在线测试与真机调试配置完成后在平台“在线测试”面板中选择“我要抽签”点击发送。如果配置正确系统会返回你的后端处理结果。测试通过后使用天猫精灵 App 绑定一台设备在 App 中开启开发者模式将设备切换为技能调试模式。然后对音箱说“天猫精灵打开欧皇之堡”就会触发你的技能。如果语音唤不醒检查技能是否已启用以及调用词是否正确。4.8 部署到云服务器本地调试通过后需要把服务部署到公网服务器。使用 gunicorn 启动 Flask 应用pip install gunicorn gunicorn -w 2 -b 127.0.0.1:5000 app:app然后在 Nginx 中配置 HTTPS 反向代理。以下为 Nginx 配置示例文件路径deploy/nginx.confserver { listen 443 ssl; server_name your.domain.com; ssl_certificate /etc/nginx/ssl/your_domain.pem; ssl_certificate_key /etc/nginx/ssl/your_domain.key; location / { proxy_pass http://127.0.0.1:5000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }配置完成后重载 Nginxnginx -t nginx -s reload部署时要特别注意生产环境不要使用 Flask 自带的开发服务器必须使用 gunicorn、uwsgi 等 WSGI 服务器。另外建议在服务器防火墙中只开放 443 端口5000 端口只允许本机访问。5. 常见问题与排查思路5.1 接口连通性测试失败问题现象常见原因解决思路测试按钮提示“服务不可达”接口地址不是 HTTPS检查服务器证书和 Nginx 配置连通性测试一直转圈服务器防火墙未放行检查安全组和防火墙规则返回 502 Bad Gatewaygunicorn 未启动或端口不对确认 gunicorn 进程和 proxy_pass 端口排查时首先在服务器本地 curl 接口curl -X POST http://127.0.0.1:5000/ -d {}如果本地能通再去排查 Nginx 和 HTTPS 部分。5.2 对话能触发但回复内容不对问题现象常见原因解决思路说“我要抽签”没反应意图名没对应上检查请求日志意图名称不管说什么都返回兜底文案请求体解析字段不对根据平台文档调整字段结构槽位值解析不到槽位名称不一致核对平台配置的槽位名返回了内容但音箱不播报响应格式字段错误对照最新协议调整返回值建议在 Flask 中增加请求日志打印把每次收到的原始 JSON 记录下来这样排错会快很多。5.3 技能通过审核却被用户投诉上线后如果用户反馈“听不懂人话”大概率是语句覆盖不足。比如用户说“堡堡今天运气怎么样”但你的意图里没有这个语句语音识别就无法映射到 DailyDraw。解决方法是持续补充常用语句定期更新语音交互模型。6. 最佳实践与工程建议6.1 签文内容设计要留有余地内容安全是技能上架审核的重点。“欧皇之堡”本质是一个运势类小游戏签文要避免涉及医疗、投资、政策等敏感领域。比如签文里不能出现“今天适合买股票”“偏方可以治病”这类内容平台审核会直接驳回。好运签就专注做情绪价值和趣味性不要越界。另外签文数量不要太少。建议每个分类至少准备 10 条以上否则用户抽几次就会发现重复体验下降。6.2 响应时间控制在 2 秒以内语音交互对延时非常敏感。如果用户说完话等 3 秒才听到回复体验会大打折扣。建议后端逻辑保持轻量不要在请求处理里查数据库或调第三方 API。签文数据直接放在内存或代码里不需要数据库。使用 gunicorn 多 worker 提升并发。如果将来要做个性化签文再把数据库引入但要做好缓存。6.3 日志与错误监控上线后要确保能拿到错误日志。推荐方案使用阿里云日志服务或其他日志平台收集 gunicorn 日志。在 Flask 中记录每次请求的完整 JSON。对异常统一捕获返回兜底文案而不是抛出 500 错误。加入健康检查接口配合云监控定期探测。6.4 版本管理与灰度发布技能修改后不建议直接全量发布。天猫精灵开放平台通常支持多版本管理可以先用测试版验证确认没问题再提交正式发布。这和我们写代码要开分支、先测试再合并是一个道理。6.5 构建可持续迭代的技能“欧皇之堡”第一版只有一个抽签功能后续可以考虑以下迭代方向增加每日打卡记录连续抽签天数。引入积分体系签到多天解锁特殊签文。增加分享功能用户可以把好运签分享到社交平台。接入闹钟能力每天早晨定时推送运势。这些扩展不会改变核心架构只是在请求处理逻辑中不断叠加新意图。7. 总结从“秋天的第一个堡堡”这个创意出发我们完成了一个完整的智能语音技能开发流程包括账号申请、意图设计、Python 后端开发、接口测试、服务器部署和常见问题排查。核心知识点有三块语音交互模型决定了用户怎么“说”后端逻辑决定了技能怎么“答”部署运维决定了服务怎么“稳”。如果你之前没有接触过语音技能开发这个项目非常适合作为第一个练手作品。它不复杂但完整覆盖了从想法到上线的全流程。接下来你可以去天猫精灵开放平台把“欧皇之堡”真正创建出来。遇到报错不要慌先看请求日志再对照协议文档大多数问题都能解决。语音交互是一个一旦入门就会觉得很有意思的领域希望你的“堡堡”也能早日上线为用户带去每天的好运。