快来领取一只天猫精灵!

简介: 天猫精灵技能应用开发平台是阿里巴巴天猫精灵面向不同类型的广大开发者推出的技能应用开发、接入平台。

@[toc]

1. 绪论

1.1 天猫精灵是啥

  天猫精灵是阿里发布的AI智能音箱,支持智能家居控制、语音购物、手机充值、叫外卖、音频音乐播放、订日程、备忘提醒、定闹钟、查天气、找手机、倒计时、卡路里查询、听新闻、查星座运势、查价格、查股票等功能。

1.2 什么是天猫精灵开放平台

  • 天猫精灵技能应用开发平台是阿里巴巴天猫精灵面向不同类型的广大开发者推出的技能应用开发、接入平台。
  • 该平台提供了从语音交互模型定义、语义解析理解能力,到技能开发、测试、部署的一整套开发工具和便捷的可视化操作工作台,帮助开发者高效地将各类技能应用快速接入到天猫精灵音箱以及精灵生态硬件终端。
  • 平台旨在将人工智能中ASR(语音识别)、NLP(自然语言处理)、TTS(语音合成)等自然语言处理技术进行整合,并配合 AI 能力和设备控制能力对外共享开放。同时,依托于强大的底层技术、智能的算法引擎、完善的云端服务和成熟的软硬件标准系统,持续不断的将全面、易用的核心技术能力进行输出,为开发者带去更多可能。最终方便各种类型的开发者都可以通过平台便捷享用,从而高效率地创建音箱端的智能应用,不断丰富应用生态,提升用户价值和满意度的同时,实现自身的利益诉求。

2. 成为开发者

2.1 登录平台

https://iap.aligenie.com/

登陆后点击控制台,选择技能应用平台并点击进入。

2.1 注册平台

根据实际情况选择认证的类型。并根据页面提示填写开发者真实信息,完成账号认证。下面以认证企业账号为例,介绍认证的操作步骤。

3. 领取一只精灵

3.1 创建语音技能

认证通过后进入技能应用平台,我们要创建一个语音技能,选中语音技能分类:点击创建技能。

3.2 填写技能基本信息

选中语音技能 中的 自定义技能 填写技能创建信息:技能名称和调用词
技能名称:展示在技能市场的技能名称,在发布时将进行唯一性检测。
技能属性选择 公有技能 / 私有技能。技能属性选择,建议您先参考【公有&私有】,由于我们要开发一个面向所有天猫精灵用户的应用,所以技能属性这里选择公有技能。
技能调用词也称为 唤醒词,是用户使用这个技能所需要说的关键字。如“天猫精灵,天气小蜜”,则使用了调用词为“天气小蜜”的技能。
填写技能调用词时系统会进行唯一性检测,截图中填写的“天气小蜜”仅仅作为范例,请您在创建技能时注意不要和范例相同或填重复过的调用词。

3.3 配置语音交互模型

创建技能成功后,需配置语音交互模型,才可与用户进行语音对话,语音交互模型包含意图、实体、问答三块,本节课先配置意图。
首先了解下什么是意图:意图是用户使用语音技能的目的,语音技能至少要有一个意图(至少向用户提供一个功能,也可以是多个)只说调用词会进入默认意图所以有调用词的技能需要有默认意图。
了解什么是意图后,接下来开始创建语音交互模型。
第一步,点击创建意图按钮进入创建意图页面;
第二步,设置意图名称、意图标识,并将这条意图设置为默认意图,设置好后点击提交。

3.4 配置后端服务

跳转到阿里云开发平台后,会自动进入 CloudIDE,平台会自动生成模板代码,查看代码路径:src/main/GenieEntry.java,您可以直接在示例代码上进行开发;

代码编写后,要把代码提交到仓库中,不然再进来就没有了,提交步骤:点击源代码管理,然后点击提交按钮;

提交完成后要选择部署环境,打开CloudIDE 左侧的 部署调试插件,进入到部署面板,选择预发环境进行部署;

