文档中心>即时通信 IM>更多实践>AI 聊天机器人方案

AI 聊天机器人方案

最近更新时间:2024-05-29 11:27:21

我的收藏
随着 AI 已成为当下开发者最为关注的焦点,AI和即时通信的结合也得到了进一步的发展和应用。腾讯云即时通信 IM 作为全球领先的通信云服务商,快速发布了相关 AI 能力调用接口,开发者基于腾讯云 IM 提供的通信底座,可以自由调用业内领先的大模型能力,用丰富的 AI 能力赋能自己,实现智能客服、创意辅助、工作助手等业务功能。
那具体该如何接入 AI 服务呢?本文将提供两种参考方案,方案一通过机器人第三方消息回调将 AI 服务能力引入到 IM 应用中,方案二通过腾讯云提供的智能机器人接入AI能力。

方案一

方案一将拆解接入 AI 服务的各个步骤,为您详细介绍如何通过腾讯云即时通信 IM 第三方回调功能,将 AI 服务能力引入到 IM 应用中,创建一个可以智能聊天的 AI 机器人(文中的实践步骤以接入 MiniMax 中文大语言模型为例,类 ChatGPT 服务均可通过文中介绍的方法实现接入)。

准备工作

注册腾讯云 IM 账号

注册并登录腾讯云账号,进入即时通信 IM 控制台,创建应用,并获取应用的 SDKAppID 和密钥(以下称为 IM Key),并创建一个管理员账号 administrator。

注册对应 AI 服务商账号

注册并登录计划接入的 AI 服务商的相应账号并获取 API 密钥(以下称为AI_SECRET_KEY)。

创建腾讯云 IM 机器人账号

通过 REST API 创建一个腾讯云 IM 机器人账号。腾讯云机器人是一种特殊的用户,UserID 以 @RBT# 开头。
curl -d '{"UserID":"@RBT#001","Nick":"MyRobot"}' "https://console.tim.qq.com/v4/openim_robot_http_svc/create_robot?sdkappid= {}&identifier=administrator&usersig={}&random=123456789&contenttype=json"
将上述命令的 sdkappid={} 和 usersig={} 替换成您的 SDKAppID 和使用 IM Key 生成的 Usersig,详情可参见 生成 UserSig。在 Linux 环境运行上述命令后,腾讯云服务器返回:
{"ActionStatus": "OK", "ErrorCode": 0, "ErrorInfo": ""}
表示成功创建了一个昵称为 MyRobot 的机器人@RBT#001。

配置腾讯云 IM 第三方回调

即时通信 IM 第三方回调即云IM后台会在某一事件发生之前或者之后,向 App 的后台服务器发送请求,App 后台可以据此进行必要的数据同步,或者干预事件的后续处理流程。我们将使用“机器人事件回调”监听用户发消息给机器人,或者在群聊中@机器人的事件,并对其做出反应。在腾讯云 IM 控制台中找到“机器人事件回调”,点击开启并保存。

编写 APP 后台服务

以单聊为例,总体上的工作流程如下:
1. 用户 user1 发消息“hello”给机器人@RBT#001;
2. 云 IM 后台发送第三方回调将事件通知 App 后台;
3. App 后台收到事件通知,通知内容包含发送方 user1,接收方 @RBT#001,消息内容 hello 以及其他信息;
4. App 后台调用 AI 服务接口(即MiniMax API),并得到响应回复内容,如 nice to meet you;
5. App 后台调用云 IM REST API接口(单聊为 sendmsg 接口,群聊为 send_group_msg 接口),将回复内容以 @RBT#001 的身份发送给 user1。



以 Golang 为例,App 后台的关键代码可参见下文。
注意:
下文代码仅作为展示用途,省略了大量异常处理代码,不可直接用于生产环境。

分发处理回调命令

我们创建一个监听在80端口的 HTTP 服务,注册一个 url 为 /im 的处理函数 handler,所有发送给 http:///im 的请求都会被 handler 处理。所有云IM发送的回调请求都带有 CallbackCommand 参数,不同的值代表不同的回调命令。在 handler 中,根据云 IM 设置的参数 CallbackCommand 进行对应的处理。
func handler(w http.ResponseWriter, r *http.Request) {
command := r.URL.Query().Get("CallbackCommand")
reqbody, _ := io.ReadAll(r.Body)
var rspbody []byte
switch command {
case "Bot.OnC2CMessage": // 机器人C2C回调命令字
dealC2c(context.Background(), reqbody)
rspbody = []byte("{\\"ActionStatus\\": \\"OK\\", \\"ErrorCode\\": 0, \\"ErrorInfo\\": \\"\\"}")
default:
rspbody = []byte("invalid CallbackCommand.")
}
w.Write(rspbody)
}
func main() { // 注册一个handler,处理发送给App后台的回调命令
http.HandleFunc("/im", handler)
http.ListenAndServe(":80", nil)
}

处理机器人接收到单聊消息事件

