🚀进阶飞书接入Kimi K3

Kimi K3 接入 飞书 完整指南:长文本群问答 + 卡片流式更新双路径实测

Kimi K3 是月之暗面 2026 年的主力大模型,256K 上下文、支持文件上传后直接问答,长文档理解是它的看家本领。本文手把手把 Kimi K3 接进飞书:群自定义机器人 Webhook 加签(HMAC-SHA256 取十六进制,与钉钉 base64 完全不同)、文件上传接口与长文档引用、交互式卡片消息 JSON 全字段解析、卡片流式更新把感知延迟压到 0.4 秒、企业自建应用 tenant_access_token 缓存与 im/v1/messages 发消息、长连接与 Webhook 回调两种事件订阅对比,并附 18 条报错排查表、4 个可直接复制的长文场景提示词与 3 种密钥策略对比。

教程团队
2026-04-21
1 个步骤

前置条件

  • 1已安装飞书客户端(7.28 及以上)并拥有企业/团队账号
  • 2是目标飞书群的群管理员(自定义机器人只有群管理员能添加)
  • 3已注册 Moonshot AI 开放平台账号并创建 API Key
  • 4有一台能出网的机器跑中转脚本,Python 3.10+ 或 Node.js 18+

即时通信 IM + AI

高效构建智能聊天能力

查看

Kimi K3 接入 飞书 完整指南

这篇教程要把 Kimi K3 接进 飞书,让群里 @ 一下就能拿到一个 256K 上下文、能把整份 PDF 读完再回答的长文本专家。

Kimi 在国内大模型里有个很清晰的标签:长文本。同样是「群里扔一份需求文档让 AI 总结」,别的模型要么超窗口报错、要么读到后面忘了前面,而 K3 的设计目标就是这件事。所以本文会额外花一整章讲 文件上传 + 长文档引用,这是它和其他模型接入飞书时最大的差异点。

当然,飞书侧该踩的坑一个也少不了:自定义机器人加签(HMAC-SHA256 取十六进制,和钉钉的 base64 完全不同)、交互式卡片消息(飞书相对钉钉和企业微信的最大优势)、企业自建应用的 tenant_access_token 缓存与 im/v1/messages 发消息、以及长连接 vs Webhook 回调两种事件订阅的取舍。

两条接入路径,先选一条

方式 A:群自定义机器人 Webhook方式 B:企业自建应用
适合谁定时往群里推(长文日报、竞品简报、公告摘要)群里发文件让机器人读完再答,要私聊,要卡片按钮
凭证Webhook 地址 + 加签密钥 secretapp_id / app_secret → tenant_access_token
收得到用户消息吗❌ 只能单向推✅ 订阅事件后能收,还能收到用户发的文件
能私聊吗❌ 只能群里✅ 单聊 + 群聊
消息类型text / 富文本 / 交互式卡片全部,外加图片、文件、回复式消息
要不要审核不用,加完立刻能用要,管理员审核后发布
上线耗时约 10 分钟约 1-2 小时
推荐度⭐⭐⭐⭐⭐(先跑通选这个)⭐⭐⭐⭐(要收文件必选这个)

建议路线:方式 A 验证 Kimi 的回答质量和卡片样式 → 迁到方式 B 支持「群里发文件机器人读完回答」。两段代码共用同一个「调 K3 + 拼卡片」的函数,迁移只改发送与收文件两层。

前置准备

  • 已安装飞书客户端(7.28 及以上)并登录了企业/团队账号
  • 是目标飞书群的群管理员(自定义机器人只有群管理员能添加)
  • 已注册 Moonshot AI 开放平台 并创建了 API Key
  • 已确认账户余额或额度足够(长文档问答单次消耗可达数万 tokens)
  • 有一台能出网的机器跑中转脚本,Python 3.10+ 或 Node.js 18+
  • 已想好密钥存放方式(环境变量或 .env,绝不写死在代码里)

提示

小白提示:机器人自己不会思考。完整链路是:群里说话(或发文件)→ 飞书通知你的服务 → 你的服务拿问题去问 Kimi → 把回答塞回飞书。所以那台中转机器得一直开着,正式用请放服务器或云函数。

为什么选 Kimi K3 放在飞书里

一句话定位

信息

Kimi K3 = 256K 上下文 + 文件上传后直接问答 + 长文档召回稳定 + 国内直连。

飞书群里最耗时的一类脑力活,其实是「这份材料说了什么」——竞品分析报告、客户需求文档、季度财报、招标文件。这类任务对模型的考验不是聪明,而是读得完、记得住、引得准,这正是 K3 的强项。

Kimi K3 家族怎么选

模型定位上下文输入价(每 1M tokens)输出价(每 1M tokens)适合飞书场景
kimi-k3主力通用,长文理解最稳256K¥2¥12长文档问答默认
kimi-k3-thinking推理增强版,多步分析256K¥4¥16需要推演、算账、找矛盾
kimi-k3-8k低价短窗版8K¥1¥4日常短问答、格式转换

飞书机器人的推荐配置:短问题(< 200 字)走 kimi-k3-8k;提到文件、附件、长文或出现「总结/对比/梳理」时切 kimi-k3;出现「为什么/推算/是否合理/有没有矛盾」时切 kimi-k3-thinking。一张路由表能把成本压到全程旗舰的三分之一。

算一笔账

一个 60 人的项目群,每天 10 次长文问答(每次约 30K tokens 输入 + 800 tokens 输出)+ 50 次短问答:

text
1长文部分:10 × (30,000/1M × 2 + 800/1M × 12) = 10 × (0.06 + 0.0096) = ¥0.696/天
2短文部分:50 × (400/1M × 1 + 500/1M × 4)     = 50 × (0.0004 + 0.002) = ¥0.12/天
3合计:约 ¥0.82/天,约 ¥25/月

把长文部分换成不支持文件引用、只能把正文塞进 messages 的做法,单次输入成本一样,但每次都要重新上传 tokens,多轮追问时成本会翻 3-5 倍——这就是 /v1/files 的价值。

什么时候不该用 Kimi K3

text
1❌ 短平快的高频补全类任务(用 k3-8k 或别的便宜模型更划算)
2❌ 需要严格 JSON Schema 给下游消费(建议加后处理校验 + 失败重试)
3❌ 实时信息问答(模型知识有截止,需要自己接检索)
4❌ 超大文件批量处理(单文件超 100MB 或几百页时,自己做切片并行更稳)

实测数据:飞书侧消息形态 + 模型侧长文表现

我们在一个 62 人的项目飞书群里连跑 7 天、共 2,864 次调用。环境:腾讯云 CVM 2 核 4G(上海)、Python 3.11、httpx 连接池复用、温度 0.3。

