交互数智人实践教程

最近更新时间:2024-12-12 17:27:52

我的收藏

交互数智人实践教程概述

交互数智人 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 语言版本):
Go
package main

import (
"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、trtc
DriverType: 1, //drivetype=1代表支持文本驱动指令;drivetype=3代表支持音频和文本驱动指令
})
if err != nil {
log.Fatalf("err:%v", err)
}
fmt.Println("获取流播放地址", createSessionRsp.PlayStreamAddr)
for {
var userInput string
fmt.Print("是否成功复制地址(输入'y'确定): ")
fmt.Scanln(&userInput)
if strings.ToLower(userInput) == "y" {
break
}
}
//第三步:循环检测会话状态直到SessionStatus=1(已就绪)
sessionStatus := createSessionRsp.SessionStatus
for 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. 腾讯行业大模型对话
说明:
请到数智人的项目创建与管理绑定数智人对话服务,只能使用数智人平台项目创建会话方式。
对话服务推荐采用文本驱动指令(WebSocket 长连接),以下是这两种配置的代码示例:
Go
// 客服机器人对话
func robotDialogue() {
fmt.Println("\\n-----云小微对话(客服机器人对话)-----")
err := api.SendTextDriveWssCommand(TextDriveWssCommand{
Data: &TextWssData{
Text: "微信简介", //根据客服机器人问答知识库回答
ChatCommand: "", //使用客服对话or大模型对话
},
})
if err != nil {
log.Fatalf("err:%v", err)
}
}
Go
// 腾讯行业大模型对话
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)
}
}

直播场景实践教程

直播场景推荐使用直播数智人服务,实践教程可直接参考直播数智人服务 API 文档


用户自行接入大模型实践教程

用户自行接入大模型: 指用户自行接入了 ChatGPT、腾讯混元等大模型,输出通常为流式文本。
该场景推荐使用流式文本驱动指令中的非子句模式(isSentence=false),非子句模式下服务端会对客户端发送的文本重新组句,能很好的配合大模型的流式输出,用户接入大模型的场景完整 Demo 参考ASR/ChatGPT/数智人 整合 demo
以下是该场景对应的代码示例:
Go
// 用户自行接入大模型来驱动数智人的场景
func SendNotSentenceStreamText() {
//模拟大模型的返回结果
rspText := "我是一个数智人,我在测试发送流式文本非子句模式。"
//模拟大模型生成流式文本
streamChan := streamResponse(rspText, time.Millisecond*500)
reqId := strings.Replace(uuid.NewV4().String(), "-", "", -1)[:32]
seq := 1
for 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
}

音频驱动场景实践教程

用户可以使用音频文件来驱动数智人,以下是该场景对应的代码示例:
Go
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 //块大小-5120B
sleepBase := 120 //间隔ms
seq := 1
reqId := 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.Millisecond
time.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