隨著ChatGPT在全球范圍的爆火,AI已成為當(dāng)下開發(fā)者最為關(guān)注的焦點蝙茶,國內(nèi)各大廠商也紛紛跟進(jìn)艺骂,推出了各自的大模型應(yīng)用與產(chǎn)品。很多應(yīng)用都在嘗試與AI結(jié)合隆夯,尋找新的發(fā)力點钳恕。而新一代大語言模型的強(qiáng)大對話交流能力與各類即時通信場景天然契合,這為IM與AI結(jié)合帶來了廣闊的想象空間蹄衷。
那即時通信IM該如何接入AI服務(wù)呢忧额?本文將拆解接入AI服務(wù)的各個步驟,為您詳細(xì)介紹如何通過騰訊云即時通信IM第三方回調(diào)功能宦芦,將AI服務(wù)能力引入到IM應(yīng)用中宙址,創(chuàng)建一個可以智能聊天的AI機(jī)器人,為用戶提供真人般對話體驗调卑,實現(xiàn)智能客服抡砂、創(chuàng)意輔助大咱、工作助手等功能。(文中的實踐步驟以接入MiniMax中文大語言模型為例注益,類ChatGPT服務(wù)均可通過文中介紹的方法實現(xiàn)接入)
準(zhǔn)備工作
注冊賬號
注冊并登錄騰訊云賬號碴巾,進(jìn)入即時通信IM控制臺,創(chuàng)建應(yīng)用丑搔,并獲取應(yīng)用的SDKAppID和密鑰(以下稱為 IM Key)厦瓢,并創(chuàng)建一個管理員賬號administrator。
注冊對應(yīng)AI服務(wù)商賬號
注冊并登錄計劃接入的AI服務(wù)商的相應(yīng)賬號并獲取API密鑰(以下稱為AI_SECRET_KEY)啤月。
創(chuàng)建即時通信IM機(jī)器人賬號
通過REST API創(chuàng)建一個機(jī)器人賬號煮仇。機(jī)器人是一種特殊的用戶,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"
復(fù)制
將上述命令的sdkappid={}和usersig={}替換成您的SDKAppID和使用IM Key生成的Usersig浙垫。Usersig的生成可以參考官網(wǎng)文檔(https://cloud.tencent.com/document/product/269/32688)。在Linux環(huán)境運行上述命令后郑诺,云服務(wù)器返回:
{"ActionStatus":"OK","ErrorCode":0,"ErrorInfo":""}
復(fù)制
表示成功創(chuàng)建了一個昵稱為MyRobot的機(jī)器人@RBT#001夹姥。
配置即時通信IM第三方回調(diào)
即時通信 IM 第三方回調(diào)即云IM后臺會在某一事件發(fā)生之前或者之后,向 App 的后臺服務(wù)器發(fā)送請求辙诞,App 后臺可以據(jù)此進(jìn)行必要的數(shù)據(jù)同步辙售,或者干預(yù)事件的后續(xù)處理流程。我們將使用“機(jī)器人事件回調(diào)”監(jiān)聽用戶發(fā)消息給機(jī)器人飞涂,或者在群聊中@機(jī)器人的事件旦部,并對其做出反應(yīng)。在即時通信IM控制臺中找到“機(jī)器人事件回調(diào)”封拧,點擊開啟并保存志鹃。
編寫APP后臺服務(wù)
以單聊為例夭问,總體上的工作流程如下:
用戶user1發(fā)消息“hello”給機(jī)器人@RBT#001泽西;
云IM后臺發(fā)送第三方回調(diào)將事件通知App后臺;
App后臺收到事件通知缰趋,通知內(nèi)容包含發(fā)送方user1捧杉,接收方@RBT#001,消息內(nèi)容hello以及其他信息秘血;
App后臺調(diào)用AI服務(wù)接口(即MiniMax API)味抖,并得到響應(yīng)回復(fù)內(nèi)容,如nice to meet you灰粮;
App后臺調(diào)用云IM REST API接口(單聊為sendmsg接口仔涩,群聊為send_group_msg接口),將回復(fù)內(nèi)容以@RBT#001的身份發(fā)送給user1粘舟。
以Golang為例熔脂,App后臺的關(guān)鍵代碼大概如下(請注意佩研,本代碼僅作為展示用途,省略了大量異常處理代碼霞揉,不可直接用于生產(chǎn)環(huán)境):
分發(fā)處理回調(diào)命令
我們創(chuàng)建一個監(jiān)聽在80端口的http服務(wù)旬薯,注冊一個url為/im的處理函數(shù)handler,所有發(fā)送給http://<your.domain.com>/im的請求都會被handler處理适秩。所有云IM發(fā)送的回調(diào)請求都帶有CallbackCommand參數(shù)绊序,不同的值代表不同的回調(diào)命令。在handler中秽荞,根據(jù)云IM設(shè)置的參數(shù)CallbackCommand進(jìn)行對應(yīng)的處理骤公。
funchandler(w http.ResponseWriter, r *http.Request) {? command := r.URL.Query().Get("CallbackCommand")? reqbody, _ := io.ReadAll(r.Body)varrspbody []byteswitchcommand {case"Bot.OnC2CMessage":// 機(jī)器人C2C回調(diào)命令字dealC2c(context.Background(), reqbody)? ? rspbody = []byte("{\"ActionStatus\": \"OK\", \"ErrorCode\": 0, \"ErrorInfo\": \"\"}")default:? ? rspbody = []byte("invalid CallbackCommand.")? }? w.Write(rspbody)}funcmain() {// 注冊一個handler,處理發(fā)送給App后臺的回調(diào)命令http.HandleFunc("/im", handler)? http.ListenAndServe(":80", nil)}
復(fù)制
處理機(jī)器人接收到單聊消息事件
處理單聊消息時扬跋,我們先檢查發(fā)送方是不是機(jī)器人(一般不會出現(xiàn)這種機(jī)器人發(fā)送消息給機(jī)器人的情況)淋样,以防止無限的回調(diào)循環(huán)。接著胁住,我們解析消息體趁猴,拿到用戶發(fā)送給機(jī)器人的消息內(nèi)容text,將發(fā)送方UserID保存到context中以方便后續(xù)調(diào)用REST API回復(fù)彪见,最后調(diào)用askAI請求AI服務(wù)儡司。
funcdealC2c(ctx context.Context, reqbody []byte) error {? root, _ := simplejson.NewJson(reqbody)? jFromAccount := root.Get("From_Account")? fromAccount, _ = jFromAccount.String()// 檢查發(fā)送方ID,不處理機(jī)器人發(fā)送給機(jī)器人的請求余指,防止無限循環(huán)ifstrings.HasPrefix(fromAccount,"@RBT#") {returnnil? }? 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)ifmsgType !="TIMTextElem"{continue}? ? msgContent, _ := msgBody["MsgContent"].(map[string]interface{})? ? text, _ := msgContent["Text"].(string)? ? ctx = context.WithValue(ctx,"from", fromAccount)? ? ctx = context.WithValue(ctx,"to", toAccount)? ? goaskAI(ctx, text)? }returnnil}
復(fù)制
調(diào)用AI服務(wù)接口
在這一步我們使用第三方AI服務(wù)公司MiniMax實現(xiàn)智能聊天的功能捕犬,您可以將MiniMax服務(wù)替換成任意的其它AI服務(wù)。需要注意的是這里演示的是簡單的completion接口酵镜,沒有保存對話的上下文碉碉,其他接口可按需查閱MiniMax文檔。
typeMiniMaxRspstruct {Replystring`json:"reply"`}// 請求MiniMax并得到回復(fù)funcaskAI(ctx context.Context, prompt string) {? url :="https://api.minimax.chat/v1/text/completion"varreqData = []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回復(fù)的內(nèi)容發(fā)送給用戶
}
復(fù)制
將AI返回的結(jié)果返回給用戶
從AI服務(wù)得到回復(fù)之后淮韭,我們只需調(diào)用云IM的REST API接口sendmsg垢粮,制定消息發(fā)送方為@RBT#001,接收方為user1靠粪,模擬機(jī)器人回復(fù)用戶蜡吧。
// 發(fā)送一個REST API請求funcdoRestAPI(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)iferr != nil {? ? log.Printf("REST API failed. %s", err.Error())return}? defer rsp.Body.Close()? rsptext, _ := io.ReadAll(rsp.Body)? log.Printf("rsp:%s", rsptext)}// 調(diào)用騰訊云IM的REST API,回復(fù)用戶funcreply(ctx context.Context, text string) {? rsp :=make(map[string]interface{})? msgbody := []map[string]interface{}{{"MsgType":"TIMTextElem","MsgContent": map[string]interface{}{"Text": text},? }}// GenUserSig 的實現(xiàn)可以參考騰訊云文檔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"] =2rsp["MsgLifeTime"] =60*60*24*7rsp["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))}
復(fù)制
通過以上步驟占键,我們便實現(xiàn)了即時通信IM在服務(wù)端和MiniMaxAI開放平臺的單聊對接昔善,接入其他AI服務(wù)商也可參照上述步驟,僅需將askAI函數(shù)替換成其他AI服務(wù)商的對應(yīng)API調(diào)用即可畔乙。對于群聊機(jī)器人君仆,開發(fā)者僅需補(bǔ)充實現(xiàn)Bot.OnGroupMessage回調(diào)命令處理即可。