这篇会介绍如何基于 TRTC SDK 实现 AI 实时对话的解决方案。
一、方案介绍
方案基于 TRTC SDK 调用 TRTC 服务,通过调用 AI 实时对话的接口,可以实现极低延迟的 AI 实时对话服务。本方案为你提供了非常灵活的集成方案,你可以根据业务的实际需求接入第三方的 LLM 和 TTS,实现高效的业务实践效果。在整体方案中,我们针对语音实时降噪、AI 智能打断、上下文管理都有较多的技术优化,不断提升用户体验。
五、前提条件
注意:AI 实时对话调用会产生使用费用,具体详情请参见 AI 实时对话计费说明。
1. 创建 TRTC 应用。
2. 开通 语音转文字 服务。
3. 创建腾讯云 TTS(可选,支持第三方)。
4. 创建 LLM 应用:可以自选适合的大模型厂商进行注册。
七、1. 导入 TRTC SDK 到项目中
·iOS 无 UI 集成指引
·Android 无 UI 集成指引
·Web&H5 无 UI 集成指引
·小程序 无 UI 集成指引
·Flutter 无 UI 集成指引
八、2. 进入 TRTC 房间
·iOS 进入 TRTC 房间
·Android 进入 TRTC 房间
·Web&H5 进入TRTC房间
·小程序 进入TRTC房间
·Flutter 进入TRTC房间
九、3. 发布音频流
Android&iOS&FlutterWeb&H5小程序你可以调用 startLocalAudio 来开启麦克风采集,该接口需要你通过 quality 参数确定采集模式。虽然这个参数的名字叫做 quality,但并不是说质量越高越好,不同的业务场景有最适合的参数选择(这个参数更准确的含义是 scene)。AI 对话场景下推荐使用 SPEECH 模式,该模式下的 SDK 音频模块会专注于提炼语音信号,尽最大限度的过滤周围的环境噪音,同时该模式下的音频数据也会获得较好的差质量网络的抵抗能力,因此该模式特别适合于“视频通话”和“在线会议”等侧重于语音沟通的场景。AndroidiOS&MacFlutter// 开启麦克风采集,并设置当前场景为:语音模式(高噪声抑制能力、强弱网络抗性)mCloud.startLocalAudio(TRTCCloudDef.TRTC_AUDIO_QUALITY_SPEECH );self.trtcCloud = [TRTCCloud sharedInstance];// 开启麦克风采集,并设置当前场景为:语音模式(高噪声抑制能力、强弱网络抗性)[self.trtcCloud startLocalAudio:TRTCAudioQualitySpeech];// 开启麦克风采集,并设置当前场景为:语音模式(高噪声抑制能力、强弱网络抗性)trtcCloud.startLocalAudio(TRTCAudioQuality.speech);使用 trtc.startLocalAudio() 方法开启麦克风,并发布到房间。await trtc.startLocalAudio();在进入房间后,调用 getPusherInstance().start() 或者开启自动推流模式即可开始推流。 enterRoom(options) { this.setData({ pusher: this.TRTC.enterRoom({ sdkAppID: 1400xxxxx, // 你的腾讯云账号 userID: 'trtc-user', //当前进房用户的userID userSig: 'xxxxxxx', // 你服务端生成的userSig roomID: 1234, // 你进房的房间号, enableMic: true, // 进房默认开启音频上行 }), }, () => { this.TRTC.getPusherInstance().start() // 开始进行推流 })},
注意:说明:
注意:AI 实时对话场景对音频采集端的降噪能力有较高要求,为了获得更好的体验,建议 打开 AI 降噪功能。此外,我们还有专门针对 AI 实时对话场景训练的降噪模型,欢迎通过商务或 提交工单 联系我们。
十一、开始 AI 对话:StartAIConversation
通过业务后台调用 开始 AI 对话任务 接口,来发起 AI 实时对话,调用成功后,AI 机器人会进入 TRTC 房间。
目前支持的 LLMConfig 和 TTSConfig 配置说明:
·大模型配置(LLMConfig)
·文字转语音配置(TTSConfig)
注意:说明:
十二、步骤3:接收 AI 对话字幕及 AI 状态
通过 TRTC SDK 接收自定义消息功能,在客户端上监听回调来接收实时字幕与 AI 状态等数据。cmdID 固定是1。
十三、接收实时字幕
消息格式
{ "type": 10000, // 10000表示是下发的实时字幕 "sender": "user_a", // 说话人的userid "receiver": [], // 接收者userid列表,该消息实际是在房间内广播 "payload": { "text":"", // 语音识别出的文本 "start_time":"00:00:01", // 这句话的开始时间 "end_time":"00:00:02", // 这句话的结束时间 "roundid": "xxxxx", // 唯一标识一轮对话 "end": true // 如果为true,代表这是一句完整的话 }}
十四、接收机器人状态
消息格式
{ "type": 10001, // 机器人的状态 "sender": "user_a", // 发送者userid,这里是机器人的id "receiver": [], // 接受者userid列表,该消息实际是在房间内广播 "payload": { "roundid": "xxx", // 唯一标识一轮对话 "timestamp": 123, "state": 1, // 1 聆听中 2 思考中 3 说话中 4 被打断 5 已说完 }}
十五、示例代码
AndroidiOSWeb&H5@Overridepublic void onRecvCustomCmdMsg(String userId, int cmdID, int seq, byte[] message) { String data = new String(message, StandardCharsets.UTF_8); try { JSONObject jsonData = new JSONObject(data); Log.i(TAG, String.format("receive custom msg from %s cmdId: %d seq: %d data: %s", userId, cmdID, seq, data)); } catch (JSONException e) { Log.e(TAG, "onRecvCustomCmdMsg err"); throw new RuntimeException(e); }}func onRecvCustomCmdMsgUserId(_ userId: String, cmdID: Int, seq: UInt32, message: Data) { if cmdID == 1 { do { if let jsonObject = try JSONSerialization.jsonObject(with: message, options: []) as? [String: Any] { print("Dictionary: \\(jsonObject)") // handleMessage(jsonObject) } else { print("The data is not a dictionary.") } } catch { print("Error parsing JSON: \\(error)") } }}trtcClient.on(TRTC.EVENT.CUSTOM_MESSAGE, (event) => { let data = new TextDecoder().decode(event.data); let jsonData = JSON.parse(data); console.log(`receive custom msg from ${event.userId} cmdId: ${event.cmdId} seq: ${event.seq} data: ${data}`); if (jsonData.type == 10000 && jsonData.payload.end == false) { // 字幕中间状态 } else if (jsonData.type == 10000 && jsonData.payload.end == true) { // 一句话说完了 }});
注意:说明:
注意:我们有更多 AI 对话客户端上的回调,具体可参见:AI 对话状态回调、AI 对话字幕回调、AI 对话指标回调、AI 对话错误回调。
十六、步骤4:发送自定义消息
统一通过端上发送 TRTC 自定义消息,cmdID 固定是2。
参见 发送和接收消息。
·可以通过发送自定义的文本,跳过 ASR 过程,直接跟 AI Service 进行文字沟通。
{ "type": 20000, // 端上发送自定义文本消息 "sender": "user_a", // 发送者userid, 服务端会check该userid是否有效 "receiver": ["user_bot"], // 接受者userid列表,只需要填写机器人userid,服务端会check该userid是否有效 "payload": { "id": "uuid", // 消息id,可以使用uuid,排查问题使用 "message": "xxx", // 消息内容 "timestamp": 123 // 时间戳,排查问题使用 }}
·可以通过发送打断信令来进行打断。
{ "type": 20001, // 端上发送打断信令 "sender": "user_a", // 发送者userid, 服务端会check该userid是否有效 "receiver": ["user_bot"], // 接受者userid列表,只需要填写机器人userid,服务端会check该userid是否有效 "payload": { "id": "uuid", // 消息id,可以使用uuid,排查问题使用 "timestamp": 123 // 时间戳,排查问题使用 }}
十七、示例代码
AndroidiOSWeb&H5public void sendInterruptCode() { try { int cmdID = 0x2; long time = System.currentTimeMillis(); String timeStamp = String.valueOf(time/1000); JSONObject payLoadContent = new JSONObject(); payLoadContent.put("timestamp", timeStamp); payLoadContent.put("id", String.valueOf(GenerateTestUserSig.SDKAPPID) + "_" + mRoomId); String[] receivers = new String[]{robotUserId}; JSONObject interruptContent = new JSONObject(); interruptContent.put("type", AICustomMsgType.AICustomMsgType_Send_Interrupt_CMD); interruptContent.put("sender", mUserId); interruptContent.put("receiver", new JSONArray(receivers)); interruptContent.put("payload", payLoadContent); String interruptString = interruptContent.toString(); byte[] data = interruptString.getBytes("UTF-8"); Log.i(TAG, "sendInterruptCode :" + interruptString); mTRTCCloud.sendCustomCmdMsg(cmdID, data, true, true); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (JSONException e) { throw new RuntimeException(e); }}@objc func interruptAi() { print("interruptAi") let cmdId = 0x2 let timestamp = Int(Date().timeIntervalSince1970 * 1000) let payload = [ "id": userId + "_\\(roomId)" + "_\\(timestamp)", // 消息id,可以使用uuid,排查问题使用 "timestamp": timestamp // 时间戳,排查问题使用 ] as [String : Any] let dict = [ "type": 20001, "sender": userId, "receiver": [botId], "payload": payload ] as [String : Any] do { let jsonData = try JSONSerialization.data(withJSONObject: dict, options: []) self.trtcCloud.sendCustomCmdMsg(cmdId, data: jsonData, reliable: true, ordered: true) } catch { print("Error serializing dictionary to JSON: \\(error)") }}const message = { "type": 20001, "sender": "user_a", "receiver": ["user_bot"], "payload": { "id": "uuid", "timestamp": 123 }};trtc.sendCustomMessage({ cmdId: 2, data: new TextEncoder().encode(JSON.stringify(message)).buffer});
注意:目前小程序端暂不支持接收和发送自定义消息,如果你想在小程序端实现接收字幕或发送消息等功能,需要使用 IM 提供的即时通信来实现,可通过商务或 提交工单 联系我们开通 IM 信令通道。
十八、步骤5:停止 AI 对话,退出 TRTC 房间
1. 服务端停止 AI 对话任务。
通过业务后台调用 停止 AI 对话 接口,停止该对话任务。
2. 客户端退出 TRTC 房间,建议参见 退出房间。
20、1. 其他服务端接口
·查询 AI 对话任务状态:DescribeAIConversation
可以查询 AI 对话任务状态。有 4 个值:
1.1 Idle表示任务未开始。
1.2 Preparing表示任务准备中。
1.3 InProgress表示任务正在运行。
1.4 Stopped表示任务已停止,正在清理资源中。
·更新 AI 对话启动参数:UpdateAIConversation
可以在对话过程中,动态更新 TTS 的音色。
·控制 AI 对话任务:ControlAIConversation
当你想让机器人主动播报文本的时候,可以使用该接口。
21、2. 开启服务端回调
可参见 AI 对话服务端回调
22、3. 其余高级功能介绍
| 功能 | 操作指引 |
| 智能打断 | 智能打断逻辑 |
| 实现上下文管理 | 如何实现上下文管理 |
| 调用 function call | 点击查看示例 |