🧜♂️为了摸鱼,我用3天从0搭建飞书聊天机器人
背景介绍
saas小公司前端切图仔,每天的业务开展需要流转于各个系统,不利于高效工作(moyu)。遂产生case,能否做一个聊天机器人,能支持ai模型会话,且能基于聊天开展日常的业务? 希望支持以下功能:
草拟方案之后,do it!
如何做?
飞书相关配置
进入 飞书开发者后台,创建企业自建应用
保存 App ID 和 App Secret 的信息
为创建好的应用添加机器人能力
为机器人添加能力
在权限管理页面进行权限配置,需开通如下 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
后端开发
如果读者只需要gpt聊天能力,可以参考这篇知乎: 手把手教你在飞书中搭建机器人
由于笔者需要机器人在支持ai模型会话的基础上,能基于预设指令执行对应的任务,故决定采用java (mybatis-plus)作为技术栈。(本人的后端水平是半吊子,如果有做得不好的地方,欢迎大家指出斧正,感谢。另外就是,前后端写混了,命名小驼峰和下划线掺杂,由于是个人项目,没有太重视)
开发消息接收接口
接下来,需要开发一个接口用于事件订阅,即在有人私聊或群聊内@机器人时,飞书会推送通知。
在开发者后台可以看到,填写订阅地址时,需要进行校验,所以我们先实现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模型会话
指令会话
转载自:https://juejin.cn/post/7374709266178572323