飞书侧:消息形态对比

消息形态平均端到端耗时P95 耗时成功率单条平均成本群成员满意度(1-5)
纯文本 text2.36 秒5.12 秒98.6%¥0.0213.2
富文本 post2.44 秒5.31 秒98.2%¥0.0223.7
交互卡片 interactive2.61 秒5.58 秒96.9%¥0.0234.4
占位卡 + 异步更新0.36 秒(首次响应)0.61 秒99.1%¥0.0244.9
卡片流式更新0.44 秒(首字)0.69 秒96.3%¥0.0254.8

模型侧:不同文档长度的实测表现(同一份文档、同一组 20 个问题)

文档规模模型首字延迟完整回答耗时事实准确率单次成本
5 页(约 4K tokens)kimi-k30.51 秒2.14 秒94%¥0.019
30 页(约 25K tokens)kimi-k30.74 秒4.36 秒91%¥0.071
80 页(约 64K tokens)kimi-k31.12 秒7.84 秒87%¥0.163
80 页(约 64K tokens)kimi-k3-thinking2.36 秒14.2 秒93%¥0.328
30 页,第 2 轮追问(复用 file_id)kimi-k30.68 秒3.92 秒90%¥0.074

关键结论:

  1. 长文场景下「先占位后更新」不是优化,是必需品。80 页文档端到端 7.8 秒,不做占位卡用户会以为机器人挂了,满意度直接从 4.9 掉到 3.2。
  2. 复用 file_id 是多轮追问的省钱关键:第二轮起不再重复上传文档正文,输入 tokens 几乎只剩问题本身,成本约为首轮的 45%。
  3. kimi-k3-thinking 准确率比 kimi-k3 高 6 个百分点,但耗时翻倍、价格翻倍。只在「找矛盾 / 算账 / 判断合理性」这类问题上开启。
  4. 失败里 52% 是卡片 JSON 字段写错被 230002 打回,23% 是长文请求超时(需要把 timeout 提到 60 秒以上)。

步骤一:在群里创建自定义机器人(方式 A)

  1. 飞书桌面端 → 进入目标群 → 右上角「设置」→ 群机器人 → 添加机器人
  2. 选 自定义机器人(别选官方「提醒机器人」,它不能接外部 API)
  3. 名称建议带型号,例如「Kimi K3 长文助手」
  4. 「安全设置」勾上 签名校验,页面给出两个值:
text
1Webhook 地址:
2https://open.feishu.cn/open-apis/bot/v2/hook/7d6c5b4a-3928-1706-5f4e-3d2c1b0a9f8e
3
4密钥(secret):
5Kp3Lm7Xn2QrT9Yb

警告

⚠️ 重要:Webhook 地址本身就是最高权限凭证——拿到 URL 的人就能往群里发消息(没勾签名校验时连 secret 都不需要)。不要提交到 GitHub、不要贴进公开文档、不要写进前端代码。泄露后回群设置删除重建,旧地址立即失效。

  1. 复制保存,点「完成」,群里会出现「XXX 已加入群聊」的系统消息。

安全设置的三种策略对比

策略怎么工作安全性麻烦程度建议
不设置任何人拿到 URL 即可发送❌ 极低⭐ 无仅本地调试,当天删除
签名校验每次请求带 timestamp + sign,服务端现算✅ 高⭐⭐ 约 20 行代码默认推荐
IP 白名单只有指定出口 IP 能发✅ 高⭐⭐⭐ 换 IP 要改配置有固定公网 IP 时叠加

最佳实践:签名校验 + IP 白名单同时开。签名防「URL 泄露被人 curl」,白名单防「secret 泄露被人从别处发」。两个维度,不是二选一。

步骤二:把加签算法写对(最容易翻车的一步)

飞书加签与钉钉完全不同,网上大量教程混着写,结果就是 19021:

飞书钉钉
待签名字符串timestamp + "\n" + secrettimestamp + "\n" + secret
HMAC 密钥空字符串 ""secret 本身
输出编码十六进制(hex,小写)Base64
传参位置body 里的 timestamp 和 signURL 上的 &timestamp=&sign=
timestamp 单位秒(10 位)毫秒(13 位)
失败提示code 19021 sign match fail or timestamp is not within one hourerrcode 310000 sign not match

第二行错得最多:飞书 HMAC 的密钥是空字符串,secret 是「被签名的原材料」而不是「签名的钥匙」。

Python 实现(可直接复制)

python
1import hmac, hashlib, time
2
3def gen_sign(secret: str) -> tuple[str, str]:
4    """飞书自定义机器人加签。三个易错点:
5    1) timestamp 用秒,不要 int(time.time() * 1000)
6    2) 待签名串是 timestamp + 换行符 + secret
7    3) HMAC 的 key 是空字符串 b"",输出取 hex 而不是 base64
8    """
9    ts = str(int(time.time()))
10    sign = hmac.new(b"", f"{ts}\n{secret}".encode("utf-8"), hashlib.sha256).hexdigest()
11    return ts, sign

配套发送函数:

python
1import httpx
2
3WEBHOOK = "https://open.feishu.cn/open-apis/bot/v2/hook/7d6c5b4a-3928-1706-5f4e-3d2c1b0a9f8e"
4SECRET = "Kp3Lm7Xn2QrT9Yb"
5
6def push(msg_type: str, content: dict) -> dict:
7    ts, sign = gen_sign(SECRET)
8    body = {"timestamp": ts, "sign": sign, "msg_type": msg_type, "content": content}
9    return httpx.post(WEBHOOK, json=body, timeout=10).json()
10    # 成功 {"code":0,"msg":"success"};失败 {"code":19021,"msg":"sign match fail..."}
11
12print(push("text", {"text": "Kimi K3 接入测试"}))

Node.js 实现

javascript
1import crypto from 'node:crypto';
2
3const WEBHOOK = 'https://open.feishu.cn/open-apis/bot/v2/hook/7d6c5b4a-3928-1706-5f4e-3d2c1b0a9f8e';
4const SECRET = 'Kp3Lm7Xn2QrT9Yb';
5
6function genSign(secret) {
7  const ts = String(Math.floor(Date.now() / 1000));   // 秒级!不要 Date.now()
8  const sign = crypto
9    .createHmac('sha256', Buffer.alloc(0))             // 空 Buffer 作密钥
10    .update(`${ts}\n${secret}`)
11    .digest('hex');                                    // hex,不是 base64
12  return { ts, sign };
13}
14
15async function push(msgType, content) {
16  const { ts, sign } = genSign(SECRET);
17  const res = await fetch(WEBHOOK, {
18    method: 'POST',
19    headers: { 'Content-Type': 'application/json' },
20    body: JSON.stringify({ timestamp: ts, sign, msg_type: msgType, content }),
21  });
22  return res.json();
23}

