从零开始搭建飞书智能助手——第一步:引入SpringBoot、FastApi实现与助手对话
用 Spring Boot FastAPI 搭建飞书 AI 个人助理整体架构DeepSeek APIbutler-agent :8000personal-butler :8080飞书开放平台飞书用户DeepSeek APIbutler-agent :8000personal-butler :8080飞书开放平台飞书用户发送文本消息POST /feishu/callback验签 / 解密 / 异步处理200 OK立即返回POST /api/chat {prompt}chat.completions.create回复文本{reply}发送消息 API机器人在会话中回复当前版本已完成「飞书 ↔ LLM 自由对话」闭环。提醒、MySQL、重复闹钟等能力在下一期迭代。项目结构personal-butlerJavapersonal_butler/ ├── pom.xml ├── Dockerfile # Maven 多阶段构建 → JRE 17 Alpine ├── docker-compose.yml # 编排 personal-butler butler-agent ├── .env # 飞书凭证不入库 └── src/main/java/com/liaoyx/personalbutler/ ├── PersonalButlerApplication.java ├── web/ # HTTP 入口 │ ├── FeishuCallbackController.java # POST /feishu/callback │ └── HealthController.java # GET /health ├── agent/ │ └── ButlerAgentClient.java # 调用 butler-agent ├── config/ │ ├── AsyncConfig.java # Async 线程池 │ ├── RestClientConfig.java # HTTP/1.1 RestClient │ └── properties/ │ ├── FeishuProperties.java │ └── ButlerAgentProperties.java └── feishu/ ├── callback/ # Webhook验签、解密、事件分发 ├── client/ # 飞书 Open API发消息、取 token └── message/ # 消息解析 → 调 agent → 回复包设计原则web/— 控制器只做 HTTP 适配feishu/callback/— 入站安全 事件路由feishu/client/— 出站Open APIfeishu/message/— 业务编排agent/— AI 服务边界以后换模型不影响飞书层butler-agentPythonbutler_agent/ ├── Dockerfile ├── requirements.txt ├── .env # DEEPSEEK_API_KEY不入库 └── app/ ├── main.py # FastAPI/health, /api/chat ├── config.py # pydantic-settings └── llm.py # DeepSeek 调用结构刻意保持极简一个文件负责路由一个文件负责 LLM后续再加agent.pyFunction Calling和reminder_client.py调 personal-butler API。飞书接入三个关键点1. Webhook 必须快速返回飞书事件订阅要求1 秒内响应否则重试。消息处理调 LLM可能耗时数秒因此AsyncpublicvoidhandleMessageReceive(FeishuCallbackPayloadpayload){// 解析文本 → 调 agent → 飞书回复}Controller 收到im.message.receive_v1后立即返回空字符串实际逻辑在异步线程执行。2. 安全验签 可选加密FeishuCallbackService处理两层安全Verification Token— 校验请求来源Encrypt Key— AES 解密 payload飞书开启加密时Signature— 校验X-Lark-Signature请求头feishuCallbackService.verifySignature(timestamp,nonce,signature,rawBody);returnfeishuCallbackService.handleCallback(rawBody);URL 验证首次配置回调地址返回 challenge{challenge:xxx}3. 发消息Tenant Access Token 缓存FeishuApiClient负责用app_idapp_secret换tenant_access_token内存缓存 token过期前 60 秒刷新调用im/v1/messages发文本消息飞书开放平台配置步骤登录 飞书开放平台创建企业自建应用开启机器人能力事件订阅→ 添加im.message.receive_v1接收消息请求地址填写https://你的域名/feishu/callback权限管理 → 开通「获取与发送单聊、群组消息」把凭证写入personal_butler/.envFEISHU_VERIFICATION_TOKENxxxFEISHU_ENCRYPT_KEYxxx# 若开启加密FEISHU_APP_IDcli_xxxFEISHU_APP_SECRETxxxBUTLER_AGENT_BASE_URLhttp://butler-agent:8000本地调试时用 ngrok 或 frp 把 8080 暴露到公网。消息处理全流程以用户发送「你好」为例FeishuCallbackController → FeishuCallbackService.handleCallback() → im.message.receive_v1 ? → FeishuMessageEventHandler.handleMessageReceive() [Async] → 跳过机器人自身消息 → FeishuMessageParser 解析文本 → ButlerAgentClient.chat(prompt) → POST http://butler-agent:8000/api/chat → FeishuMessageService.reply(chatId, reply) → FeishuApiClient.sendTextMessage()服务间 HTTP 契约POST /api/chat Content-Type: application/json {prompt: 用户说的话} → {reply: AI 回复}butler-agentDeepSeek 代理butler-agent 目前是一个LLM 代理核心代码defchat(prompt:str)-str:clientOpenAI(api_keysettings.deepseek_api_key,base_urlsettings.deepseek_base_url,)responseclient.chat.completions.create(modelsettings.deepseek_model,messages[{role:user,content:prompt}],)returnresponse.choices[0].message.contentor配置项.envDEEPSEEK_API_KEYsk-xxxDEEPSEEK_BASE_URLhttps://api.deepseek.comDEEPSEEK_MODELdeepseek-chat使用 OpenAI 兼容 SDK 调 DeepSeek换模型只需改环境变量。踩坑记录RestClient 与 uvicorn 的 HTTP/2 问题Spring Boot 3 默认 RestClient 可能走 JDK HttpClient 并尝试 HTTP/2 升级与 uvicorn 存在兼容问题。解决方式显式使用 HTTP/1.1BeanRestClientrestClient(){returnRestClient.builder().requestFactory(newSimpleClientHttpRequestFactory()).build();}避免回复循环飞书机器人在群里发消息后也会触发im.message.receive_v1。需要在 handler 里过滤sender_type app的消息否则会无限对话。密钥不要入库.env已在.gitignore中。团队协作用.env.example提供模板不含真实密钥。Docker 部署personal_butler/docker-compose.yml一键启动两个服务services:personal-butler:build:.ports:[8080:8080]env_file:[.env]environment:BUTLER_AGENT_BASE_URL:http://butler-agent:8000depends_on:[butler-agent]butler-agent:build:../../butler_agentports:[8000:8000]env_file:[../../butler_agent/.env]启动cdpersonal_butlerdockercompose up--build容器端口健康检查personal-butler8080GET /healthbutler-agent8000GET /healthpersonal-butler 使用多阶段 DockerfileMaven 编译 → 拷贝 jar 到 Alpine JRE 镜像最终镜像体积小、无构建工具残留。技术栈汇总层级personal-butlerbutler-agent语言Java 17Python 3.11框架Spring Boot 3.3.5FastAPI 0.115HTTP 客户端RestClient—LLM—OpenAI SDK → DeepSeek构建/运行Maven Dockerpip uvicorn测试JUnit 5 MockMvc—当前能力 vs 演进路线能力现状下一期飞书收发消息✅—LLM 自由对话✅ 单轮多轮记忆自然语言建提醒❌butler-agent Function Calling单次 / 重复闹钟❌personal-butler MySQL MyBatis提前 N 分钟提醒❌advance_minutes 定时调度到点飞书推送❌Scheduled 扫描 主动发消息下一期目标架构MySQLbutler-agentpersonal-butler飞书用户MySQLbutler-agentpersonal-butler飞书用户到点提醒我今天下午2点有面试/api/chat带 userId, chatIdLLM 识别 create_reminderPOST /api/remindersMyBatis 写入已设置提醒查到期提醒⏰ 提醒面试总结personal-butler butler-agent 的组合用最小可行架构跑通了飞书 AI 助理的核心链路personal-butler负责「脏活累活」— 飞书安全、异步、发消息butler-agent负责「聪明的事」— LLM 理解与决策Docker Compose让两个服务一键联调这种拆分让每一层职责清晰后续加提醒、加数据库、加更多 Agent 工具都不需要动飞书接入层。附录API 速查personal-butler方法路径说明GET/health健康检查POST/feishu/callback飞书 Webhookbutler-agent方法路径说明GET/health健康检查POST/api/chatLLM 对话

相关新闻