处理单聊消息时,我们先检查发送方是不是机器人(一般不会出现这种机器人发送消息给机器人的情况),以防止无限的回调循环。接着,我们解析消息体,拿到用户发送给机器人的消息内容 text,将发送方 UserID 保存到 context 中以方便后续调用 REST API 回复,最后调用 askAI 请求 AI 服务。
func dealC2c(ctx context.Context, reqbody []byte) error {
root, _ := simplejson.NewJson(reqbody)
jFromAccount := root.Get("From_Account")
fromAccount, _ = jFromAccount.String()
// 检查发送方ID,不处理机器人发送给机器人的请求,防止无限循环
if strings.HasPrefix(fromAccount, "@RBT#") {
return nil
}
jToAccount := root.Get("To_Account")
toAccount, _ := jToAccount.String()
msgBodyList, _ := root.Get("MsgBody").Array()
for _, m := range msgBodyList {
msgBody, _ := m.(map[string]interface{})
msgType, _ := msgBody["MsgType"].(string)
if msgType != "TIMTextElem" {
continue
}
msgContent, _ := msgBody["MsgContent"].(map[string]interface{})
text, _ := msgContent["Text"].(string)
ctx = context.WithValue(ctx, "from", fromAccount)
ctx = context.WithValue(ctx, "to", toAccount)
go askAI(ctx, text)
}
return nil
}

调用 AI 服务接口

在这一步我们使用第三方AI服务公司 MiniMax 实现智能聊天的功能,您可以将 MiniMax 服务替换成任意的其它 AI 服务。需要注意的是这里演示的是简单的 completion 接口,没有保存对话的上下文,其他接口可按需查阅 MiniMax 文档。
type MiniMaxRsp struct {
Reply string `json:"reply"`
}

// 请求MiniMax并得到回复
func askAI(ctx context.Context, prompt string) {
url := "https://api.minimax.chat/v1/text/completion"
var reqData = []byte(`{
"model": "abab5-completion",
"prompt": prompt
}`)
request, _ := http.NewRequest("POST", url, bytes.NewBuffer(reqData))
request.Header.Set("Content-Type", "application/json; charset=UTF-8)
request.Header.Set("Authorization", API_SECRET_KEY)
client := &http.Client{}
response, _ := client.Do(request)
defer response.Body.Close()
body, _ := ioutil.ReadAll(response.Body)
rsp := &MiniMaxRsp{}
json.Unmarshal(body, rsp)
reply(ctx, rsp.Reply) // 将AI回复的内容发送给用户
}

将 AI 返回的结果返回给用户

从 AI 服务得到回复之后,我们只需调用云 IM 的 REST API 接口 sendmsg,制定消息发送方为@RBT#001,接收方为 user1,模拟机器人回复用户。
// 发送一个REST API请求
func doRestAPI(host string, sdkappid int, admin, usersig, command, body string) {
url := fmt.Sprintf("https://%s/v4/%s?sdkappid=%d&identifier=%s&usersig=%s&random=%d&contenttype=json",
host, command, sdkappid, admin, usersig, rand.Uint32())
req, _ := http.NewRequest("POST", url, bytes.NewBufferString(body))
req.Header.Set("Content-Type", "application/json")
cli := &http.Client{}
rsp, err := cli.Do(req)
if err != nil {
log.Printf("REST API failed. %s", err.Error())
return
}
defer rsp.Body.Close()
rsptext, _ := io.ReadAll(rsp.Body)
log.Printf("rsp:%s", rsptext)
}

// 调用腾讯云IM的REST API,回复用户
func reply(ctx context.Context, text string) {
rsp := make(map[string]interface{})
msgbody := []map[string]interface{}{{
"MsgType": "TIMTextElem",
"MsgContent": map[string]interface{}{"Text": text},
}}
// GenUserSig 的实现可以参考腾讯云文档
usersig, _ := GenUserSig(IM_SDKAPPID, IM_KEY, "administrator", 60)
rsp["From_Account"] = ctx.Value("to").(string) //"@RBT#001"
rsp["To_Account"] = ctx.Value("from").(string)
rsp["SyncOtherMachine"] = 2
rsp["MsgLifeTime"] = 60 * 60 * 24 * 7
rsp["MsgSeq"] = rand.Uint32()
rsp["MsgRandom"] = rand.Uint32()
rsp["MsgBody"] = msgbody
rspbody, _ := json.Marshal(rsp)
doRestAPI("console.tim.qq.com", IM_SDKAPPID, "administrator", usersig, "openim/sendmsg", string(rspbody))
}

效果展示

使用腾讯云 IM 的 demo 实现,最终的效果展示如下:



通过以上步骤,我们便实现了腾讯云 IM 在服务端和 MiniMaxAI 开放平台的单聊对接,接入其他 AI 服务商也可参照上述步骤,仅需将 askAI 函数替换成其他 AI服务商的对应 API 调用即可。对于群聊机器人,开发者仅需补充实现 Bot.OnGroupMessage 回调命令处理即可。

常见问题:

如何实现机器人欢迎语?(打开机器人聊天对话,机器人自动发送欢迎消息)

客户端可以在用户打开机器人聊天对话框时,客户端发送一条静默的自定义消息,设置 onlineUserOnly 为 true(设置该 flag 表示不存漫游),App 后台通过回调接收到此自定义消息后,调用 REST API 发送欢迎消息。

方案二

实现AI聊天机器人处理使用上述的回调方案之外,还可以考虑使用IM已有智能机器人的方案,通过智能机器人可以轻松实现 FAQ 智能问答、闲聊、数据运营看板等AI能力,结合腾讯云即时通信 IM 产品,您可以快速实现多平台跨终端互通的聊天机器人。相关的详细方案文档请参考智能机器人