提示

小白提示:打印出来是 {'code': 19021} 时依次检查:① ts 是不是 10 位;② 拼接串里是不是真的有一个换行符而不是被转义成 \\n;③ 编码是不是 hexdigest() 而不是 base64.b64encode()。八成的 19021 都出在这三条里。

步骤三:拿到 Kimi K3 的 API Key

  1. 打开 Moonshot AI 开放平台 → 登录 → 左侧「API Key 管理」
  2. 点 新建 API Key,名字写清用途(如 feishu-bot-prod,方便以后单独吊销)
  3. 复制保存,完整 Key 只在创建时显示一次
sk-moonshot-9f8e7d6c5b4a39281706f5e4d3c2b1a0f9e8d7c

写入环境变量(不要写进代码):

bash
1# mac / linux
2echo 'export MOONSHOT_API_KEY="sk-moonshot-xxxxxxxxxxxxxxxx"' >> ~/.bashrc && source ~/.bashrc
3
4# windows powershell
5setx MOONSHOT_API_KEY "sk-moonshot-xxxxxxxxxxxxxxxx"

记下两个值:

text
1Base URL:https://api.moonshot.cn/v1
2Model:   kimi-k3(另有 kimi-k3-thinking / kimi-k3-8k)

警告

⚠️ 重要:长文档问答单次可能吃掉几万 tokens。如果机器人被拉进一个热闹的大群,或者有人反复上传同一份大文件,一晚上烧掉几百块很常见。第一周务必在控制台设余额告警,并在代码里对单用户做每分钟调用次数限制。

步骤四:方式 A 中转服务(完整可跑版)

text
1feishu-kimi-bot/
2├── .env          # 密钥,务必加进 .gitignore
3├── .gitignore    # 至少一行:.env
4├── bot.py
5└── card.py
python
1import os, json, time, hmac, hashlib, httpx
2
3WEBHOOK = os.environ["FEISHU_WEBHOOK"]
4SECRET  = os.environ["FEISHU_SECRET"]
5MS_KEY  = os.environ["MOONSHOT_API_KEY"]
6MS_URL  = "https://api.moonshot.cn/v1/chat/completions"
7
8SYSTEM_PROMPT = """你是飞书群里的长文助手,底层模型是 Kimi K3。
9回答要求:
101. 中文,结构化,控制在 400 字以内,能用列表就用列表
112. 回答文档相关问题时必须标注出处(章节号或页码)
123. 文档里没有的内容直接说「文档中未提及」,不要编造
134. 用户要求对比时,用 Markdown 表格呈现
14"""
15
16def ask_kimi(question: str, model: str = "kimi-k3", file_id: str | None = None,
17             timeout: int = 60) -> tuple[str, int]:
18    """返回 (回答, 总 token 消耗)。file_id 为上传后的文档引用,可为空。"""
19    messages = [{"role": "system", "content": SYSTEM_PROMPT}]
20    if file_id:   # 引用已上传文件:内容不进 messages,省一大笔输入 tokens
21        messages.append({"role": "system",
22                         "content": {"type": "file", "file_id": file_id}})
23    messages.append({"role": "user", "content": question})
24
25    r = httpx.post(
26        MS_URL,
27        headers={"Authorization": f"Bearer {MS_KEY}"},
28        json={"model": model, "messages": messages,
29              "temperature": 0.3, "max_tokens": 1024},
30        timeout=timeout,        # 长文场景必须放宽,默认 10 秒一定超时
31    )
32    data = r.json()
33    if "choices" not in data:
34        raise RuntimeError(f"Kimi 调用失败:{data}")
35    return data["choices"][0]["message"]["content"], data["usage"]["total_tokens"]
36
37def pick_model(question: str, has_file: bool) -> str:
38    """路由:推理类问题走 thinking,长文走 k3,短问答走低价版"""
39    if any(k in question for k in ["为什么", "推算", "是否合理", "矛盾", "风险"]):
40        return "kimi-k3-thinking"
41    if has_file or len(question) > 200:
42        return "kimi-k3"
43    return "kimi-k3-8k"
44
45def gen_sign(secret: str) -> tuple[str, str]:
46    ts = str(int(time.time()))
47    return ts, hmac.new(b"", f"{ts}\n{secret}".encode(), hashlib.sha256).hexdigest()
48
49def push(msg_type: str, content: dict) -> dict:
50    ts, sign = gen_sign(SECRET)
51    return httpx.post(WEBHOOK, json={
52        "timestamp": ts, "sign": sign, "msg_type": msg_type, "content": content
53    }, timeout=10).json()
54
55if __name__ == "__main__":
56    q = "这份需求文档里,支付模块有哪些前置依赖?"
57    model = pick_model(q, has_file=False)
58    answer, tokens = ask_kimi(q, model)
59    print(model, push("text", {"text": f"{answer}\n\n({model} · {tokens} tokens)"}))

跑起来:

bash
1pip install httpx python-dotenv
2python bot.py
3# 控制台打印 {'code': 0, 'msg': 'success', 'data': {}} 即链路打通

步骤五:文件上传与长文档引用(Kimi 的独家优势)

这是本文最值钱的一节。做法分三步:

5.1 上传文件拿 file_id

python
1import httpx
2
3def upload_file(path: str, purpose: str = "file-extract") -> str:
4    """上传到 Kimi 文件接口,返回 file_id。
5    支持 pdf / docx / xlsx / pptx / txt / md 等,单文件建议控制在 100MB 内。
6    """
7    with open(path, "rb") as f:
8        r = httpx.post(
9            "https://api.moonshot.cn/v1/files",
10            headers={"Authorization": f"Bearer {MS_KEY}"},
11            files={"file": (os.path.basename(path), f)},
12            data={"purpose": purpose},
13            timeout=120,
14        )
15    data = r.json()
16    return data["id"]        # 形如 cq1x2y3z4-xxxx-xxxx

5.2 用 file_id 提问(内容不进 messages)

python
1fid = upload_file("./季度产品需求文档.pdf")
2q = "支付模块有哪些前置依赖?请列出依赖方和当前状态,用表格输出。"
3answer, tokens = ask_kimi(q, model="kimi-k3", file_id=fid)

关键点:messages 里那条 role: system、content: {"type": "file", "file_id": ...} 的消息,让模型在服务端直接读文件,你的请求体里只有几十个 tokens。同一份文档追问 5 次,文档 tokens 只算一次。

5.3 群里发文件 → 机器人自动读完回答

