从去年 OpeniAI 的 Codex CLI 正式发布之后,终端里“用自然语言驱动编程”的玩法就开始被越来越多的人接受。社区里经常调侃它就是 OpenAI 的“亲儿子”,因为新模型的能力总是优先在它身上落地。可在实际项目里,很多团队并不愿意把整份代码上下文都交给某一家厂商,原因无非是成本、合规和选型自由度。于是,把 Codex 这类官方工具接到国产开源模型上,就成了一个非常实际的话题。本文就从 OpenAI 兼容 API 这个核心机制讲起,完整演示如何把 Codex CLI、OpenAI SDK 切换到通义千问 Qwen、DeepSeek 等开源模型服务上。
1. 背景与核心思路
先说结论:把 Codex CLI 切换到国产开源模型,并不需要重写工具链,也不需要自己训练模型,核心只需要改三个东西——接口地址、API Key、模型名。为什么能做到这么简单?因为主流国产大模型服务商都提供了 OpenAI 兼容接口,也就是说,原本写给https://api.openai.com/v1/chat/completions的请求,换一个base_url和api_key,就能直接请求到 Qwen 或 DeepSeek。
这个方案的收益是很明显的:
- 成本可控:开源模型的 API 定价普遍低于 OpenAI 旗舰模型,日常代码生成、单元测试编写这类高频任务,使用 Qwen 或 DeepSeek 能省下一笔不小的费用。
- 数据边界更清晰:企业内部代码往往涉及业务逻辑、数据库结构、内部工具链,团队可以按项目决定哪些上下文发送给外部模型,哪些走私有化部署。
- 选型不绑定:OpenAI 模型固然强,但团队希望保持“随时能换模型”的能力,而不是被一家厂商锁死。
- 链路不改:由于协议兼容,Codex CLI、OpenAI SDK、以及大量基于 OpenAI 协议开发的上层工具,都只需要改配置,不用改代码。
所以,本文要解决的核心问题就一句话:如何让 OpenAI 官方工具链跑在国产开源模型之上,并且跑得稳、跑得省。
文章适合正在使用或准备尝试 Codex CLI 的开发者,也适合后端团队、算法工程师和运维同学。读完你会掌握 OpenAI 兼容 API 的接入方式,能把 Codex CLI 指向 Qwen 或 DeepSeek,能用几行 Python 代码完成连通性验证,还能在出问题时快速定位是配置错了还是网络问题。
2. 环境准备与版本说明
动手之前先把环境准备好。本文示例不依赖特定操作系统,macOS、Ubuntu、Windows 都可以跑,Windows 用户更推荐使用 WSL2 来模拟 Linux 环境。
需要提前确认以下软件环境:
- Node.js 版本建议 18 及以上,Codex CLI 通过 npm 分发。
- npm 版本建议 9 及以上,过低版本可能导致包安装失败。
- Python 版本建议 3.10 及以上,用于 SDK 调用示例。
- 需要一个支持 OpenAI 兼容接口的模型服务商账号,并创建好 API Key。
先检查本机环境:
node -v npm -v python --version如果你还没有安装 Node.js 或 Python,可以去各自官网下载 LTS 版本。这里不展开安装步骤,重点是确保命令能正常执行。
关于版本问题,特别提示一句:Codex CLI 更新速度很快,配置模型供应商的方式在不同版本之间可能有差异。本文给出的配置思路在大多数较新版本中适用,但如果你手里的版本较旧,建议先升级到最新版,或者运行codex --help查看当前版本支持的参数。
npm install -g @openai/codex codex --version3. 核心概念:OpenAI 兼容 API 与模型切换原理
3.1 Chat Completions 协议是什么
OpenAI 的主流大模型接口是 Chat Completions,简单理解就是一个 HTTP 接口,客户端把模型名和消息列表发给服务端,服务端返回模型生成的内容。请求核心部分长这样:
{ "model": "qwen-plus", "messages": [ {"role": "system", "content": "你是一名资深程序员"}, {"role": "user", "content": "帮我写一个二分查找函数"} ] }返回结果中,choices[0].message.content就是模型生成出来的文本。Codex CLI 这类工具之所以能用自然语言操作代码,本质上就是不断调用这种对话补全接口,把仓库文件内容、用户指令、工具执行结果拼进上下文,再根据模型返回的内容决定下一步操作。
3.2 兼容接口为什么能“零改造”切换
当国产模型服务商实现同样的 Chat Completions 协议时,客户端代码可以完全不动,只需要替换三个配置:
base_url:服务地址,决定请求发到哪里。api_key:服务商给你分配的密钥,决定你有没有权限调用。model:模型名,决定实际使用哪个模型。
因为协议一致,工具内部根本感知不到“对面”是 OpenAI 还是 Qwen 或 DeepSeek。这就是整个迁移方案可行的根本原因。
3.3 常用服务商接入信息
下面整理了几家常见服务的接入信息,供配置时对照。注意接口地址和模型名可能会随服务商版本调整,以官方文档为准。
| 服务商 | base_url 示例 | 模型名示例 | 说明 |
|---|---|---|---|
| OpenAI | https://api.openai.com/v1 | gpt-4o-mini | 官方服务 |
| 阿里云百炼(Qwen) | https://dashscope.aliyuncs.com/compatible-mode/v1 | qwen-plus、qwen-max | 提供 OpenAI 兼容模式 |
| DeepSeek | https://api.deepseek.com/v1 | deepseek-chat、deepseek-reasoner | 官方接口支持 OpenAI 兼容 |
3.4 环境变量与配置文件的关系
很多 OpenAI 生态工具默认支持通过环境变量设置密钥和地址,例如:
OPENAI_API_KEYOPENAI_BASE_URL- 部分工具支持
OPENAI_MODEL
环境变量适合临时切换,配置文件适合长期固定。一般情况下,工具解析配置的优先级是:命令行参数优先于配置文件,配置文件优先于环境变量,环境变量优先于默认值。如果你设置了环境变量但 Codex 仍然调用默认模型,优先检查是否有配置文件覆盖了环境变量,或者当前登录方式是否走了其他认证通道。
4. 实战:把 Codex CLI 接入国产开源模型
4.1 安装 Codex CLI
确认 Node.js 环境没问题后,全局安装 Codex CLI:
npm install -g @openai/codex如果 npm 安装速度较慢,可以临时使用国内镜像源,安装完成后再恢复:
npm config set registry https://registry.npmmirror.com npm install -g @openai/codex npm config set registry https://registry.npmjs.org安装完成后,查看版本:
codex --versionCodex CLI 首次运行一般会引导登录,常见的有两种方式:ChatGPT 账号登录(OAuth)和 API Key 方式。要切换到第三方模型服务商,建议使用 API Key 方式。如果之前已经用 ChatGPT 账号登录过,配置环境变量可能不会立即生效,因为 OAuth 登录会携带官方身份信息。遇到这种情况,可以先退出当前登录状态,或者把 API Key 方式作为首选。
4.2 注册模型服务商并创建 API Key
以阿里云百炼为例,开通百炼服务后,在控制台的“API Key 管理”页面创建新的 Key。注意复制完整字符串,不要把 Key 写进代码仓库或提交到 Git。
DeepSeek 开放平台的操作类似:注册账号、完成实名认证、开通模型服务、在平台创建 API Key。Key 的权限范围一般可以限定到“仅 API 调用”,不建议用项目级密钥作为个人开发密钥。
4.3 配置 Codex 使用 Qwen 或 DeepSeek
最简单的方式是设置环境变量。以 Qwen 为例:
export OPENAI_API_KEY="sk-你的百炼APIKey" export OPENAI_BASE_URL="https://dashscope.aliyuncs.com/compatible-mode/v1" export OPENAI_MODEL="qwen-plus"如果是 DeepSeek:
export OPENAI_API_KEY="sk-你的DeepSeekAPIKey" export OPENAI_BASE_URL="https://api.deepseek.com/v1" export OPENAI_MODEL="deepseek-chat"设置完成后,直接启动 Codex:
codex "给当前目录下所有 Python 文件补充类型注解,并运行测试"如果 Codex 能正常进入任务流程,说明配置已经生效。如果仍然连接 OpenAI 官方地址,可以通过codex --help确认当前版本是否支持环境变量覆盖,或者查看配置文件的写法。
较新版本的 Codex CLI 支持通过配置文件~/.codex/config.toml声明模型供应商,配置思路类似下面这样:
model = "qwen-plus" [model_providers.dashscope] base_url = "https://dashscope.aliyuncs.com/compatible-mode/v1" api_key_env_var = "DASHSCOPE_API_KEY"export DASHSCOPE_API_KEY="sk-你的百炼APIKey" codex "实现一个函数:统计文本中出现次数最多的前五个单词"这里要再次提醒:config.toml的字段在不同版本中存在差异。如果直接使用报错,优先运行codex --help或查看官方配置文档,根据实际字段名调整。
4.4 运行验证与结果说明
配置完成后,建议先用一个最小的任务验证链路:
codex "写一个 Python 函数,判断一个字符串是否是回文,并运行验证"正常情况下,Codex 会:
- 读取当前目录文件或创建新文件;
- 编写回文判断函数和测试代码;
- 执行
python命令运行测试; - 输出运行结果或修改建议。
此时可以到模型服务商的控制台查看“调用记录”或“计量统计”,如果出现了一笔来自你账号的 Qwen 或 DeepSeek 调用记录,就说明 Codex 确实已经跑在国产开源模型上了。
5. 实战补充:用 OpenAI SDK 调用开源模型
Codex CLI 是完整产品,但在调试模型接口、写自动化脚本时,直接用 OpenAI SDK 更灵活。这一节给出可直接运行的 Python 示例。
5.1 安装 SDK
pip install openai安装完成后,先用一个最简脚本验证 SDK 能正常请求。
5.2 Qwen 对话示例
新建文件demo_qwen.py:
# 文件路径:demo_qwen.py from openai import OpenAI client = OpenAI( api_key="sk-你的百炼APIKey", base_url="https://dashscope.aliyuncs.com/compatible-mode/v1" ) response = client.chat.completions.create( model="qwen-plus", messages=[ {"role": "system", "content": "你是一个乐于解释概念的技术助手。"}, {"role": "user", "content": "请用三句话解释什么是 OpenAI 兼容 API。"} ] ) print(response.choices[0].message.content)运行:
python demo_qwen.py预期输出是一段关于 OpenAI 兼容 API 的中文解释。如果控制台出现 404 或 401 错误,优先检查模型名和 API Key。
5.3 DeepSeek 对话示例
DeepSeek 的接入方式和 Qwen 几乎一致,只是base_url和model不同。新建文件demo_deepseek.py:
# 文件路径:demo_deepseek.py from openai import OpenAI client = OpenAI( api_key="sk-你的DeepSeekAPIKey", base_url="https://api.deepseek.com/v1", ) response = client.chat.completions.create( model="deepseek-chat", messages=[ {"role": "system", "content": "你是代码审查助手。"}, {"role": "user", "content": "下面的代码有什么问题?\n\nif x = 1:\n print(x)"} ] ) print(response.choices[0].message.content)这个示例既验证了 DeepSeek 的连通性,也展示了一个真实使用场景:让模型审查有明显语法错误的代码。注意 Python 中if x = 1:是语法错误,正确写法是if x == 1:,模型应当能指出这一点。
5.4 流式输出示例
Codex CLI 在做代码生成时,体验更像“打字机”,靠的是流式接口。下面是一个 Qwen 流式输出示例:
# 文件路径:demo_stream.py from openai import OpenAI client = OpenAI( api_key="sk-你的百炼APIKey", base_url="https://dashscope.aliyuncs.com/compatible-mode/v1" ) stream = client.chat.completions.create( model="qwen-plus", messages=[ {"role": "user", "content": "用 Python 写一个快速排序函数,并解释思路。"} ], stream=True, ) for chunk in stream: delta = chunk.choices[0].delta if delta and delta.content: print(delta.content, end="", flush=True)6. 常见问题与排查思路
6.1 高频报错速查表
| 问题现象 | 常见原因 | 解决思路 |
|---|---|---|
| 401 authentication error | API Key 未设置或填写错误 | 检查环境变量是否生效,复制完整 Key |
| 404 model not found | 模型名不存在或未开通 | 到服务商控制台确认模型名和开通状态 |
| 429 rate limit exceeded | 请求频率超过限制或余额不足 | 检查控制台配额,调低并发或充值 |
| 502 Bad Gateway | 服务商服务不稳定 | 稍后重试,查看服务商状态页 |
| Codex 仍然调用 OpenAI 模型 | 配置未生效或 OAuth 登录优先 | 退出 ChatGPT 登录,确认只使用 API Key 方式 |
| 响应内容被截断 | max_tokens设置过小 | 调大max_tokens或上下文窗口 |
| 流式输出中断 | 网络不稳定,请求超时 | 缩短单次请求长度,或改为非流式重试 |
6.2 关键排查步骤
步骤一,确认环境变量真实值:
echo $OPENAI_BASE_URL echo $OPENAI_MODEL步骤二,用 curl 直接测试接口连通性。以 DeepSeek 为例:
curl https://api.deepseek.com/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sk-你的DeepSeekAPIKey" \ -d '{ "model": "deepseek-chat", "messages": [{"role": "user", "content": "hi"}] }'如果 curl 能返回正常 JSON,说明网络和密钥都没问题,问题大概率出在工具配置上。
步骤三,检查 Codex 登录方式。如果你之前用 ChatGPT 账号登录过 Codex,第三方模型配置可能不会生效。优先使用 API Key 方式,并确保环境变量在 Codex 启动前已经设置。
7. 最佳实践与工程建议
7.1 密钥与配置管理
API Key 是敏感信息,不要写进代码仓库、不要写在config.toml的明文里。推荐用环境变量或密钥管理服务统一管理。CI 或生产环境单独创建专用 Key,避免个人 Key 被其他成员误用。定期轮换 Key,离职人员对应的 Key 要及时删除。
7.2 模型选型与成本控制
日常代码补全、写单元测试、解释报错,可以用qwen-plus或deepseek-chat这类性价比更高的模型。复杂重构、跨文件分析、架构设计类任务,再用qwen-max或deepseek-reasoner。建议在服务商控制台设置月度预算、配额和用量告警,避免某个任务因循环调用产生意外费用。
7.3 安全边界与回退策略
把代码发到外部模型服务之前,先做数据分级。涉及核心密钥、客户数据、内部系统拓扑的代码,不要直接发送给第三方 API。企业项目建议先和法务、安全团队确认合规要求。
同时要保留回退能力。第三方模型服务可能因为流量高峰、限流、故障而变慢,核心工作流可以保留 OpenAI 官方模型作为备用,或者准备两家开源模型服务,按“主用 + 备用”的方式切换,这样单点故障不会阻塞开发。
8. 总结与下一步
本文围绕“把 OpenAI 官方工具链接到国产开源模型”这个目标,讲了三个关键点:OpenAI 兼容 API 的原理、Codex CLI 的配置方式、OpenAI SDK 的调用示例。有了这套链路,你的 Codex 不再只能连 OpenAI,也可以随时指向 Qwen、DeepSeek 或其他兼容服务。模型变了,工具链不变。
下一步可以继续研究几个方向:一是函数调用(Function Calling),让开源模型也能触发本地工具;二是长上下文模型,比如qwen-long处理超大仓库;三是本地私有化部署,利用 Ollama 或 vLLM 把开源模型完全放在公司内网,真正做到数据不出域。
动手实践永远比看文章更快。建议你现在就注册一个模型服务商的账号,申请一个最便宜的 API Key,先跑通“Codex + Qwen”的最小链路,再慢慢加入真实项目任务。遇到报错不要慌,按第 6 节的排查顺序过一遍,大多数问题都出在 Key、模型名和登录方式这三个地方。