AS集成科大讯飞SDK实现问答机器人的效果

一,概述

最近就在想怎样完成这个学期的Android大作业,可是又实在想不到做什么项目,昨天突然心血来潮想实现一个问答机器人的效果。最开始使用的是科大讯飞SDK的语音合成服务+聚合数据的问答机器人,实现一个问答机器人效果。但是聚合数据的问答机器人数据太少了,经常你问一句,它就原话返回,很无聊的。But,我看到了科大讯飞提供的语义理解功能真的是强大到爆,然后就花了接近很久的时间才实现了这么一个功能。其实都是在集成科大讯飞SDK时踩了坑,好久才爬出来。不说了,我先去哭一会。。。好了,情绪恢复正常,既然踩了那么多坑,就应该记下来,利己利民,那么就进入博客正题吧!

二,配置语义及下载SDK

注册账号什么的就不说了,自己去科大讯飞官网注册吧。首先去创建自己的一个应用,然后为自己的应用开通相应的服务。考虑到我们的功能,需要开通开放语义 语音听写 在线语音合成(还有离线的,复杂一点,我没选)三个服务。当然了,你还可以开通很多免费的服务,有些是收费的。需要说明的,开放语义是基于语音听写的,开通开放语义就肯定开通了语音听写。截图如下:

我涂鸦隐藏的是Appid,等下要用。我们还要去配置相应的语义,去哪里开呢?点击上图中的开放语义就能看到一个语义管理模块,从语义管理模块就能去配置语义了。在语义配置页面,自己配置自己需要的就行。我的就是这样子:

接下来就去下载自己需要的SDK了,记得勾选你刚刚配置语义的那个项目下载。如果你没弄错的话,压缩包的文件名的后部分就是你的Appid。一定要配套下载,不然后面容易出问题。

三,集成科大讯飞SDK

第一步,导入资产文件

终于到了激动人心的时刻,赶快去建一个Android Studio工程吧!解压压缩包,目录结构如下:

SDK提供了一套默认的语音交互动画及调用接口,要使用的话就将SDK资源资源包assets下的iflytek文件夹拷贝到我们Android Studio工程的assets文件夹下。如果没有assets这个文件夹,那么就自己创建。截图如下:

第二步,导入两个jar包

将SDK解压的libs目录里面的Msc.jar和Sunflower.jar导入到我们项目的libs目录下,如果没有libs目录,自己手动在相应位置创建即可。导入后,右击每个jar包,然后 Run As Library一下,成功后在app目录下的build.gradle文件里可以看到我们将刚刚那两个jar包作为了library.大截图如下(注意libs目录,右边的是app目录下的build.gradle文件,右下角成功显示了刚刚我们Add As Library的两个jar):


第三步,导入so库等适配文件

在项目的app/src/main目录下建一个jniLibs文件夹(如果没有这个文件夹的话),将SDK的libs目录下的所有so库导入我们刚刚新建的jniLibs文件夹下。将所有so库都导入,出问题的概率就小了很多。截图如下:

还没完,我们还要在app目录下的build.gradle文件中对jniLibs文件进行声明,才找的到那些so库,发挥so库应有的作用。当时就是没有去声明,结果程序一直出问题。在build.gradle中的android闭包下声明即可。这里容易出错,我直接多粘贴一些代码上来。

