跳转至

语音对话接入文档

文档状态

文件标识: TuringOS-Chat-V1.1
系统版本: SDK
完成日期: 2022年11月24日

文档修订记录

文档版本号 修订日期 修订原因
V1.0 2022.8.30 创建文档
V1.1 2022.11.24 增加语音翻译及文本翻译说明
V1.2 2023.9.11 新增AIGC使用说明
V1.3 2023.10.12 优化文档
V1.4 2023.11.15 新增口语老师接口说明
V1.5 2024.05.06 新增口语老师Demo源码下载地址等
V1.6 2024.05.10 口语老师协议新增超纲词汇

概述

语音对话人机交互(FIXME 产品补充)

语音对话功能是 ASR + NLP + TTS 的串联,即完整的人机交互链路。外部输入文字或者语音,支持SDK内置录音及APP端录音,SDK返回语义理解后的文字和音频数据。

集成步骤

1. 添加依赖库

//必须依赖库
implementation 'com.google.code.gson:gson:2.6.2'
implementation 'com.squareup.okhttp3:okhttp:3.9.0'
implementation "org.java-websocket:Java-WebSocket:1.4.0"
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'com.aliyun.dpa:oss-android-sdk:2.9.11'//SDKV2.4.1.25 以后需加入
//vad所需
implementation 'com.microsoft.onnxruntime:onnxruntime-android:1.15.1'

2. 权限声明

网络权限 - 使用过程中,会有https与wss请求、网络状态检测

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> 

存储权限 - 使用过程中,会写入日志文件、保存临时音频文件(debug),请在清单中指定以下内容。

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />   
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- android10 以上需要额外添加-->
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />

在android10及以上需要在application标签下添加如下配置

<application android:requestLegacyExternalStorage="true">

音频录制权限 - 在使用过程中录制音频,您的应用必须申请音频捕获权限。

<uses-permission android:name="android.permission.RECORD_AUDIO" />  

3. 配置文件

将turing_config.json配置文件放在main/assets文件夹下

{
  "authorization": {
    "apikey": "您的apikey",
    "secret": "您的secret"
  },
  "ability": {
    "nlp": {
      "codes": [],
      "robotSkills": {
      }
    },
    "tts": {
      "tone": "huiting",
      "format": "MP3_16_16",
      "speed": 5,
      "volume": 3,
      "pitch": 5,
      "arousal": 6
    },
    "asr": {
      "asrSrcFormatEnum": -1,
      "asrFormatEnum": 0,
      "asrLanguageEnum": 0,
      "asrRateEnum": 16000,
      "channel": 1,
      "enableITN": true,
      "enablePunctuation": false,
      "enableVoiceDetection": false,
      "intermediateResult": true,
      "maxEndSilence": 1000,
      "maxStartSilence": 5000,
      "vadThreshold": 0.1,
      "vadReviseTime": 1200,
      "vadState": false,
      "interactionTime": 20,
      "enableCloudVad": false,
      "enableVolume": false,
      "audioSource": 1
    }
  }
}

4. 代码混淆

代码混淆文件proguard-project.txt,添加如下内容

    -keep class com.turing.**{ *;}
    -dontwarn com.turing.**

    -keep class com.tuling.**{ *;}
    -dontwarn com.tuling.**

    -keep class org.java_websocket.**{*;}
    -dontwarn org.java_websocket.**
    -keep class org.slf4j.**{*;}
    -dontwarn org.slf4j.**

    -keep class org.eclipse.** { *; }
    -dontwarn org.eclipse.**

5. SDK 初始化

使用任何能力前调用,请先调用SDK初始化代码。(SDK初始化详情见《接入指南说明文档》)

TuringInitializer.getInstance().initV3XXX()

6. 实例化

var turingChat = TuringChat.getInstance(this)

接口说明

public interface TuringChatInterface {
    /**
     * 获取SDK版本
     *
     * @return 版本号
     */
    @Deprecated
    String getSDKVersion();

    /**9
     * 资源释放
     */
    void release();

    /**
     * 输入文字不播放音频,使用全局配置文件Turing_config.json中的参数
     *
     * @param text        输入文本
     * @param isAssignNlp 是否使用配置文件中的nlp参数
     * @param isAssignTts 是否使用配置文件中的tts参数
     * @param listener    回调接口
     */
    void actionChat(@NonNull String text, boolean isAssignNlp, boolean isAssignTts, final TuringOSClientListener listener);

    /**
     * 输入文字不播放音频,参数局部生效,如:nlpRequestConfig仅在此方法生效
     *
     * @param text             输入文本
     * @param nlpRequestConfig nlp请求参数,如设置为空,则使用全局配置文件中的nlp配置,如没有nlp配置,则使用默认值
     * @param ttsRequestConfig tts请求参数,如设置为空,则使用全局配置文件中的tts配置,如没有tts配置,则使用默认值
     * @param listener         回调接口
     */
    void actionChat(@NonNull String text, NlpRequestConfig nlpRequestConfig, TtsRequestConfig ttsRequestConfig, final TuringOSClientListener listener);

    /**
     * 输入文字并播放音频,使用全局配置文件Turing_config.json中的参数,需配置nlp、tts参数
     *
     * @param text         输入文本
     * @param listener     对话回调
     * @param playListener 音频播放回调
     */
    void actionChatAndPlay(@NonNull String text, TuringOSClientListener listener, TuringOSClientPlayListener playListener);

    /**
     * 输入文字并播放音频
     *
     * @param text             输入文本
     * @param nlpRequestConfig nlp请求参数,如设置为空,则使用全局配置文件中的nlp配置,如没有nlp配置,则使用默认值
     * @param ttsRequestConfig tts请求参数,如设置为空,则使用全局配置文件中的tts配置,如没有tts配置,则使用默认值
     * @param listener         回调接口
     * @param playListener     音频播放回调接口
     */
    void actionChatAndPlay(@NonNull String text, NlpRequestConfig nlpRequestConfig, TtsRequestConfig ttsRequestConfig, TuringOSClientListener listener, TuringOSClientPlayListener playListener);

    /**
     * 输入文字不播放音频,使用全局配置文件Turing_config.json中的参数
     *
     * @param text        输入文本
     * @param enableTts   参数可以指定此次对话是否需要返回音频,当为false时,不返回语义理解结果对应的音频,只返回语义理解的文字结果
     * @param isAssignNlp 是否使用配置文件中的nlp参数
     * @param isAssignTts 是否使用配置文件中的tts参数
     * @param listener    回调接口
     */
    void actionChat(@NonNull String text, boolean enableTts, boolean isAssignNlp, boolean isAssignTts, final TuringOSClientListener listener);

    /**
     * 输入文字不播放音频
     *
     * @param text             输入文本
     * @param enableTts        参数可以指定此次对话是否需要返回音频,当为false时,不返回语义理解结果对应的音频,只返回语义理解的文字结果
     * @param nlpRequestConfig nlp请求参数,如设置为空,则使用Turing_config.json中的nlp配置,如没有nlp配置,则使用默认值
     * @param ttsRequestConfig tts请求参数,如设置为空,则使用Turing_config.json中的tts配置,如没有tts配置,则使用默认值
     * @param listener         回调接口
     */
    void actionChat(@NonNull String text, boolean enableTts, NlpRequestConfig nlpRequestConfig, TtsRequestConfig ttsRequestConfig, final TuringOSClientListener listener);

    /**
     * 录音不播放音频,使用全局配置文件Turing_config.json中的参数,需配置nlp、tts、asr参数。
     *
     * @param enableTts   参数可以指定此次对话是否需要返回音频,当为false时,不返回语义理解结果对应的音频,只返回语义理解的文字结果
     * @param isAssignAsr 是否使用配置文件中的asr参数
     * @param isAssignNlp 是否使用配置文件中的nlp参数
     * @param isAssignTts 是否使用配置文件中的tts参数
     * @param listener    回调接口
     */
    void startChatWithRecorder(boolean enableTts, boolean isAssignAsr, boolean isAssignNlp, boolean isAssignTts, TuringOSClientAsrListener listener);

