🦞 OpenClaw 部署填坑记(续):从 404 到丝滑对话,我到底改了什么?

2 阅读4分钟

这是 OpenClaw 部署系列的第二篇。上一篇我记录了从零开始安装、配置局域网访问的全过程。本以为大功告成,结果模型调用始终返回 404。折腾了一整天,最后发现只是少了一个 /v1。这篇文章记录这个“致命细节”的发现过程,以及最终的正确配置。


📌 前情回顾

上一篇文章里,我成功地在 Ubuntu 虚拟机里装好了 OpenClaw,配置好了网关,甚至能从局域网访问 Web 界面。但卡在了最后一步:模型调用返回 404

现象是这样的:

  • 在 Ubuntu 里直接 curl Ollama 的 OpenAI 兼容端点:✅ 成功返回 JSON
  • 在 OpenClaw 的 TUI 里发消息:❌ 一直报 HTTP 404: 404 page not found

日志里反复出现这行:

[agent/embedded] embedded run agent end: ... error=HTTP 404: 404 page not found

明明 curl 能通,OpenClaw 却调不通,说明问题出在配置细节上。


🔍 排查过程

第一步:确认 Ollama 的 OpenAI 兼容模式是否开启

我在 Windows 上用 Docker 启动 Ollama 时,已经加了环境变量:

docker run -d --gpus all `
  -v ollama:/root/.ollama `
  -p 11434:11434 `
  -e OLLAMA_HOST=0.0.0.0 `
  -e OLLAMA_OPENAI_COMPAT=1 `   # ← 这个就是关键
  --name ollama `
  ollama/ollama

用 curl 验证:

curl http://192.168.175.1:11434/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{"model": "qwen2.5:7b", "messages": [{"role": "user", "content": "hi"}]}'

返回了正常的 JSON 响应,说明 Ollama 端没问题。

第二步:检查 OpenClaw 配置

一开始我是这样配的(网上很多教程也是这么写的):

"ollama": {
  "baseUrl": "http://192.168.175.1:11434",   // ← 没有 /v1
  "api": "openai-completions",
  "models": [...]
}

直觉告诉我,OpenClaw 应该会自动拼接 /v1 吧?毕竟 api 都写的是 openai-completions

但事实是:它不会

第三步:用 curl 模拟 OpenClaw 的请求

为了确认 OpenClaw 到底在请求什么,我试着直接调用 OpenClaw 的网关 API:

curl -X POST http://127.0.0.1:18789/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "ollama/qwen2.5:7b",
    "messages": [{"role": "user", "content": "hi"}]
  }'

也返回 404。说明 OpenClaw 的 API 路径根本不是 /v1/chat/completions,这个路径是给模型用的,不是给网关用的。测试方向错了。

第四步:查看网关日志,看真实请求

开启 debug 日志:

export OPENCLAW_LOG_LEVEL=debug
systemctl --user restart openclaw-gateway.service

然后在 TUI 发消息,看日志。虽然没有直接打印 URL,但结合错误信息,我推测 OpenClaw 是在 baseUrl 后面直接拼接了 OpenAI 的 API 路径。

也就是说:

  • 如果 baseUrlhttp://192.168.175.1:11434
  • OpenClaw 实际请求的是 http://192.168.175.1:11434/chat/completions(没有 /v1
  • 而 Ollama 的 OpenAI 兼容端点在 /v1/chat/completions

所以 404 的根本原因:路径对不上。

第五步:验证猜想

我直接把 baseUrl 改成包含 /v1

"ollama": {
  "baseUrl": "http://192.168.175.1:11434/v1",
  "api": "openai-completions",
  ...
}

重启网关,再发消息——通了!


✅ 最终正确配置

{
  "models": {
    "providers": {
      "ollama": {
        "baseUrl": "http://192.168.175.1:11434/v1",   // ← 必须包含 /v1
        "api": "openai-completions",
        "models": [
          {
            "id": "qwen2.5:7b",
            "name": "qwen2.5:7b",
            "contextWindow": 32000,
            "maxTokens": 8000
          }
        ]
      }
    }
  },
  "agents": {
    "defaults": {
      "model": {
        "primary": "ollama/qwen2.5:7b"
      }
    }
  }
}

💡 关键总结

组件关键点
Ollama 启动必须加 -e OLLAMA_OPENAI_COMPAT=1
OpenClaw 配置baseUrl 必须包含 /v1
验证方式直接 curl http://IP:11434/v1/chat/completions
调试手段journalctl --user -u openclaw-gateway.service -f

🎯 为什么第一篇没写对?

上一篇我写“baseUrl 不要加 /v1,OpenClaw 会自动拼接”——这个结论是错误的。感谢读者 @[你的用户名] 的反馈和验证,让我意识到这个细节的差异。

可能的原因:

  • OpenClaw 版本差异(我用的 2026.3.13 不会自动补全 /v1
  • Ollama 版本差异(某些版本可能支持路径重定向)
  • 不同 api 类型的行为不同

建议:统一在 baseUrl 中显式包含 /v1,这样最保险。


🚀 最终效果

现在,在 TUI 或 Web 界面里,我可以丝滑地和本地千问模型对话了:

> 你好,请介绍一下自己

你好!我是 Qwen,一个由阿里云开发的大型语言模型...

CPU 占用不高,GPU 跑起来温度稳定,响应速度很快。Windows 上的 Docker 容器 + Ubuntu 虚拟机里的 OpenClaw,整套架构跑通了。


📚 相关资源


希望这篇文章能帮你少踩一个坑。如果你也在折腾 OpenClaw,欢迎交流!