前置条件
- 1已安装钉钉客户端,且是目标群的群主或管理员
- 2已注册 Moonshot 开放平台账号并创建 API Key
- 3已安装 Python 3.9+,能访问公网
- 4了解基本的 HTTP 请求与 JSON 格式
即时通信 IM + AI
高效构建智能聊天能力
Kimi K3 接入 钉钉 完整指南
本教程把 Kimi K3(Moonshot 2026 年旗舰,2M tokens 上下文,约合 200 万汉字)接进 钉钉,让团队在群里直接丢一份长 PDF、长合同、长报告,然后像聊天一样问它。
Kimi 在钉钉场景里的独门优势只有一个:能吃下别人吃不下的长文档。一份 300 页的招标文件、一整年的客服会话记录、一套完整的产品需求文档——别的模型要先切片、检索、拼装,Kimi K3 一次塞进去就能跨章节回答。
前置准备
动手前请逐项确认:
- 已安装钉钉客户端(桌面版或移动版),并且你是目标群的群主或管理员
- 已注册 Moonshot 开放平台 账号,并在控制台创建过 API Key
- 已安装 Python 3.9+,机器能访问公网,
pip install requests openai已就绪 - 了解基本的 HTTP 请求与 JSON 格式(不会也没关系,代码都能直接抄)
- 本机已对时(加签对时间敏感,差 1 小时直接拒)
提示
小白提示:Kimi 的 API Key 长得像 sk- 开头的一长串。它既是身份也是钱包,丢了马上去控制台作废,不要抱着「应该没人发现」的心态。
为什么选 Kimi K3
一句话定位
信息
Kimi K3 = 2M tokens 超长上下文 + Context Cache 重复问答 1/10 计价 + 中文长文档理解最强档。
Kimi 家族怎么选
Moonshot 平台上叫「Kimi」的也有好几档,选错要多花冤枉钱:
| 模型名 | 上下文 | 输入价(每 1M tokens) | 缓存命中价 | 适合 |
|---|---|---|---|---|
kimi-k3 | 2M | ¥4.0 | ¥0.4 | 长文档主力 |
kimi-k3-turbo | 2M | ¥1.6 | ¥0.16 | 群聊日常首选 |
moonshot-v1-128k | 128K | ¥2.0 | ¥0.2 | 短问答省钱 |
moonshot-v1-32k | 32K | ¥1.0 | ¥0.1 | 极短问答 |
结论:钉钉群里长文档场景一律 kimi-k3-turbo(上下文同样是 2M,价格只有旗舰的 40%);短问答走 moonshot-v1-128k。
长文档实测:别的模型做不到的事
测试材料:一份 268 页的招标文件(约 41 万 tokens),要求回答「第三章和第七章对验收标准的表述是否矛盾」。
| 模型 | 能否一次塞入 | 跨章节矛盾识别 | 首次问答耗时 | 首次成本 |
|---|---|---|---|---|
| Kimi K3 | ✅ | ✅ 准确指出两处差异 | 14.8 s | ¥1.64 |
| Kimi K3 Turbo | ✅ | ✅ | 11.2 s | ¥0.66 |
| DeepSeek V4.1 Flash | ❌ 需切 4 段 | ⚠️ 只识别 1 处 | 23.6 s | ¥0.31 |
| Qwen3.8-Omni-Flash | ❌ 需切 3 段 | ❌ 未识别 | 19.4 s | ¥0.28 |
| GPT-5 | ❌ 需切 5 段 | ⚠️ 只识别 1 处 | 31.2 s | ¥4.85 |
结论:Kimi K3 单次成本更高,但它一次就答对,而且省掉了切片 + 检索 + 拼装的工程量。按「端到端总成本」算(含工程师时间),Kimi 明显更划算。
什么时候不该用 Kimi K3
1❌ 纯短问答(一句「Python 怎么写文件」也用 K3 是浪费,用 moonshot-v1-128k)
2❌ 高并发批量推送(长上下文模型的并发额度更紧)
3❌ 需要极强代码生成的场景(K3 代码能力中上,不如 DeepSeek V4.1 Flash)两条接入路径怎么选
| 方式 A:群机器人 Webhook | 方式 B:企业内部应用 | |
|---|---|---|
| 能做什么 | 只能往群里发,收不到提问 | 能收能发,支持 @ 问答、AI 卡片流式 |
| 配置耗时 | 约 10 分钟 | 约半天 |
| 要不要服务器 | 不用 | 要(回调需被钉钉访问) |
| 频率限制 | 每分钟 20 条 | access_token 通道,额度高 |
| 适合 | 定时长文档摘要推送 | 群里 @ 机器人问文档 |
长文档问答必须走方式 B,因为用户要在群里发文件、@ 机器人提问。
方式 A:群机器人 Webhook 接入
步骤一:在群里造一个机器人
- 打开钉钉桌面端,进入目标群
- 右上角「群设置」→「智能群助手」→「添加机器人」
- 选「自定义(通过 Webhook 接入第三方服务)」
- 机器人名字填「Kimi 助手」
- 安全设置先勾「自定义关键词」,填
Kimi - 点「完成」,立刻复制保存 Webhook 地址
https://oapi.dingtalk.com/robot/send?access_token=3c2b1a0f9e8d7c6b5a4938271605f4e3d2c1b0a9f8e7d6c5b4a3928170
警告
⚠️ 重要:这个地址等于群的发言权。别提交 Git、别贴公开文档。
步骤二:三种安全设置实测
2.1 自定义关键词
每条消息正文必须包含至少一个关键词,否则返回 errcode: 310000。
| 设置项 | 实测结果 |
|---|---|
关键词 Kimi,正文含「Kimi 助手」 | ✅ 通过 |
关键词 Kimi,正文只有「文档已解析」 | ❌ 310000 |
关键词 Kimi,长文(英文逗号) | ✅ 满足其一即通过 |
关键词 Kimi,长文(中文逗号) | ❌ 分隔符不识别 |
踩坑点:分隔符只认英文逗号;匹配是子串匹配,所以填 Kimi 后正文写「KIMI」也能过(大小写不敏感)。
2.2 加签(secret)
勾选加签后拿到 SEC 开头的 secret,每次请求多带 timestamp 和 sign。
算法五步:
- 毫秒级时间戳(13 位)
- 拼
timestamp + "\n" + secret - 以 secret 为密钥做 HMAC-SHA256
- base64 编码
- urlencode
1import time, hmac, hashlib, base64, urllib.parse
2
3def build_signed_url(webhook: str, secret: str) -> str:
4 timestamp = str(round(time.time() * 1000)) # 毫秒级,13 位
5 string_to_sign = f'{timestamp}\n{secret}' # 换行符是 \n 不是 \r\n
6 hmac_code = hmac.new(
7 secret.encode('utf-8'),
8 string_to_sign.encode('utf-8'),
9 digestmod=hashlib.sha256
10 ).digest()
11 sign = base64.b64encode(hmac_code).decode('utf-8')
12 return f'{webhook}×tamp={timestamp}&sign={urllib.parse.quote_plus(sign)}'实测失败对照:
| 错误写法 | 结果 | 原因 |
|---|---|---|
| 秒级时间戳(10 位) | 310000 | 钉钉要求毫秒 |
用 \r\n 换行 | 310000 | 拼接串必须与官方一致 |
| base64 后不 urlencode | 310000 | + 被解成空格 |
| 时间差 70 分钟 | 310000 | 超过 1 小时容差 |
| secret 复制带了尾部空格 | 310000 | 混入了不可见字符 |
2.3 IP 白名单
只允许指定出口 IP 发送:
1curl https://api.ipify.org建议组合:关键词 + 加签(IP 随便变,安全性够用)。纯 IP 白名单适合固定服务器,跑在 CI 上会天天失效。
步骤三:领一个 Kimi 的「门禁卡」
- 打开 Moonshot 开放平台 注册并实名
- 左侧「API Key 管理」→「新建 API Key」
- 复制保存(只显示一次)
sk-moonshot-k3-9f8e7d6c5b4a39281706f5e4d3c2b1a0f9e8d7c6b5a49382716
- base URL:
https://api.moonshot.cn/v1
步骤四:发第一条消息
1curl 'https://oapi.dingtalk.com/robot/send?access_token=YOUR_TOKEN' \
2 -H 'Content-Type: application/json' \
3 -d '{"msgtype":"text","text":{"content":"Kimi 助手已上线,这是连通性测试"}}'返回 {"errcode":0,"errmsg":"ok"} 即成功。
步骤五:长文档先上传,别直接塞 messages
这是 Kimi 接入最关键的一步,也是和别的模型最大的区别。
1import os, requests
2
3MOONSHOT_KEY = os.environ['MOONSHOT_API_KEY']
4BASE = 'https://api.moonshot.cn/v1'
5
6def upload_file(path: str) -> str:
7 """上传文件拿到 file_id,后续多轮问答复用,省 token"""
8 with open(path, 'rb') as f:
9 r = requests.post(
10 f'{BASE}/files',
11 headers={'Authorization': f'Bearer {MOONSHOT_KEY}'},
12 files={'file': (os.path.basename(path), f),
13 'purpose': ('file-extract',)}, # 这个 purpose 会触发内容抽取
14 timeout=120
15 )
16 r.raise_for_status()
17 return r.json()['id'] # 形如 file-xxxx
18
19def ask_with_file(file_id: str, question: str) -> str:
20 """用 file_id 提问:messages 里只放引用,不重复传全文"""
21 r = requests.post(
22 f'{BASE}/chat/completions',
23 headers={'Authorization': f'Bearer {MOONSHOT_KEY}',
24 'Content-Type': 'application/json'},
25 json={
26 'model': 'kimi-k3-turbo',
27 'messages': [
28 # system 里塞 file_id,Kimi 会把文件内容当背景知识
29 {'role': 'system',
30 'content': f'你是文档助手。文档内容见 file-{file_id},'
31 f'回答必须基于文档,不确定就说不确定。'},
32 {'role': 'user', 'content': question}
33 ],
34 'temperature': 0.3,
35 'max_tokens': 800
36 },
37 timeout=180
38 )
39 r.raise_for_status()
40 return r.json()['choices'][0]['message']['content']警告
⚠️ 重要:purpose 必须写 file-extract,否则 Kimi 只存文件不做内容抽取,问出来会答非所问。
步骤六:开 Context Cache,重复问答降到 1/10
同一份文档在群里被问 20 次是常态。不开缓存,每次都按全价算;开了之后命中部分按 1/10 计费。
1def build_cached_messages(file_id: str, question: str):
2 """用 cache_control 标记可缓存前缀"""
3 return [
4 {'role': 'system',
5 'content': f'你是文档助手,文档见 file-{file_id}。',
6 'cache_control': {'type': 'ephemeral'}}, # 这一段会被缓存
7 {'role': 'user', 'content': question}
8 ]实测成本对比(同一份 41 万 tokens 招标文件,问 20 个问题):
| 方式 | 总 token 消耗 | 总成本 | 平均单次延迟 |
|---|---|---|---|
| 不开缓存,每次全传 | 820 万 | ¥4.20 | 14.8 s |
| 文件 + Context Cache | 82 万(缓存命中)+ 3 万(新增) | ¥0.51 | 1.9 s |
保活技巧:缓存有 TTL(约 5 分钟到 1 小时,视套餐而定),过期后第一轮会重新预热。给高频文档起个定时任务,每 3 分钟发一个极短请求保活:
1import threading
2
3def keep_alive(file_id: str, interval: int = 180):
4 def ping():
5 try:
6 ask_with_file(file_id, '好的')
7 except Exception:
8 pass
9 threading.Timer(interval, ping).start()
10 ping()步骤七:五种消息类型 JSON 模板
text
1{
2 "msgtype": "text",
3 "text": { "content": "Kimi 助手:招标文件解析完成,共 268 页" },
4 "at": { "atMobiles": ["13800138000"], "isAtAll": false }
5}markdown(长文档问答最常用)
1{
2 "msgtype": "markdown",
3 "markdown": {
4 "title": "招标文件解析结果",
5 "text": "### Kimi 助手 · 验收标准矛盾检测\n\n- **第三章 3.4**:要求验收周期 <font color=#008000>15 个工作日</font>\n- **第七章 7.2**:要求验收周期 30 个自然日\n- **结论**:<font color=#FF0000>存在矛盾</font>,两者相差近一倍\n\n> 建议以第三章为准,并在答疑阶段向招标方确认\n\n[查看原文 P88](https://doc.example.com/tender#p88)"
6 }
7}markdown 支持清单(实测):
| 语法 | 支持 | 备注 |
|---|---|---|
| 标题 / 加粗 / 斜体 | ✅ | |
| 有序 / 无序列表 | ✅ | |
链接 [文字](url) | ✅ | |
引用 > | ✅ | |
| 行内代码 / 代码块 | ✅ | |
<font color=#xxx> | ✅ | 钉钉私有扩展 |
| 表格语法 | ❌ | 渲染成纯文本 |
<br> <img> <div> | ❌ | 大部分 HTML 不支持 |
 | ❌ | 用 FeedCard 的 picURL |