    /**
     * 录音不播放音频
     *
     * @param enableTts        参数可以指定此次对话是否需要返回音频,当为false时,不返回语义理解结果对应的音频,只返回语义理解的文字结果
     * @param asrRequestConfig asr请求参数,如设置为空,则使用Turing_config.json中的asr配置,如没有asr配置,则使用默认值
     * @param nlpRequestConfig nlp请求参数,如设置为空,则使用Turing_config.json中的nlp配置,如没有nlp配置,则使用默认值
     * @param ttsRequestConfig tts请求参数,如设置为空,则使用Turing_config.json中的tts配置,如没有tts配置,则使用默认值
     * @param listener         回调接口
     */
    void startChatWithRecorder(boolean enableTts, AsrRequestConfig asrRequestConfig, NlpRequestConfig nlpRequestConfig, TtsRequestConfig ttsRequestConfig, final TuringOSClientAsrListener listener);


    /**
     * 录音并播放音频,使用全局配置文件Turing_config.json中的参数,需配置nlp、tts、asr参数。
     * 该方式SDK会开启录音进行ASR识别,并将ASR结果请求NLP和TTS,成功获取结果后会直接播放音频;
     *
     * @param listener     回调接口
     * @param playListener 音频播放回调接口
     */
    void startChatWithRecorderAndSpeak(TuringOSClientAsrListener listener, TuringOSClientPlayListener playListener);

    /**
     * 录音并播放音频
     * 该方式SDK会开启录音进行ASR识别,并将ASR结果请求NLP和TTS,成功获取结果后会直接播放音频;
     *
     * @param asrRequestConfig asr请求参数,如设置为空,则使用Turing_config.json中的asr配置,如没有asr配置,则使用默认值
     * @param nlpRequestConfig nlp请求参数,如设置为空,则使用Turing_config.json中的nlp配置,如没有nlp配置,则使用默认值
     * @param ttsRequestConfig tts请求参数,如设置为空,则使用Turing_config.json中的tts配置,如没有tts配置,则使用默认值
     * @param listener         回调接口
     * @param playListener     音频播放回调接口
     */
    void startChatWithRecorderAndSpeak(AsrRequestConfig asrRequestConfig, NlpRequestConfig nlpRequestConfig, TtsRequestConfig ttsRequestConfig, TuringOSClientAsrListener listener, TuringOSClientPlayListener playListener);

    /**
     * 初始化语音链路,不播放音频,用于应用发送音频到SDK的方式。使用全局配置文件Turing_config.json中的参数,需配置nlp、tts、asr参数
     * 配合sendAudio(byte[] dataBuffer, int length)方法使用。
     *
     * @param enableTts   是否合成TTS
     * @param isAssignNlp 是否使用配置文件中的nlp参数
     * @param isAssignTts 是否使用配置文件中的tts参数
     * @param listener    回调接口
     */
    void initChatStream(boolean enableTts, boolean isAssignNlp, boolean isAssignTts, final TuringOSClientAsrListener listener);

    /**
     * 初始化语音链路,不播放音频,用于应用发送音频到SDK的方式。配合sendAudio(byte[] dataBuffer, int length)方法使用。
     *
     * @param enableTts        是否合成TTS
     * @param asrRequestConfig asr请求参数,如设置为空,则使用Turing_config.json中的asr配置,如没有asr配置,则使用默认值
     * @param nlpRequestConfig nlp请求参数,如设置为空,则使用Turing_config.json中的nlp配置,如没有nlp配置,则使用默认值
     * @param ttsRequestConfig tts请求参数,如设置为空,则使用Turing_config.json中的tts配置,如没有tts配置,则使用默认值
     * @param listener         回调接口
     */
    void initChatStream(boolean enableTts, AsrRequestConfig asrRequestConfig, NlpRequestConfig nlpRequestConfig, TtsRequestConfig ttsRequestConfig, final TuringOSClientAsrListener listener);

    /**
     * 初始化语音链路,播放音频,用于应用发送音频到SDK的方式。使用全局配置文件Turing_config.json中的参数,需配置nlp、tts,asr参数
     * 配合sendAudio(byte[] dataBuffer, int length)方法使用。
     *
     * @param listener     回调接口
     * @param playListener 播放音频回调接口
     */
    void initChatStreamAndPlay(TuringOSClientAsrListener listener, TuringOSClientPlayListener playListener);

    /**
     * 初始化语音链路,播放音频,用于应用发送音频到SDK的方式。使用全局配置文件Turing_config.json中的参数,配合sendAudio(byte[] dataBuffer, int length)方法使用。
     *
     * @param asrRequestConfig asr请求参数,如设置为空,则使用Turing_config.json中的asr配置,如没有asr配置,则使用默认值
     * @param nlpRequestConfig nlp请求参数,如设置为空,则使用Turing_config.json中的nlp配置,如没有nlp配置,则使用默认值
     * @param ttsRequestConfig tts请求参数,如设置为空,则使用Turing_config.json中的tts配置,如没有tts配置,则使用默认值
     * @param listener         回调接口
     * @param playListener     播放音频回调接口
     */
    void initChatStreamAndPlay(AsrRequestConfig asrRequestConfig, NlpRequestConfig nlpRequestConfig, TtsRequestConfig ttsRequestConfig, TuringOSClientAsrListener listener, TuringOSClientPlayListener playListener);

    /**
     * 发送音频数据流
     *
     * @param dataBuffer 音频数据,建议单包长度为1280个byte,小于6400个byte
     * @param length     音频数据长度
     */
    void sendAudio(byte[] dataBuffer, int length);

    /**
     * 结束录音,正常返回结果
     * 不使用vad功能时或想提前结束录音时,调用此接口
     */
    void stopChat();

    /**
     * 取消对话,丢弃本次对话结果
     */
    void cancelChat();

    /**
     * @return 是否正在播放语音
     */
    boolean isPlaying();

    /**
     * 暂停播放
     *
     * @return 是否暂停成功
     */
    boolean actionPausePlay();

    /**
     * 重新播放
     *
     * @return 是否播放成功
     */
    boolean actionResumePlay();

    /**
     * 停止播放
     *
     * @return 是否停止播放成功
     */
    boolean actionStopPlay();

    /**
     * 上传通讯录与APP列表
     *
     * @param appAndContactsBean     上传数据;数据封装在 {@link AppAndContactsBean}中
     * @param turingOSClientListener 网络请求回调 {@link TuringOSClientListener}
     */
    void uploadAppsAndContacts(AppAndContactsBean appAndContactsBean, TuringOSClientListener turingOSClientListener);

    /**
     * 上传状态,如点赞 。//状态263
     *
     * @param config   请求参数
     * @param listener 回调接口
     */
    void uploadState(StateRequestConfig config, TuringOSClientListener listener);

    /**
     * 获取语言推荐指令接口
     *
     * @param useCodes 技能推荐指令(注意不一定所有可使用技能都有提示语)
     * @param listener 回调接口
     */
    public void getSkillCmd(int[] useCodes, TuringListener<List<SkillCmd>> listener);

    /**
     * 获取指定技能的AIGC结果
     * @param requestCode 技能code
     * @param param 请求参数
     */
    void aigcSkill(int requestCode, Map<String,Object> param,TuringOSClientListener listener);
}

使用说明

功能描述

  • 语音对话模块支持输入音频和文字,对话请求结果支持SDK直接播放或者返回音频内容
  • 输入的音频与ASR模块一致,支持SDK内部录音器或者输入音频字节流数据;
  • 该模块录音场景默认单句识别场景(识别到完整的一句话将停止录音,进入其他链路模块)。

支持的所有方式:

  • 输入文字不播放音频:输入文字,返回对话结果的内容和音频链接,开发者自行实现播放;
  • 输入文字并播放音频:输入文字,返回对话结果的内容,SDK直接进入播放,播放接受基本的暂停/停止等操作,但不返回具体的播放进度等信息;
  • 录音不播放音频:打开SDK录音器识别,返回对话结果的内容和音频链接,开发者自行实现播放;
  • 录音并播放音频:打开SDK录音器识别,返回对话结果的内容,SDK直接进入播放,播放接受基本的暂停/停止等操作,但不返回具体的播放进度等信息;
  • 音频流输入不播放音频:输入音频字节流数据,返回对话结果的内容和音频链接,开发者自行实现播放;
  • 音频流输入并播放音频:输入音频字节流数据,返回对话结果的内容,SDK直接进入播放,播放接受基本的暂停/停止等操作,但不返回具体的播放进度等信息;

备注

1.开发者可根据产品具体需求和不同场景自行选取合适的方式;

2.所有场景中,ASR通道同一时间只能开启一个,包括语音聊天、ASR识别、绘本内的录音交互。

语音对话调用

