在实时对话式 AI 场景下,你可能需要获取 AI 对话过程中智能体任务的实时状态变化消息以便在业务端及时进行后续处理或保证业务的稳定性。你可以通过接收相应的回调来获取这些状态消息。
你可以使用三种方式接收回调信息:
前往 RTC 控制台-功能配置,在回调设置中添加实时对话式 AI 相关配置。配置完成后,智能体任务状态发生变化时,你配置的回调 URL 会收到回调消息。回调消息格式为 JSON 格式,具体参看 VoiceChat。
将 StartVoiceChat.AgentConfig.EnableConversationStateCallback
设置为 1
,并填入ServerMessageURLForRTS
和 ServerMessageSignatureForRTS
,在智能体任务状态发生变化时,你配置的回调 URL 会收到回调消息。
收到的回调格式如下:
参数名 | 类型 | 描述 |
---|---|---|
message | String | Base 64 编码的二进制消息内容。长度不超过 48 KB。格式参看二进制消息格式。 |
signature | String | 鉴权签名。可与StartVoiceChat 接口中传入的ServerMessageSignatureForRTS 字段值进行对比以进行鉴权验证。 |
二进制消息格式如下:
参数名 | 类型 | 描述 |
---|---|---|
magic number | binary | 消息格式,固定为 conv 。 |
length | binary | 消息长度,单位为 bytes。存放方式为大端序。 |
conversion_status_message | binary | 消息详细信息。格式参看 conversion_status_message 格式。 |
conversion_status_message:
参数名 | 类型 | 描述 |
---|---|---|
TaskId | String | 智能体任务 ID。 |
UserID | String | 说话人 UserId。 |
RoundID | Int64 | 对话轮次。从 0 开始计数。 |
EventTime | Int64 | 该事件在 RTC 服务器上发生的 Unix 时间戳 (ms)。 |
Stage | Stage | 任务状态详细描述。 |
Stage
参数名 | 类型 | 描述 |
---|---|---|
Code | Int | 任务状态码。
|
Description | String | 任务状态描述。 |
你可以参考以下示例代码对回调信息中的 message
内容进行解析。
package main import ( "encoding/base64" "encoding/binary" "encoding/json" "fmt" ) const ( conversationStageHeader = "conv" exampleSignature = "example_signature" ) type RtsMessage struct { Message string `json:"message"` Signature string `json:"signature"` } type Conv struct { TaskID string `json:"TaskId"` UserID string `json:"UserID"` RoundID int64 `json:"RoundID"` EventTime int64 `json:"EventTime"` Stage StageInfo `json:"Stage"` } type StageInfo struct { Code stageCode `json:"Code"` Description string `json:"Description"` } type stageCode int const ( _ stageCode = iota listening thinking answering interrupted answerFinish ) var ( stageListening = StageInfo{Code: listening, Description: "listening"} stageThinking = StageInfo{Code: thinking, Description: "thinking"} stageAnswering = StageInfo{Code: answering, Description: "answering"} stageInterrupted = StageInfo{Code: interrupted, Description: "interrupted"} stageAnswerFinish = StageInfo{Code: answerFinish, Description: "answerFinish"} ) func HandleConversationStageMsg(c *gin.Context) { msg := &RtsMessage{} if err := c.BindJSON(&msg); err != nil { fmt.Printf("BindJson failed,err:%v\n", err) return } if msg.Signature != exampleSignature { fmt.Printf("Signature not match\n") return } conv, err := Unpack(msg.Message) if err != nil { fmt.Printf("Unpack failed,err:%v\n", err) return } fmt.Println(conv) //业务逻辑 c.String(200, "ok") } func Unpack(msg string) (*Conv, error) { data, err := base64.StdEncoding.DecodeString(msg) if err != nil { return nil, fmt.Errorf("DecodeString failed,err:%v", err) } if len(data) < 8 { return nil, fmt.Errorf("Data invalid") } dataHeader := string(data[:4]) if dataHeader != conversationStageHeader { return nil, fmt.Errorf("Header not match") } dataSize := binary.BigEndian.Uint32(data[4:8]) if dataSize+8 != uint32(len(data)) { return nil, fmt.Errorf("Size not match") } subData := data[8:] conv := &Conv{} err = json.Unmarshal(subData, conv) if err != nil { return nil, fmt.Errorf("Unmarshal failed,err:%v\n", err) } return conv, nil } func main() { r := gin.Default() r.POST("/example_domain/vertc/cstage", HandleConversationStageMsg) r.Run() }