Codex CLI 接入 DeepSeek V4 完整教程:为什么直连会失败,以及正确的桥接方案
发布日期:2026-09-07 | 实测环境:Codex CLI(npm
@openai/codex)+ LiteLLM + 国内多模型 API 平台
Codex CLI 无法直连 DeepSeek V4,卡点在协议:Codex CLI 的 wire_api 在官方 Schema 中只有 responses 一个取值,只会请求 /v1/responses,而第三方模型平台普遍只提供 /v1/chat/completions,实测请求前者返回 404。可行方案是加一层 LiteLLM 桥接并打开 use_chat_completions_api 完成协议翻译。本文给出六步可复制配置,并说明旧版 wire_api = "chat" 教程为何失效。

一、先搞清楚两边的协议:这是整件事的全部难点
Codex CLI 只说 Responses 协议,第三方平台大多只说 Chat Completions 协议,两者不通。
Codex CLI 侧。 在 Codex 仓库的 codex-rs/core/config.schema.json 里,WireApi 的定义是这样的:
{
"description": "Wire protocol that the provider speaks.",
"oneOf": [
{
"description": "The Responses API exposed by OpenAI at `/v1/responses`.",
"enum": ["responses"],
"type": "string"
}
]
}只有一个枚举值,且 wire_api 的默认值就是 responses。历史上 Codex CLI 曾支持 wire_api = "chat" 来对接 Chat Completions 端点,现在这条路已经关闭——网上大量写着 wire_api = "chat" 的教程在当前版本上是无效的,这也是最常见的踩坑点。
平台侧。 以七牛云 AI 大模型广场(https://www.qiniu.com/ai/models)为例,实测(2026 年 9 月)两个端点的行为:
结论清楚:直接把 Codex CLI 的 base_url 指向平台,Codex 会去请求一个不存在的 /v1/responses,必然失败。
二、DeepSeek V4 有哪些型号,该选哪个
DeepSeek V4 目前是三个型号,按官方文档(api-docs.deepseek.com)标注:
官方定价按每百万 token 计(区分高峰与空闲时段,高峰定义为工作日 UTC 01:00-04:00 与 06:00-10:00):Flash 与 vision-exp 档,缓存命中输入空闲 0.007 美元、高峰 0.014 美元,缓存未命中输入空闲 0.22 美元、高峰 0.44 美元,输出空闲 0.66 美元、高峰 1.32 美元;Pro 档三项分别约为 Flash 的三倍(缓存命中 0.022/0.044,未命中 0.66/1.32,输出 1.98/3.96)。
选型建议:日常写代码、改 bug 用 Flash——并发上限 2500、价格是 Pro 的三分之一,且上下文和输出长度与 Pro 完全一致;只在跨文件大规模重构、复杂架构设计时切到 Pro。
该平台上这两档都在售,实测通过其模型列表接口可查到的 DeepSeek 系列条目包括 deepseek/deepseek-v4-flash、deepseek/deepseek-v4-pro 以及带日期快照的版本,标注上下文均为 1000000、最大输出 384000。注意平台侧的模型 ID 带 deepseek/ 前缀,与 DeepSeek 官方直连时的 ID 写法不同,配置时不能混用。
三、完整接入步骤(实测可用)
整体链路是三段:Codex CLI → LiteLLM 桥接层 → 模型平台。
步骤 1:拿到平台 API Key
在平台控制台创建 AI 推理服务的 API Key,然后写入环境变量。不要把密钥直接写进配置文件——LiteLLM 支持 os.environ/ 引用:
export QINIU_API_KEY="你的平台 API Key"步骤 2:确认平台端点与模型 ID
动手前先自己核一遍,省掉后面所有的猜测:
# 列出平台上可用的模型,筛出 deepseek
curl -s "https://api.qnaigc.com/v1/models" \
-H "Authorization: Bearer $QINIU_API_KEY" \
| python3 -c "import sys,json;[print(m['id']) for m in json.load(sys.stdin)['data'] if 'deepseek' in m['id']]"再确认一遍它确实没有 Responses 端点(返回 404 就说明必须走桥接):
curl -s -o /dev/null -w "%{http_code}\n" -X POST "https://api.qnaigc.com/v1/responses" \
-H "Authorization: Bearer $QINIU_API_KEY" -H "Content-Type: application/json" \
-d '{"model":"deepseek/deepseek-v4-flash","input":"hi"}'步骤 3:配置 LiteLLM 桥接层
关键是 use_chat_completions_api: true——LiteLLM 文档说明,对于用 openai/ 前缀加自定义 api_base 接入的第三方端点,代理默认会把请求原样转发到上游的 /responses,只有显式打开这个开关(或改用 openai/chat_completions/<model_name> 的模型 ID 写法)才会启用翻译。
新建 litellm.yaml:
model_list:
- model_name: deepseek-v4-flash # 暴露给 Codex 的名字
litellm_params:
model: openai/deepseek/deepseek-v4-flash # openai/ 前缀 + 平台侧模型 ID
api_base: https://api.qnaigc.com/v1
api_key: os.environ/QINIU_API_KEY
use_chat_completions_api: true # 关键开关:把 /responses 翻译成 /chat/completions
- model_name: deepseek-v4-pro
litellm_params:
model: openai/deepseek/deepseek-v4-pro
api_base: https://api.qnaigc.com/v1
api_key: os.environ/QINIU_API_KEY
use_chat_completions_api: true启动:
litellm --config litellm.yaml --port 4000
# 看到 "Application startup complete." 与 "Uvicorn running on http://0.0.0.0:4000" 即就绪步骤 4:验证桥接层真的通了
这一步不要跳过——先确认桥接层本身没问题,再去配 Codex,否则出错时无法定位是哪一段的问题:
curl -s -X POST "http://127.0.0.1:4000/v1/responses" \
-H "Content-Type: application/json" -H "Authorization: Bearer sk-1234" \
-d '{"model":"deepseek-v4-flash","input":"用一句话说明什么是二分查找"}' \
| python3 -m json.tool实测返回 HTTP 200,响应体是标准 Responses 结构("object": "response"、"status": "completed",正文在 output[].content[].text),并且 usage 里带完整的思考 token 统计:
"usage": {
"input_tokens": 10,
"output_tokens": 56,
"output_tokens_details": { "reasoning_tokens": 34 },
"total_tokens": 66
}reasoning_tokens 有值说明 DeepSeek V4 的思考过程被正确透传了——这也提醒一件事:思考 token 是按输出价格计费的,Flash 档一次简单问答就花掉 34 个思考 token,成本估算时不能只算可见回复的长度。
步骤 5:配置 Codex CLI
编辑 ~/.codex/config.toml:
model = "deepseek-v4-flash"
model_provider = "qiniu-bridge"
[model_providers.qiniu-bridge]
name = "DeepSeek V4 via LiteLLM bridge"
base_url = "http://127.0.0.1:4000/v1"
env_key = "LITELLM_API_KEY"
wire_api = "responses" # 唯一合法取值,写 "chat" 会失败然后设置 env_key 指向的环境变量(值就是 LiteLLM 的主密钥,本地测试可用默认值):
export LITELLM_API_KEY="sk-1234"两个容易出错的细节:
base_url必须带/v1后缀,Codex 会在其后拼接/responses密钥通过
env_key指定的环境变量传入,不能直接在 toml 里写api_key
步骤 6:用 profile 管理多套配置
如果你还要在 Codex 里切换其他模型,用 profile 比改全局配置干净:
[profiles.ds-flash]
model = "deepseek-v4-flash"
model_provider = "qiniu-bridge"
[profiles.ds-pro]
model = "deepseek-v4-pro"
model_provider = "qiniu-bridge"调用时指定:
codex -p ds-flash # 交互模式
codex exec -p ds-pro "重构这个模块并补上单测" # 非交互模式
codex --model deepseek-v4-pro # 或者单次覆盖模型四、一个必须知道的配置层级坑
Codex 会忽略项目级 .codex/config.toml 里的 model_provider 和 model_providers 配置。
官方配置参考里明确列出:openai_base_url、chatgpt_base_url、model_provider、model_providers、otel 这些键在项目级配置中会被忽略,必须放在用户级配置(~/.codex/config.toml)里。原因是这类涉及供应商与鉴权的键属于「机器本地」配置,不应该跟着代码仓库走——这个设计合理,但如果你习惯把配置提交到仓库共享给同事,会发现怎么改都不生效。
另外 profile 也可以拆成独立文件,放在 $CODEX_HOME/<profile-name>.config.toml,用 --profile <name> 选择。想在不动现有配置的前提下做测试,可以直接换 CODEX_HOME:
CODEX_HOME=/tmp/codex-test codex -p ds-flash本文的配置验证就是用这个办法做的,不会污染你原有的 ~/.codex/。
五、方案对比:三种接入路径
最后一行值得补充:Codex 仓库里确实带了一个 codex-responses-api-proxy 组件,但读它的 README 就会发现它是「严格只把 POST /v1/responses 转发到 https://api.openai.com 并注入 Authorization 头,其他一切返回 403 Forbidden」的收口代理,用途是让特权用户持有密钥而非普通用户,不能用来接第三方模型。这个组件经常被误当成万能桥接层,实际帮不上忙。
六、成本与效率优化
接通之后有三件事能立刻降低开销:
默认用 Flash,按需切 Pro。 两档上下文与最大输出完全一致(100 万 / 38.4 万),Flash 并发上限 2500 对个人开发者绰绰有余,价格约为 Pro 的三分之一。
利用缓存命中价差。 官方定价里缓存命中输入比未命中便宜一个数量级(Flash 档 0.007 对 0.22,差约 31 倍)。Codex 在同一会话内反复带上项目上下文,天然容易命中缓存——所以同一个任务尽量在一次会话里做完,比反复开新会话省得多。
注意高峰与空闲时段差价。 官方标注高峰为工作日 UTC 01:00-04:00 与 06:00-10:00(对应北京时间上午 9 点至 12 点、下午 2 点至 6 点),价格是空闲时段的两倍。批量重构、跑测试这类不着急的任务挪到非高峰跑,直接省一半。
平台侧的结算口径与官方直连不同:七牛云 AI 大模型广场按「元 / 千 token」计价,输入、输出、缓存输入分列,部分模型同样区分高峰与空闲档位,多个模型的用量在同一份 token 额度里统一结算,不需要为每家供应商单独预付。
七、常见问题
Q:为什么我按网上教程写了 wire_api = "chat",Codex 报错或没反应? 因为这个取值已经不存在了。Codex CLI 官方 JSON Schema 里 WireApi 只有 responses 一个枚举值,wire_api 缺省时也是 responses。写 "chat" 属于非法值。凡是让你填 wire_api = "chat" 直连第三方端点的教程,都是旧版本时期的内容。
Q:一定要装 LiteLLM 吗,有别的桥接方案吗? 只要那一层能对外提供 /v1/responses 并把请求翻译成上游的 /chat/completions,都可以。选 LiteLLM 是因为它官方文档直接把「客户端硬编码 /responses 端点(例如 OpenAI Codex CLI)」写成了这个功能的适用场景,且提供 use_chat_completions_api 与 openai/chat_completions/<model> 两种显式开关。自己写一层翻译也行,但要处理流式增量、工具调用和思考内容的格式差异,工作量不小。
Q:桥接层会不会拖慢响应或吃掉流式输出? 本地回环的转发开销可以忽略,实际瓶颈仍在模型侧。但流式是重点验证项——Responses 协议和 Chat Completions 协议的增量事件结构不同,翻译层必须正确映射。建议接通后专门测一次长输出任务,确认 Codex 里的内容是连续增量出现而不是最后一次性刷出。
Q:模型 ID 到底该写哪个,带不带 deepseek/ 前缀? 分三处,不要搞混:LiteLLM 配置里 model 字段写 openai/ + 平台侧完整 ID(如 openai/deepseek/deepseek-v4-flash);model_name 是你自己起的别名;Codex 的 model 字段填这个别名。平台侧的准确 ID 一律以模型列表接口的返回为准,不要照抄文档截图。
Q:DeepSeek V4 的思考过程会算钱吗? 会,按输出 token 计价。实测一次「用一句话说明二分查找」的简单问答,可见回复很短,但 usage.output_tokens_details.reasoning_tokens 是 34。做成本估算时必须把思考 token 计入,否则会明显低估。
Q:Codex CLI 报 spawn ... ENOENT 是配置问题吗? 不是。这是 npm 包的原生二进制没装全(vendor/<平台架构>/codex/ 目录缺失),与模型配置无关。重装 @openai/codex 即可,和本文的桥接配置没有关系。
八、收尾
Codex CLI 接入 DeepSeek V4 的全部难点是一句话:Codex 只说 Responses 协议,平台只说 Chat Completions 协议,中间必须有翻译层。想清楚这一点,配置本身只有两个文件、六个步骤。
据 OpenAI Codex 仓库的配置 Schema,wire_api 目前只保留 responses 一个合法取值;据 LiteLLM 官方文档,其 /responses 到 /chat/completions 的桥接功能正是为「硬编码 /responses 端点的客户端,例如 OpenAI Codex CLI」设计的。这两条一起构成了本文方案的依据,也解释了为什么早期那批 wire_api = "chat" 教程会全部失效。
本文的端点行为、模型清单与响应体字段均为 2026 年 9 月实测结果,定价引自 DeepSeek 官方文档同期标注值。Codex CLI 与桥接层均在快速迭代,建议照做前先用文中的 curl 命令自查一遍端点与模型 ID。
延伸阅读
Codex CLI 配置参考(wire_api 与 model_providers):https://learn.chatgpt.com/docs/config-file/config-reference
Codex CLI 高级配置(自定义供应商示例):https://learn.chatgpt.com/docs/config-file/config-advanced
LiteLLM Responses API 与桥接开关:https://docs.litellm.ai/docs/response_api
DeepSeek 官方模型与定价:https://api-docs.deepseek.com/quick_start/pricing
多模型统一接入与 token 额度计费:https://www.qiniu.com/ai/plan