接口类型

  • 类型一:全局使用turing_config中的配置参数,需要在 turing_config.json 中添加 nlpttsasr 节点,节点字段见《接入指南说明文档》配置文件参数说明。可使用TuringConfig.setConfigData设置全局配置参数,此参数在使用到配置文件的接口全局生效,适用于不频繁修改参数场景
  • 类型二:不使用 turing_config.json 中的配置,使用入参带AsrRequestConfig、NlpRequestConfig、TtsRequestConfig 的接口,此参数仅调用时生效,适用于频繁修改参数场景。

对象实例化

val turingChat: TuringChatInterface = TuringChat.getInstance(this)

一、输入文字不播放音频

  • 该方式可以输入文字,返回对话结果的文本内容以及音频链接,可根据返回的音频链接自行实现播放的过程,播放过程由开发者控制;
  • 文字输入的语音对话不包括ASR识别过程,所以回调接口需要使用TuringOSClientListener。
  • enableTts可指定此次对话是否合成tts

方法一:使用全局配置文件turing_config.json中的参数,nlp参数和tts参数,默认使用聊天技能

//直接修改全局配置参数,所有使用到全局配置参数的方法都会生效
val nlp = TuringConfig.getInstance(this).configData.ability.nlp
nlp.codes = mutableListOf(1000018)
val tts = TuringConfig.getInstance(this).configData.ability.tts
tts.speed = 10
turingChat.actionChat("今天天气",true,true,object :TuringOSClientListener{
            override fun onResult(
                code: Int,
                result: String?,
                baseResp: BaseResp?,
                extension: String?
            ) {
                TODO("Not yet implemented")
            }

            override fun onError(code: Int, msg: String?) {
                TODO("Not yet implemented")
            }

        })

方法二:使用局部生效参数,输入NlpRequestConfig和TtsRequestConfig参数,可以指定此次对话使用的技能参数与此次对话合成的音频参数

