天猫精灵AI语音技能开发(最终章)

374 阅读3分钟

此篇为天猫精灵语音技能开发的最后一篇,实现效果是:使用特定词唤醒天猫精灵,然后播放后台写好的词条,支持上一条,下一条,退出。话不多说冲冲冲!

1.创建语音技能,截图如下;

1.png

2.后端服务创建应用,截图如下1,绑定阿里云云开发账号,登录workbench.aliyun.com 完成授权后,新建应用,截图如下2,完成创建; 2.png

3.png

3.查看语音交互模型,因为我们刚才选用的是官方模板,所以这里的意图已经自动创建好了,大家也可以在这基础上修改适合自己技能的意图,这里我就不修改了。截图如下;

4.png

4.后台开发,进入代码编辑,点击前往开发,进入cloudIDE标签,修改代码,保存-提交-推送,部署,截图如下;

5.png

6.png

GenieEntry.java参考代码如下:

package com.alibaba.ailabs;

import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;

import com.alibaba.ailabs.common.AbstractEntry;
import com.alibaba.da.coin.ide.spi.meta.ExecuteCode;
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;

/**
 * @Description 天猫精灵技能函数入口,FC handler:com.alibaba.ailabs.GenieEntry::handleRequest
 * @Version 1.0
 **/
public class GenieEntry extends AbstractEntry {

    private static final Map<String, LinkedList<Integer>> USER_MAP = new ConcurrentHashMap<>();

    private static final List<String> KNOWLEDGE;

    private static Random random = new Random();

    static {
        //这里的列表就是所有的词条
        KNOWLEDGE = Arrays.asList(
            "星星发亮是为了让每一个人有一天都能找到属于自己的星星",
            "如果你爱上了某个星球的一朵花。那么,只要在夜晚仰望星空,就会觉得漫天的繁星就像一朵朵盛开的花",
            "所有的大人都曾经是小孩,虽然,只有少数的人记得",
            "如果你要驯服一个人,就要冒着掉眼泪的危险",
            "因为是心甘情愿地沉溺,即使死亡也无须被拯救",
            "语言是误解的源头",
            "这是我的一个秘密,再简单不过的秘密:一个人只有用心去看,才能看到真实。事情的真相只用眼睛是看不见的",
            "如果你想造一艘船,不要抓一批人来搜集材料,不要指挥他们做这个做那个,你只要教他们如何渴望大海就够了"
        );
    }

    @Override
    public ResultModel<TaskResult> execute(TaskQuery taskQuery, Context context) {
        context.getLogger().info("taskQuery: " + JSON.toJSONString(taskQuery));

        String userId = taskQuery.getRequestData().get("userOpenId");
        userId = userId == null ? "testUser" : userId;

        LinkedList<Integer> list = USER_MAP.get(userId);

        //欢迎意图 或 用户缓存数据为空
        if ("welcome".equals(taskQuery.getIntentName()) || list == null) {
            list = new LinkedList<>();
            int randomIndex = random.nextInt(KNOWLEDGE.size());
            list.addLast(randomIndex);
            USER_MAP.put(userId, list);
            return intentChangeReply(KNOWLEDGE.get(randomIndex));
        }

        //下一个意图,随机选择一个内容回复,并将index追加到用户数据的LinkedList集合最后
        if ("next".equals(taskQuery.getIntentName())) {
            int randomIndex = random.nextInt(KNOWLEDGE.size());
            list.addLast(randomIndex);
            return intentChangeReply(KNOWLEDGE.get(randomIndex));
        }

        //上一个意图,将用户数据的LinkedList集合中最后一个index移除,并返回该index的内容。首先要判断集合内是否有元素,没有则不需要移除
        if ("prev".equals(taskQuery.getIntentName())) {
            if (list.size() > 0) {
                list.removeLast();
            }
            
            if (list.size() == 0) {
                return intentChangeReply("这已经是第一个了。");
            }

            return intentChangeReply(KNOWLEDGE.get(list.get(list.size() - 1)));
        }

        //退出意图,清除用户缓存
        if ("exit".equals(taskQuery.getIntentName())) {
            USER_MAP.remove(userId);
            return reply("已为您退出,再见。");
        }

        return reply("请检查意图名称是否正确,或者新增的意图没有在代码里添加对应的处理分支。");
    }

    /**
     * 结束对话的回复,回复后音箱闭麦
     */
    private ResultModel<TaskResult> reply(String reply) {
        return getResult(reply, ResultType.RESULT);
    }

    /**
     * 未指定追问参数,音箱自动开麦,用户的回答可跳转到其它意图
     */
    private ResultModel<TaskResult> intentChangeReply(String reply) {
        return getResult(reply, ResultType.ASK_INF);
    }

    private ResultModel<TaskResult> getResult(String reply, ResultType askInf) {
        ResultModel<TaskResult> res = new ResultModel<>();
        TaskResult taskResult = new TaskResult();
        taskResult.setReply(reply);
        taskResult.setExecuteCode(ExecuteCode.SUCCESS);
        taskResult.setResultType(askInf);
        res.setReturnCode("0");
        res.setReturnValue(taskResult);
        return res;
    }
}

5.部署完成后,进入到测试界面,进行在线测试,截图如下;

7.png

6.云应用下线。

附:如有不懂的可参考官方文档(AliGenie - 技能应用平台)