境选择好之后,我们要检查路由、函数映射表,第一个字段是应用访问的路径,格式为:/skill-78623/entry,其中数字 67954 为智能应用平台上此应用的技能id,技能id显示在技能概览页中的基本信息表中,这个字段一般系统会默认自动填好。

第二个字段表示某个文件的函数入口,如果选择Java语言, 此数据为:com.alibaba.ailabs.GenieEntry::handleRequest,表示当应用发布之后,天猫精灵这边的请求会发送到 com.alibaba.ailabs.GenieEntry类的handleRequest方法,handleRequest是从AbstractEntry类中继承的方法, 请不要重写此方法。如果选择NodeJS语言或Python语言,此数据为:index.handler,表示含义和前面类似;由于我们选的是java语言, 所以第二个字段我们要填com.alibaba.ailabs.GenieEntry::handleRequest。


package com.alibaba.ailabs;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.alibaba.ailabs.common.AbstractEntry;
import com.alibaba.da.coin.ide.spi.meta.AskedInfoMsg;
import com.alibaba.da.coin.ide.spi.meta.ExecuteCode;
import com.alibaba.da.coin.ide.spi.meta.GwCommand;
import com.alibaba.da.coin.ide.spi.meta.ResultType;
import com.alibaba.da.coin.ide.spi.standard.ResultModel;
import com.alibaba.da.coin.ide.spi.standard.TaskQuery;
import com.alibaba.da.coin.ide.spi.standard.TaskResult;
import com.alibaba.fastjson.JSON;

import com.aliyun.fc.runtime.Context;
import com.google.common.collect.Lists;

/**
 * @Description 天猫精灵技能函数入口,FC handler:com.alibaba.ailabs.GenieEntry::handleRequest
 * @Version 1.0
 **/
public class GenieEntry extends AbstractEntry {
    @Override
    public ResultModel<TaskResult> execute(TaskQuery taskQuery, Context context) {
        context.getLogger().info("taskQuery: " + JSON.toJSONString(taskQuery));

        //String screenStatus = taskQuery.getRequestData().get("screenStatus");
        String screenStatus = "online";

        // 从请求中获取意图参数以及参数值
        Map<String, String> paramMap = taskQuery.getSlotEntities().stream().collect(
            Collectors.toMap(slotItem -> slotItem.getIntentParameterName(), slotItem -> slotItem.getOriginalValue()));
        String reply;

        String city = paramMap.get("city");
        String date = paramMap.get("date");

        //处理名称为 weather 的意图
        if ("weather".equals(taskQuery.getIntentName())) {

            //weather 意图中 date 参数勾选了必选,请求数据中一定会携带 date 参数,只需要判断 city 参数有没有。
            if (city == null) {
                reply = "您要查询哪个城市的天气?";
                return askReply(reply, "city", taskQuery.getIntentId());
            }

            //TODO 根据参数获取天气信息,这里使用假数据替代
            reply = city + date + "天气 晴。";
            if ("online".equals(screenStatus)) {
                return weatherTplReply(reply, city);
            } else {
                return reply(reply);
            }

            //处理名称为 air_quality 的意图
        } else if ("air_quality".equals(taskQuery.getIntentName())) {
            //air_quality 意图中 date 参数勾选了必选,请求数据中一定会携带 date 参数,只需要判断 city 参数有没有。
            if (city == null) {
                reply = "您要查询哪个城市的空气质量?";
                return askReply(reply, "city", taskQuery.getIntentId());
            }

            //TODO 根据参数获取空气质量信息,这里使用假数据替代
            reply = city + date + "空气质量46 优。";
            if ("online".equals(screenStatus)) {
                return airTplReply(reply, city);
            } else {
                return reply(reply);
            }
        }
        reply = "请检查意图名称是否正确,或者新增的意图没有在代码里添加对应的处理分支。";
        return reply(reply);
    }

    /**
     * 结束对话的回复,回复后音箱闭麦
     */
    private ResultModel<TaskResult> reply(String reply) {
        ResultModel<TaskResult> res = new ResultModel<>();
        TaskResult taskResult = new TaskResult();
        taskResult.setReply(reply);
        taskResult.setExecuteCode(ExecuteCode.SUCCESS);
        taskResult.setResultType(ResultType.RESULT);
        res.setReturnCode("0");
        res.setReturnValue(taskResult);
        return res;
    }

