likes
comments
collection
share

🧜‍♂️为了摸鱼,我用3天从0搭建飞书聊天机器人

作者站长头像
站长
· 阅读数 28

🧜‍♂️为了摸鱼,我用3天从0搭建飞书聊天机器人

背景介绍

saas小公司前端切图仔,每天的业务开展需要流转于各个系统,不利于高效工作(moyu)。遂产生case,能否做一个聊天机器人,能支持ai模型会话,且能基于聊天开展日常的业务? 希望支持以下功能:

🧜‍♂️为了摸鱼,我用3天从0搭建飞书聊天机器人

草拟方案之后,do it!

如何做?

飞书相关配置

进入 飞书开发者后台,创建企业自建应用

🧜‍♂️为了摸鱼,我用3天从0搭建飞书聊天机器人

保存 App ID 和 App Secret 的信息

🧜‍♂️为了摸鱼,我用3天从0搭建飞书聊天机器人

为创建好的应用添加机器人能力

🧜‍♂️为了摸鱼,我用3天从0搭建飞书聊天机器人

为机器人添加能力

在权限管理页面进行权限配置,需开通如下 6 个权限:

  • im:message
  • im:message.group_at_msg
  • im:message.group_at_msg:readonly
  • im:message.p2p_msg
  • im:message.p2p_msg:readonly
  • im:message:send_as_bot

🧜‍♂️为了摸鱼,我用3天从0搭建飞书聊天机器人

后端开发

如果读者只需要gpt聊天能力,可以参考这篇知乎: 手把手教你在飞书中搭建机器人

由于笔者需要机器人在支持ai模型会话的基础上,能基于预设指令执行对应的任务,故决定采用java (mybatis-plus)作为技术栈。(本人的后端水平是半吊子,如果有做得不好的地方,欢迎大家指出斧正,感谢。另外就是,前后端写混了,命名小驼峰和下划线掺杂,由于是个人项目,没有太重视)

🧜‍♂️为了摸鱼,我用3天从0搭建飞书聊天机器人

开发消息接收接口

接下来,需要开发一个接口用于事件订阅,即在有人私聊或群聊内@机器人时,飞书会推送通知。

🧜‍♂️为了摸鱼,我用3天从0搭建飞书聊天机器人

在开发者后台可以看到,填写订阅地址时,需要进行校验,所以我们先实现CHALLENGE校验

@Slf4j
@Controller
@Api(tags = "阁宝机器人")
@RequestMapping(value = "/gebao")
public class GeBaoController {

    @Autowired
    GebaoService gebaoService;

    @ResponseBody
    @ApiOperation(value = "飞书通知webhook")
    @RequestMapping(value = "/feishu/notice", method = RequestMethod.POST)
    public JSONObject postFeishuNotice(@RequestBody JSONObject body) {
        log.info("飞书通知接口被请求,请求体为:" + body.toJSONString());

        //处理消息
        gebaoService.handleMessage(body);

        //以下代码用于处理challenge校验
        JSONObject res = new JSONObject();
        res.put("challenge", body.getString("challenge"));
        return res;
    }

}

处理接收到消息订阅的后续逻辑

在GebaoService内,实现handleMessage方法,对私聊或群聊@机器人的消息进行处理

//处理聊天消息
@Override
public void handleMessage(JSONObject body) throws Exception {
    JSONObject header = body.getJSONObject("header");
    JSONObject event = body.getJSONObject("event");
    JSONObject message = event.getJSONObject("message");
    JSONObject sender = event.getJSONObject("sender");
    String event_type = header.getString("event_type");
    //判断是否为飞书开放平台的事件回调
    if (event_type.equals("im.message.receive_v1")) {
        String event_id = header.getString("event_id");
        JSONObject content = JSONObject.parseObject(message.getString("content"));
        String content_text = content.getString("text").replaceAll("@_user_1\s", "");
        String chat_id = message.getString("chat_id");
        JSONObject sender_id = sender.getJSONObject("sender_id");
        String sender_open_id = sender_id.getString("open_id");

        log.info("过滤后的content_text:" + content_text);

        // 对于同一个事件,只处理一次
        if (redisUtil.get("gebao-event_id-" + event_id) != null) {
            log.info("事件重复,不处理");
            return;
        }
        //缓存event_id
        redisUtil.set("gebao-event_id-" + event_id, event_id);

        // 私聊直接回复
        if (message.getString("chat_type").equals("p2p")) {
            handleTextMessage(message, content_text, "open_id", sender_open_id);
        }

        // 群聊需要@机器人
        if (message.getString("chat_type").equals("group")) {
            JSONArray mentions = message.getJSONArray("mentions");
            // 没有 @ 机器人,不处理
            if (mentions.isEmpty() || !mentions.getJSONObject(0).getString("name").equals("阁宝")) return;
            handleTextMessage(message, content_text, "chat_id", chat_id);
        }
    }

}

接下来,实现handleTextMessage方法,主要功能是对会话内容进行区分,预设指令执行对应的逻辑,其余消息通过ai模型获取回复

//处理文本消息
private void handleTextMessage(JSONObject message, String content_text, String receive_id_type, String receive_id) throws Exception {
    // 不是文本消息,不处理
    if (!message.getString("message_type").equals("text")) {
        feishuPower.sendMessage(receive_id_type, receive_id, "text", getContent("暂不支持其他类型的消息"));
        return;
    }
    // 是文本消息,判断是否为预设指令
    if (!handleInstruction(receive_id_type, receive_id, content_text)) {
        //不为预设指令,获取模型的回复
        String reply_text = hunyuanPower.getHunyuanReply(receive_id, content_text);
        log.info("模型的回复:" + reply_text);
        if (reply_text != null) {
            String reply_content = getContent(reply_text);
            feishuPower.sendMessage(receive_id_type, receive_id, "text", reply_content);
        }
    }

}

笔者这里选用的腾讯混元大模型,支持国产。读者可基于偏好自行选用

核心逻辑如上。读者开发时,可自行实现通过ai获取回复、发送消息到飞书等能力,官方都有提供sdk

成品效果展示

ai模型会话

🧜‍♂️为了摸鱼,我用3天从0搭建飞书聊天机器人

🧜‍♂️为了摸鱼,我用3天从0搭建飞书聊天机器人

指令会话

🧜‍♂️为了摸鱼,我用3天从0搭建飞书聊天机器人

转载自:https://juejin.cn/post/7374709266178572323
评论
请登录