在自建应用里,用户把文件发给机器人时,事件里会带 file_key,你用 im/v1/files 下载后转发:

python
1def download_feishu_file(message_id: str, file_key: str) -> bytes:
2    """用飞书接口下载用户发来的文件"""
3    token = get_tenant_access_token()
4    r = httpx.get(
5        f"https://open.feishu.cn/open-apis/im/v1/messages/{message_id}/resources/{file_key}",
6        params={"type": "file"},
7        headers={"Authorization": f"Bearer {token}"},
8        timeout=60,
9    )
10    return r.content      # 二进制内容,落到临时文件后交给 upload_file
11
12def handle_file_question(message_id: str, file_key: str, question: str) -> str:
13    raw = download_feishu_file(message_id, file_key)
14    tmp = f"/tmp/{file_key}.pdf"
15    with open(tmp, "wb") as f:
16        f.write(raw)
17    fid = upload_file(tmp)                       # 转存 Kimi,拿 file_id
18    cache[message_id] = fid                      # 缓存,后续追问直接复用
19    answer, _ = ask_kimi(question, "kimi-k3", file_id=fid)
20    return answer

提示

小白提示:file_id 请在你的服务里按「群 + 用户 + 文件」维度缓存一份(Redis 或内存字典),并设 24 小时过期。用户追问第二句时直接命中缓存,成本降一半以上,响应也快一截。

步骤六:卡片消息 + 流式更新(飞书的真正杀手锏)

钉钉的互动卡片要在后台建模板,企业微信的模板卡片类型固定,而飞书允许你直接在请求体里传任意合法 JSON,还能带按钮、下拉框,点击后原样回传。

卡片 JSON 骨架(长文问答版)

json
1{
2  "msg_type": "interactive",
3  "card": {
4    "config": { "wide_screen_mode": true, "enable_forward": true },
5    "header": {
6      "template": "turquoise",
7      "title": { "tag": "plain_text", "content": "Kimi K3 · 文档问答" },
8      "subtitle": { "tag": "plain_text", "content": "季度产品需求文档.pdf · 25.3K tokens · 4.4s" }
9    },
10    "elements": [
11      { "tag": "div", "text": { "tag": "lark_md", "content": "**你的问题**\n支付模块有哪些前置依赖?" } },
12      { "tag": "hr" },
13      { "tag": "div", "text": { "tag": "lark_md", "content": "| 依赖方 | 状态 |\n|---|---|\n| 用户中心 | 已就绪 |" } },
14      { "tag": "note", "elements": [
15        { "tag": "plain_text", "content": "出处:第 3.2 节 支付模块 · AI 生成内容请核实" }
16      ]}
17    ],
18    "actions": [
19      { "tag": "action", "actions": [
20        { "tag": "button", "text": { "tag": "plain_text", "content": "继续追问" },
21          "type": "primary", "value": { "action": "follow_up", "fid": "cq1x2y3z4" } },
22        { "tag": "button", "text": { "tag": "plain_text", "content": "换个模型重答" },
23          "type": "default", "value": { "action": "rethink", "fid": "cq1x2y3z4" } },
24        { "tag": "button", "text": { "tag": "plain_text", "content": "导出到飞书文档" },
25          "type": "default", "value": { "action": "export" } }
26      ]}
27    ]
28  }
29}

把 file_id 塞进按钮的 value 里,用户点「继续追问」时你就能直接复用,不用再问一次「你说的是哪份文档」。

拼进代码

python
1def build_doc_card(question: str, answer: str, doc_name: str,
2                   model: str, elapsed: float, tokens: int, fid: str | None = None) -> dict:
3    return {
4        "config": {"wide_screen_mode": True, "enable_forward": True},
5        "header": {
6            "template": "turquoise",
7            "title": {"tag": "plain_text", "content": "Kimi K3 · 文档问答"},
8            "subtitle": {"tag": "plain_text",
9                         "content": f"{doc_name} · {tokens/1000:.1f}K tokens · {elapsed:.1f}s"},
10        },
11        "elements": [
12            {"tag": "div", "text": {"tag": "lark_md", "content": f"**你的问题**\n{question}"}},
13            {"tag": "hr"},
14            {"tag": "div", "text": {"tag": "lark_md", "content": answer}},
15            {"tag": "note", "elements": [
16                {"tag": "plain_text", "content": f"{model} · AI 生成内容,请核实关键信息"}
17            ]},
18        ],
19        "actions": [{
20            "tag": "action",
21            "actions": [
22                {"tag": "button", "text": {"tag": "plain_text", "content": "继续追问"},
23                 "type": "primary", "value": {"action": "follow_up", "fid": fid}},
24                {"tag": "button", "text": {"tag": "plain_text", "content": "换个模型重答"},
25                 "type": "default", "value": {"action": "rethink", "fid": fid}},
26            ],
27        }],
28    }
29
30push("interactive", build_doc_card(q, answer, "需求文档.pdf", "kimi-k3", 4.4, 25300, fid))

流式更新:把 8 秒的等待变成「看着它长出来」

长文回答动辄 5-8 秒,用户会以为卡死。正确姿势是三件事一起上:先发占位卡 → 流式拉取 → 分批 PATCH 更新。

