对讲机模式

用户与智能体的对话模式分为自然对话模式与对讲机模式。本篇文档旨在为您介绍如何实现对讲机模式。

功能介绍

在对讲机模式下,用户的每一次输入与智能体的每一次响应均为独立事件,此模式类似于传统对讲机的使用方式。在这种模式下,用户与智能体之间的交流显得更加结构化且有序。通过对讲机模式,用户能够以更高效、更有组织的方式与智能体进行交互。

前提条件

交互流程

image

消息协议说明

开启/关闭对讲机模式

消息类型:1105

消息体如下:

{
  "type": 1105,
  "senderId": "user_1",     // 发送人id
  "receiverId": "robot_1",  // 机器人Id
  "data": {
    "enable": true          // true表示开启对讲机模式,false表示关闭对讲机模式
  }
}

对讲机开启/关闭状态传递

消息类型:1007

消息体如下:

{
  "type": 1007,
  "seqId": 5,
  "senderId": "robot_1",    // AI智能体uid
  "receiverId": "",   			// 无需指定接收人Id,一般情况下为空
  "data": {
    "enable": true       // true表示当前智能体进入对讲机模式,false当前智能体退出了对讲机模式
  }
}
说明

无论是OpenAPI,还是通过DataChannel开启/关闭对讲机模式,智能体服务都会发送该消息告诉结果。

按下开始讲话

消息类型:1106

消息体如下:

{
  "type": 1106,
  "senderId": "user_1",    // 发送人id
  "receiverId": "robot_1"  // 机器人Id
}

松开发送讲话

消息类型:1107

消息体如下:

{
  "type": 1107,
  "senderId": "user_1",    // 发送人id
  "receiverId": "robot_1"  // 机器人Id
}

松开取消讲话

消息类型:1108

消息体如下:

{
  "type": 1108,
  "senderId": "user_1",    // 发送人id
  "receiverId": "robot_1"  // 机器人Id
}

代码示例

iOS

// 启动或关闭对讲机模式
public func enablePushToTalk(enable: Bool) {
    var sendDict: [String: Any] = [
        "type": 1105,
    ]
    sendDict.updateValue(myUid, forKey: "senderId")
    sendDict.updateValue(robotUid, forKey: "receiverId")
    sendDict.updateValue(["enable": enable], forKey: "data")
    
    if let sendData = sendDict.aicall_jsonString.data(using: .utf8) {
        let rtcMsg = AliRtcDataChannelMsg()
        rtcMsg.type = .custom
        rtcMsg.data = sendData
        self.rtcEngine.sendDataChannelMessage(rtcMsg)

        self.rtcEngine.muteLocalMic(enable, mode: .allAudioMode)
    }
}

// 按住讲话,请确保已经启动对讲机模式
public func startPushToTalk() {
    var sendDict: [String: Any] = [
        "type": 1106,
    ]
    sendDict.updateValue(myUid, forKey: "senderId")
    sendDict.updateValue(robotUid, forKey: "receiverId")
    
    if let sendData = sendDict.aicall_jsonString.data(using: .utf8) {
        let rtcMsg = AliRtcDataChannelMsg()
        rtcMsg.type = .custom
        rtcMsg.data = sendData
        self.rtcEngine.sendDataChannelMessage(rtcMsg)
        // 取消静音麦克风
        self.rtcEngine.muteLocalMic(false, mode: .allAudioMode)
    }
}

// 完成讲话,请确保已经启动对讲机模式
public func finishPushToTalk() {
    var sendDict: [String: Any] = [
        "type": 1107,
    ]
    sendDict.updateValue(myUid, forKey: "senderId")
    sendDict.updateValue(robotUid, forKey: "receiverId")
    
    if let sendData = sendDict.aicall_jsonString.data(using: .utf8) {
        let rtcMsg = AliRtcDataChannelMsg()
        rtcMsg.type = .custom
        rtcMsg.data = sendData
        self.rtcEngine.sendDataChannelMessage(rtcMsg)
        // 取消静音麦克风
        self.rtcEngine.muteLocalMic(true, mode: .allAudioMode)
    }
}

// 取消这次发送,请确保已经启动对讲机模式
public func cancelPushToTalk() {
    var sendDict: [String: Any] = [
        "type": 1108,
    ]
    sendDict.updateValue(myUid, forKey: "senderId")
    sendDict.updateValue(robotUid, forKey: "receiverId")
    
    if let sendData = sendDict.aicall_jsonString.data(using: .utf8) {
        let rtcMsg = AliRtcDataChannelMsg()
        rtcMsg.type = .custom
        rtcMsg.data = sendData
        self.rtcEngine.sendDataChannelMessage(rtcMsg)
        // 取消静音麦克风
        self.rtcEngine.muteLocalMic(true, mode: .allAudioMode)
    }
}