    /**
     * 指定追问参数,音箱自动开麦,用户的回答优先匹配追问的参数
     */
    private ResultModel<TaskResult> askReply(String reply, String parameterName, Long intentId) {
        ResultModel<TaskResult> res = new ResultModel<>();
        TaskResult taskResult = new TaskResult();
        taskResult.setReply(reply);
        taskResult.setExecuteCode(ExecuteCode.SUCCESS);
        taskResult.setResultType(ResultType.ASK_INF);
        AskedInfoMsg askedInfoMsg = new AskedInfoMsg(parameterName, intentId);
        taskResult.setAskedInfos(Lists.newArrayList(askedInfoMsg));
        res.setReturnCode("0");
        res.setReturnValue(taskResult);
        return res;
    }

    /**
     * 天气查询意图的TPL回复
     */
    private ResultModel<TaskResult> weatherTplReply(String reply, String city) {
        return commonReply(reply, city, reply);
    }

    /**
     * 空气质量查询意图的TPL回复
     */
    private ResultModel<TaskResult> airTplReply(String reply, String city) {
        return commonReply(reply, city, reply);
    }

    private ResultModel<TaskResult> commonReply(String reply, String city, String detail) {
        //屏显模板数据需要使用gwCommands字段携带,会导致reply失效。回复内容通过speak指令返回
        GwCommand speakGwCommand = new GwCommand("AliGenie.Speaker", "Speak");

        HashMap<String, Object> payload = new HashMap<>();
        payload.put("type", "text");
        payload.put("text", reply);
        speakGwCommand.setPayload(payload);

        //携带屏显模板数据的指令
        GwCommand tplGwCommand = new GwCommand("AliGenie.Screen", "Render");
        HashMap<String, Object> payload1 = new HashMap<>();
        payload1.put("pageType", "TPL.RenderTemplate");
        payload1.put("pageTitle", "天气小助手");

        //模板标识数据
        HashMap<String, Object> data = new HashMap<>();
        data.put("template", "aligenie_weather_tpl_demo");

        //模板中展示内容的字段 dataSource
        HashMap<String, String> dataSource = new HashMap<>();
        dataSource.put("imageUrl", "https://ailabs-iot.aligenie.com/iap/platform3.0/weather-banner.png");
        dataSource.put("city", city);
        dataSource.put("minTemperature", "36°");
        dataSource.put("maxTemperature", "38°");
        dataSource.put("detail", detail);

        data.put("dataSource", dataSource);
        payload1.put("data", data);

        tplGwCommand.setPayload(payload1);

        return tplReply(Lists.newArrayList(speakGwCommand, tplGwCommand));
    }

    /**
     * 携带TPL数据的结束对话回复,回复后音箱闭麦
     */
    private ResultModel<TaskResult> tplReply(List<GwCommand> gwCommands) {
        ResultModel<TaskResult> res = new ResultModel<>();
        TaskResult taskResult = new TaskResult();
        taskResult.setExecuteCode(ExecuteCode.SUCCESS);
        taskResult.setResultType(ResultType.RESULT);
        taskResult.setGwCommands(gwCommands);
        res.setReturnCode("0");
        res.setReturnValue(taskResult);
        return res;
    }
}

3.4 测试天猫精灵

输入创建技能时设置的调用词“天气小蜜”并发送,测试欢迎意图是否配置成功,系统回复默认欢迎语则技能测试成功;
输入创建技能时设置的调用词并发送(调用词以技能创建时的为准),本教程中以“天气小蜜”调用词为例,系统回复则表示技能部署成功。