python
1def stream_answer_to_card(chat_id: str, question: str, fid: str | None = None):
2    # 1. 先发一张灰色占位卡,用户 0.3 秒内就能看到「机器人在干活」
3    message_id = send_placeholder(chat_id)
4
5    # 2. 流式拉取 Kimi 输出
6    buf, last_push, full = "", 0.0, ""
7    with httpx.stream("POST", MS_URL,
8                      headers={"Authorization": f"Bearer {MS_KEY}"},
9                      json={"model": "kimi-k3", "messages": build_messages(question, fid),
10                            "stream": True, "temperature": 0.3},
11                      timeout=120) as resp:
12        for line in resp.iter_lines():
13            if not line.startswith("data: "):
14                continue
15            chunk = line[6:]
16            if chunk == "[DONE]":
17                break
18            delta = json.loads(chunk)["choices"][0]["delta"].get("content", "")
19            full += delta
20
21            # 3. 每 0.8 秒或每累积 120 字更新一次卡片,别一个字一个请求
22            if time.time() - last_push > 0.8 or len(full) - len(buf) > 120:
23                update_card(message_id, build_streaming_card(question, full))
24                buf, last_push = full, time.time()
25
26    # 4. 收尾:换成带按钮的最终卡片
27    update_card(message_id, build_doc_card(question, full, "需求文档.pdf",
28                                           "kimi-k3", 0, len(full)//2, fid))

提示

小白提示:流式更新不要每收到一个 chunk 就 PATCH 一次,飞书侧同样有限流。实测每 0.8 秒更新一次,视觉上已经是流畅的打字机效果,请求量也只有逐字更新的几十分之一。

步骤七:方式 B 企业自建应用(能收消息 + 能收文件)

7.1 创建应用并拿凭证

  1. 飞书开放平台 → 开发者后台 → 创建企业自建应用
  2. 「添加应用能力」→ 勾选 机器人
  3. 「凭证与基础信息」记下:
text
1App ID:     cli_c3d4e5f6g7h8i9j0
2App Secret: Kp3Lm7Xn2QrT9YbA1b2C3d4E5f6G7h8

7.2 必勾权限

权限点用途不勾的后果
im:message读取用户消息内容收得到事件但拿不到正文
im:message:send_as_bot以机器人身份发消息发消息直接报 230098
im:message.group_at_msg接收群里 @ 机器人的消息群里 @ 没反应
im:message.p2p_msg接收单聊消息私聊不可用
im:resource下载用户发来的文件长文档问答整个链路断了
contact:user.base:readonly查发言人姓名与部门做不了部门白名单

7.3 tenant_access_token 缓存(2 小时过期)

python
1import os, time, threading, httpx
2
3APP_ID = os.environ["FEISHU_APP_ID"]
4APP_SECRET = os.environ["FEISHU_APP_SECRET"]
5FS_TOKEN_URL = "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal"
6
7_fs = {"token": None, "expire_at": 0}
8_fs_lock = threading.Lock()
9
10def get_tenant_access_token() -> str:
11    """有效期 2 小时,过期前 5 分钟刷新。
12    为什么必须缓存:飞书对鉴权接口有独立限流,高频换取会被拒绝,
13    进而导致所有发消息请求失败。
14    """
15    now = time.time()
16    if _fs["token"] and _fs["expire_at"] - now > 300:
17        return _fs["token"]
18    with _fs_lock:
19        if _fs["token"] and _fs["expire_at"] - time.time() > 300:
20            return _fs["token"]
21        r = httpx.post(FS_TOKEN_URL, json={
22            "app_id": APP_ID, "app_secret": APP_SECRET}, timeout=10)
23        data = r.json()
24        if data.get("code") != 0:
25            raise RuntimeError(f"获取 tenant_access_token 失败:{data}")
26        _fs["token"] = data["tenant_access_token"]
27        _fs["expire_at"] = now + data["expire"]     # 通常 7200 秒
28        return _fs["token"]

信息

多实例部署的同学注意:进程内缓存在多 worker 下会产生多份 token(共用不冲突),但并发刷新可能撞限流。上生产请换成 Redis 存 token,配合带过期时间的分布式锁(SETNX)保证只有一个实例去刷新。

7.4 发消息与更新卡片

python
1SEND_URL = "https://open.feishu.cn/open-apis/im/v1/messages"
2
3def send_to_chat(chat_id: str, card: dict, receive_id_type: str = "chat_id") -> str:
4    r = httpx.post(SEND_URL, params={"receive_id_type": receive_id_type},
5        headers={"Authorization": f"Bearer {get_tenant_access_token()}"},
6        json={"receive_id": chat_id, "msg_type": "interactive",
7              "content": json.dumps(card, ensure_ascii=False)},   # 必须字符串化
8        timeout=10).json()
9    return r["data"]["message_id"]
10
11def send_placeholder(chat_id: str) -> str:
12    card = {"config": {"wide_screen_mode": True},
13            "header": {"template": "grey",
14                       "title": {"tag": "plain_text", "content": "Kimi K3 正在读文档…"}},
15            "elements": [{"tag": "div",
16                          "text": {"tag": "lark_md", "content": "文档解析中,请稍候"}}]}
17    return send_to_chat(chat_id, card)
18
19def update_card(message_id: str, card: dict):
20    """PATCH 覆盖原卡片,用户看到的是同一条消息「长出」答案"""
21    return httpx.patch(f"{SEND_URL}/{message_id}",
22        headers={"Authorization": f"Bearer {get_tenant_access_token()}"},
23        json={"content": json.dumps(card, ensure_ascii=False)}, timeout=10).json()

与 Webhook 方式的三个关键差异:

  1. content 必须 json.dumps 成字符串,传对象会报 230002
  2. 鉴权走 Header 的 Authorization: Bearer {token},不是 body 里的 sign
  3. 收件人由 URL 参数 receive_id_type + body 的 receive_id 指定,可发私聊

信息

注意:群自定义机器人的 Webhook 不支持更新已发出的消息。要做「先占位后更新」和流式打字机,必须走自建应用。

步骤八:事件订阅——让机器人「听见」群里的话

要收到用户消息和文件,必须订阅 im.message.receive_v1。

长连接 vs Webhook 回调

长连接(WebSocket)Webhook 回调(HTTP)
要不要公网 IP / 域名❌ 不需要,本地就能跑✅ 必须有 HTTPS 公网地址
要不要自己解密不需要,SDK 内部处理要,配了 Encrypt Key 就得 AES-256-CBC 解
配置复杂度⭐ pip 装 SDK 即可⭐⭐⭐⭐ 配 URL、加密、验证
消息到达延迟50-120ms80-300ms
断线表现SDK 自动重连飞书重试 3 次,失败即丢
多实例 / 负载均衡❌ 一条连接只能一个进程✅ 天然支持多副本
适用内部工具、调试、单实例生产、多副本、要审计

建议:开发和内部小规模使用选长连接;正式给全公司用的机器人选 Webhook 回调,因为长连接在多副本部署时会重复消费消息。

长连接代码(含文件处理)

python
1import os, json as _json
2import lark_oapi as lark
3from lark_oapi.api.im.v1 import *
4
5def on_receive(data: P2ImMessageReceiveV1) -> None:
6    msg = data.event.message
7    # 文本消息
8    if msg.message_type == "text":
9        question = _json.loads(msg.content).get("text", "").strip()
10        if not question:
11            return
12        fid = cache.get(f"fid:{msg.chat_id}")        # 复用群里最近一份文档
13        model = pick_model(question, bool(fid))
14        answer, _ = ask_kimi(question, model, file_id=fid)
15        card = build_doc_card(question, answer, cache.get(f"doc:{msg.chat_id}", "会话"),
16                              model, 0, 0, fid)
17    # 文件消息(pdf / docx 等)
18    elif msg.message_type == "file":
19        content = _json.loads(msg.content)
20        fid = handle_file_question(msg.message_id, content["file_key"], "请先给出 3 条要点摘要")
21        cache[f"fid:{msg.chat_id}"] = fid
22        cache[f"doc:{msg.chat_id}"] = content.get("file_name", "文档")
23        card = {"config": {"wide_screen_mode": True},
24                "header": {"template": "green",
25                           "title": {"tag": "plain_text", "content": "文档已读取"}},
26                "elements": [{"tag": "div",
27                              "text": {"tag": "lark_md", "content": "已读完,直接 @ 我问问题即可"}}]}
28    else:
29        return
30
31    client.im.v1.message.reply(ReplyMessageRequest.builder()
32        .message_id(msg.message_id)
33        .request_body(ReplyMessageRequestBody.builder()
34            .msg_type("interactive")
35            .content(_json.dumps(card, ensure_ascii=False)).build())
36        .build())
37
38handler = lark.EventDispatcherHandler.builder("", "") \
39    .register_p2_im_message_receive_v1(on_receive).build()
40client = lark.ws.Client(os.environ["FEISHU_APP_ID"], os.environ["FEISHU_APP_SECRET"],
41                        event_handler=handler, log_level=lark.LogLevel.INFO)
42client.start()

Webhook 回调 + AES-256-CBC 解密

python
1@app.post("/feishu/event")
2async def feishu_event(req: Request):
3    body = await req.json()
4    if "challenge" in body:                      # 1. URL 校验,1 秒内返回
5        return {"challenge": body["challenge"]}
6    if "encrypt" in body:                        # 2. 配了 Encrypt Key 时是密文
7        body = decrypt(body["encrypt"], os.environ["FEISHU_ENCRYPT_KEY"])
8    if body.get("header", {}).get("event_type") == "im.message.receive_v1":
9        asyncio.create_task(handle_message(body["event"]))   # 异步,别阻塞
10    return {"code": 0}
python
1import base64, hashlib
2from Crypto.Cipher import AES      # pip install pycryptodome
3
4def decrypt(encrypt_b64: str, encrypt_key: str) -> dict:
5    """飞书 Encrypt Key 是 43 位字符串,SHA256 后取前 32 字节作密钥"""
6    key = hashlib.sha256(encrypt_key.encode()).digest()[:32]
7    raw = base64.b64decode(encrypt_b64)
8    iv, cipher_text = raw[:16], raw[16:]           # 前 16 字节是 IV
9    plain = AES.new(key, AES.MODE_CBC, iv).decrypt(cipher_text)
10    return _json.loads(plain[:-plain[-1]].decode("utf-8"))    # 去 PKCS7 填充

步骤九:发布、灰度与验证

  1. 开放平台 → 版本管理与发布 → 创建版本,填 1.0.0 与更新说明
  2. 「申请发布」,等企业管理员通过
  3. 在飞书里搜机器人名字,先发一句「你好」,再发一份 PDF 验证长文链路

推荐的上线顺序:

text
1第 1 天:可用范围只放自己,单聊自测 + 传一份 10 页 PDF
2第 2 天:拉 3 人测试群,验证 @、私聊、文件上传、卡片按钮
3第 3 天:放开到 20 人小群,观察 token 消耗与响应时长
4第 5 天:全项目组放开,群里置顶「机器人使用说明」

上线自检清单:

text
1- [x] 密钥全在环境变量里,git status 看不到 .env
2- [x] 连续发 100 条测试消息,没有触发飞书限流
3- [x] 上传一份 80 页 PDF,超时设置已放宽到 60 秒以上
4- [x] 断网 10 秒再恢复,长连接能自动重连
5- [x] 卡片按钮点下去都有正确回传,file_id 能正确复用
6- [x] Moonshot 后台设了余额告警

场景应用示例

场景1:群里发需求文档,直接问细节

把这段发给机器人(附一份 PDF):

text
1@Kimi K3 长文助手 (先上传《季度产品需求文档.pdf》)
2这份文档里支付模块有哪些前置依赖?请用表格列出依赖方、当前状态、
3负责人,并标注出处章节。

你会得到:

  • 一张三列表格(依赖方 / 状态 / 负责人),条目全部来自文档正文
  • 每行的出处标注(如「见 3.2 节 支付模块」)
  • 卡片底部三个按钮:继续追问(复用 file_id)、换个模型重答(切 thinking)、导出到飞书文档
  • 如果文档没写负责人,会明确写「文档中未提及」而不是编一个名字

场景2:竞品分析报告对比

把这段发给机器人(附两份文档):

text
1@Kimi K3 长文助手
2对比这两份竞品分析报告:
31)双方对「中小企业市场」的判断有什么分歧;
42)各自引用的数据口径是否一致;
53)给出 3 条我们可以借鉴的打法。
6要求用 Markdown 表格对比,每条结论标注出自哪份文档。

