首发于「林间昭语」 | 作者:程序员林间 | 阅读时间:约 10 分钟
关联阅读:前一篇《RAG 效果调优》
一、为什么接入企微/钉钉才是真正的交付?
很多技术人搭建 RAG 系统,做完向量数据库 + LLM 对话就结束了。
但对客户来说,花钱买的东西如果不能用起来 = 没用。
我把知识库接到客户的企业微信或钉钉里,客户点开就能用——这一步才叫"交付完成"。
这篇文章,讲讲怎么把 RAG 知识库接入企业微信和钉钉,让客户真正用起来。
二、两种主流接入方案对比
| 方案 | 优点 | 缺点 | 适用场景 |
|------|------|------|----------|
| 企业微信客服 | 微信生态、体验好 | 需要企业认证 | 大多数企业客户 |
| 钉钉机器人 | 阿里生态、开放性好 | 体验一般 | 阿里系企业 |
| Web / API 接口 | 最灵活 | 需要二次开发 | 有技术团队的客户 |
我的选择:90% 的客户项目优先选企业微信,原因:客户使用成本最低(每个人都用微信)。
三、企业微信接入方案
3.1 架构概览
用户(微信)
↓
企业微信客服消息
↓
RAG 知识库 API
↓
LLM 生成回答
↓
返回给用户
3.2 开通企业微信客服
- 登录企业微信管理后台:work.weixin.qq.com/
- 进入「应用管理」→「创建应用」
- 配置「接收消息」服务器
3.3 核心代码实现
from flask import Flask, request, jsonify
from wechatpy import parse_message, create_reply
from wechatpy.work import WeChatCorp
app = Flask(__name__)
# 企业微信配置
CORP_ID = "your_corp_id"
APP_SECRET = "your_app_secret"
AGENT_ID = 1000001
wechat = WeChatCorp(
corp_id=CORP_ID,
secret=APP_SECRET,
agent_id=AGENT_ID
)
@app.route("/wechat", methods=["GET", "POST"])
def wechat_handler():
if request.method == "GET":
# 验证企业微信回调
return request.args.get("echostr", "")
# 处理消息
msg = parse_message(request.data)
if msg.type == "text":
user_question = msg.content
# 调用 RAG 知识库
answer = rag_chain.invoke({"query": user_question})
# 构建回复
reply = create_reply(answer["result"], msg)
return reply.render()
return "success"
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000)
3.4 开通企业微信客服步骤
- 创建客服账号:企业微信后台 → 客户联系 → 开通企业微信客服
- 配置接待人员:把客服账号分配给员工
- 获取接口权限:调用企业微信客服消息接口
# 企业微信客服消息发送
from wechatpy.work.agent import WeChatAgent
agent = WeChatAgent(
corp_id=CORP_ID,
secret=APP_SECRET,
agent_id=AGENT_ID
)
def send_message_to_user(user_id, content):
agent.send_text_message(
user_id=user_id,
content=content
)
四、钉钉接入方案
4.1 架构概览
用户(钉钉)
↓
钉钉群机器人
↓
RAG 知识库 API
↓
LLM 生成回答
↓
返回到群聊
4.2 创建钉钉机器人
- 打开钉钉群 → 设置 → 智能群助手
- 添加机器人 → 自定义机器人
- 获取 Webhook 地址和密钥
4.3 核心代码实现
import requests
import json
import time
import hmac
import hashlib
import base64
import urllib.parse
class DingTalkRobot:
def __init__(self, webhook, secret):
self.webhook = webhook
self.secret = secret
def _sign(self):
timestamp = str(round(time.time() * 1000))
secret_enc = self.secret.encode('utf-8')
string_to_sign = '{}\n{}'.format(timestamp, self.secret)
string_to_sign_enc = string_to_sign.encode('utf-8')
hmac_code = hmac.new(secret_enc, string_to_sign_enc, digestmod=hashlib.sha256).digest()
sign = urllib.parse.quote_plus(base64.b64encode(hmac_code))
return timestamp, sign
def send_text(self, content):
timestamp, sign = self._sign()
url = f"{self.webhook}×tamp={timestamp}&sign={sign}"
headers = {"Content-Type": "application/json"}
data = {
"msgtype": "text",
"text": {
"content": content
}
}
response = requests.post(url, headers=headers, data=json.dumps(data))
return response.json()
# 使用
robot = DingTalkRobot(
webhook="https://oapi.dingtalk.com/robot/send?access_token=xxx",
secret="SECxxx"
)
# 处理用户问题
def handle_dingtalk_question(question):
# 调用 RAG 知识库
result = rag_chain.invoke({"query": question})
# 发送回答到钉钉群
response = robot.send_text(
f"🤖智能助手回答:\n\n{result['result']}\n\n---"
)
return response
五、两种方案同时接入(推荐)
很多客户同时用企业微信和钉钉,可以做一个统一的接入层:
class UnifiedRAGBot:
def __init__(self, platform="wechat"):
self.platform = platform
self.rag_chain = load_rag_chain()
def handle_message(self, message, user_info):
# 统一处理入口
if self.platform == "wechat":
return self.handle_wechat(message, user_info)
elif self.platform == "dingtalk":
return self.handle_dingtalk(message, user_info)
def handle_wechat(self, message, user_info):
# 调用 RAG
result = self.rag_chain.invoke({"query": message})
# 返回企业微信格式
return {
"msgtype": "text",
"text": {"content": result["result"]}
}
def handle_dingtalk(self, message, user_info):
# 调用 RAG
result = self.rag_chain.invoke({"query": message})
# 返回钉钉格式
return {
"msgtype": "text",
"text": {"content": f"🤖 {result['result']}"}
}
六、上线后的配置与优化
6.1 消息处理优化
# 添加欢迎语
WELCOME_MESSAGE = """
您好!我是您的智能助手,可以回答关于【XX产品/XX知识】的问题。
💡 您可以这样问我:
- "合同模板在哪里?"
- "如何申请报销?"
- "第三季度的销售数据是多少?"
请直接输入您的问题 ~
"""
# 添加快捷菜单(企业微信)
def get_wechat_menu():
return {
"button": [
{
"type": "click",
"name": "常见问题",
"key": "V1001_FAQ"
},
{
"type": "view",
"name": "知识库入口",
"url": "https://your-knowledge-base.com"
}
]
}
6.2 限流与安全
from functools import wraps
import time
# 简单限流
user_requests = {}
def rate_limit(max_requests=10, window=60):
def decorator(func):
@wraps(func)
def wrapper(user_id, *args, **kwargs):
now = time.time()
if user_id not in user_requests:
user_requests[user_id] = []
# 清理过期的请求记录
user_requests[user_id] = [
t for t in user_requests[user_id]
if now - t < window
]
if len(user_requests[user_id]) >= max_requests:
return "抱歉,您的问题太频繁了,请稍后再试 ~"
user_requests[user_id].append(now)
return func(user_id, *args, **kwargs)
return wrapper
return decorator
@rate_limit(max_requests=10, window=60)
def handle_question(user_id, question):
# 实际处理逻辑
return rag_chain.invoke({"query": question})
七、常见问题
| 问题 | 原因 | 解决方案 |
|------|------|----------|
| 消息收不到 | 回调 URL 不通 | 检查防火墙、Ngrok 内网穿透 |
| 回答慢 | LLM 调用慢 | 换成 DeepSeek 等国内模型 |
| 内容违规 | 敏感词 | 加内容审核过滤 |
| 并发太高 | 限流没配 | 加上限流逻辑 |
总结
三个核心要点:
- 知识库不接入用户场景 = 没交付:企业微信是最低成本的使用方式
- 企业微信接入更简单:有 SDK,有完整文档,按步骤配置即可
- 上线只是开始:限流、安全、体验优化都是持续要做的事
下一步
把知识库接到企业微信/钉钉里,客户才能真正用起来。
这一步做不好,前面搭得再好也是白搭。
如果你也在做知识库交付,欢迎扫码聊一聊。
我可以帮你评估现有系统,给出具体的接入方案建议。
备注"接入",送你一份《企业微信/钉钉接入 checklist》👇
关注「林间昭语」,用技术创造可能。
点击上方蓝色公众号名称 → 设为星标 🌟,第一时间收到干货。