快速跑通
本文将介绍如何基于 TRTC SDK 实现 AI 实时对话的解决方案。
方案介绍
方案基于 TRTC SDK 调用 TRTC 服务,通过调用 AI 实时对话的接口,可以实现极低延迟的 AI 实时对话服务。本方案为您提供了非常灵活的集成方案,您可以根据业务的实际需求接入第三方的 LLM 和 TTS,实现高效的业务实践效果。在整体方案中,我们针对语音实时降噪、AI 智能打断、上下文管理都有较多的技术优化,不断提升用户体验。
方案架构图

业务流程图

集成指引
前提条件
注意:
1. 创建 TRTC 应用。
2. 创建腾讯云 TTS(可使用第三方)。
3. 创建 LLM 应用:可以自选适合的大模型厂商进行注册。
一、集成 TRTC SDK
第一步:导入 TRTC SDK 到项目中
第二步:进入 TRTC 房间
第三步:发布音频流
您可以调用 startLocalAudio 来开启麦克风采集,该接口需要您通过 quality 参数确定采集模式。虽然这个参数的名字叫做 quality,但并不是说质量越高越好,不同的业务场景有最适合的参数选择(这个参数更准确的含义是 scene)。
AI 对话场景下推荐使用 SPEECH 模式,该模式下的 SDK 音频模块会专注于提炼语音信号,尽最大限度的过滤周围的环境噪音,同时该模式下的音频数据也会获得较好的差质量网络的抵抗能力,因此该模式特别适合于“视频通话”和“在线会议”等侧重于语音沟通的场景。
// 开启麦克风采集,并设置当前场景为:语音模式(高噪声抑制能力、强弱网络抗性)mCloud.startLocalAudio(TRTCCloudDef.TRTC_AUDIO_QUALITY_SPEECH );
self.trtcCloud = [TRTCCloud sharedInstance];// 开启麦克风采集,并设置当前场景为:语音模式(高噪声抑制能力、强弱网络抗性)[self.trtcCloud startLocalAudio:TRTCAudioQualitySpeech];
// 开启麦克风采集,并设置当前场景为:语音模式(高噪声抑制能力、强弱网络抗性)trtcCloud.startLocalAudio(TRTCAudioQuality.speech);
await trtc.startLocalAudio();
说明:
二、发起 AI 对话
开始 AI 对话:StartAIConversation
注意:
RoomId
需要和客户端进房的 RoomId
保持一致,并且房间号的类型(数字房间号、字符串房间号)也必须相同(既机器人和用户需要在同一个房间)。LLMConfig
和 TTSConfig
均为 JSON 字符串,需要正确配置才能成功发起 AI 实时对话。目前支持的
LLMConfig
和 TTSConfig
配置说明:说明:
如果以上步骤都操作正确,现在已经可以和 AI 进行对话啦!
三、接收 AI 对话字幕及 AI 状态
接收实时字幕
消息格式
{"type": 10000, // 10000表示是下发的实时字幕"sender": "user_a", // 说话人的userid"receiver": [], // 接收者userid列表,该消息实际是在房间内广播"payload": {"text":"", // 语音识别出的文本"translation_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 被打断}}
示例代码
@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) {// 一句话说完了}});
四、发送自定义消息
统一通过端上发送 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 // 时间戳,排查问题使用}}
示例代码
public 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 = 0x2let 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});
注意:
五、停止 AI 对话,退出 TRTC 房间
1. 服务端停止 AI 对话任务。
2. 客户端退出退出 TRTC 房间,建议参见 退出房间(Android&iOS&Windows&Mac)。
六、其他功能
1、其他服务端接口
查询 AI 对话任务状态:DescribeAIConversation
可以查询 AI 对话任务状态。有 4 个值:
1.1
Idle
表示任务未开始。1.2
Preparing
表示任务准备中。1.3
InProgress
表示任务正在运行。1.4
Stopped
表示任务已停止,正在清理资源中。更新 AI 对话启动参数:UpdateAIConversation
可以在对话过程中,动态更新 TTS 的音色。
控制 AI 对话任务:ControlAIConversation
当您想让机器人主动播报文本的时候,可以使用该接口。