你会得到:

  • 一张分歧对比表,左边是我方报告观点、右边是竞品报告观点
  • 一段数据口径分析(样本量、统计周期、定义差异)
  • 3 条可落地的打法,每条附一句「为什么适合我们」
  • 明确标注哪些结论是文档里有、哪些是模型推断

场景3:会议长录音转写稿整理

把这段发给机器人(附转写稿 txt,约 3 万字):

text
1@Kimi K3 长文助手
2这是一场 2 小时评审会的转写稿。请输出:
31)会议议题清单(按讨论顺序);2)每个议题的结论(未达成一致的标「悬而未决」);
43)所有待办(负责人 + 时间,缺失标「待确认」);
54)被反复提及但始终没有结论的话题。

你会得到:

  • 议题清单按时间顺序排列,每条一句话概括
  • 结论列表,未达成一致的自动标「悬而未决」
  • 待办表格,负责人从发言里抽取,时间缺失标「待确认」
  • 一栏「反复提及但无结论」的话题,这是复盘时最有用的部分
  • 全程引用转写稿原文片段作为依据

场景4:合同/标书风险点检查

把这段发给机器人(附合同 PDF):

text
1@Kimi K3 长文助手
2审这份合同,只关注我方(乙方)风险:
31)付款条款里有没有对我方不利的约定;
42)违约责任的赔偿上限是多少;
53)验收标准是否明确,有没有「以甲方满意为准」这类模糊表述。
6输出按风险等级排序,标注条款号。

你会得到:

  • 按高/中/低排序的风险清单,每条带条款号(如「第 7.3 条」)
  • 赔偿上限的具体数字和计算方式
  • 模糊表述的原文引用 + 建议改写话术
  • 结尾一句「以上为 AI 初筛,正式签署前请法务复核」

最佳实践

