前言
企业和个人开发者越来越希望把大模型能力嵌入微信,实现自动回复、智能客服、私域运营等场景。但调用云端 GPT/Claude 每次都产生 API 费用,且数据上传第三方存在隐私顾虑。Ollama 让你在本机或内网服务器跑 Llama 3、Qwen2、Gemma 等开源模型,零成本、零数据泄露。本文详细拆解如何把 WechatApi 个人微信 HTTP 接口 与本地 Ollama 打通,实现私有化微信智能机器人的完整方案。
一、整体架构:三层联动原理
在动手写代码之前,先把整个调用链路搞清楚,能避免很多踩坑。
微信客户端(手机/iPad)
↕ iPad 协议长连接
WechatApi 云端接入层(负责协议维持、消息推送)
↕ Webhook 或轮询
你的中间服务(Python/Node 等)
↕ HTTP POST /api/generate
Ollama 本地大模型(Llama3 / Qwen2 / 其他)
WechatApi 基于 微信 iPad 协议 实现稳定的个人微信接入,提供标准 HTTP REST 接口,你无需关心底层协议细节,只需接收 Webhook 推送的消息、再调用发送接口回复即可。Ollama 则在本地或内网跑模型推理,二者通过你写的中间服务(以下称"Bot Server")串联起来。
这套架构的优势:
- 微信协议层完全托管给 WechatApi,稳定性有保障;
- 推理层完全在本地,数据不出内网;
- 中间服务逻辑可以自由定制,加角色设定、知识库检索、会话记忆都行。
二、环境准备
2.1 安装并启动 Ollama
前往 ollama.com 下载对应操作系统的安装包,或在 Linux 上一行搞定:
bashcurl -fsSL https://ollama.com/install.sh | sh
拉取你想用的模型(以中文效果较好的 Qwen2 为例):
bashollama pull qwen2:7b
# 启动服务(默认监听 127.0.0.1:11434)
ollama serve
验证模型是否就绪:
bashcurl http://127.0.0.1:11434/api/generate \
-d '{"model":"qwen2:7b","prompt":"你好","stream":false}'
返回 JSON 中有 response 字段即为成功。
注意:若 Bot Server 与 Ollama 不在同一台机器,需在 Ollama 启动时设置 OLLAMA_HOST=0.0.0.0:11434 并开放防火墙端口。
2.2 注册并配置 WechatApi
访问 WechatApi 控制台 注册账号,完成设备绑定(扫码登录个人微信号)。绑定成功后,你会拿到两个关键凭证:
| 凭证 | 说明 | 示例格式 |
|---|---|---|
VideosApi-token | 请求鉴权头,每账号唯一 | vt-xxxxxxxxxxxxxxxx |
appId | 设备 ID,区分多设备多微信 | wx_device_xxxxxxxx |
在控制台的"消息推送"设置里,填入你 Bot Server 的公网 URL(或内网穿透地址),WechatApi 会把收到的微信消息实时 POST 到该地址。
三、Bot Server 核心实现(Python 示例)
下面用 Python + Flask 实现接收消息、调用 Ollama 推理、再通过 WechatApi 发送回复的完整链路。
pythonimport requests
from flask import Flask, request, jsonify
app = Flask(__name__)
# ── WechatApi 配置 ──────────────────────────────────
WECHAT_API_BASE = "https://your-wechatapi-endpoint.wechatapi.net"
VIDEOS_API_TOKEN = "vt-your-token-here" # 替换为控制台获取的 token
APP_ID = "wx_device_your_appid" # 替换为你的设备 appId
# ── Ollama 配置 ──────────────────────────────────────
OLLAMA_API = "http://127.0.0.1:11434/api/generate"
OLLAMA_MODEL = "qwen2:7b"
# 简单会话记忆(生产环境建议改用 Redis)
session_history: dict[str, list] = {}
def ask_ollama(user_id: str, user_message: str) -> str:
"""拼接历史上下文,调用 Ollama 推理"""
history = session_history.get(user_id, [])
# 构造 prompt(简单拼接示范,可替换为 chat 接口格式)
system_prompt = (
"你是一个专业的微信智能助手,回答简洁友好,"
"不超过200字。"
)
context = "\n".join(
[f"用户:{h['user']}\n助手:{h['bot']}" for h in history[-5:]]
)
full_prompt = f"{system_prompt}\n{context}\n用户:{user_message}\n助手:"
resp = requests.post(OLLAMA_API, json={
"model": OLLAMA_MODEL,
"prompt": full_prompt,
"stream": False
}, timeout=60)
resp.raise_for_status()
answer = resp.json().get("response", "抱歉,推理失败,请稍后再试。")
# 存入历史
history.append({"user": user_message, "bot": answer})
session_history[user_id] = history[-20:] # 只保留最近20轮
return answer
def send_wechat_text(to_wxid: str, content: str):
"""通过 WechatApi 发送文字消息"""
headers = {
"VideosApi-token": VIDEOS_API_TOKEN,
"Content-Type": "application/json"
}
payload = {
"appId": APP_ID,
"toWxId": to_wxid,
"content": content
}
resp = requests.post(
f"{WECHAT_API_BASE}/api/sendText", # 示意路径,以文档为准
headers=headers,
json=payload,
timeout=10
)
return resp.json() # {"ret":200,"msg":"success","data":{}}
@app.route("/webhook", methods=["POST"])
def webhook():
"""接收 WechatApi 推送的消息"""
data = request.get_json(force=True)
msg_type = data.get("msgType") # 消息类型:文字=1
from_wxid = data.get("fromWxId") # 发送者 wxid
content = data.get("content", "")
# 只处理私聊文字消息,群消息可按需扩展
if msg_type == 1 and from_wxid:
answer = ask_ollama(from_wxid, content)
result = send_wechat_text(from_wxid, answer)
print(f"[发送结果] {result}")
return jsonify({"status": "ok"})
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000, debug=False)
关键点说明:
- 鉴权:每个请求头必须带
VideosApi-token,缺少或错误会返回ret:401。 - appId:标识是哪台设备(哪个微信号)在发消息,多设备场景必填。
- 超时:Ollama 本地推理 7B 模型一般 5-15 秒,设置 timeout ≥ 60s 防止请求中断。
四、WechatApi 调用规范与返回格式
无论发消息还是查询好友,WechatApi 接口都遵循统一范式,理解这一点对调试非常有帮助。
请求格式(HTTP POST + JSON):
jsonPOST /api/sendText
Headers:
VideosApi-token: vt-your-token-here
Content-Type: application/json
Body:
{
"appId": "wx_device_your_appid",
"toWxId": "wxid_xxxxxxxxxxxxxxx",
"content": "你好,我是 AI 助手,有什么可以帮你?"
}
成功响应:
json{
"ret": 200,
"msg": "success",
"data": {
"newMsgId": "1234567890123456789",
"clientMsgId": "xxxxxxxx"
}
}
常见错误码:
| ret 值 | 含义 | 处理建议 |
|---|---|---|
| 200 | 成功 | — |
| 401 | Token 无效或过期 | 检查 VideosApi-token 是否正确 |
| 400 | 参数缺失或格式错误 | 检查 appId / toWxId / content |
| 500 | 服务端内部错误 | 稍后重试,可联系 WechatApi 支持 |
| -1 | 设备离线 | 重新扫码登录或检查设备状态 |
完整接口列表见 WechatApi 开发文档,涵盖发文字、发图片、发文件、获取群成员、拉人入群等数十个接口,足以支撑完整的 微信机器人开发 需求。
五、群聊场景:@机器人才响应
私聊机器人直接回复即可,但群聊里如果对每条消息都调用 Ollama 推理,既消耗资源又打扰群成员。通常的做法是:只在消息中 @ 了机器人时才触发推理。
WechatApi Webhook 推送的群消息结构通常包含 atList(被@的人的 wxid 列表)和 isRoom(是否群聊)字段。改写 webhook 路由如下:
python@app.route("/webhook", methods=["POST"])
def webhook():
data = request.get_json(force=True)
msg_type = data.get("msgType")
from_wxid = data.get("fromWxId")
room_id = data.get("roomId") # 群 ID,私聊为空
content = data.get("content", "")
at_list = data.get("atList", []) # 被 @ 的 wxid 列表
BOT_WXID = "wxid_your_bot_wxid_here" # 机器人自己的 wxid
if msg_type != 1:
return jsonify({"status": "skip"})
is_group = bool(room_id)
if is_group:
# 群聊:只在被 @ 时响应
if BOT_WXID not in at_list:
return jsonify({"status": "not_at"})
# 去掉消息里的 @昵称 前缀
content = content.replace(f"@助手 ", "").strip()
reply_to = room_id # 回复到群
else:
reply_to = from_wxid # 私聊直接回复对方
answer = ask_ollama(from_wxid, content)
send_wechat_text(reply_to, answer)
return jsonify({"status": "ok"})
这样机器人在群里就只回应 @它 的消息,不打扰正常聊天,也大幅降低推理频率。
六、进阶:接入知识库(RAG 简易方案)
纯聊天机器人已经能用了,但真正落地业务场景往往需要机器人掌握特定领域知识,比如产品手册、FAQ、内部规范。这时候需要 RAG(检索增强生成)。
最简方案:把知识库文本预先切片存入向量数据库(如 Chroma),用户问题来了先检索最相关的段落,再拼进 prompt 让 Ollama 根据检索结果回答。
pythonimport chromadb
from sentence_transformers import SentenceTransformer
# 初始化向量库和 embedding 模型(本地运行,同样零隐私泄露)
chroma_client = chromadb.Client()
collection = chroma_client.get_or_create_collection("kb")
embedder = SentenceTransformer("BAAI/bge-small-zh-v1.5")
def retrieve_context(query: str, top_k: int = 3) -> str:
"""从知识库检索最相关段落"""
q_vec = embedder.encode([query]).tolist()
results = collection.query(query_embeddings=q_vec, n_results=top_k)
docs = results.get("documents", [[]])[0]
return "\n".join(docs)
def ask_ollama_with_rag(user_id: str, user_message: str) -> str:
context = retrieve_context(user_message)
rag_prompt = (
f"参考以下资料回答用户问题,资料之外不要猜测:\n"
f"【资料】\n{context}\n\n"
f"【用户问题】{user_message}\n"
f"【回答】"
)
resp = requests.post(OLLAMA_API, json={
"model": OLLAMA_MODEL,
"prompt": rag_prompt,
"stream": False
}, timeout=60)
return resp.json().get("response", "暂无相关信息。")
这套方案全程本地化:embedding 模型本地跑、向量库本地存、推理本地完成,配合 WechatApi 的消息通道,整个智能客服系统数据完全不出公司内网,非常适合对数据安全有要求的场景,也是 微信客服机器人 和 微信群管理机器人 落地的主流技术路线。
七、常见问题与注意事项
1. Webhook 没有收到推送
检查 Bot Server 是否有公网可访问地址。本地开发可用 ngrok http 5000 或 frp 做内网穿透,把公网地址填到 WechatApi 控制台的 Webhook 设置里,注意路径要完整(如 https://xxx.ngrok.io/webhook)。
2. Ollama 推理太慢导致微信端等待体验差
可以先立即回复"正在思考中…"(调一次 send_wechat_text),再异步跑推理完成后发送正式回答。也可以把 stream 模式打开,逐句推送,但微信不支持"打字机"效果,分段发多条消息的体验通常不好,不如等全文完成后一次性发送。
3. 微信账号被风控
WechatApi 采用 iPad 协议,相对于 PC Hook 方案稳定性更高,详见 微信 iPad 协议 介绍。即便如此,使用机器人账号时也应注意:避免回复速度过于均匀(加入随机延迟)、控制每天消息总量、不在短时间内大量拉群或加好友。
4. 模型选择建议
| 模型 | 参数量 | 显存需求 | 中文效果 | 推荐场景 |
|---|---|---|---|---|
| qwen2:7b | 7B | ≥8GB GPU / 16GB CPU | ★★★★☆ | 通用客服、问答 |
| llama3:8b | 8B | ≥8GB GPU / 16GB CPU | ★★★☆☆ | 英文/双语场景 |
| qwen2:14b | 14B | ≥16GB GPU | ★★★★★ | 复杂推理、长文本 |
| gemma2:9b | 9B | ≥10GB GPU | ★★★☆☆ | 轻量英文任务 |
没有 GPU 的机器用 CPU 跑 7B 模型也可以,但推理时间会延长到 30-60 秒,生产环境建议至少配备 8GB 显存的 GPU。
5. 多微信号管理
WechatApi 支持一个账户下绑定多个设备(多个微信号),每个设备对应不同的 appId。你只需在中间服务里根据 Webhook 推送里的 appId 字段区分来源,即可用同一套 Bot Server 服务多个微信号,适合 微信 SCRM 和多账号私域运营场景。
小结
本文完整演示了微信机器人接入本地 Ollama 大模型的三层架构:WechatApi 负责微信协议接入与消息收发,Ollama 在本地或内网完成大模型推理,中间 Bot Server 负责业务逻辑串联。整套方案零月付推理费用、数据不出内网,是当前私有化微信智能助手的最优解之一。
如需快速上手,可访问 WechatApi 官网 了解接入方式,查阅 开发文档 获取完整接口列表,或直接前往 控制台 注册体验。更多 微信二次开发 场景欢迎进一步探索。
