快来领取一只天猫精灵!

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

@[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 测试天猫精灵

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

相关实践学习
达摩院智能语音交互 - 声纹识别技术
声纹识别是基于每个发音人的发音器官构造不同,识别当前发音人的身份。按照任务具体分为两种: 声纹辨认:从说话人集合中判别出测试语音所属的说话人,为多选一的问题 声纹确认:判断测试语音是否由目标说话人所说,是二选一的问题(是或者不是) 按照应用具体分为两种: 文本相关:要求使用者重复指定的话语,通常包含与训练信息相同的文本(精度较高,适合当前应用模式) 文本无关:对使用者发音内容和语言没有要求,受信道环境影响比较大,精度不高 本课程主要介绍声纹识别的原型技术、系统架构及应用案例等。 讲师介绍: 郑斯奇,达摩院算法专家,毕业于美国哈佛大学,研究方向包括声纹识别、性别、年龄、语种识别等。致力于推动端侧声纹与个性化技术的研究和大规模应用。
目录
相关文章
【喜大普奔】阿里云高校学生专区正式上线啦
为高校学生打造的“一站式学成”阵地,完成8月闯关任务,有机会获得云小宝勋章,更有免费暑期夏令营机会等你!
|
11月前
|
程序员 云栖大会
2023云栖大会来了,免费早鸟票领取攻略
亚运会之后,杭州最大的盛会即将举行,这是疫情三年后的首届云栖大会
168 0
2023云栖大会来了,免费早鸟票领取攻略
|
数据可视化 数据挖掘
阿里云训练营学知识领奖品
阿里云训练营学知识领奖品
91 0
|
弹性计算 人工智能 关系型数据库
618的省钱技术攻略 来啦 -体验场景 领取10元猫超卡!
免费云资源+免费实操手册,开心过个618,一切免费还有好礼~6月7号-6月15日活动期间,体验云起实验室场景即可领取猫超卡~
618的省钱技术攻略 来啦 -体验场景 领取10元猫超卡!
|
数据采集 Java Linux
阿里ESC试用体验
记录阿里云ESC服务器的使用体验-Euclid_Jie
195 1
阿里ESC试用体验
|
存储 人工智能 网络协议
阿里云飞天企航活动,领取1415元上云津贴,还有购后抽奖!
本文介绍了最新推出的飞天企航活动情况。
316 0
阿里云飞天企航活动,领取1415元上云津贴,还有购后抽奖!
|
弹性计算 Linux Windows
高校计划体验心得
阿里云高校计划极大地满足了学生对云服务器的学习和使用,免费的两个星期服务器体验收获颇多
|
UED 开发者
新年重磅!万元豪礼、云上超级电脑限时免费领!
参与产品测评更有价值数千元的天猫超市卡、无影卡片式云电脑终端,阿里云MVP晋升通道等权益等你来拿!
新年重磅!万元豪礼、云上超级电脑限时免费领!
|
弹性计算 安全 Linux
阿里云高校计划体验心得
作为一个在云翼计划时期使用过阿里云ECS的人,在读研后还可以以学生身份使用阿里云的服务器可真是太棒了。云服务器使用方便并且安全,在平时我也偶尔会租云服务器来完成科研任务,这次使用了几天,搭建了自己的博客,我觉得还是一如既往的好,希望可以让我再多使用一段时间的ECS,让我好好体验下强大的阿里云服务器去实现自己的创造!
217 2
|
弹性计算 Java 关系型数据库
云翼计划体验
我是在飞天加速计划的界面领取使用ECS,选择的是centOS 7.5系统。之后有想要学习的相关内容可以在ECS上部署,并且已经在ECS上搭建的基本的JAVA环境,以及正在学习安装hadoop3的环境,已经能够使用Xshell以及Xftp链接到ECS进行操作。