语音对话接入文档
文档状态
| 文件标识: | 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 中添加 nlp、tts、asr 节点,节点字段见《接入指南说明文档》配置文件参数说明。可使用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内部播放处理的相关的方法时(即调用startChatWithRecorderAndSpeak、actionChatAndPlay、initChatStreamAndPlay方法时),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()
}
})