You need to enable JavaScript to run this app.
导航
接收状态变化消息
最近更新时间:2025.01.09 17:23:24首次发布时间:2025.01.09 17:23:24

在实时对话式 AI 场景下,你可能需要获取 AI 对话过程中智能体任务的实时状态变化消息以便在业务端及时进行后续处理或保证业务的稳定性。你可以通过接收相应的回调来获取这些状态消息。
你可以使用三种方式接收回调信息:

  • 在 RTC 控制台配置你想接收的智能体任务变化状态回调。
  • 通过 StartVoiceChat 接口配置接收状态消息 URL 地址。

通过控制台配置接收状态变化消息

前往 RTC 控制台-功能配置,在回调设置中添加实时对话式 AI 相关配置。配置完成后,智能体任务状态发生变化时,你配置的回调 URL 会收到回调消息。回调消息格式为 JSON 格式,具体参看 VoiceChat

通过 StartVoiceChat 接口配置接收状态变化消息

StartVoiceChat.AgentConfig.EnableConversationStateCallback设置为 1,并填入ServerMessageURLForRTSServerMessageSignatureForRTS,在智能体任务状态发生变化时,你配置的回调 URL 会收到回调消息。

收到的回调格式如下:

参数名类型描述
messageStringBase 64 编码的二进制消息内容。长度不超过 48 KB。格式参看二进制消息格式
signatureString鉴权签名。可与StartVoiceChat接口中传入的ServerMessageSignatureForRTS字段值进行对比以进行鉴权验证。

二进制消息格式如下:

alt

参数名类型描述
magic numberbinary消息格式,固定为 conv
lengthbinary消息长度,单位为 bytes。存放方式为大端序。
conversion_status_messagebinary消息详细信息。格式参看 conversion_status_message 格式

conversion_status_message:

参数名类型描述
TaskIdString智能体任务 ID。
UserIDString说话人 UserId。
RoundIDInt64对话轮次。从 0 开始计数。
EventTimeInt64该事件在 RTC 服务器上发生的 Unix 时间戳 (ms)。
StageStage任务状态详细描述。

Stage

参数名类型描述
CodeInt任务状态码。
  • 1:智能体聆听中。
  • 2:智能体思考中。
  • 3:智能体说话中。
  • 4:智能体被打断。
  • 5:智能体说话完成。
DescriptionString任务状态描述。

你可以参考以下示例代码对回调信息中的 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()
}