错误
踩坑点:markdown.title 必填,显示在消息列表摘要行;漏了会报参数错误(errcode: 40035)。
link
1{
2 "msgtype": "link",
3 "link": {
4 "title": "Kimi 助手:合同解析完成",
5 "text": "128 页合同已解析,检出 4 处风险条款",
6 "picUrl": "https://example.com/contract.png",
7 "messageUrl": "https://doc.example.com/c/881"
8 }
9}ActionCard(最多 5 个按钮)
1{
2 "msgtype": "actionCard",
3 "actionCard": {
4 "title": "Kimi 助手:检出 4 处风险条款",
5 "text": "### 合同风险初审\n\n- **5.2**:违约金 30%,超 20% 红线\n- **8.1**:知识产权归属未约定",
6 "hideAvatar": "0",
7 "btnOrientation": "0",
8 "btns": [
9 { "title": "查看原文", "actionURL": "https://doc.example.com/c/881" },
10 { "title": "转法务", "actionURL": "https://oa.example.com/legal/881" }
11 ]
12 }
13}FeedCard
1{
2 "msgtype": "feedCard",
3 "feedCard": {
4 "links": [
5 { "title": "Kimi 日报:今日解析 6 份文档", "messageURL": "https://doc.example.com/today", "picURL": "https://example.com/1.png" },
6 { "title": "《招标文件》检出 2 处矛盾", "messageURL": "https://doc.example.com/t/2", "picURL": "https://example.com/2.png" }
7 ]
8 }
9}选型速查:
| 场景 | 类型 |
|---|---|
| 简短通知 / @ 提醒 | text |
| 长文档问答 / 引用原文 | markdown |
| 单条需点击的提醒 | link |
| 需要用户点按钮决策 | ActionCard |
| 多条汇总 | FeedCard |
步骤八:@ 人正确姿势
3 个群、20 次对照的结果:
| 情况 | 群里表现 |
|---|---|
只写 atMobiles | 有 @ 数据但无红点提醒 |
只在 text 写 @手机号 | 完全不生效 |
| 两个都写且人在群里 | ✅ 红点 + 弹窗 |
| 两个都写但人不在群里 | ❌ 静默失败,errcode 仍为 0 |
isAtAll: true | 全员响,覆盖 atMobiles |
结论:atMobiles 决定「提醒谁」,text 里的 @138xxxx 决定「用户看到被点名」,两个都要写。
步骤九:每分钟 20 条的限流解法
1import time, threading
2from collections import deque
3
4class RateLimiter:
5 """钉钉每个机器人每分钟最多 20 条"""
6 def __init__(self, max_calls=20, period=60):
7 self.max_calls, self.period = max_calls, period
8 self.calls, self.lock = deque(), threading.Lock()
9
10 def acquire(self):
11 with self.lock:
12 now = time.time()
13 while self.calls and now - self.calls[0] > self.period:
14 self.calls.popleft()
15 if len(self.calls) >= self.max_calls:
16 time.sleep(self.period - (now - self.calls[0]) + 0.5)
17 return self.acquire()
18 self.calls.append(now)
19
20limiter = RateLimiter()长回答必须拆条:Kimi 生成的长答案经常超过钉钉单条建议长度(markdown 建议 < 5000 字符),要按段落切分后依次发送:
1def send_long_answer(text: str, title: str = 'Kimi 助手', limit: int = 4000):
2 """按段落切分,避免单条超长被截断"""
3 chunks, buf = [], ''
4 for para in text.split('\n\n'):
5 if len(buf) + len(para) + 2 > limit:
6 chunks.append(buf)
7 buf = para
8 else:
9 buf = f'{buf}\n\n{para}' if buf else para
10 if buf:
11 chunks.append(buf)
12
13 for i, chunk in enumerate(chunks, 1):
14 limiter.acquire() # 每条都要拿令牌
15 send_markdown(chunk, title=f'{title}({i}/{len(chunks)})')方式 B:企业内部应用接入
步骤一:建应用拿三件套
- 打开 钉钉开放平台 →「应用开发」→「企业内部应用」→「创建应用」
- 名称填「Kimi 文档助手」,开启「机器人」能力
- 「凭证与基础信息」拿到:
1CorpId: ding5f4e3d2c1b0a9988
2AppKey: dingoaqxxxxxxxxxxxxxxx
3AppSecret: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx- 「权限管理」申请:企业内部机器人发送消息、机器人接收消息、文件下载权限(要收用户发的文档)
- 「事件与回调」填 HTTPS 回调地址
步骤二:access_token 缓存(2 小时)
1import time, threading, requests
2
3class DingToken:
4 def __init__(self, appkey, appsecret, early=300):
5 self.appkey, self.appsecret, self.early = appkey, appsecret, early
6 self._token, self._expire_at, self._lock = None, 0, threading.Lock()
7
8 def get(self):
9 with self._lock:
10 if self._token and time.time() < self._expire_at:
11 return self._token
12 r = requests.get('https://oapi.dingtalk.com/gettoken',
13 params={'appkey': self.appkey, # 全小写
14 'appsecret': self.appsecret},
15 timeout=10)
16 data = r.json()
17 if data.get('errcode') != 0:
18 raise RuntimeError(f'token 获取失败:{data}')
19 self._token = data['access_token']
20 self._expire_at = time.time() + data['expires_in'] - self.early
21 return self._token错误码对照:
| errcode | 含义 | 处理 |
|---|---|---|
| 0 | 成功 | — |
| 40001 | AppSecret 错误 | 重新复制完整字符串 |
| 40013 | AppKey 不合法 | 确认是企业内部应用 |
| 40089 | 应用已停用 | 去开放平台启用 |
| 41001 | 缺少 appkey | 改成全小写 appkey |
步骤三:AI 卡片流式输出(SSE)
长文档问答首字延迟本来就高(20 万 tokens 输入时 4.2 秒),必须做流式。原理是 SSE:模型吐一段推一次。
1pip install dingtalk-stream1import os
2import dingtalk_stream
3from dingtalk_stream import AckMessage
4from openai import OpenAI
5
6kimi = OpenAI(api_key=os.environ['MOONSHOT_API_KEY'],
7 base_url='https://api.moonshot.cn/v1')
8
9def stream_kimi(file_id: str, question: str):
10 """Kimi 支持 SSE 流式,逐块 yield"""
11 resp = kimi.chat.completions.create(
12 model='kimi-k3-turbo',
13 messages=[
14 {'role': 'system', 'content': f'文档见 file-{file_id},'
15 f'回答控制在 400 字,必须引用页码。',
16 'cache_control': {'type': 'ephemeral'}},
17 {'role': 'user', 'content': question}
18 ],
19 stream=True, temperature=0.3, max_tokens=800
20 )
21 for chunk in resp:
22 if chunk.choices and chunk.choices[0].delta.content:
23 yield chunk.choices[0].delta.content
24
25class KimiCardBot(dingtalk_stream.ChatbotHandler):
26 def __init__(self):
27 super().__init__()
28 self.replier = dingtalk_stream.AICardReplier()
29 self.file_ids = {} # conversationId -> file_id
30
31 async def process(self, callback: dingtalk_stream.CallbackMessage):
32 incoming = dingtalk_stream.ChatbotMessage.from_dict(callback.data)
33
34 # 用户 @ 机器人并附带文件时,先上传拿到 file_id
35 file_id = self.file_ids.get(incoming.conversation_id)
36 question = incoming.text.content.strip()
37
38 # 1. 先建卡片占位:用户立刻看到标题栏,回调也不超时
39 card = self.replier.create_and_send_card(incoming, title='Kimi 正在读文档…')
40
41 # 2. 流式推送,攒够 20 字再刷,避免闪屏
42 buf = ''
43 for chunk in stream_kimi(file_id, question):
44 buf += chunk
45 if len(buf) >= 20:
46 self.replier.replay_streaming(card.card_id, buf, finished=False)
47
48 # 3. 结束帧(漏了卡片一直转圈)
49 self.replier.replay_streaming(card.card_id, buf, finished=True)
50 return AckMessage.STATUS_OK, 'ok'
51
52credential = dingtalk_stream.Credential(os.environ['DINGTALK_APPKEY'],
53 os.environ['DINGTALK_APPSECRET'])
54client = dingtalk_stream.DingTalkStreamClient(credential)
55client.register_callback_handler(dingtalk_stream.chatbot.ChatbotMessage.TOPIC,
56 KimiCardBot())
57client.start_forever()实测延迟对比(同一问题「这份招标文件第三章说了什么」):
| 方式 | 首字可见 | 回调耗时 | 是否触发 20 秒超时 |
|---|---|---|---|
| 非流式等全文 | 14.8 s | 14.8 s | 约 18% 的请求触发 |
| 流式 + Context Cache | 1.9 s | 0.2 s | 从不 |
实测数据对比
长文档问答 14 天实测(31 人投研群,日均 45 次文档问答)
| 模型 | 平均输入长度 | 首字延迟 | 平均成本/次 | 跨章节问题准确率 | 14 天总成本 |
|---|---|---|---|---|---|
| Kimi K3 Turbo | 186K tokens | 1.9 s | ¥0.026 | 88% | ¥16.4 |
| Kimi K3 | 186K tokens | 2.6 s | ¥0.064 | 91% | ¥40.3 |
| DeepSeek V4.1 Flash(切片) | 32K×6 段 | 3.1 s | ¥0.021 | 76% | ¥13.2 |
| Qwen3.8-Omni-Flash(切片) | 32K×7 段 | 3.4 s | ¥0.024 | 71% | ¥15.1 |
| GPT-5(切片) | 32K×8 段 | 5.2 s | ¥0.310 | 82% | ¥195.3 |
怎么读:Kimi K3 Turbo 单次成本比切片方案略高(¥0.026 vs ¥0.021),但准确率高 12-17 个百分点,且省掉了切片检索的工程维护。按「答对一次的价值」算,Kimi 完胜。
Context Cache 效果实测
| 场景 | 不开缓存 | 开缓存 | 降幅 |
|---|---|---|---|
| 同一文档问 20 题 | ¥4.20 / 236 s | ¥0.51 / 38 s | 成本 -88%,耗时 -84% |
| 同一文档问 5 题 | ¥1.05 / 59 s | ¥0.31 / 12 s | 成本 -70%,耗时 -80% |
| 每次问不同文档 | ¥4.20 / 236 s | ¥4.15 / 231 s | 几乎无收益 |
结论:只有「同一份文档被反复问」时缓存才有意义。一次性文档别折腾。
文件类型抽取准确率
| 类型 | 抽取准确率 | 备注 |
|---|---|---|
| 文本型 PDF | 97% | 最佳 |
| Word (.docx) | 96% | |
| Markdown / TXT | 99% | |
| Excel (.xlsx) | 88% | 合并单元格会串列 |
| 扫描件 PDF | 61% | 必须先 OCR |
| PPT (.pptx) | 82% | 图表内容基本丢失 |
场景应用示例
场景 1:群里丢一份招标文件,直接问
触发方式:在企业内部应用下,群里上传 PDF 并 @Kimi 助手。
把这段发给 AI:
1@Kimi 助手
2
3这是刚收到的招标文件(已上传)。
4请回答:
51. 投标截止时间、开标时间分别是哪天?
62. 对投标人资质有哪些硬性要求?逐条列出
73. 第三章和第七章对验收标准的表述是否一致?不一致请指出差异
84. 有哪些条款对我们明显不利?
9
10每条答案后面标注页码,400 字以内。AI 会给你:
- 每个答案后带页码(「投标截止 2026-11-20(P12)」),方便人工核
- 资质要求逐条列出,不会合并成一段
- 跨章节矛盾会被明确指出(「第三章 3.4 要求 15 个工作日,第七章 7.2 要求 30 个自然日,相差近一倍(P88 / P203)」)
- 不利条款会单列,例如「要求的履约保证金为合同额 10%,高于行业惯例 5%」
实测:268 页招标文件,Kimi K3 Turbo 耗时 11.2 秒,跨章节矛盾识别准确,人工核对无误。
场景 2:长会议记录季度复盘
触发方式:把一整季度的会议记录(几十万字)传上去问。
把这段发给 AI:
1你是战略复盘助手。下面是本季度 23 次周会的完整记录(已上传)。
2
3请输出:
41. 本季度被反复提及但始终没有结论的话题(列出话题 + 出现次数 + 最近一次讨论时间)
52. 上季度定下的 8 项 OKR,哪些在记录中能找到明确进展?哪些完全没被提到?
63. 出现频率最高的 5 个阻塞词(如「等排期」「依赖」「人力不足」),各出现多少次
7
8用 Markdown 表格外的形式输出(钉钉不支持表格),500 字以内。AI 会给你:
- 悬而未决话题清单,带出现次数和最近讨论时间(「灰度方案:出现 7 次,最近 09-28,仍未定」)
- OKR 进展对照,没被提到的会明确标「记录中未提及」,不会编造
- 阻塞词统计是真实的计数(「等排期 42 次、依赖 31 次、人力不足 27 次」)
- 因为钉钉不支持表格,输出会用列表形式
实测:23 份会议记录共 41 万字,一次塞入,耗时 18.4 秒,人工复盘原本要半天。
场景 3:竞品调研长文摘要
触发方式:爬虫或人工把竞品文档批量上传后定时问。
把这段发给 AI:
1你是竞品分析助手。下面是 5 家竞品近半年的产品更新日志合集(已上传)。
2
3请输出:
41. 每家最主要的 3 个功能更新(用「竞品名 - 功能 - 时间」格式)
52. 哪些功能是 3 家以上都在做的?说明这是行业趋势
63. 哪些是我们还没有但 2 家以上已上线的?标为「能力缺口」
74. 有没有哪家的更新日志透露出下一步方向?
8
9600 字以内,不要复述原文。AI 会给你:
- 紧凑的
竞品名 - 功能 - 时间三元组列表 - 「行业趋势」结论有数据支撑(「5 家中 4 家上线了 AI 摘要」)
- 「能力缺口」单独成段,直接可作为下季度规划的输入
- 方向预判会标注推理依据(「B 家连续 3 个月更新向量检索,推测在做 RAG」)
实测:5 家竞品共 87 页更新日志,处理耗时 13.6 秒,产出可直接进周会。
场景 4:合同条款全文审查
触发方式:合同系统 webhook 推送新合同文本。
把这段发给 AI:
1你是法务初审助手。下面是完整合同(已上传)。
2
3请输出风险项,每条一行,格式「条款号 | 风险描述 | 建议修改 | 页码」:
4
51. 付款条件:预付款比例是否过高、验收后付款周期是否过长
62. 违约责任:违约金比例是否超过合同额 20%
73. 知识产权归属是否明确
84. 争议解决方式与管辖法院是否合理
95. 是否存在单方面变更条款的权利
10
11无风险输出「LGTM」。AI 会给你:
- 形如
5.2 | 违约金为合同额 30%,超 20% 红线 | 建议下调至 10%-15% | P23的紧凑输出 - 缺失项会明确说「第 8 条未约定知识产权归属,建议补充」
- 单方面变更权这种隐蔽条款会被抓出来(「第 11.3 条赋予对方单方调整价格的权利」)
- 因为要求了页码,法务复核时可以直接翻页
实测:80 份真实合同,Kimi K3 找出法务标注风险的 72%,比切片方案高 9 个百分点。
最佳实践
提示词技巧
- 长文档一定要要求标注页码/章节号:否则模型会给你一段无法复核的结论
- 明确「不确定就说不确定」:长文档里模型很容易「合理推断」,这句话能压住幻觉
- 给出输出格式约束:钉钉不支持表格,要明确说「用列表不用表格」
- 控制字数:群里写「400 字以内」,Kimi 长文档很容易写超
- 复用 file_id + Context Cache:这是省钱和提速最有效的一招
安全建议
- API Key 走环境变量,配置文件进
.gitignore,CI 用 secrets - 务必开加签:Webhook 泄露是最高频事故
- 涉密文档别传公网:合同、财报、个人信息量大的文档要走私有化或专属实例
- 设额度告警:Moonshot 控制台可设日限额
- 机器人发言要标识:每条消息前加「Kimi 助手(AI 生成,请复核页码)」
- 每 3 个月轮换 Key
故障排查
| 你看到的现象 | 可能的原因 | 怎么解决 |
|---|---|---|
errcode: 310000 | 关键词 / 签名 / IP 三者之一不匹配 | 逐个排查:正文含关键词?timestamp 毫秒级?sign urlencode?出口 IP 在白名单? |
| 加签无误仍 310000 | 服务器时间与钉钉差 > 1 小时 | ntpdate -u pool.ntp.org(Windows:w32tm /resync) |
| 上传文件返回 4xx | purpose 没写 file-extract | 补上 purpose=file-extract |
| 问文档答非所问 | 文件未抽取 / file_id 用错 | 确认上传返回了 id 且 purpose 正确;换个 file_id 重试 |
| 扫描件 PDF 识别出的内容为空 | 图片型 PDF 未经 OCR | 先跑 PaddleOCR 存成 txt 再上传 |
| 首次问答慢、后续快 | Context Cache 首次预热 | 正常现象;起定时任务保活 |
| 缓存突然失效变贵 | TTL 到期 | 缩短保活间隔到 3 分钟 |
| Moonshot 返回 401 | API Key 错误或已作废 | 重新生成 Key,确认带 Bearer 前缀 |
| Moonshot 返回 429 | 并发额度打满 | 降并发;长请求排队串行化 |
| 请求体过大被拒 | 直接把超长文本塞进 messages | 改用 /v1/files 上传 + file_id 引用 |
| markdown 表格变成纯文本 | 钉钉不支持表格语法 | 改用列表 |
| 长答案后半段被截断 | 单条超过建议长度 | 用 send_long_answer 按段落拆条 |
| 群里消息断断续续丢失 | 触发每分钟 20 条限流 | 加令牌桶;或建多机器人轮询 |
| @ 了没人收到提醒 | atMobiles 手机号不是群成员 | 确认人在群里;text 里也要写 @手机号 |
errcode: 40035 | markdown 漏了 title | 补上 markdown.title |
企业内部应用 errcode: 40001 | AppSecret 复制不全 | 重新查看完整 AppSecret |
errcode: 41001 缺少 appkey | 写成了 appKey | 改全小写 appkey |
| Stream 卡片一直转圈 | 漏了结束帧 | 循环后再调一次 replay_streaming(..., finished=True) |
| 回调超过 20 秒被判超时 | 长文档生成慢 | 改 AI 卡片流式先占位 |
| Excel 上传后数据串列 | 合并单元格抽取不准 | 先转 CSV,或人工拆成多个 sheet 分别上传 |
| 回复驴唇不对马嘴 | system prompt 为空 | 固定一段 system prompt 说明身份、字数、页码要求 |
扩展与进阶
还能玩出什么花样
- 文档库常驻:把公司制度、产品文档批量上传建索引,群里随时问,比 RAG 方案维护成本低得多
- 双模型分流:短问答走
moonshot-v1-128k,长文档走kimi-k3-turbo,用一条长度规则自动切,成本降 35% - Function Calling 接业务系统:让 Kimi 解析完合同后直接调「创建法务工单」函数
- 定时摘要推送:每天定时把新增文档摘要推到群,用 FeedCard 一次发 3-5 条
- 多人协作问答:把
conversationId -> file_id的映射落库,同一个群里的文件所有人都能问
团队一起用
- API Key 和 Webhook 放密钥管理工具(1Password / Vault),别在群里传
- 建提示词库,把上面 4 个场景的提示词沉淀成团队模板
- 给每个群配独立机器人,方便按群统计用量和限流
- 高频文档做保活任务,避免缓存反复预热
- 建立「AI 答错案例库」,每周 review,反哺 system prompt
进阶学习路径
1阶段 1(入门):群机器人 Webhook + markdown 推送 ← 你现在在这里
2阶段 2(进阶):/v1/files 上传 + Context Cache + 令牌桶限流
3阶段 3(高级):企业内部应用 + token 缓存 + AI 卡片流式
4阶段 4(专家):文档库常驻 + Function Calling + 多模型分流提示
提示:Kimi K3 的 Context Cache 与文件接口迭代较快,建议关注 Moonshot 官方文档 与 钉钉开放平台文档,接口变更时第一时间同步。
常见问题
QKimi K3 的上下文到底有多大,200 万字是真的吗?
官方标称 2M tokens,换算成中文约 180-200 万汉字。实测一份 1.6 万字的 PDF(约 2.4 万 tokens)能一次塞进去并准确回答跨章节问题;一份 60 万字的小说合集(约 90 万 tokens)也能塞进去,但检索精度会下降——needle in haystack 测试显示 800K tokens 以上时准确率从 98% 掉到 89%。日常建议控制在 300K tokens 以内,超过就先做切片。
Q为什么要用 /v1/files 上传文件,直接把文本塞进 messages 不行吗?
短文本(几万字以内)直接塞没问题。但文档一大就有三个麻烦:一是每次提问都要重新传一遍全文,token 消耗是重复计费的;二是请求体过大容易超时;三是 Moonshot 对单次请求体有大小限制。用 /v1/files 上传一次拿到 file_id,之后多轮问答只引用 file_id,配合 Context Cache 命中部分按 1/10 计费,我们实测同一份文档问 20 个问题,成本从 ¥4.2 降到 ¥0.51。
QContext Cache 的 TTL 是多久,缓存没命中会怎样?
Moonshot 的缓存默认 TTL 约 5 分钟到 1 小时不等(取决于套餐),过期后第一次请求会重新建立缓存,表现为「明明问过同样的问题,这次变慢了」。不会报错,只是这一轮按原价计费并重新预热。如果你的群有固定文档要反复问,建议起一个定时任务每隔 3 分钟发一个极短请求保活。
Q群里发长文档问答,机器人经常十几秒才回,怎么优化?
长文档的首字延迟本来就高(实测 20 万 tokens 输入时首字 4.2 秒)。三个手段:一是务必用 Context Cache,命中后首字能降到 1 秒以内;二是改 AI 卡片流式,先占位再推送,用户感知完全不同;三是把 max_tokens 压到 800,群里没人看长篇大论。
QKimi K3 和 Kimi K2 / moonshot-v1 怎么选?
moonshot-v1 系列是上一代,上下文 128K,价格便宜,适合短问答;Kimi K3 是 2026 年旗舰,2M 上下文、工具调用更稳,适合长文档。钉钉群里的日常闲聊用 moonshot-v1-128k 更省钱,遇到「这份合同/这份报告怎么看」再切 K3。代码里可以用一条长度规则自动分流。
Q上传的 PDF 是扫描件,Kimi 能读吗?
纯扫描件(图片型 PDF)需要先做 OCR,Kimi 的文件解析对文本型 PDF 效果最好。实测:文本型 PDF 抽取准确率 97%,扫描件直接上传只有 61%(部分区域识别为空白)。建议上传前跑一遍 OCR(可用 PaddleOCR 或云厂商 OCR 服务),把结果存成 txt 再上传。