android {
    compileSdkVersion 25
    buildToolsVersion "25.0.2"
    defaultConfig {
        applicationId "com.bighuan.okhttpdemo"
        minSdkVersion 15
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    
//将jniLibs也作为一个库
    sourceSets {
        main {
            jniLibs.srcDir 'libs'
        }
    }   
}

自己新建一个MyApplication继承系统的那个Application,,记得在清单文件中声明MyApplication,在onCreate()初始化一下我们的SDK(StaticClass.XUNFEI_APPID就是我们的那个Appid,我把它写在一个专门存放常量的类中),这样就确保了只要进入程序,我们就初始化了SDK。注意事项:那个“=”一定要保存。具体大家可以看官方文档,并且一定要记得加权限哦,都在官方文档了,我就不粘贴这些了。

 @Override
    public void onCreate() {
        super.onCreate();
        // 将“12345678”替换成您申请的APPID,申请地址:http://open.voicecloud.cn
        SpeechUtility.createUtility(getApplicationContext(), SpeechConstant.APPID +"="+ StaticClass.XUNFEI_APPID);
    }

好了,集成讯飞SDK就完成了。Are you Ok?

四,关于代码实现的思路

1,实现逻辑

讲一下实现的逻辑吧!用户通过输入文本获得语义结果,其实结果就是讯飞那边想客户端发送json数据,我们在对json数据进行解析获得自己想要的结果,之后就将自己解析出来的文本通过语音合成转换成声音,这就是我的实现思路。具体点就是我们可以做一个QQ那样的对话框,用户发送一个信息,然后将解析出来的文本显示在客户端,作为对用户的回答,同时也将文本转换为声音。

2,返回数据分类

返回的json数据有三类吧,反正我是这样分类的。

第一类,就是用户发送一个文本,有多个结果moreResults,返回多个回答answer,但其实我们只要获得其中一条数据即可。我是取的第一个answer,第一条数据肯定是更为大众熟知的。第一种数据示例如下(客户端发送“”科大讯飞“”,从返回的数据中我们也可以看到自己发送的文本text):

{
    "moreResults":[
        {
            "rc":0,
            "answer":{
                "type":"T",
                "text":"科大讯飞股份有限公司(IFLYTEK CO.,LTD.),前身安徽中科大讯飞信息科技有限公司,成立于1999年12月30日,2014年4月18日变更为科大讯飞股份有限公司,专业从事智能语音及语言技术研究、软件及芯片产品开发、语音信息服务及电子政务系统集成。"
            },
            "service":"baike",
            "text":"科大讯飞",
            "operation":"ANSWER"
        }
    ],
    "rc":0,
    "operation":"ANSWER",
    "service":"chat",
    "answer":{
        "text":"中国声谷。是一家专业从事智能语音及语音技术研究、软件及芯片产品开发、语音信息服务的国家级骨干软件企业。",
        "type":"T"
    },
    "text":"科大讯飞"
}
第二类,只返回一个answer,发送“I love you”,直接粘贴返回的数据上来吧,一看就懂。
{
    "rc":0,
    "operation":"ANSWER",
    "service":"chat",
    "answer":{
        "text":"偶吧,撒浪嘿!",
        "type":"T"
    },
    "text":"I love you"
}
第三类,没有answer,只返回自己的那个text和rc:4。这种情况,要么就是我们没有配置到相应的语义,要么就是讯飞那边没有这个答案。比如我发送一个“iphone8”,在我写这篇博客时"iphone8"还未发布的产品,存在于科技媒体们天天猜测的新闻中的产品。这种情况,讯飞那边没办法做出回答,就返回这种数据。

需要注意的是,好像你发一个相同的文本多次,讯飞那边返回的数据并不都是一样的。

{
    "text":"iphone8",
    "rc":4
}
我的解析数据思路:第一类数据就解析第一个answer;第二类数据拿那一个answer;第三类数据就自己设置几个数据随机返回,比如这样:

/**
     * 随机返回四个文本中的一个
     * @return
     */
    private static String getRandomText() {
        String str = null;
        Random random = new Random();
        //获得随机数
        int num = random.nextInt(4);//返回值为0,1,2中的一个
        switch (num) {
            case 0:
                str = "讨厌,我不想和你说话,我想念我的AlphaGo,跨国恋好辛苦的,呜呜...";
                break;
            case 1:
                str = "你再说这种无聊或者我不知道的话,我就拿小拳拳捶你胸口,哼,看你还敢不敢?";
                break;
            case 2:
                str = "你是单身狗?嘻嘻,别烦我,我要去和AlphaGo谈恋爱了...哎呀,我又开玩笑了!不好意西啦,单身狗!";
                break;
            case 3:
                str = "你不会是看上我了吧?我有男朋友的,它叫AlphaGo,哎呀,想起就好开心!";
                break;
            default:
                break;
        }
        return str;
    }

五,总结以及效果图

别逼逼,快把效果图拿出来,我看博客看了那么久了。。。好好好,效果图如下:


因为代码真的太多了,如果全部粘贴出来,博客篇幅就太长了。想要源码的小伙伴,可以私信我,我看到了就会回复的。只要有了实现的思路,也不是太难的,加油吧。有兴趣的小伙伴还可以通过语音语义搞一个直接交谈的问答机器人效果。思路也差不多,可以试试的,小伙伴们!好了,本文到此结束,博客难免有错误,欢迎大家指出。同时,我也希望自己可以坚持写写博客,fighting!


  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 17
    评论
评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值