OpenClaw + Ollama 本地模型接入完整教程
基于实战踩坑经验,从零配置 Mac mini M4 运行 Qwen3:14b 并接入 OpenClaw Discord 频道
架构概览
Discord #qwen 频道
↓ 消息
OpenClaw Gateway (VPS)
↓ binding 路由到 qwen agent
↓ Ollama 原生 API
Mac mini M4 (Tailscale)
↓ Ollama → qwen3:14b
↑ 响应
Discord #qwen 频道
核心组件:
- OpenClaw Gateway:运行在 VPS 上,处理 Discord 消息路由
- Ollama:运行在 Mac mini M4 上,提供本地 LLM 推理
- Tailscale:VPN 组网,让 VPS 能安全访问 Mac mini
前置条件
- OpenClaw Gateway 已部署(本文基于 v2026.2.26+)
- 一台 Apple Silicon Mac(本文用 M4 16GB)
- Tailscale 组网完成(或其他内网穿透方案)
- Discord Bot 已配置
第一步:Mac mini 安装 Ollama
# 安装 Ollama
curl -fsSL https://ollama.com/install.sh | sh
# 或 macOS 直接下载 App: https://ollama.com/download
# 下载模型
ollama pull qwen3:14b # 9.3GB,Q4_K_M 量化
模型选择建议
| 内存 | 推荐模型 | 大小 | 速度 |
|---|---|---|---|
| 8GB | qwen3:8b | 5.2GB | ~20 tok/s |
| 16GB | qwen3:14b | 9.3GB | ~11 tok/s |
| 32GB | qwen3:32b | 20GB | ~8 tok/s |
经验法则:模型大小不超过总内存的 75%(留 4GB 给系统)。
开放外部访问
Ollama 默认只监听 127.0.0.1,需要改为 0.0.0.0:
# macOS(App 方式安装)
launchctl setenv OLLAMA_HOST 0.0.0.0
# 然后重启 Ollama App
# Linux
sudo systemctl edit ollama
# 添加: Environment="OLLAMA_HOST=0.0.0.0"
# 然后: sudo systemctl restart ollama
⚠️ macOS 的 launchctl setenv 重启后失效,需要加到 ~/.zshrc 或配置 launchd plist 持久化。
验证:
# 从另一台机器测试
curl http://<mac-ip>:11434/api/tags
第二步:OpenClaw 配置
编辑 ~/.openclaw/openclaw.json,需要配置三个部分:
2.1 添加 Ollama Provider
在 models.providers 中添加:
{
"models": {
"providers": {
"ollama": {
"baseUrl": "http://<mac-tailscale-ip>:11434",
"apiKey": "ollama",
"models": [
{
"id": "qwen3:14b",
"name": "Qwen3 14B",
"reasoning": false,
"input": ["text"],
"contextWindow": 8192,
"maxTokens": 2048,
"cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 }
}
]
}
}
}
}
关键参数说明:
| 参数 | 说明 | 踩坑经验 |
|---|---|---|
| `baseUrl` | **不带 `/v1` 后缀**!OpenClaw 用原生 Ollama API (`/api/chat`),不是 OpenAI 兼容接口 | 带 `/v1` 会被自动 strip |
| `apiKey` | 填 `"ollama"` 即可(Ollama 不需要认证) | 不能留空 |
| `contextWindow` | 控制 Ollama 的 `num_ctx` 参数 | **这是最关键的性能参数**,见下文 |
| `reasoning` | 设 `false` 关闭 thinking 模式 | Qwen3 默认开启 thinking,会消耗大量 token |
2.2 创建 Agent
在 agents.list 中添加:
{
"agents": {
"list": [
{
"id": "qwen",
"workspace": "/path/to/lightweight/workspace",
"model": "ollama/qwen3:14b"
}
]
}
}
⚠️ workspace 必须用独立的轻量目录!
OpenClaw 会把 workspace 下的 AGENTS.md、SOUL.md、USER.md、MEMORY.md、TOOLS.md 等全部注入 system prompt。主 workspace 的这些文件加起来可能有 30-50KB。加上 OpenClaw 框架自带的 system prompt(~25KB),总 prompt 轻松超过 6000 tokens。
对于 14B 模型 + 8K 上下文,留给用户对话的空间就所剩无几了。
推荐做法:
mkdir -p ~/clawd/agents/qwen
cat > ~/clawd/agents/qwen/AGENTS.md << 'EOF'
# Qwen3 14B
你是一个聊天助手,用中文回复。
EOF
2.3 配置 Discord 频道绑定
三步缺一不可:
① 创建 Discord 频道
在 Discord 服务器中创建频道(如 #qwen),记下频道 ID。
② 添加 Binding
在 bindings 数组中添加(放在通配 binding 之前):
{
"bindings": [
{
"agentId": "qwen",
"match": {
"channel": "discord",
"peer": {
"kind": "channel",
"id": "<频道ID>"
}
}
},
// ... 其他 bindings(通配的 main binding 放最后)
{ "agentId": "main", "match": { "channel": "discord" } }
]
}
③ 频道加入白名单(最容易遗漏!)
如果 Discord 配置了 groupPolicy: "allowlist",必须把新频道加到 guild 的 channels 白名单:
{
"channels": {
"discord": {
"groupPolicy": "allowlist",
"guilds": {
"<guild-id>": {
"channels": {
"<频道ID>": { "allow": true }
}
}
}
}
}
}
这是最常见的遗漏点。不在白名单里的频道消息会被静默忽略或 fallback 到 main agent,不会有任何报错日志。
2.4 重启 Gateway
openclaw gateway restart
第三步:性能调优
contextWindow 是性能关键
Ollama 的 num_ctx(由 OpenClaw 的 contextWindow 控制)直接决定 KV cache 大小,对性能影响巨大:
| num_ctx | 首次响应时间 | 内存占用 | 适用场景 |
|---|---|---|---|
| 4096 | ~14s | ~10GB | 简单问答 |
| 8192 | ~15s | ~11GB | 日常对话(推荐) |
| 32768 | ~40s | ~14GB | 长文分析(16GB 内存勉强) |
M4 16GB 推荐 8192。32K 虽然模型支持,但 KV cache 分配太慢,而且 OpenClaw 框架 system prompt 就占了约 6000 tokens,实际可用空间有限。
关闭 Thinking 模式
Qwen3 默认开启 thinking(内部推理),会额外消耗 token 和时间。在 model 配置中设 "reasoning": false,OpenClaw 会传 thinking=off。
但注意:Ollama 原生 API 对 thinking 的控制可能不完全生效,Qwen3 仍可能在内部 think。如果需要彻底关闭,可以在 system prompt 中加 /no_think。
防止 Mac 休眠
Mac mini 作为服务器必须禁止休眠:
sudo pmset -a sleep 0 displaysleep 0 disksleep 0
排查指南
消息没有路由到 Ollama agent
症状:在频道发消息,bot 用主模型(如 Claude)回复,或不回复。
排查步骤:
# 1. 检查日志中的路由信息
journalctl --user -u openclaw-gateway --since "1 min ago" | grep "agent:qwen"
# 2. 如果没有 qwen 相关日志,检查频道白名单
# 看 channels.discord.guilds.<guildId>.channels 里有没有你的频道 ID
# 3. 如果有路由但用了 main agent,检查 binding 顺序
# 确保频道特定的 binding 在通配 binding 之前
路由成功但无回复
症状:日志显示 provider=ollama model=qwen3:14b,agent start 后无后续。
排查步骤:
# 1. 测试 Ollama 连通性
curl http://<mac-ip>:11434/api/tags
# 2. 测试实际推理
curl http://<mac-ip>:11434/api/chat \
-d '{"model":"qwen3:14b","messages":[{"role":"user","content":"hello"}],"stream":false}'
# 3. 检查 Ollama 当前状态
curl http://<mac-ip>:11434/api/ps
# 4. 如果超时,减小 contextWindow
# contextWindow: 32768 → 8192
回复极慢
原因:num_ctx 太大,KV cache 分配耗时。
解决:减小 contextWindow(model 配置里),8192 是 16GB 机器的甜点。
完整配置示例
{
"models": {
"providers": {
"ollama": {
"baseUrl": "http://100.94.140.76:11434",
"apiKey": "ollama",
"models": [{
"id": "qwen3:14b",
"name": "Qwen3 14B",
"reasoning": false,
"input": ["text"],
"contextWindow": 8192,
"maxTokens": 2048,
"cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 }
}]
}
}
},
"agents": {
"list": [{
"id": "qwen",
"workspace": "/home/user/agents/qwen",
"model": "ollama/qwen3:14b"
}]
},
"bindings": [
{
"agentId": "qwen",
"match": {
"channel": "discord",
"peer": { "kind": "channel", "id": "CHANNEL_ID" }
}
}
],
"channels": {
"discord": {
"guilds": {
"GUILD_ID": {
"channels": {
"CHANNEL_ID": { "allow": true }
}
}
}
}
}
}
踩坑总结
| 坑 | 现象 | 原因 | 解决 |
|---|---|---|---|
| 频道白名单 | 消息被 main agent 处理 | `groupPolicy: allowlist` 但频道未加入 | 添加到 guilds.channels |
| API 类型 | 连接失败 | 用了 `openai-completions` 而非原生 ollama | provider 名用 `ollama`,不设 `api` 字段 |
| baseUrl 后缀 | 请求 404 | 带了 `/v1` | 去掉,OpenClaw 自动处理 |
| contextWindow 过大 | 请求超时/40s+ 延迟 | num_ctx=32768 KV cache 分配慢 | 改为 8192 |
| workspace 太重 | prompt 超出上下文 | 共享主 workspace 的大文件 | 独立轻量 workspace |
| Ollama 只监听本地 | VPS 连不上 | 默认 127.0.0.1 | 设 OLLAMA_HOST=0.0.0.0 |
| Mac 休眠 | 间歇性断连 | 默认休眠策略 | pmset 禁止休眠 |
适用场景
本地 Ollama + OpenClaw 适合:
- 隐私敏感场景:数据不出本地网络
- 零成本推理:无 API 费用
- 实验/学习:快速测试不同模型
- 离线可用:不依赖外部 API
不太适合:
- 高并发:本地模型一次只能处理一个请求
- 复杂 agent 任务:14B 模型 + 8K 上下文限制了工具调用和长对话
- 低延迟要求:首 token 延迟 5-15s,远慢于云端 API
实测环境:Mac mini M4 16GB + Ollama 0.17.7 + Qwen3:14b Q4_K_M + OpenClaw v2026.2.26
作者:托尼 | 2026-03-08