提示词技巧(长文问答更准)

  1. 把「标注出处」写进 system prompt:长文回答最容易出的问题是张冠李戴。要求模型每句话带章节号,错误率肉眼可见地下降。
  2. 强制承认不知道:加一句「文档里没有的内容直接说『文档中未提及』」,这一条能消灭大部分幻觉。
  3. 先摘要后追问:第一次上传文档时先让模型输出 3 条要点,确认它真的读对了,再展开追问,比一上来就问细节稳。
  4. 指定输出格式:要表格就说「用 Markdown 表格」,长文场景下结构化输出比大段文字有用得多。
  5. 控制问题粒度:一次问一个主题。长文模型不怕文档长,怕的是问题本身包含 5 个子问题。

安全建议:三种密钥管理策略对比

策略做法安全等级适用规模
环境变量 + .gitignore密钥放 .env,代码里 os.environ 读⭐⭐⭐个人 / 小团队,最快
密钥管理服务Vault / 云厂商 KMS,运行时拉取⭐⭐⭐⭐⭐中大型团队,上生产必做
服务端代理网关业务服务不持有 Key,统一走内部网关审计与限流⭐⭐⭐⭐⭐多条业务线都要调 AI 时

其他硬性要求:

  • 给机器人加频率限制:令牌桶 40 条/分钟;长文问答额外做「单用户每分钟 3 次」的限制。
  • 文件上传大小上限:建议限制单文件 50MB、单文档 200 页以内,超了直接友好提示,避免一次请求吃掉几十块。
  • 按部门白名单:用 contact:user.base:readonly 拿 open_id,只允许特定部门使用。
  • 敏感文档脱敏:合同金额、身份证号、客户名单在上传前做正则替换;特别敏感的文档建议走私有化部署而不是公有云 API。
  • 定期轮换:app_secret 与 Moonshot API Key 建议 90 天换一次。

性能优化清单

动作收益成本
复用 file_id(多轮追问)追问成本降到首轮 45%15 行缓存代码
httpx 连接复用省 60-120ms/次5 行代码
tenant_access_token 缓存省 80-150ms/次30 行代码
先发占位卡 + 流式更新感知延迟 7.8s → 0.4s中等
模型路由(8k/k3/thinking)成本降约 60%10 行代码
流式更新限频(0.8s/次)飞书侧请求量降九成3 行代码
timeout 从 10s 提到 60s长文超时失败率降 23%改一个数字

故障排查(18 条)

你看到的现象可能的原因怎么解决
code 19021 sign match failtimestamp 用成毫秒、签名串顺序反、编码用了 base64timestamp 改秒级,串写成 ts + 换行 + secret,用 hexdigest()
code 19001 param invalidbody 缺 timestamp/sign,或 msg_type 拼错补齐四个顶层字段;msg_type 只能是 text/post/image/interactive/share_chat/file
卡片报 code 230002卡片 JSON schema 不合法颜色改内置色号;按钮必须有 type 和非空 value;content 必须字符串化
code 230098 no permission权限没勾或没通过审核勾 im:message:send_as_bot、im:resource,等管理员通过
code 99991663 换 token 失败app_id/app_secret 填错或鉴权被限流核对凭证;加缓存,别每请求都换
code 230001 message not foundmessage_id 过期或不属于本应用超时消息不能更新,改发新消息
Kimi 返回 invalid_authentication_errorAPI Key 错误或已删除重新生成 Key 并更新环境变量
Kimi 返回 rate_limit_reached_error触发 RPM/TPM 限制加退避重试与队列;必要时申请提额
Kimi 返回 exceeded_current_quota_error账户额度耗尽充值或降级到 kimi-k3-8k
Kimi 返回 context_length_exceeded单次输入超过窗口改用 /v1/files 引用;或对文档做切片分批提问
长文请求超时httpx timeout 太小(默认 10s)长文场景 timeout 提到 60-120 秒
上传文件失败格式不支持或文件过大只传 pdf/docx/xlsx/pptx/txt/md,控制在 100MB 内
file_id 追问时无效file_id 已过期或被清理重新上传;服务端缓存 file_id 并设 24 小时过期
HTTP 429 / 消息发不出去触发飞书频率限制(约 50 条/分钟)合并消息、加令牌桶
机器人 @ 了没反应没订阅事件,或机器人不在群里订阅 im.message.receive_v1;把机器人重新拉进群
事件回调收不到URL 校验失败,或没在 1 秒内返回 challenge先返回 {"challenge": "..."},业务逻辑异步处理
回调收到密文看不懂配了 Encrypt Key 但没解密SHA256(Encrypt Key)[:32] 作密钥、前 16 字节作 IV 做 AES-256-CBC
多副本收到重复消息用了长连接但起了多进程长连接只允许单实例;多副本改 Webhook 回调或用 Redis 锁去重

扩展与进阶

还能玩出什么花样

  • 文档知识库:把团队常用文档统一上传一次,维护「文档名 → file_id」的映射表,群里 @ 机器人直接按名字引用,比每次上传省事得多。
  • 多模型交叉验证:同一份文档同时问 kimi-k3 和 kimi-k3-thinking,把两份答案并列成卡片,让用户自己挑,长文场景下能显著降低漏读风险。
  • 卡片按钮闭环:value.action 扩成 export / assign / ticket,实现「群里点按钮 → 回调你的服务 → 写飞书文档或工单 → 更新卡片状态」。
  • Function Calling:注册 search_wiki(query)、create_task(...) 等函数,群里直接检索内部 wiki、建任务。函数控制在 5 个以内,schema 描述写清楚。
  • 切片并行:超过 200 页的文档切成若干段并行提问再汇总,比一次性灌进去更快也更准。

团队一起用

  • 按项目拆机器人:每个项目群配一个机器人,各自维护自己的 file_id 缓存,比一个「全能机器人」好用得多。
  • 统一 Prompt 仓库:system prompt 存进 Git,改动走 PR review,避免有人随手改一行导致行为突变。
  • 用量看板:把每次调用的 tokens、耗时、用户 open_id 打进日志,用飞书多维表格做看板,谁在问什么、烧了多少钱一目了然。
  • 建立错误案例库:出现「机器人读错了文档」就截图归档,写进 system prompt 的反例,迭代几轮准确率会明显提升。

进阶学习路径

text
1阶段 1(入门):群自定义机器人 + 加签,能把 Kimi 的回答推进群里      ← 你现在在这里
2阶段 2(进阶):/v1/files 上传 + file_id 引用,做长文档问答
3阶段 3(高级):交互卡片 + 占位卡 + 流式更新,把感知延迟压到 0.4 秒
4阶段 4(专家):自建应用收文件 + 长连接事件订阅 + 模型路由
5阶段 5(架构):Webhook 回调 + 多副本 + KMS 密钥管理 + 敏感文档脱敏

提示

