Feishu-ChatGPT - 用 JavaScript 五分钟开发一个飞书 ChatGPT 机器人用 JavaScript 五分钟开发一个飞书 ChatGPT 机器人用 JavaScript 五分钟开发一个飞书 ChatGPT 机器人

    本文帮助你快速实现一个飞书对话机器人,并在其中接入 ChatGPT 的能力,可以直接问它问题,也可以在群聊天中 at 它,返回 ChatGPT 的回答。(以下为效果截图)

    用 JavaScript 开发飞书 ChatGPT 机器人(含全部源码,免费托管,手把手教程) - 图1

    学习路径

    1、创建飞书机器人,并配置事件和权限
    2、使用 AirCode 的「一键 Copy 代码」功能,实现机器人的聊天能力
    3、将机器人接入 ChatGPT 能力

    第一步:创建飞书机器人

    1、在飞书开发者后台中创建一个应用,并且添加机器人能力。

    用 JavaScript 开发飞书 ChatGPT 机器人(含全部源码,免费托管,手把手教程) - 图2

    用 JavaScript 开发飞书 ChatGPT 机器人(含全部源码,免费托管,手把手教程) - 图3

    用 JavaScript 开发飞书 ChatGPT 机器人(含全部源码,免费托管,手把手教程) - 图4

    2、创建好的机器人就有 App ID 和 App Secret,可以复制备用。

    用 JavaScript 开发飞书 ChatGPT 机器人(含全部源码,免费托管,手把手教程) - 图5

    第二步:创建 AirCode 应用

    1、通过 AirCode 源码链接中右上角的「Get a copy」按钮快速生成一个自己的 AirCode Node.js 应用。如果没有登录,需先登录 AirCode。

    用 JavaScript 开发飞书 ChatGPT 机器人(含全部源码,免费托管,手把手教程) - 图6

    用 JavaScript 开发飞书 ChatGPT 机器人(含全部源码,免费托管,手把手教程) - 图7

    用 JavaScript 开发飞书 ChatGPT 机器人(含全部源码,免费托管,手把手教程) - 图8

    2、将飞书开发者后台中刚创建应用的「凭证与基础信息」页面中的 App ID 和 App Secret,粘贴到刚创建的 AirCode 应用的环境变量(Environments)中,在 feishuAppId 和 feishuAppSecret 中分别填入粘贴过来的机器人 App ID 和 App Secret 的值。

    用 JavaScript 开发飞书 ChatGPT 机器人(含全部源码,免费托管,手把手教程) - 图9

    3、配置好环境变量(Environments)后,点击页面上方的「Deploy 按钮」部署整个应用,使所有配置生效。

    用 JavaScript 开发飞书 ChatGPT 机器人(含全部源码,免费托管,手把手教程) - 图10

    第三步:配置机器人的事件和权限

    1、AirCode 应用部署成功后,你就能看到当前服务的调用 URL,将它复制,填到飞书开发者后台刚刚创建机器人的「事件订阅-请求地址」中。

    用 JavaScript 开发飞书 ChatGPT 机器人(含全部源码,免费托管,手把手教程) - 图11

    用 JavaScript 开发飞书 ChatGPT 机器人(含全部源码,免费托管,手把手教程) - 图12

    2、点击保存时,如果失败,可以将 AirCode 应用再次部署。

    用 JavaScript 开发飞书 ChatGPT 机器人(含全部源码,免费托管,手把手教程) - 图13

    3、给机器人添加聊天相关的事件:
    ●获取用户在群组中@机器人的消息
    ●接收群聊中@机器人消息事件
    ●获取用户发给机器人的单聊消息

    用 JavaScript 开发飞书 ChatGPT 机器人(含全部源码,免费托管,手把手教程) - 图14

    用 JavaScript 开发飞书 ChatGPT 机器人(含全部源码,免费托管,手把手教程) - 图15

    用 JavaScript 开发飞书 ChatGPT 机器人(含全部源码,免费托管,手把手教程) - 图16

    4、配置好了之后,需要发布机器人才能生效,并且能够搜索到。

    用 JavaScript 开发飞书 ChatGPT 机器人(含全部源码,免费托管,手把手教程) - 图17

    第四步:测试聊天机器人

    1、将机器人发布后,可在聊天窗口中与机器人私聊,或者将机器人加入到群中 at 机器人聊天,此时机器人可以对话。由于还没有配置 ChatGPT 能力,所以机器人会直接将你的消息返回,这时表示机器人已经配置成功。

    用 JavaScript 开发飞书 ChatGPT 机器人(含全部源码,免费托管,手把手教程) - 图18

    2、可以在 AirCode 中查看完整的请求数据,并且使用线上 request 调试代码。

    用 JavaScript 开发飞书 ChatGPT 机器人(含全部源码,免费托管,手把手教程) - 图19

    第五步:接入 ChatGPT 能力

    1、到 OpenAI 的控制台中,点「Create new secret key」生成并且复制这个新生成的 Key,粘贴到刚创建的 AirCode 应用的环境变量(Environments)中,粘贴到 OpenAISecret 的 value 中。如果没有 OpenAI 账号,可以到网络中搜索一下获取方式,提前购买准备好。

    用 JavaScript 开发飞书 ChatGPT 机器人(含全部源码,免费托管,手把手教程) - 图20

    用 JavaScript 开发飞书 ChatGPT 机器人(含全部源码,免费托管,手把手教程) - 图21

    2、再次部署服务,后测试。目前 ChatGPT 服务比较慢,尤其是模型版本越高级、问题越复杂,ChatGPT 服务的返回时间会越长。

    用 JavaScript 开发飞书 ChatGPT 机器人(含全部源码,免费托管,手把手教程) - 图22

    问题反馈
    1、可以加入我们的飞书用户群
    2、来到我们的 GitHub 仓库,可以提 issue 或者直接贡献代码
    3、欢迎加入我们的 Discord 讨论区

    附:Chat.js

    // 引入基础依赖包 constaircode=require(‘aircode’); constaxios=require(‘axios’);
    // 引入 OpenAI 的 SDK constopenai=require(“openai”);
    // 从环境变量中获取 OpenAI 的 Secret constOpenAISecret=process.env.OpenAISecret; letchatGPT=null; if(OpenAISecret){ // 与 ChatGTP 聊天的方法,传入字符串即可 constconfiguration=newopenai.Configuration({apiKey:OpenAISecret}); constclient=newopenai.OpenAIApi(configuration); chatGPT=async(content)=>{ returnawaitclient.createChatCompletion({ // 使用当前 OpenAI 开放的最新 3.5 模型,如果后续 4 发布,则修改此处参数即可 model:‘gpt-3.5-turbo’, // 让 ChatGPT 充当的角色为 assistant messages:[{role:‘assistant’,content}], }); }; }
    // 从环境变量中获取飞书机器人的 App ID 和 App Secret constfeishuAppId=process.env.feishuAppId; constfeishuAppSecret=process.env.feishuAppSecret;
    // 获取飞书 tenant_access_token 的方法 constgetTenantToken=async()=>{ consturl=https://open.feishu.cn/open-apis/v3/auth/tenant_access_token/internal/; constres=awaitaxios.post(url,{ ‘app_id’:feishuAppId,‘app_secret’:feishuAppSecret, }); returnres.data.tenant_access_token; };
    // 用飞书机器人回复用户消息的方法 constfeishuReply=async(objs)=>{ consttenantToken=awaitgetTenantToken(); consturl=https://open.feishu.cn/open-apis/im/v1/messages/</font><font style="color:rgb(38, 44, 49);">${</font><font style="color:rgb(35, 41, 48);">objs</font><font style="color:rgb(225, 0, 35);">.</font><font style="color:rgb(140, 72, 231);">msgId</font><font style="color:rgb(38, 44, 49);">}</font><font style="color:rgb(125, 89, 89);">/reply; letcontent=objs.content;
    // 实现 at 用户能力 if(objs.openId)content=<at user_id="</font><font style="color:rgb(38, 44, 49);">${</font><font style="color:rgb(35, 41, 48);">objs</font><font style="color:rgb(225, 0, 35);">.</font><font style="color:rgb(140, 72, 231);">openId</font><font style="color:rgb(38, 44, 49);">}</font><font style="color:rgb(125, 89, 89);">"></at> </font><font style="color:rgb(38, 44, 49);">${</font><font style="color:rgb(35, 41, 48);">content</font><font style="color:rgb(38, 44, 49);">}</font><font style="color:rgb(125, 89, 89);">; constres=awaitaxios({ url,method:‘post’, headers:{‘Authorization’:Bearer </font><font style="color:rgb(38, 44, 49);">${</font><font style="color:rgb(35, 41, 48);">tenantToken</font><font style="color:rgb(38, 44, 49);">}</font><font style="color:rgb(125, 89, 89);">}, data:{msg_type:‘text’,content:JSON.stringify({text:content})}, }); returnres.data.data; };
    // 飞书 ChatGPT 机器人的入口函数 module.exports=asyncfunction(params,context){
    // 用来做飞书接口校验,飞书接口要求有 challenge 参数时需直接返回 if(params.challenge)return{challenge:params.challenge};
    // 所有调用当前函数的参数都可以直接从 params 中获取 // 飞书机器人每条用户消息都会有 event_id consteventId=params.header.event_id;
    // 可以使用数据库极其简单地写入数据到数据表中 // 实例化一个名字叫做 contents 的表 constcontentsTable=aircode.db.table(‘contents’);
    // 搜索 contents 表中是否有 eventId 与当前这次一致的 constcontentObj=awaitcontentsTable.where({eventId}).findOne();
    // 如果 contentObj 有值,则代表这条 event 出现过 // 由于 ChatGPT 返回时间较长,这种情况可能是飞书的重试,直接 return 掉,防止重复调用 if(contentObj)return; constmessage=params.event.message;
    // 获取用户具体消息 constcontent=JSON.parse(message.content).text.replace(‘@_user_1 ‘,‘’);
    // 获取发送消息的人信息 constsender=params.event.sender;
    // 将消息体信息储存到数据库中,以备后续查询历史或做上下文支持使用 awaitcontentsTable.save({ eventId:params.header.event_id, msgId:message.message_id, openId:sender.sender_id.open_id, content, });
    // 机器人默认将收到的消息直接返回 letreplyContent=content;
    // 如果配置了 OpenAI Key 则让 ChatGPT 回复 if(OpenAISecret){
    // 将用户具体消息发送给 ChatGPT constresult=awaitchatGPT(content);
    // 获取到 ChatGPT 的回复 replyContent=</font><font style="color:rgb(38, 44, 49);">${</font><font style="color:rgb(35, 41, 48);">result</font><font style="color:rgb(225, 0, 35);">.</font><font style="color:rgb(140, 72, 231);">data</font><font style="color:rgb(225, 0, 35);">.</font><font style="color:rgb(140, 72, 231);">choices</font><font style="color:rgb(38, 44, 49);">[</font><font style="color:rgb(0, 79, 180);">0</font><font style="color:rgb(38, 44, 49);">]</font><font style="color:rgb(225, 0, 35);">.</font><font style="color:rgb(140, 72, 231);">message</font><font style="color:rgb(225, 0, 35);">.</font><font style="color:rgb(140, 72, 231);">content</font><font style="color:rgb(225, 0, 35);">.</font><font style="color:rgb(140, 72, 231);">trim</font><font style="color:rgb(38, 44, 49);">(</font><font style="color:rgb(38, 44, 49);">)</font><font style="color:rgb(38, 44, 49);">}</font><font style="color:rgb(125, 89, 89);">; }
    // 将 ChatGPT 的回复通过飞书机器人发送给用户 awaitfeishuReply({ msgId:message.message_id, openId:sender.sender_id.open_id, content:replyContent, });
    // 整个函数调用结束,需要有返回 returnnull; }