// 处理接收到的DataChannel消息
public func onDataChannelMessage(_ uid: String, controlMsg: AliRtcDataChannelMsg) {    
    if controlMsg.type != .custom {
        return
    }

    let dataDict = (try? JSONSerialization.jsonObject(with: controlMsg.data, options: .allowFragments)) as? [String : Any]
    guard let dataDict = dataDict else {
        return
    }
    debugPrint("onDataChannelMessage:\(dataDict)")
    if dataDict["type"] as? Int32 == 1007 {
        let data = dataDict["data"] as? [String: Any]
        if let data = data {
            if let enable = data["enable"] as? Bool {
                // 服务端已经开启/关闭对讲机模式,参考流程
                DispatchQueue.main.async {
                    self.enablePushToTalk = enable
                    self.rtcEngine.muteLocalMic(enable, mode: .allAudioMode)
                }
            }
            
        }
    }
    // 处理其他消息
    ...
}

Android

public void sendCustomMessage(int msgType, JSONObject data) {
    if (null != mAliRtcEngine) {
        try {
            String senderId; // 自己的用户id
            String receiverId; // 机器人用户id

            JSONObject jsonObject = new JSONObject();
            jsonObject.put("type", msgType);
            jsonObject.put("senderId", senderId);
            jsonObject.put("receiverId", receiverId);
            if (null != data) {
                jsonObject.put("data", data);
            }
            AliRtcEngine.AliRtcDataChannelMsg rtcDataChannelMsg = new AliRtcEngine.AliRtcDataChannelMsg();
            rtcDataChannelMsg.type = AliEngineDataMsgCustom;
            rtcDataChannelMsg.data = jsonObject.toString().getBytes(StandardCharsets.UTF_8);
            mAliRtcEngine.sendDataChannelMsg(rtcDataChannelMsg);
        } catch (JSONException ex) {
            ex.printStackTrace();
        }
    }
}

// 启动或关闭对讲机模式
public boolean enablePushToTalk(boolean enable) {
JSONObject jsonObject = new JSONObject();
jsonObject.put("enable", enable);
// 向机器人发送消息
sendCustomMessage(1105, jsonObject);
// 静音麦克风
mAliRtcEngine.muteLocalMic(enable, AliRtcEngine.AliRtcMuteLocalAudioMode.AliRtcMuteAllAudioMode);
}

// 按住讲话,请确保已经启动对讲机模式
public func startPushToTalk() {
    // 向机器人发送消息
    sendCustomMessage(1106, null);
    // 取消静音麦克风
    mAliRtcEngine.muteLocalMic(false, AliRtcEngine.AliRtcMuteLocalAudioMode.AliRtcMuteAllAudioMode);
}

// 完成讲话,请确保已经启动对讲机模式
public func finishPushToTalk() {
    // 向机器人发送消息
    sendCustomMessage(1107, null);
    // 静音麦克风
    mAliRtcEngine.muteLocalMic(true, AliRtcEngine.AliRtcMuteLocalAudioMode.AliRtcMuteAllAudioMode);
}

// 取消这次发送,请确保已经启动对讲机模式
public func cancelPushToTalk() {
    // 向机器人发送消息
    sendCustomMessage(1108, null);
    // 静音麦克风
    mAliRtcEngine.muteLocalMic(true, AliRtcEngine.AliRtcMuteLocalAudioMode.AliRtcMuteAllAudioMode);
}

// 处理接收到的DataChannel消息
private AliRtcEngineNotify mRtcEngineRemoteNotify = new AliRtcEngineNotify() {

    @Override
    public void onDataChannelMessage(String uid, AliRtcEngine.AliRtcDataChannelMsg msg) {
        super.onDataChannelMessage(uid, msg);
        if (msg.type == AliEngineDataMsgCustom) {
            String dataStr = new String(msg.data);
            JSONObject jsonObject = new JSONObject(dataStr);
            JSONObject dataJson = jsonObject.optJSONObject("data");
            int msgType = jsonObject.optInt("type");
            if (msgType == 1007) {
                boolean enable = dataJson.optBoolean("enable");
                // 机器人通知对讲机模式状态,业务处理...
            }
        }
    }
}

Web

// 启动或关闭对讲机模式
public enablePushToTalk(enable: boolean) { }

// 按住讲话,请确保已经启动对讲机模式
public startPushToTalk(): boolean { }

// 完成讲话,请确保已经启动对讲机模式
public finishPushToTalk(): boolean { }

// 取消这次发送,请确保已经启动对讲机模式
public cancelPushToTalk(): boolean { }

controller.on('AICallPushToTalkChanged', (enable: boolean) => {
    // 当前对讲机模式变化为 {enable}
})