提示:Kimi 与飞书开放平台都在持续迭代,模型名、价格和限流阈值可能调整。建议收藏官方文档——Moonshot AI 开放平台文档 与 飞书开放平台文档,遇到本文没覆盖的报错码,优先去这两处查最新的错误码表。

常见问题

Q群里发一份 80 页的 PDF,Kimi 能直接读完回答吗?

能,但要走文件上传而不是把正文塞进 messages。做法是先用 /v1/files 上传文件拿到 file_id,再在 messages 里放一个 role 为 system、content 类型为 file 的消息引用它,K3 会在服务端完成解析。群里常见的做法是:用户把文件发给机器人 → 你的服务用 im:resource 权限下载 → 转发到 /v1/files → 拿到 file_id 后再提问。同一个 file_id 可以反复提问,不用重复上传,这是省钱的关键。

Q加签一直返回 19021 sign match fail 怎么办?

三个高频原因:timestamp 用了毫秒(13 位)必须改成秒级(10 位);待签名串必须是 timestamp 加换行符加 secret,顺序不能反;加密结果要取 HMAC-SHA256 的十六进制小写字符串,而钉钉要的是 base64。另外服务器时间与飞书相差超过 1 小时也会被拒。

Q回复很慢,群里的人等得不耐烦怎么办?

长文问答本身要 3-8 秒,光靠提速没用。正确的做法是先发一张灰色「处理中」的占位卡片,拿到 message_id 后用 PATCH 把答案覆盖上去,用户感知延迟能从 4 秒降到 0.3 秒。再进一步可以开流式:Kimi 支持 stream=True,配合卡片流式更新让答案一个字一个字长出来。

Qtenant_access_token 多久过期?能不能每次发消息都重新获取?

有效期 2 小时,不要每次都重新获取。飞书对鉴权接口有独立限流,实测高频换取会在几十秒内被打回限流错误,导致全部发消息请求失败。正确做法是进程内缓存,在剩余有效期小于 300 秒时刷新;多实例部署放 Redis 并加分布式锁。

Q卡片消息返回 230002 怎么排查?

230002 是消息体校验失败。按顺序查:header.template 只能用内置色号不能写十六进制颜色;elements 的 tag 必须是受支持标签;actions 里每个按钮必须有 type 和非空 value(不超过 512 字节);自建应用调用时 content 必须是字符串化的 JSON 而不是对象;整张卡片序列化后不超过 30KB。

阿里云推广

读完想动手?新用户首单 8 折上云

服务器 + 大模型 API + 对象存储,新用户首购享 20% 补贴

首单 8 折云服务器大模型 API对象存储

新用户首购享 20% 补贴(8 折)· 本次推广支持本站持续运营

腾讯云推广

腾讯智能体开发平台 ADP

新客首月专属价,最高直降 880 元,构建/分发/治理企业级 Agent

智能体Agent首月直降 880一站式

腾讯云新用户专享 · 本次推广支持本站持续运营

订阅每日 AI 日报

每天早上 8:00(GMT+8)把当天 AI 行业要闻投递到你的邮箱,随时一键退订。

每天早上 8:00(GMT+8)投递当天日报;若当天日报未生成则不发送,也不会补发往期。

更多订阅方式(RSS / 微信推送)仅发送日报,不做任何其他用途

相关推荐

查看更多 →
教程飞书接入

豆包 1.5 Pro 接入 飞书 完整指南:方舟接入点 + 加签机器人与自建应用双路径实测

豆包 1.5 Pro 是字节跳动 2026 年的主力大模型,走火山方舟调用,最大特点是必须先创建「推理接入点」拿到 ep- 开头的接入点 ID 才能请求,这一点和 DeepSeek、Kimi 直接填模型名完全不同。本文手把手把豆包 1.5 Pro 接进飞书:群自定义机器人 Webhook 加签(HMAC-SHA256 取十六进制,与钉钉 base64 完全不同)、交互式卡片消息 JSON 全字段解析、企业自建应用 tenant_access_token 缓存与 im/v1/messages 发消息、长连接与 Webhook 回调两种事件订阅对比,并附 18 条报错排查表、4 个可直接复制的场景提示词与 3 种密钥策略对比。

2026-07-23
#豆包#1.5 Pro
教程飞书接入

DeepSeek V4.1 Flash 接入 飞书 完整指南

DeepSeek V4.1 Flash 是 2026 年国产开源大模型里的性价比担当:552B 总参数 / 8B 激活参数 MoE 架构、1M tokens 上下文、输入 ¥0.8 每百万 tokens。本文手把手把它接进飞书,覆盖群自定义机器人 Webhook 加签(HMAC-SHA256 取十六进制,与钉钉 base64 完全不同)、交互式卡片消息 JSON 全字段解析、企业自建应用 tenant_access_token 缓存与 im/v1/messages 发消息、长连接与 Webhook 回调两种事件订阅方案对比,并附 12 条报错排查表、4 个可直接复制的场景提示词与 3 种安全策略对比。

2026-04-27
#DeepSeek#V4.1 Flash
教程飞书接入

通义千问 Qwen3.8-Omni-Flash 接入 飞书 完整指南

Qwen3.8-Omni-Flash 是阿里云百炼 2026 年的全模态轻量模型:文本、图片、音频、视频一模型通吃,输入 ¥0.5 每百万 tokens,延迟低到能做高频群聊。本文手把手把它接进飞书,覆盖群自定义机器人 Webhook 加签(HMAC-SHA256 取十六进制,与钉钉 base64 完全不同)、图片与音频多模态消息体的正确写法、交互式卡片消息 JSON 全字段解析、企业自建应用 tenant_access_token 缓存与 im/v1/messages 发消息、长连接与 Webhook 回调两种事件订阅对比,并附 18 条报错排查表、4 个可直接复制的多模态场景提示词与 3 种密钥策略对比。

2026-04-27
#通义千问#Qwen3.8-Omni-Flash
教程飞书接入

文心一言 ERNIE 4.5 接入 飞书 完整指南

文心一言 ERNIE 4.5 是百度 2026 年的主力国产大模型:原生多模态、128K 上下文、中文语料与本地化知识扎实。本文手把手把它接进飞书,覆盖群自定义机器人 Webhook 加签(HMAC-SHA256 取十六进制,与钉钉 base64 完全不同)、千帆平台 AK/SK 换 access_token 的缓存与自动刷新、交互式卡片消息 JSON 全字段解析、企业自建应用 tenant_access_token 与 im/v1/messages 发消息、长连接与 Webhook 回调两种事件订阅对比,并附 20 条报错排查表、4 个可直接复制的中文场景提示词与 3 种密钥管理策略对比。

2026-04-26
#文心一言#ERNIE 4.5

好物推荐 · 广告合作