最佳实践 | 即时通信IM接入AI服务,高效构建智能聊天能力

2023年8月11日 836点热度 0条评论

6db188e09d3551d568cb870dc99a0295-1

腾讯云即时通信IM接入AI服务,高效构建智能聊天能力 https://cloud.tencent.com/act/cps/redirect?redirect=45&cps_key=388be5651b83aac337c2a73702e02ec3&from=console

随着ChatGPT在全球范围的爆火,AI已成为当下开发者最为关注的焦点,国内各大厂商也纷纷跟进,推出了各自的大模型应用与产品。很多应用都在尝试与AI结合,寻找新的发力点。而新一代大语言模型的强大对话交流能力与各类即时通信场景天然契合,这为IM与AI结合带来了广阔的想象空间。

在办公场景,用户可以直接通过对话让AI辅助自己高效完成工作纪要、文案编写、信息搜集等需求;在客服场景,与AI结合的智能客服可以提供真人客服般的会话体验,更有效地引导用户进行购买、使用;在社交场景,AI聊天机器人可以为用户提供24小时在线的心理咨询和情感陪伴,提升用户粘性……腾讯云即时通信IM作为全球领先的通信云服务商,也看到了AI在即时通信场景的巨大潜力,快速发布了相关AI能力调用接口。开发者基于腾讯云IM提供的通信底座,可以自由调用业内领先的大模型能力,用丰富的AI能力赋能自己,高效实现场景创新。

那具体该如何接入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的生成可以参考官网文档(https://cloud.tencent.com/document/product/269/32688)。在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。

61918b2f5db8f3d0ca3bf34fd86312b0-1

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

分发处理回调命令

我们创建一个监听在80端口的http服务,注册一个url为/im的处理函数handler,所有发送给http://<your.domain.com>/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实现,最终的效果展示如下:

32bc849cf11fb715e2944b19deafdb49-1

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


如果您对接入流程或我们产品有任何疑问或建议,欢迎扫描下方二维码添加音视频小姐姐微信,与我们的技术团队深入沟通交流。

腾讯云即时通信IM接入AI服务,高效构建智能聊天能力 https://cloud.tencent.com/act/cps/redirect?redirect=45&cps_key=388be5651b83aac337c2a73702e02ec3&from=console

harry

这个人很懒,什么都没留下

文章评论