交互数智人实践教程概述
交互数智人 apaas 接口的调用建议参考以下流程:
1. 初始化 API 调用对象:设置 API 调用的基础信息,包括 appkey、access token 以及 HTTP 和 WebSocket 的域名。
2. 创建视频流:使用形象资产 ID 或数智人平台项目 ID 创建视频流,指定视频流协议和驱动类型。
3. 检测会话状态:循环检查会话状态,直到会话状态变为已就绪(SessionStatus=1)。
4. 开启会话:调用 API 以开启会话。
5. 创建长链接通道:建立长链接通道,以便进行持续的通信。启动两个线程,一个用于定期获取下行信息,另一个用于定期发送心跳指令,以保持连接活跃。
6. 发送驱动指令:根据不同的场景(参见本文档:1.数智人绑定对话服务场景、2.直播场景、3.用户自行接入大模型场景、4.音频驱动场景),发送相应的驱动指令,详细的适用场景与驱动指令的关系参考驱动指令说明。
7. 关闭长连接通道和会话:根据不同场景的情况关闭长连接通道和会话。
其中步骤需要根据不同的场景来选择不同的驱动指令,其他步骤的逻辑基本一致。以下是该流程的代码 Demo(目前只提供 go 语言版本):
package mainimport ("encoding/base64""fmt""io""log""os""strings""time"uuid "github.com/satori/go.uuid""k8s.io/apimachinery/pkg/util/rand")func main() {//第一步:初始化api调用对象var api = NewVHApi("your appkey", //your appkey"your accesstoken", //your accesstoken"https://gw.tvs.qq.com", //http domain"wss://gw.tvs.qq.com") //wss domain//第二步:使用形象资产ID或数智人项目ID创建视频流(使用形象资产ID可以指定音色相关参数,对话场景这些也没有明确;使用数智人项目ID里面包含了音色信息以及对话服务配置)//这里使用数智人项目ID创建视频流,以webrtc协议为例createSessionRsp, err := api.CreateSession(CreateSessionReq{UserId: "your user id",VirtualmanProjectId: "your virtualman project id",Protocol: "webrtc", //可选:webrtc、rtmp、trtcDriverType: 1, //drivetype=1代表支持文本驱动指令;drivetype=3代表支持音频和文本驱动指令})if err != nil {log.Fatalf("err:%v", err)}fmt.Println("获取流播放地址", createSessionRsp.PlayStreamAddr)for {var userInput stringfmt.Print("是否成功复制地址(输入'y'确定): ")fmt.Scanln(&userInput)if strings.ToLower(userInput) == "y" {break}}//第三步:循环检测会话状态直到SessionStatus=1(已就绪)sessionStatus := createSessionRsp.SessionStatusfor sessionStatus != 1 {time.Sleep(time.Second * 1)statSessionRsp, err := api.StatSession()if err != nil {log.Fatalf("err:%v", err)}sessionStatus = statSessionRsp.SessionStatus}//第四步:开启会话_, err = api.StartSession()if err != nil {log.Fatalf("err:%v", err)}//第五步:创建长链接通道err = api.CommandChannel()if err != nil {log.Fatalf("err:%v", err)}// 开启协程每过3s获取下行信息go func() {for {time.Sleep(time.Second * 3)fmt.Println("\\n-----开始调用长连接下行信息-----")api.ReadWssMessage()}}()//开启协程每过1分钟发送心跳指令go func() {for {time.Sleep(time.Minute * 1)fmt.Println("\\n-----开始调用长连接发送心跳指令-----")api.SendHeartBeatCommand()}}()//第六步:发送驱动指令//根据不同的场景选择不同的函数发送驱动指令,如大模型对话,调用以下函数(更多场景请见下文)largeModelDialogue()//第七步:关闭长连接通道和会话//90s后关闭长连接通道(根据自己的场景来选择断连时间)time.Sleep(time.Second * 90)api.CloseSession()}
数智人绑定对话服务实践教程
数智人绑定的对话服务目前主要有如下两种配置:
1. 云小微对话(客服机器人对话)
2. 腾讯行业大模型对话
说明:
// 客服机器人对话func robotDialogue() {fmt.Println("\\n-----云小微对话(客服机器人对话)-----")err := api.SendTextDriveWssCommand(TextDriveWssCommand{Data: &TextWssData{Text: "微信简介", //根据客服机器人问答知识库回答ChatCommand: "", //使用客服对话or大模型对话},})if err != nil {log.Fatalf("err:%v", err)}}
// 腾讯行业大模型对话func largeModelDialogue() {fmt.Println("\\n-----腾讯行业大模型对话-----")err := api.SendTextDriveWssCommand(TextDriveWssCommand{Data: &TextWssData{Text: "你是谁", //可以在模型管理里面自定义配置问答ChatCommand: "", //使用客服对话or大模型对话ChatRoundId: strings.Replace(uuid.NewV4().String(), "-", "", -1)[:32], //使用腾讯行业大模型对话服务的数智人项目需要传入此字段,用于区分多轮对话},})if err != nil {log.Fatalf("err:%v", err)}}
直播场景实践教程
用户自行接入大模型实践教程
用户自行接入大模型: 指用户自行接入了 ChatGPT、腾讯混元等大模型,输出通常为流式文本。
该场景推荐使用流式文本驱动指令中的非子句模式(isSentence=false),非子句模式下服务端会对客户端发送的文本重新组句,能很好的配合大模型的流式输出,用户接入大模型的场景完整 Demo 参考ASR/ChatGPT/数智人 整合 demo。
以下是该场景对应的代码示例:
// 用户自行接入大模型来驱动数智人的场景func SendNotSentenceStreamText() {//模拟大模型的返回结果rspText := "我是一个数智人,我在测试发送流式文本非子句模式。"//模拟大模型生成流式文本streamChan := streamResponse(rspText, time.Millisecond*500)reqId := strings.Replace(uuid.NewV4().String(), "-", "", -1)[:32]seq := 1for char := range streamChan {api.SendStreamTextDriveWssCommand(StreamTextDriveWssCommand{ReqId: reqId,Data: &StreamTextWssData{Text: char,Seq: seq,},})seq++}// 发送final数据包api.SendStreamTextDriveWssCommand(StreamTextDriveWssCommand{ReqId: reqId,Data: &StreamTextWssData{Seq: 1,IsFinal: true,},})}func streamResponse(text string, delay time.Duration) <-chan string {ch := make(chan string)go func() {for _, char := range text {//模拟大模型流式返回延时time.Sleep(delay)ch <- string(char)}close(ch)}()return ch}
音频驱动场景实践教程
用户可以使用音频文件来驱动数智人,以下是该场景对应的代码示例:
func SendAudio() {/*音频格式:格式-PCM,采样率-16kHz,采样位深-16bits,声道-单声道。1.如果是麦克风实时收音发送,每录制160ms(5120B)的数据即可发出,中间不需要间隔等待;如果是读取离线音频文件发送,片包大小为160ms(5120B),片包发送间隔为120ms。2.最后一个片包大小按实际发送(需小于160ms)。3.当数据包发送完毕后,必须再发送一个IsFinal=true的空数据包(Audio字段填空串)结束当次音频驱动使数字人回到静默状态。4.发送音频实时率要介于[0.75,1],小于0.75会触发限速,大于1会导致画面卡顿。比如160ms音频片包大小,发送间隔不能低于120ms,不能高于160ms。*/chunkSize := 5120 //块大小-5120BsleepBase := 120 //间隔msseq := 1reqId := strings.Replace(uuid.NewV4().String(), "-", "", -1)[:32]//读取音频二进制文件voiceFile, err := os.Open("your_audio_file.pcm")if err != nil {log.Fatalf("err:%v", err)}defer voiceFile.Close()buffer := make([]byte, chunkSize)for {n, err := voiceFile.Read(buffer)if err != nil && err != io.EOF {fmt.Println("Error reading file:", err)break}if n == 0 { // 文件读取完毕break}err = api.SendVoiceDriveCommand(VoiceDriveCommand{ReqId: reqId,Data: &VoiceData{Audio: base64.StdEncoding.EncodeToString(buffer), //声音二进制数据编码Base64后的值。Seq: seq,IsFinal: false,},})if err != nil {log.Fatalf("err:%v", err)}seq++ // 递增序列号// 等待120ms到160ms的随机时间sleepDuration := time.Duration(sleepBase+rand.Intn(41)) * time.Millisecondtime.Sleep(sleepDuration)}// 发送final数据包api.SendVoiceDriveCommand(VoiceDriveCommand{ReqId: reqId,Data: &VoiceData{Seq: seq,IsFinal: true,},})}
完整 Demo 列表
Demo 内容 | Demo 概述 | 语言 | 最新版本文件名 | Demo 下载链接 |
ASR/ChatGPT/数智人 整合 demo | 本 Demo 展示了如何通过ASR/ChatGPT,与数智人进行交互。 | python | asr_chatgpt_vh_demo_20241212.zip |