//指定全文翻译技能1000018
val nlpConfig = NlpRequestConfig.Builder().codes(mutableListOf(1000018)).build()
//设置合成tts的速度为10
val ttsConfig = TtsRequestConfig.Builder().speed(10).build()
turingChat.actionChat("今天天气",nlpConfig,ttsConfig,object :TuringOSClientListener{
    override fun onResult(
        code: Int,
        result: String?,
        baseResp: BaseResp?,
        extension: String?
    ) {
        TODO("Not yet implemented")
    }
    override fun onError(code: Int, msg: String?) {
        TODO("Not yet implemented")
    }

输出说明

该方式的返回结果TuringOSClientListener接口中回调:

  • 对话结果的文本内容和播放内容在BaseResp-NlpResponse-List-Results中,其他详细内容具体字段说明参考BaseResp说明;
  • 每一次独立的对话请求会返回onResult或onError;
  • 请求成功的结果json字符串对应result;
  • extension:扩展输出字段,该模块暂时没有输出。

二、输入文字并播放音频

  • 该方式输入目标文字之后,会返回对话结果的文字,并且SDK会播放音频,回调播放状态;
  • 播放状态将在TuringOSClientPlayListener回调;
  • 该方式不输出音频相关的链接或者文件,请求后直接进入播放状态;
  • NlpRequestConfig、TtsRequestConfigke可以为null。

方法一:使用全局配置文件turing_config.json中的参数,nlp参数和tts参数

//直接修改全局配置参数,所有使用到全局配置参数的方法都会生效
val nlp = TuringConfig.getInstance(this).configData.ability.nlp
nlp.codes = mutableListOf(1000018)
val tts = TuringConfig.getInstance(this).configData.ability.tts
tts.speed = 10
turingChat.actionChatAndPlay("今天天气",object :TuringOSClientListener{
            override fun onResult(
                code: Int,
                result: String?,
                baseResp: BaseResp?,
                extension: String?
            ) {
                TODO("Not yet implemented")
            }

            override fun onError(code: Int, msg: String?) {
                TODO("Not yet implemented")
            }
        },object :TuringOSClientPlayListener{
            override fun onPlayStart(text: String?) {
                TODO("Not yet implemented")
            }

            override fun onPlayError(message: String?) {
                TODO("Not yet implemented")
            }

            override fun onPlayComplete() {
                TODO("Not yet implemented")
            }

            override fun onPlayPaused() {
                TODO("Not yet implemented")
            }

            override fun onPlayResumed() {
                TODO("Not yet implemented")
            }

        })          

方法二:使用局部生效参数,输入NlpRequestConfig和TtsRequestConfig参数,可以指定此次对话使用的技能参数与此次对话合成的音频参数

//指定全文翻译技能1000018
val nlpConfig = NlpRequestConfig.Builder().codes(mutableListOf(1000018)).build()
//设置合成tts的速度为10
val ttsConfig = TtsRequestConfig.Builder().speed(10).build()
turingChat.actionChatAndPlay("今天天气",nlpConfig,ttsConfig,object :TuringOSClientListener{
    override fun onResult(
        code: Int,
        result: String?,
        baseResp: BaseResp?,
        extension: String?
    ) {
        TODO("Not yet implemented")
    }

    override fun onError(code: Int, msg: String?) {
        TODO("Not yet implemented")
    }
},object :TuringOSClientPlayListener{
    override fun onPlayStart(text: String?) {
        TODO("Not yet implemented")
    }

    override fun onPlayError(message: String?) {
        TODO("Not yet implemented")
    }

    override fun onPlayComplete() {
        TODO("Not yet implemented")
    }

    override fun onPlayPaused() {
        TODO("Not yet implemented")
    }

    override fun onPlayResumed() {
        TODO("Not yet implemented")
    }

})

输出说明

该方式的返回结果TuringOSClientListener接口中回调,播放状态在TuringOSClientPlayListener接口中回调

  • 对话结果的文本内容在BaseResp-NlpResponse-List-Results中,不包含播放内容,其他详细内容具体字段说明参考BaseResp说明;
  • 每一次独立的对话请求会返回onResult或onError;
  • 请求成功的结果json字符串对应result;
  • extension:扩展输出字段,该模块暂时没有输出;
  • 调用开启后直接进入播放状态,播放状态控制参考播放控制。

三、录音不播放音频

  • 该方式包含ASR识别过程,所以整个过程有两次关键性的返回:1.ASR识别的最终识别结果(如果ASR参数打开了实时返回识别结果的开关,TuringOSClientAsrListener接口的onResult会实时回调识别结果;2.NLP+TTS处理之后的结果,即语音对话的结果;
  • enableTts参数可以指定此次对话是否需要返回音频,当为false时,不返回语义理解结果对应的音频,只返回语义理解的文字结果;
  • 当使用场景中不需要音频时可以设置enableTts位false,这样可以降低请求耗时;
  • 录音的控制参考ASR模块ASR的停止和释放。

方法一:使用全局配置文件turing_config.json中的参数,nlp、tts、asr参数,enableTts可以指定此次对话是否需要返回音频

//直接修改全局配置参数,所有使用到全局配置参数的方法都会生效
val nlp = TuringConfig.getInstance(this).configData.ability.nlp
nlp.codes = mutableListOf(1000018)
val tts = TuringConfig.getInstance(this).configData.ability.tts
tts.speed = 10
val asr = TuringConfig.getInstance(this).configData.ability.asr
asr.asrRateEnum = AsrRequestConfig.RATE_16000
asr.channel = AsrRequestConfig.CHANNEL_IN_MONO
turingChat.startChatWithRecorder(true,true,true,true,
    object : TuringOSClientAsrListener {
        override fun onRecorderStart() {
            TODO("Not yet implemented")
        }

        override fun onStop() {
            TODO("Not yet implemented")
        }

        override fun onStreamOpen() {
            TODO("Not yet implemented")
        }

        override fun onResult(
            code: Int,
            result: String?,
            isLast: Boolean,
            baseResp: BaseResp?
        ) {
            TODO("Not yet implemented")
        }

        override fun onTimer(second: Int) {
            TODO("Not yet implemented")
        }

        override fun onError(code: Int, msg: String?) {
            TODO("Not yet implemented")
        }

        override fun onVoiceVolume(i: Int) {
            TODO("Not yet implemented")
        }

    })

方法二:使用局部生效参数,可以指定AsrRequestConfig、NlpRequestConfig、TtsRequestConfig,enableTts可以指定此次对话是否需要返回音频

//设置单声道,16k采样率
val asrConfig = AsrRequestConfig.Builder().channel(AsrRequestConfig.CHANNEL_IN_MONO)
    .asrRateEnum(AsrRequestConfig.RATE_16000).build()
//指定全文翻译技能1000018
val nlpConfig = NlpRequestConfig.Builder().codes(mutableListOf(1000018)).build()
//设置合成tts的速度为10
val ttsConfig = TtsRequestConfig.Builder().speed(10).build()
turingChat.startChatWithRecorder(true,asrConfig,nlpConfig,ttsConfig,
    object : TuringOSClientAsrListener {
        override fun onRecorderStart() {
            TODO("Not yet implemented")
        }

        override fun onStop() {
            TODO("Not yet implemented")
        }

        override fun onStreamOpen() {
            TODO("Not yet implemented")
        }

        override fun onResult(
            code: Int,
            result: String?,
            isLast: Boolean,
            baseResp: BaseResp?
        ) {
            TODO("Not yet implemented")
        }

        override fun onTimer(second: Int) {
            TODO("Not yet implemented")
        }

        override fun onError(code: Int, msg: String?) {
            TODO("Not yet implemented")
        }

        override fun onVoiceVolume(i: Int) {
            TODO("Not yet implemented")
        }

    })

输出说明

该方式的返回结果TuringOSClientAsrListener接口中回调,播放状态在TuringOSClientPlayListener接口中回调

  • ASR识别结果会在onResult中输出,具体过程与ASR模块ASR识别一致,当ASR识别结果完整,即isLast为true时,开始输出对话的结果;
  • 对话结果也在onResult中输出,具体文本内容和播放内容在BaseResp-NlpResponse-List-Results中,其他详细内容具体字段说明参考BaseResp说明;
  • 请求成功的结果json字符串对应result;
  • extension:扩展输出字段,该模块暂时没有输出;
  • 该方法需要开发者自行播放音频。

四、录音并播放音频

  • 该方式包含ASR识别过程,所以整个过程有两次关键性的返回:1.ASR识别的最终识别结果(如果ASR参数打开了实时返回识别结果的开关,TuringOSClientAsrListener接口的onResult会实时回调识别结果;2.NLP+TTS处理之后的结果,即语音对话的结果;
  • 该方式SDK会开启录音进行ASR识别,并将ASR结果请求NLP和TTS,成功获取结果后会直接播放音频;
  • 播放状态由TuringOSClientPlayListener回调;
  • 录音的控制参考ASR模块ASR的停止和释放。

方法一:使用全局配置文件Turing_config.json中的参数,需配置nlp、tts、asr参数

//直接修改全局配置参数,所有使用到全局配置参数的方法都会生效
val nlp = TuringConfig.getInstance(this).configData.ability.nlp
nlp.codes = mutableListOf(1000018)
val tts = TuringConfig.getInstance(this).configData.ability.tts
tts.speed = 10
val asr = TuringConfig.getInstance(this).configData.ability.asr
asr.asrRateEnum = AsrRequestConfig.RATE_16000
turingChat.startChatWithRecorderAndSpeak(turingOSClientAsrListener,turingOSClientPlayListener)                 

方法二:使用局部生效参数,可以指定AsrRequestConfig、NlpRequestConfig、TtsRequestConfig,enableTts可以指定此次对话是否需要返回音频

//设置单声道,16k采样率
val asrConfig = AsrRequestConfig.Builder().channel(AsrRequestConfig.CHANNEL_IN_MONO)
    .asrRateEnum(AsrRequestConfig.RATE_16000).build()
//指定全文翻译技能1000018
val nlpConfig = NlpRequestConfig.Builder().codes(mutableListOf(1000018)).build()
//设置合成tts的速度为10
val ttsConfig = TtsRequestConfig.Builder().speed(10).build()
turingChat.startChatWithRecorderAndSpeak(asrConfig,nlpConfig,ttsConfig,turingOSClientAsrListener,turingOSClientPlayListener)

输出说明

该方式的返回结果TuringOSClientAsrListener接口中回调,播放状态在TuringOSClientPlayListener接口中回调

  • ASR识别结果会在onResult中输出,具体过程与ASR模块ASR识别一致,当ASR识别结果完整,即isLast为true时,开始输出对话的结果;
  • 对话结果也在onResult中输出,具体文本内容和播放内容在BaseResp-NlpResponse-List-Results中,其他详细内容具体字段说明参考BaseResp说明;
  • 请求成功的结果json字符串对应result;
  • extension:扩展输出字段,该模块暂时没有输出;
  • 调用开启后直接进入播放状态,播放状态控制参考播放控制。

五、音频流不播放音频

  • 该方式包含ASR识别过程,所以整个过程有两次关键性的返回:1.ASR识别的最终识别结果(如果ASR参数打开了实时返回识别结果的开关,TuringOSClientAsrListener接口的onResult会实时回调识别结果;2.NLP+TTS处理之后的结果,即语音对话的结果;
  • 该方式支持输入音频数据流进行聊天对话,返回音频播放地址,播放过程由开发者控制;
  • enableTts参数可以指定此次对话是否需要返回音频,当为false时,不返回语义理解结果对应的音频,只返回语义理解的文字结果;
  • 当使用场景中不需要音频时可以设置enableTts位false,这样可以降低请求耗时。
  • 调用过程与流式输入ASR识别过程一样,具体参考ASR模块流式输入。

方法说明

第一步:先调用初始化方法

初始化方法一:使用全局配置文件Turing_config.json中的参数,需配置nlp、tts、asr参数

//直接修改全局配置参数,所有使用到全局配置参数的方法都会生效
val nlp = TuringConfig.getInstance(this).configData.ability.nlp
nlp.codes = mutableListOf(1000018)
val tts = TuringConfig.getInstance(this).configData.ability.tts
tts.speed = 10
val asr = TuringConfig.getInstance(this).configData.ability.asr
asr.asrRateEnum = AsrRequestConfig.RATE_16000
//必须设置此参数,详细说明见asr参数说明
asr.asrSrcFormatEnum = AsrRequestConfig.PCM
asr.channel = AsrRequestConfig.CHANNEL_IN_MONO
turingChat.initChatStream(true,true,true,object :TuringOSClientAsrListener{
            override fun onRecorderStart() {
                TODO("Not yet implemented")
            }

            override fun onStop() {
                TODO("Not yet implemented")
            }

            override fun onStreamOpen() {
                //在此方法中启动录音
                startRecord()
            }

            override fun onResult(
                code: Int,
                result: String?,
                isLast: Boolean,
                baseResp: BaseResp?
            ) {
                TODO("Not yet implemented")
            }

            override fun onTimer(second: Int) {
                TODO("Not yet implemented")
            }

            override fun onError(code: Int, msg: String?) {
                TODO("Not yet implemented")
            }

            override fun onVoiceVolume(i: Int) {
                TODO("Not yet implemented")
            }

        })

初始化方法二:使用局部生效参数,可以指定AsrRequestConfig、NlpRequestConfig、TtsRequestConfig,enableTts可以指定此次对话是否需要返回音频

//设置单声道,16k采样率
val asrConfig = AsrRequestConfig.Builder().channel(AsrRequestConfig.CHANNEL_IN_MONO)
    .asrRateEnum(AsrRequestConfig.RATE_16000)
    .asrSrcFormatEnum(AsrRequestConfig.PCM)//必须设置此参数
    .build()
//指定全文翻译技能1000018
val nlpConfig = NlpRequestConfig.Builder().codes(mutableListOf(1000018)).build()
//设置合成tts的速度为10
val ttsConfig = TtsRequestConfig.Builder().speed(10).build()
turingChat.initChatStream(true,true,true,turingOSClientAsrListener)

第二步:调用发送音频的方法

fun startRecord(){ 
    val oneFrame = ByteArray(1280)
    if (ActivityCompat.checkSelfPermission(
            this,
            Manifest.permission.RECORD_AUDIO
        ) != PackageManager.PERMISSION_GRANTED
    ) {
        return
    }
    audioRecordr = AudioRecord(
        MediaRecorder.AudioSource.VOICE_RECOGNITION, 16000,
        AudioFormat.CHANNEL_IN_STEREO, AudioFormat.ENCODING_PCM_16BIT, FRAME_SIZE
    )
    audioRecordr?.startRecording()
    mIsRecording = true
    CoroutineScope(job).launch {
        while (mIsRecording) {
            var readLen = -1
            readLen = audioRecordr!!.read(oneFrame, 0, oneFrame.size)
            if (readLen > 0)//在读取音频的回调中发送音频
                turingChat.sendAudio(oneFrame.clone(), oneFrame.size)
            else if (mIsRecording) {
                mIsRecording = false
                break
            }
        }
    }
}

第三步:结束录音

如果没有使用vad,或者需要提前结束录音,可以调用此方法,如果使用了vad,则可不调此方法

​ 方法一:正常返回此次结果。

turingChat.stopChat()

​ 方法二:取消对话,不返回此次结果,可用打断识别,不需要结果的场景

turingChat.cancelChat()

输出说明

该方式的返回结果TuringOSClientAsrListener接口中回调:

  • ASR识别结果会在onResult中输出,具体过程与ASR模块ASR识别一致,当ASR识别结果完整,即isLast为true时,开始输出对话的结果;
  • 对话结果也在onResult中输出,具体文本内容和播放内容在BaseResp-NlpResponse-List-Results中,其他详细内容具体字段说明参考BaseResp说明;
  • 请求成功的结果json字符串对应result;
  • extension:扩展输出字段,该模块暂时没有输出。

六、音频流并播放音频

  • 该方式包含ASR识别过程,所以整个过程有两次关键性的返回:1.ASR识别的最终识别结果(如果ASR参数打开了实时返回识别结果的开关,TuringOSClientAsrListener接口的onResult会实时回调识别结果;2.NLP+TTS处理之后的结果,即语音对话的结果;
  • 该方式SDK会开启录音进行ASR识别,并将ASR结果请求NLP和TTS,成功获取结果后会直接播放音频;
  • 播放状态由TuringOSClientPlayListener回调。
  • 调用过程与流式输入ASR识别过程一样,具体参考ASR模块流式输入。

方法说明

第一步:先调用初始化方法

初始化方法一:使用全局配置文件Turing_config.json中的参数,需配置nlp、tts、asr参数

//直接修改全局配置参数,所有使用到全局配置参数的方法都会生效
val nlp = TuringConfig.getInstance(this).configData.ability.nlp
nlp.codes = mutableListOf(1000018)
val tts = TuringConfig.getInstance(this).configData.ability.tts
tts.speed = 10
val asr = TuringConfig.getInstance(this).configData.ability.asr
asr.asrRateEnum = AsrRequestConfig.RATE_16000
//必须设置此参数,详细说明见asr参数说明
asr.asrSrcFormatEnum = AsrRequestConfig.PCM
asr.channel = AsrRequestConfig.CHANNEL_IN_MONO

turingChat.initChatStreamAndPlay(object :TuringOSClientAsrListener{
    override fun onRecorderStart() {
        TODO("Not yet implemented")
    }

    override fun onStop() {
        TODO("Not yet implemented")
    }

    override fun onStreamOpen() {
        //在此方法中启动录音
        startRecord()
    }

    override fun onResult(
        code: Int,
        result: String?,
        isLast: Boolean,
        baseResp: BaseResp?
    ) {
        TODO("Not yet implemented")
    }

    override fun onTimer(second: Int) {
        TODO("Not yet implemented")
    }

    override fun onError(code: Int, msg: String?) {
        TODO("Not yet implemented")
    }

    override fun onVoiceVolume(i: Int) {
        TODO("Not yet implemented")
    }

},object :TuringOSClientPlayListener{
    override fun onPlayStart(text: String?) {
        TODO("Not yet implemented")
    }

    override fun onPlayError(message: String?) {
        TODO("Not yet implemented")
    }

    override fun onPlayComplete() {
        TODO("Not yet implemented")
    }

    override fun onPlayPaused() {
        TODO("Not yet implemented")
    }

    override fun onPlayResumed() {
        TODO("Not yet implemented")
    }

})

初始化方法二:使用局部生效参数,可以指定AsrRequestConfig、NlpRequestConfig、TtsRequestConfig,enableTts可以指定此次对话是否需要返回音频

//设置单声道,16k采样率
val asrConfig = AsrRequestConfig.Builder().channel(AsrRequestConfig.CHANNEL_IN_MONO)
    .asrRateEnum(AsrRequestConfig.RATE_16000)
    .asrSrcFormatEnum(AsrRequestConfig.PCM)//必须设置此参数
    .build()
//指定全文翻译技能1000018
val nlpConfig = NlpRequestConfig.Builder().codes(mutableListOf(1000018)).build()
//设置合成tts的速度为10
val ttsConfig = TtsRequestConfig.Builder().speed(10).build()
turingChat.initChatStreamAndPlay(asrConfig,nlpConfig,ttsConfig,turingOSClientAsrListener,turingOSClientPlayListener)

第二步:调用发送音频的方法

fun startRecord(){ 
    val oneFrame = ByteArray(1280)
    if (ActivityCompat.checkSelfPermission(
            this,
            Manifest.permission.RECORD_AUDIO
        ) != PackageManager.PERMISSION_GRANTED
    ) {
        return
    }
    audioRecordr = AudioRecord(
        MediaRecorder.AudioSource.VOICE_RECOGNITION, 16000,
        AudioFormat.CHANNEL_IN_STEREO, AudioFormat.ENCODING_PCM_16BIT, FRAME_SIZE
    )
    audioRecordr?.startRecording()
    mIsRecording = true
    CoroutineScope(job).launch {
        while (mIsRecording) {
            var readLen = -1
            readLen = audioRecordr!!.read(oneFrame, 0, oneFrame.size)
            if (readLen > 0)//在读取音频的回调中发送音频
                turingChat.sendAudio(oneFrame.clone(), oneFrame.size)
            else if (mIsRecording) {
                mIsRecording = false
                break
            }
        }
    }
}

第三步:结束录音

​ 方法一:正常返回此次结果。如果没有使用vad,或者需要提前结束录音,可以调用此方法,如果使用了vad,则可不调此方法

turingChat.stopChat()

​ 方法二:取消对话,不返回此次结果,可用打断识别,不需要结果的场景

turingChat.cancelChat()

输出说明

该方式的返回结果TuringOSClientAsrListener接口中回调,播放状态在TuringOSClientPlayListener接口中回调

  • ASR识别结果会在onResult中输出,具体过程与ASR模块ASR识别一致,当ASR识别结果完整,即isLast为true时,开始输出对话的结果;
  • 对话结果也在onResult中输出,具体文本内容和播放内容在BaseResp-NlpResponse-List-Results中,其他详细内容具体字段说明参考BaseResp说明;
  • 请求成功的结果json字符串对应result;
  • extension:扩展输出字段,该模块暂时没有输出;
  • 调用开启后直接进入播放状态,播放状态控制参考播放控制。

播放控制

语音对话模块调用了SDK内部播放的方法时,可以使用以下方法来控制播放。

停止播放:

turingChat.actionStopPlay();

暂停播放:

turingChat.actionPausePlay();

继续播放:

turingChat.actionResumePlay(); 

注意:以上播放控制的方法对TTS合成模块同样有效,所以尽可能明确设备正在处理播放的模块。

VAD

如何使用vad,详情见《在线ASR接入文档》

英英口语老师

统一使用aigcSkill方法,使用方式如下:

val param = mutableMapOf<String,Any>()
        /**
         * 生成话题
         */
        param["grade"]=6
        param["topic"]="哪里比较好玩"
        param["scene"]="旅游出行"
turingChat.aigcSkill(SkillCode.GENERATED_TOPIC,param,object :TuringOSClientListener{
    override fun onResult(
        code: Int,
        result: String?,
        baseResp: BaseResp?,
        extension: String?
    ) {
        //解析result
        Log.e(TAG,result!!)
    }

    override fun onError(code: Int, msg: String?) {
        Log.e(TAG,msg!!)
    }

})

技能code

常量名 说明
SESSION_REPLY 2200 主题对话回复
RECOMMENDED_REPLY 2201 推荐回复
GRAMMAR_CORRECTION 2202 语法纠正
EXPRESSION_RELEVANCY 2203 表达相关度
GENERATED_TOPIC 2204 生成话题
EXPRESSIVE_POLISH 2206 表达润色

主题对话回复

入参说明

参数 类型 是否必须 取值范围 说明
grade int Y 1-6 年级
scene String Y - 场景内容,最多4个汉字
topic String Y - 话题内容,最多7个汉字
lastA String N 英文输入 必须和lastQ同时存在或不存在
lastQ String N 英文输入 必须和lastA同时存在或不存在

输出实例

{
    "desc": "success",
    "code": 200,
    "globalId": 237142832557798000,
    "payload": {
        "beyondWords": [
            {
                "word": "Sure",
                "trans": "确信;确知;肯定;有把握"
            },
            {
                "word": "would",
                "trans": "(will 的过去式,用于转述)将,将会"
            },
            {
                "word": "question",
                "trans": "问题;疑问"
            },
            {
                "word": "supplies",
                "trans": "供应量;供给量;储备"
            }
        ],
        "reply": "Sure, I'd be happy to answer your question. What would you like to know about your school supplies?"
    }
}
参数 类型 是否必须 说明
reply String Y 主题对话回复
beyondWords List N 超纲单词列表
beyondWords-word String N 超纲单词
beyondWords-trans String N 超纲单词翻译

推荐回复

入参说明

参数 类型 是否必须 取值范围 说明
grade int Y 1-6 年级
currQ String Y 英文输入 本轮对话

输出示例

{
    "desc": "success",
    "code": 200,
    "globalId": 237142909709798000,
    "payload": {
        "recommend": [
            "I like to use my pencil to draw pictures.",
            "I like to use my eraser to fix my mistakes.",
            "I like to use my ruler to draw straight lines."
        ],
        "beyondWords": [
            {
                "word": "fix",
                "trans": "使固定;安装"
            },
            {
                "word": "use",
                "trans": "使用;利用;运用"
            },
            {
                "word": "mistakes",
                "trans": "(言语或行为上的)错误,失误"
            },
            {
                "word": "lines",
                "trans": "线;线条"
            }
        ]
    }
}
参数 类型 是否必须 取值范围 说明
recommend array Y - 推荐回复

beyondWords:见主题对话参数说明

语法纠正

入参说明

参数 类型 是否必须 取值范围 说明
currA String Y 英文输入 本轮用户的对话

输出示例

{
    "desc": "success",
    "code": 200,
    "globalId": null,
    "payload": {
        "result": true,
        "message": "这句话是一个简单的陈述句,主语是I,谓语是have,宾语是a pencil。",
        "knowledge": "这句话没有语法错误。"
    }
}
参数 类型 是否必须 取值范围 说明
result boolean Y - 是否有语法错误;true为没语法问题,false为有语法问题
message String N - 错误分析
knowledge String N - 相关语法讲解

表达相关度

入参说明

参数 类型 是否必须 取值范围 说明
currA String Y 英文输入 本轮用户的对话
currQ String Y 英文输入 本轮机器人的对话

输出示例

{
    "desc": "success",
    "code": 200,
    "globalId": null,
    "payload": {
        "score": 80,
        "message": "回答符合语境,学生有铅笔,可以展示给老师看"
    }
}
参数 类型 是否必须 取值范围 说明
score int Y - 表达相关度得分
message String N - 错误分析

生成话题

入参说明

参数 类型 是否必须 取值范围 说明
grade int Y 1-6 年级
topic String Y - 话题内容,最多7个汉字
scene String N - 场景内容,最多4个汉字

输出示例

{
    "desc": "success",
    "code": 200,
    "globalId": 237143234387798000,
    "payload": {
        "chats": [
            {
                "teacher": "What are we going to do in the society activity?",
                "student": "We are going to learn how to put up a tent."
            },
            {
                "teacher": "Great! How do we put up a tent?",
                "student": "First, we need to find a good place to put up the tent."
            },
            {
                "teacher": "What should we do next?",
                "student": "Then, we need to unfold the tent and put the poles in."
            },
            {
                "teacher": "How do we finish putting up the tent?",
                "student": "Finally, we need to secure the tent with stakes and ropes."
            },
            {
                "teacher": "That sounds like a lot of work. Do you think it will be fun?",
                "student": "Yes, I think it will be a lot of fun to learn how to put up a tent and go camping."
            }
        ],
        "beyondWords": [
            {
                "word": "lot",
                "trans": "大量;许多"
            },
            {
                "word": "tent",
                "trans": "帐篷;帐棚"
            },
            {
                "word": "society",
                "trans": "社会(以群体形式生活在一起的人的总称)"
            },
            {
                "word": "camping",
                "trans": "野营度假"
            },
            {
                "word": "stakes",
                "trans": "桩;标桩;篱笆桩"
            },
            {
                "word": "activity",
                "trans": "活动;热闹状况;活跃"
            },
            {
                "word": "putting",
                "trans": "轻击;推球入洞"
            },
            {
                "word": "poles",
                "trans": "竿;杆子;杖;篙"
            },
            {
                "word": "place",
                "trans": "位置;地点;场所;地方"
            },
            {
                "word": "ropes",
                "trans": "粗绳;线缆;绳索"
            },
            {
                "word": "secure",
                "trans": "安心的;有把握的"
            },
            {
                "word": "unfold",
                "trans": "(使)展开;打开"
            },
            {
                "word": "Finally",
                "trans": "终于;最终"
            }
        ]
    }
}
参数 类型 是否必须 取值范围 说明
teacher String Y - 对话内容
student String Y - 对话内容

beyondWords:见主题对话参数说明

表达润色

入参说明

参数 类型 是否必须 取值范围 说明
lastA String Y 限英文 用户的回答文本

输出示例

{
    "desc": "success",
    "code": 200,
    "globalId": 237142981801798000,
    "payload": {
        "express": "The student standing there hailed from Beijing.",
        "beyondWords": [
            {
                "word": "standing",
                "trans": "长期存在的;永久性的;常设的"
            },
            {
                "word": "student",
                "trans": "大学生;研究生"
            },
            {
                "word": "hailed",
                "trans": "赞扬(或称颂)…为(尤用于报章等)"
            }
        ]
    }
}
参数 类型 是否必须 取值范围 说明
express String Y - 润色后内容

beyondWords:见主题对话参数说明

Code说明

code 说明
200 正确返回
-1 未知错误,查看desc信息
44001 非法requestCode请求
44002 请求参数错误,查看desc信息
44003 大模型超时,请重试
44004 请求缺失requestCode
44005 大模型输出参数错误,查看desc信息
44006 参数解密失败
44007 入参为空,未加密apikey不能使用data入参!
44008 PROMPT EMPTY,参数错误,请检查
44009 大模型请求失败 (注意apikey是否授权ChatGPT)
44010 大模型返回json错误(返回中有具体大模型返回内容)

Demo下载

https://turing-appstore.oss-cn-beijing.aliyuncs.com/android/demo/AITeacher.zip

其他功能

上传通讯录与APP列表

private fun uploadAppConstant() {
    val appData = AppAndContactsBean()
    val appMap = HashMap<String, String>()
    //TODO 目前上传接口不支持传入带”:“冒号的字符串,需要自行转换
    appMap.put("微信", "home-//turing-9898/app/main");//"home://turing:9898/app/main"
    appData.appsMap = appMap;
    turingChat.uploadAppsAndContacts(appData, object : TuringOSClientListener {
        override fun onResult(
            code: Int, result: String?, baseResp: BaseResp?,
            extension: String?
        ) {
            Log.d(TAG, "uploadAppsAndContacts onResult:$result")
        }

        override fun onError(code: Int, msg: String?) {
            Log.e(TAG, "uploadAppsAndContacts onError:$msg")
        }
    })
}

上传状态,如点赞

private fun uploadState() {
    val logRequestMap = HashMap<String, Any>();
    val map = HashMap<String, Any>();
    map["type"] = 1
    map["globalId"] = globalId
    logRequestMap["logRequest"] = map
    val config =
        StateRequestConfig.Builder().setActionCode(2081).setActionArgs(logRequestMap).build()
    turingChat.uploadState(config, object : TuringOSClientListener {
        override fun onResult(
            code: Int,
            result: String?,
            baseResp: BaseResp?,
            extension: String?
        ) {
            Log.i(TAG, "uploadState onResult:" + baseResp?.result)
        }

        override fun onError(code: Int, msg: String?) {
            Log.i(TAG, "uploadState onError:$code msg:$msg")
        }

    })
}

获取语言推荐指令

private fun getSkillCmd() {
    val useCode = intArrayOf(10005)
    turingChat.getSkillCmd(useCode, object : TuringListener<List<SkillCmd>> {
        override fun onSuccess(result: List<SkillCmd>?) {
            result?.let {
                for (cmd in result) {
                    Log.e(TAG, cmd.name)
                }
            }
        }

        override fun onError(code: Int, message: String?) {
            Log.e(TAG, "code:$code mes:$message")
        }

    })
}

参数说明

语音对话模块包含了ASR、NLP、TTS,所有相关参数与相应模块相同。

输入参数

  • NlpRequestConfig

对应turing_config.json中的nlp参数

详细说明见 语义理解接入文档#NlpRequestConfig

  • TtsRequestConfig

对应turing_config.json中的tts参数

详细说明见 在线TTS接入文档#TtsRequestConfig

  • AsrRequestConfig

对应turing_config.json中的asr参数

详细说明见 在线ASR接入文档#AsrRequestConfig

  • StateRequestConfig
参数 类型 是否必须 说明
actionCode int 需设置2081
actionArgs Map 拓展参数

actionArgs

参数 类型 是否必须 说明
logRequest Map Y 拓展参数
logRequest-type int Y 默认0(无操作),1踩 2赞
logRequest-globalId String Y 踩、赞那条对话的GID
  • AppAndContactsBean
参数 类型 是否必须 说明
appsMap Map N APP列表。Map key对应A的是PP名称列表,value对应的是APP名称的包名,或者应用启动Scheme
contactMap Map N 联系人列表。Map key对应的是联系人名称,value对应的是联系人联系方式

回调接口

  • TuringOSClientListener:文字输入方式时,对话结果使用该接口回调,接口信息与其他模块一致,使用方式参考文字输入方式的方法说明;
public interface TuringOSClientListener {
    /**
     * 请求成功结果
     * @param code          请求Code
     * @param result        请求结果 JSON
     * @param baseResp      请求结果 BaseResp,只包含基础字段
     * @param extension     扩展信息
     */
    void onResult(int code, String result, BaseResp baseResp, String extension);

    /**
     * 请求失败
     * @param code          请求失败Code,参考错误码
     * @param msg           请求失败信息
     */
    void onError(int code, String msg);
}
  • TuringOSClientAsrListener:录音或者音频流输入时,ASR通道状态、ASR识别结果以及对话结果都使用该接口回调,具体参考下面对应方法的示例说明;
public interface TuringOSClientAsrListener {

    /**
     * 当使用SDK录音器开启的识别,此方法会在录音开始后回调
     * 一般用于UI显示开始录音,更新UI需要放到主线程,不能再此回调方法中更新
     */
    void onRecorderStart();

    /**
     * asr识别停止,包括请求Error或者外部调用client.stopAsr都会回调
     */
    void onStop();

    /**
     * 允许输入音频数据流,在该方法回调之后开始调用sendAudio
     */
    void onStreamOpen();

    /**
     *
     * 请求结果返回
     *
     * @param code 具体参考code说明
     * @param result 返回的json字符串
     * @param isLast Asr识别结果;last : 是否是最终结果
     * @param baseResp  返回的json字符串转换的Java对象
     */
    void onResult(int code, String result, boolean isLast, BaseResp baseResp);

    /**
     * Asr识别单论交互倒计时 最大值20s
     * 单句语音识别场景下的倒计时限制,连续识别不受影响
     *
     * @param second
     */
    void onTimer(int second);

    /**
     * 请求发生错误的信息
     *
     * @param code
     * @param msg
     */
    void onError(int code, String msg);

    /**
     * 使用内部录音时,返回声音音量变化,该方法的回调需要先设置参数enableVolume为true
     *
     */
    void onVoiceVolume(int i);

}
  • TuringOSClientPlayListener:凡是涉及播放的方法都会使用该接口回调播放状态,具体参考下面对应方法说明;
public interface TuringOSClientPlayListener {
    /**
     * TTS开始播放
     */
    void onPlayStart(String text);
    /**
     * TTS播放错误
     */
    void onPlayError(String message);
    /**
     * TTS播放完成
     */
    void onPlayComplete();
    /**
     * TTS播放暂停
     */
    void onPlayPaused();
    /**
     * TTS继续播放
     */
    void onPlayResumed();
}

TuringOSClientPlayListener中onPlayStart方法回调的特殊说明

在语音对话模块,凡是调用需要DK内部播放处理的相关的方法时(即调用startChatWithRecorderAndSpeakactionChatAndPlayinitChatStreamAndPlay方法时),onPlayStart方法会回调开始播放某一个节点信息的内容,即聊天场景中,对话结果播放内容可能是多条播放数据,每一条开始播放时会回调准备开始播放的信息,具体参考如下示例:

场景举例:

输入文字/音频:谁在叫

调用方法:输入文字并播放音频actionChatAndPlay或者startChatWithRecorderAndSpeak

返回结果Json:

{
    "code":200,
    "globalId":"120336450868599001",
    "message":"success",
    "nlpResponse":{
        "intent":{
            "code":404003,
            "operateState":12001
        },
        "results":[
            {
                "groupType":0,
                "resultType":"text",
                "values":{
                    "ttsStreamId":"007d5cf1420f45b59d2da267950924da",
                    "text":"小朋友,欢迎你进入‘谁在叫’闯关游戏。一会我会发出一个声音,你来猜猜它是什么声音吧,如果不想玩了,可以跟我说退出或不想玩了。准备好哦,开始闯关喽!第1关:"
                }
            },
            {
                "groupType":0,
                "resultType":"voice",
                "values":{
                    "voice":"http://download.turingapi.com/voice/125.mp3",
                    "identifier":"125"
                }
            },
            {
                "groupType":0,
                "resultType":"text",
                "values":{
                    "ttsStreamId":"aca5ba49415c44068b7321fdfb566d98",
                    "text":"听清楚了吗,是什么声音,想再听一遍就对我说:再来一次。不想玩了请对我说:退出。"
                }
            }
        ]
    }
}

nlpResponse-results结果解释

results数组中的第一条数据

 {
                "groupType":0,
                "resultType":"text",
                "values":{
                    "ttsStreamId":"007d5cf1420f45b59d2da267950924da",
                    "text":"小朋友,欢迎你进入‘谁在叫’闯关游戏。一会我会发出一个声音,你来猜猜它是什么声音吧,如果不想玩了,可以跟我说退出或不想玩了。准备好哦,开始闯关喽!第1关:"
                }
            }

语义结果,即谁在叫触发技能,云端给出此次对话结果的第一段文字和ttsStreamId(该参数SDK内部用于处理播放的数据的标识,可以忽略);

results数组中的第二条数据

 {
                "groupType":0,
                "resultType":"voice",
                "values":{
                    "voice":"http://download.turingapi.com/voice/125.mp3",
                    "identifier":"125"
                }
            }

该技能会返回附加的音频mp3链接;

results数组中的第三条数据

{
                "groupType":0,
                "resultType":"text",
                "values":{
                    "ttsStreamId":"aca5ba49415c44068b7321fdfb566d98",
                    "text":"听清楚了吗,是什么声音,想再听一遍就对我说:再来一次。不想玩了请对我说:退出。"
                }
            }

语义结果,云端给出此次对话结果的第二段文字。

上述场景回调过程如下:

ChatActivity: SpeakListener onPlayStart小朋友,欢迎你进入‘谁在叫’闯关游戏。一会我会发出一个声音,你来猜猜它是什么声音吧,如果不想玩了,可以跟我说退出或不想玩了。准备好哦,开始闯关喽!第1关:
ChatActivity: SpeakListener onPlayStarthttp://download.turingapi.com/voice/125.mp3
ChatActivity: SpeakListener onPlayStart听清楚了吗,是什么声音,想再听一遍就对我说:再来一次。不想玩了请对我说:退出。
ChatActivity: SpeakListener onPlayComplete

onPlayStart方法会回调开始播放某一个节点信息的内容,如果为文字,则输出文字,如果时音频链接,则输出音频链接。

输出参数

1.调用了音频输入的方法时,ASR结果和对话结果都在TuringOSClientAsrListener中回调,整个过程有两次关键性的返回。1.ASR识别的最终识别结果(如果ASR参数打开了实时返回识别结果的开关,TuringOSClientAsrListener接口的onResult会实时回调识别结果);2.NLP+TTS处理之后的结果,即语音对话的结果;

具体示例:

asr结果:

{
    "asrResponse":{
        "binarysId":"2d456834-d82c-491d-a92d-312a1a86c300",
        "state":200,
        "value":"您好"
    },
    "code":200,
    "globalId":"98413305835000000",
    "message":"success"
}

NLP+TTS处理之后的结果

{
    "code":200,
    "globalId":"98413305835000000",
    "message":"success",
    "nlpResponse":{
        "intent":{
            "code":100000,
            "operateState":1010
        },
        "results":[
            {
                "groupType":0,
                "resultType":"text",
                "values":{
                    "ttsUrl":[
                        "http://turing-iot.oss-cn-beijing.aliyuncs.com/tts/tts-0b6c2dd6687a4c8cb73a3ca49ed9b3ca-c63480507c8844cca59e36d7859d63ef.mp3"
                    ],
                    "emotionId":0,
                    "sentenceId":201,
                    "text":"恩恩,你也好,我好喜欢小主人哦!"
                }
            }
        ]
    }
}

2.调用了含有播放的方法,此次对话的语音播放由SDK来处理,播放状态在TuringOSClientPlayListener中回调;

3.ASR是识别结果与ASR模块一致,具体请参考ASR识别输出说明。

  • BaseResp字段说明

在语音对话模块中,语音聊天会触发技能,每个技能的参数字段由所差异,所以BaseResp只解析基础字段,技能的实体内容字段需要自行实现实体类来解析

参数 类型 说明
code int 请求响应Code,具体可参考Code说明
done boolean 此次对话是否结束状态,如果是最终结果则是true,否则是false
globalId String 此次对话的唯一标识
message String 请求响应的消息描述
nlpResponse NlpResponse 语义请求结果,具体可参考NLP结果说明
asrResponse AsrResponse ASR请求结果,具体可参考ASR结果说明
ttsResponse TtsResponse TTS合成结果,可忽略
aigcResponse AigcResponse AIGC请求结果
result Map 拓展参数(uploadState接口中踩赞的结果)
  • AigcResponse
参数 类型 是否必须 取值范围 说明
intentCode int N 进入AIGC的技能code
state int N 210,200,400,500 210:中间结果;200:最终结果;400:异常;500:图灵非法词异常
results List N - AIGC的结果
extendArgs Map N - 透传大模型输出内容
errorCode int N - 透传大模型异常code
errorMsg String N - 异常信息说明

AigcResponse.Results

参数 类型 是否必须 取值范围 说明
resultType String N 目前支持:image/text value 数据内容,image输出url 数据类型
value String N - 具体类型的值

技能说明

技能code

聊天对话:
知识库(100302)、十万个为什么(200205)、儿童聊天(100000)、维基百科(200209)

趣味应用:
单位换算(新)(1000732)、动物叫声(200301)、大自然声音(200302)、乐器声音(200303)

实用功能:
歌曲点播(200101)、故事点播(200201)、诗词背诵(200401)、天气查询(201401)、日期查询(200702)、中英互译(201711)、时间查询(200702)

设备控制:
闹钟(200710)、电量查询(900110)、休眠(900101)、屏幕亮度(900110)、跳舞(200701)、打开应用(201601)

详细说明:

http://docs.turingos.cn/1.0/api/apiV2/#turingos

指定技能

方法一:使用全局配置参数

"ability": {
    "nlp": {
      "codes": [1000018],
      "robotSkills": {
      }
    }
}

//全文翻译
TuringConfig.getInstance(this).configData.ability.nlp.codes = listOf(1000018)
turingChat.startChatWithRecorder(enableTts,true,true,true,object : TuringOSClientAsrListener {****})

方法二:使用局部参数

val nlpConfig = NlpRequestConfig.Builder().codes(mutableListOf(1000018)).build()
turingChat.startChatWithRecorderAndSpeak(asrConfig,nlpConfig,ttsConfig,turingOSClientAsrListener,turingOSClientPlayListener)

常用技能

全文翻译

//语音翻译方式
val nlpConfig = NlpRequestConfig.Builder().codes(mutableListOf(1000018)).build()
turingChat.startChatWithRecorderAndSpeak(asrConfig,nlpConfig,ttsConfig,turingOSClientAsrListener,turingOSClientPlayListener)
//文本翻译方式
TuringChat.getInstance(this).actionChat(text, true, true, new TuringOSClientListener());

特殊天气技能

调用示例

NlpRequestConfig.Builder builder = new NlpRequestConfig.Builder();
AppStateBean weather = new AppStateBean();
weather.setCode(201401);
Map<String, Object> weatherInfo = new HashMap<>();
weatherInfo.put("city", "深圳");
//城市和坐标可以二选一
weatherInfo.put("longitude", "114.062252");
weatherInfo.put("latitude", "22.559938");
builder.location(weatherInfo);
builder.appStateBean(weather);
NlpRequestConfig requestConfig = builder.build();

turingChat.actionChat("今天天气怎么样!", requestConfig,ttsConfig,new listener);
//或者
turingNlp.actionNlp("今天天气怎么样!", requestConfig, new listener);

天气城市使用顺序:

1.最优先使用用户输入文本;

2.使用缓存;

3.使用用户输入的location信息。

AIGC

①在配置文件中配置如下

"nlp": {
      "codes": [2081],
      "robotSkills": {
        "2081": {
          "version":"v1"
        }
     }
 }
参数 类型 说明
book String 绘本/人设入参,算法参数透传[优先使用输入,admin支持配置]
needNlu bool 是否使用大模型nlu[优先使用输入,admin支持配置]
nlu bool 使用哪个nlu输入(使用时needNlu必须为false)
version String AIGC模型版本,可输入 v2;v3(必须admin授权)
contextLength int 可输入 0-10,请求aigc对话入参上下文轮数
extendV2Args json 拓展参数

②调用接口:

void actionChat(@NonNull String text,boolean enableTts,boolean isAssignNlp,boolean isAssignTts,final TuringOSClientListener listener);

或者

void startChatWithRecorder(boolean enableTts, boolean isAssignAsr, boolean isAssignNlp, boolean isAssignTts,TuringOSClientAsrListener listener);

可根据自身需求选择其他接口

val msg = "基于给出的话题、关键词、年级内容,生成只有两角色的8句与内容相关的英语对话及翻译,每句不超过15个单词及话题内容和话题的翻译,生成内容:话题:该睡觉了,关键词:闹钟,年级:二年级,生成结果需要返回json格式,示例:" +
                "{\n" +
                "    \"title\": \"该睡觉了\",\n" +
                "    \"translation\": \"it's time to go to bed\",\n" +
                "    \"dialogue\": [\n" +
                "        {\n" +
                "            \"speaker\": \"Mom\",\n" +
                "            \"word\": \"David should go to bed now\",\n" +
                "            \"translation\": \"大卫,该睡觉了\"\n" +
                "        },\n" +
                "        {\n" +
                "            \"speaker\": \"David\",\n" +
                "            \"word\": \"Mom What time is it?\",\n" +
                "            \"translation\": \"妈妈,现在几点了?\"\n" +
                "        }\n" +
                "    ]\n" +
                "}"+
                "。生成的内容:话题:${title},关键词:${keyword},年级:${grade}。"

TuringChat.getInstance(MyApplication.getContext()).actionChat(msg,false,true,true,object :TuringOSClientListener{
    override fun onResult(p0: Int, p1: String?, baseResp: BaseResp?, p3: String?) {
        baseResp?.apply {
            if (baseResp.isDone)
                dismissProgress()
            if (p0==262){
                try {
                    val value = aigcResponse.results[0].value
                    var result = value.substring(value.indexOf("{"),lastIndexOf(value,'}',value.length)+1)
                    result = result.replace("\n","").replace("\"\"","\",\"")
                    LogManager.e(TAG,"result:$result")
                    val typeToken: TypeToken<Topic> = object : TypeToken<Topic>() {}
                    val gson = Gson()
                    val topic:Topic =gson.fromJson(result,typeToken.type)
                    topic.themeId = Constants.TOPIC_ID_MINE
                    topic.theme = "我的"
                    val random =SecureRandom()
                    val topicId = random.nextInt(10000)+20000
                    LogManager.d(TAG,topicId.toString())
                    topic.topicId = topicId
                    val set = HashSet<String>()
                    for (dialog in topic.dialogue){
                        set.add(dialog.speaker)
                        dialog.id = topicId*100+random.nextInt(100000)
                    }
                    if (set.size>2){
                        LogManager.e(TAG,"对话人数${set.size},超2人")
                        showToast("对话人数${set.size},超2人,请重试~")
                        return
                    }
                    topic.createTime = System.currentTimeMillis();
                    CoroutineScope(job).launch {
                        Repository.insertTopic(topic)
                        TopicActivity.startActivity(activity!!,topic)
                    }
                } catch (e: Exception) {
                    LogManager.e(TAG,"createTopic error",e)
                    showToast("生成失败,请重试~")
                }
            }
        }?:run{
            dismissProgress()
            showToast("生成失败,请重试~")
        }

    }

    override fun onError(p0: Int, p1: String?) {
        showToast("生成失败:$p1")
        dismissProgress()
    }
})