相关实践学习
达摩院智能语音交互 - 声纹识别技术
声纹识别是基于每个发音人的发音器官构造不同,识别当前发音人的身份。按照任务具体分为两种: 声纹辨认:从说话人集合中判别出测试语音所属的说话人,为多选一的问题 声纹确认:判断测试语音是否由目标说话人所说,是二选一的问题(是或者不是) 按照应用具体分为两种: 文本相关:要求使用者重复指定的话语,通常包含与训练信息相同的文本(精度较高,适合当前应用模式) 文本无关:对使用者发音内容和语言没有要求,受信道环境影响比较大,精度不高 本课程主要介绍声纹识别的原型技术、系统架构及应用案例等。 讲师介绍: 郑斯奇,达摩院算法专家,毕业于美国哈佛大学,研究方向包括声纹识别、性别、年龄、语种识别等。致力于推动端侧声纹与个性化技术的研究和大规模应用。
目录
相关文章
|
9月前
|
自然语言处理 前端开发 安全
CMS网站管理系统的优势及选择。
CMS是内容管理系统,可创建特色网站,实现内容创作、编辑、发布等,支持多用户管理、模板切换、多语言等,常用于企业、商城、论坛等,缩短建站成本和周期。
459 6
|
10月前
|
机器学习/深度学习 人工智能 自然语言处理
AICG:认识你,真好
在这个科技飞速发展的时代,AIGC(人工智能生成内容)正以惊人的速度改变我们的生活和工作方式。AIGC通过学习大量数据,能够自动生成文本、图像、音频、视频等内容,提高内容生产的效率和质量,为文学创作、新闻媒体、广告营销、艺术设计、教育培训等领域带来巨大变革。它不仅降低了成本,还提供了更多创意和个性化服务,展现了科技的无限潜力。
|
9月前
|
消息中间件 存储 JSON
Net使用EasyNetQ简化与RabbitMQ的交互
EasyNetQ是专为.NET环境设计的RabbitMQ客户端API,简化了与RabbitMQ的交互过程。通过NuGet安装EasyNetQ,可轻松实现消息的发布与订阅,支持多种消息模式及高级特性。文中提供了详细的安装步骤、代码示例及基础知识介绍,帮助开发者快速上手。关注公众号“Net分享”获取更多技术文章。
261 1
Net使用EasyNetQ简化与RabbitMQ的交互
|
存储 算法 安全
微信团队分享:来看看微信十年前的IM消息收发架构,你做到了吗
好的架构是迭代出来的,却也少不了良好的设计,本文将带大家回顾微信背后最初的也是最核心的IM消息收发技术架构,愿各位读者能从中获得启发。
492 1
|
11月前
|
人工智能 算法 前端开发
无界批发零售定义及无界AI算法,打破传统壁垒,累积数据流量
“无界批发与零售”是一种结合了批发与零售的商业模式,通过后端逻辑、数据库设计和前端用户界面实现。该模式支持用户注册、登录、商品管理、订单处理、批发与零售功能,并根据用户行为计算信用等级,确保交易安全与高效。
【Python的魅力】:利用Pygame实现游戏坦克大战——含完整源码
【Python的魅力】:利用Pygame实现游戏坦克大战——含完整源码
|
存储 C语言 C++
C++中STL常用容器(vector、deque、list、map、set)一文带你了解
C++中STL常用容器(vector、deque、list、map、set)一文带你了解
420 0
|
分布式计算 关系型数据库 MySQL
开源数据集成平台SeaTunnel:MySQL实时同步到es
免费支持 MySQL 实时同步到 ElasticSearch 的工具很少,Apache SeaTunnel 是一个高性能开源大数据集成工具,提供灵活易用、易扩展并支持千亿级数据集成的解决方案,已经在B站、腾讯云、字节等数百家公司使用。
1766 1
|
弹性计算 Linux 开发工具
2023年阿里云学生服务器配置及免费学生机领取攻略
2023年阿里云学生服务器配置及免费学生机领取攻略,阿里云学生服务器优惠活动:高效计划,可以免费领取一台阿里云服务器,如果你是一名高校学生,想搭建一个linux学习环境、git代码托管服务器,或者创建个人博客网站记录自己的学习成长历程,拥有一台云服务器是很有必要的。阿里云的飞天加速计划3.0——高校计划,面向学生开发者提供免费的云服务器福利,通过学生身份认证及续费任务后,最多可领取7个月免费云服务器ECS资源
1123 0