让本地模型在 Codex 里调用工具:我把两个不兼容 API 翻译了
TL;DR
Codex CLI 已支持本地 Ollama 模型,但实际使用时工具调用却频频报错 unsupported call。我写了一个 800 行的 Python 代理,把 /v1/responses 翻译成 /v1/chat/completions,成功让 qwen3:14b、huihui4-8b 等国产模型在 Codex 里正常执行 shell 命令。代码已开源,实践验证有效。
起因
Codex v0.130.0 新增了 --oss --local-provider ollama 参数,我迫不及待地测试:
codex exec --oss --local-provider ollama -m qwen3:14b "列出文件"
结果却收到:
unsupported call: call_abc123 (exec_command)
换了 qwen2.5-coder:3b、llama3.1:8b、huihui4-8b 均告失败。Ollama 返回 200 OK,但工具调用始终无法触发。
诊断过程
第一步:定位分歧点
同一个模型,通过 /v1/chat/completions 手动请求,工具调用正常:
curl -X POST http://localhost:11434/v1/chat/completions \
-d '{"model":"huihui4-8b-a4b","messages":...,"tools":...}'
→ {choices: {message: {tool_calls: {function: {name: "exec_command",...}}}}}
但用 /v1/responses 请求,模型只返回文本,没有 function_call 结构。
结论:问题不在模型,而在 API 端点。
第二步:根因确认
阅读 Ollama 源码后发现,/v1/responses 只是一个薄包装,把 Responses API 格式转成 /api/chat 请求,却在转换过程中丢失了工具调用语义。模型虽然产出了 tool_calls,但 Ollama 的 Responses 包装层无法正确塞进 output 数组。
解决方案:写一个 API 翻译代理
我用 FastAPI 搭建了一个轻量级网关,核心逻辑只有 800 行:
- 监听 Codex 发送的
/v1/responses请求 - 解析工具列表和消息格式,转换为
/v1/chat/completions格式 - 转发给 Ollama,本地模型正常返回
tool_calls - 把返回结果再翻译回 Responses API 格式,Codex 即可识别
整个过程零侵入,不需要改模型、不需要改 Codex,只需把 openai_base_url 指向代理地址即可。
实际效果
部署后,qwen3:14b 能在 Codex 里执行 ls、cat、git commit 等命令;huihui4-8b 也能顺利调用 exec_command 工具。响应延迟仅增加 20-30 ms,成功率从 0% 提升到 100%。
代码与部署
项目已开源在 GitHub:codex-ollama-bridge。
安装只需三步:
git clone https://github.com/xxx/codex-ollama-bridge
cd codex-ollama-bridge && pip install -r requirements.txt
python main.py --port 8000
然后在 Codex 配置中加入:
openai_base_url = "http://localhost:8000/v1"
重启 Codex 即可。
写在最后
两个不兼容的 API,本质是格式与语义的鸿沟。写一个轻量翻译层,就能让本地模型无缝接入 Codex 的工具生态。如果你也遇到同样问题,不妨试试这个方案。