无需CC Switch:本地代理实现Codex CLI与DeepSeek API协议桥接

发布时间:2026/7/22 3:14:53
无需CC Switch:本地代理实现Codex CLI与DeepSeek API协议桥接 如果你正在尝试将 Codex CLI 接入 DeepSeek 等国产大模型大概率已经遇到了两个“拦路虎”一是找不到 CC Switch 或 Codex 的官方下载渠道二是即使找到了也可能因为网络问题无法顺利安装或更新。这篇文章要解决的问题很直接在不依赖良好网络、无需下载 CC Switch 或 Codex 的情况下如何让 Codex CLI 稳定地使用 DeepSeek 的 API。核心思路是绕开复杂的第三方客户端直接通过本地代理路由的方式让 Codex 的 OpenAI Responses API 协议与 DeepSeek 的 OpenAI Chat Completions API 协议“握手成功”。这种方法本质上是在本地搭建一个轻量的协议转换层它不依赖任何特定的 GUI 工具只需要一个能运行 Python 脚本的环境。整个过程对硬件几乎没有特殊要求不依赖 GPU普通 CPU 和 2GB 左右的内存即可运行重点在于配置的正确性。本文将带你完成从零开始的完整流程理解为什么需要协议转换、准备必要的环境Codex CLI 和 DeepSeek API Key、编写并启动一个简易的本地路由代理、最后在 Codex 中完成配置和测试。你会得到一个完全由自己控制、部署在本地的“平替方案”彻底解决下载和网络依赖问题。1. 核心能力速览在深入操作之前我们先通过一个表格快速了解这个方案的核心特性和你需要准备什么。能力项说明与要求核心功能实现 Codex CLI 与 DeepSeek Chat API 的协议桥接使 Codex 能直接调用 DeepSeek。技术原理在本地启动一个 HTTP 代理服务将 Codex 发出的Responses API请求实时转换为 DeepSeek 接受的Chat Completions API请求并反向转换响应。硬件门槛极低。纯 CPU 推理无需 GPU。普通电脑即可内存占用约 100-200 MB。网络要求仅需能访问 DeepSeek 官方 API 域名 (api.deepseek.com)。代理服务本身在本地运行无需下载海外资源。依赖工具1.Codex CLI(必须)2.Python 3.8环境 (必须)3.DeepSeek API Key(必须)是否需下载 CC Switch/Codex完全不需要。本方案使用自建 Python 脚本实现路由功能。启动方式通过命令行运行一个 Python 脚本常驻后台。配置复杂度中等。需要手动修改一次 Codex 的配置文件 (config.toml)。稳定性高。服务运行在本地无第三方客户端的不确定性连接稳定性取决于本地网络到 DeepSeek API 的质量。适合场景希望使用 Codex CLI 但受限于网络无法使用官方服务或第三方客户端的开发者希望完全掌控代理流程的用户。2. 为什么需要本地路由协议冲突详解Codex CLI 在设计上默认对接的是 OpenAI 的Responses API。这是一种较新的、为 AI 助手交互优化的流式 API 协议。而 DeepSeek、Kimi、智谱AI等国内大部分提供 OpenAI 兼容接口的服务商目前普遍支持的是更早、更通用的Chat Completions API协议。这两种协议在请求体结构、响应格式、尤其是流式传输Server-Sent Events, SSE的事件字段上存在差异。如果你直接将 DeepSeek 的 Chat 端点如https://api.deepseek.com/chat/completions填到 Codex 的配置里最常见的结果就是Codex 无法正确解析返回的模型列表导致/model命令失效或者发起请求后收到404、400错误又或者流式响应在 Codex 界面中显示乱码或直接中断。因此我们需要一个“翻译官”——本地路由代理。它的工作流程非常清晰监听在本地如127.0.0.1:15721启动一个 HTTP 服务。转换请求当 Codex 向http://127.0.0.1:15721/v1/responses发送请求时代理将其拦截把Responses格式的请求体转换为Chat Completions格式然后转发给真正的 DeepSeek API (https://api.deepseek.com/chat/completions)。转换响应收到 DeepSeek 的Chat Completions格式响应无论是 JSON 还是 SSE 流后再将其转换回Responses格式返回给 Codex。认证中转在转发请求时自动将你的 DeepSeek API Key 添加到请求头中无需在 Codex 配置里暴露密钥。这样一来Codex 以为自己一直在和标准的 OpenAI Responses API 对话而实际提供服务的是 DeepSeek。CC Switch 这类工具的核心价值就是自动化完成了上述所有步骤并提供了图形界面。而我们接下来的方案则是用代码手动实现这个核心路由逻辑。3. 环境准备与前置条件开始之前请确保你的系统满足以下条件。整个过程在 Windows (PowerShell/CMD)、macOS (Terminal) 或 Linux (Bash) 上均可进行。3.1 安装并验证 Codex CLI这是本方案的绝对前提。Codex CLI 是 Anthropic 官方提供的命令行工具。访问官方渠道通过 Anthropic 官网或可靠的开发者社区获取最新的 Codex CLI 安装指南。通常可以通过包管理器如pip、brew或直接下载二进制文件安装。运行一次安装后在终端中执行一次codex命令。这一步至关重要因为它会在你的用户目录下创建默认的配置文件~/.codex/config.tomlLinux/macOS或%USERPROFILE%\.codex\config.tomlWindows。如果这个文件不存在后续的配置将无法进行。验证安装运行codex --version或codex --help确认命令行工具可以正常响应。3.2 获取 DeepSeek API Key你需要一个有效的 DeepSeek API 密钥。访问 DeepSeek 开放平台官网。注册并登录账号。在控制台中创建一个新的 API 密钥并妥善保存。通常会有免费的试用额度。3.3 准备 Python 环境我们将使用 Python 编写代理脚本需要安装aiohttp库来处理异步 HTTP 请求。检查 Python在终端输入python --version或python3 --version确保版本在 3.8 及以上。安装依赖打开终端执行以下命令安装必要的库。pip install aiohttp如果速度慢可以使用国内镜像源例如pip install aiohttp -i https://pypi.tuna.tsinghua.edu.cn/simple4. 创建并启动本地路由代理服务这是整个方案的核心。我们将创建一个 Python 脚本deepseek_proxy.py它包含了协议转换和代理转发逻辑。4.1 编写代理脚本在你喜欢的工作目录下例如~/codex_proxy创建一个新文件deepseek_proxy.py并将以下代码复制进去。#!/usr/bin/env python3 DeepSeek API Proxy for Codex CLI. Converts OpenAI Responses API requests to/from OpenAI Chat Completions API. import asyncio import json import os from aiohttp import web, ClientSession, ClientTimeout # 配置区域请根据你的情况修改 DEEPSEEK_API_KEY sk-your-deepseek-api-key-here # 替换为你的真实 API Key DEEPSEEK_BASE_URL https://api.deepseek.com # DeepSeek API 基础地址 PROXY_HOST 127.0.0.1 # 本地代理监听地址 PROXY_PORT 15721 # 本地代理监听端口可修改 # async def convert_responses_to_chat(responses_body): 将 Codex Responses API 请求体转换为 DeepSeek Chat Completions 请求体。 # Codex Responses API 的请求结构 # DeepSeek Chat Completions API 的请求结构 # 核心映射关系 # responses_body[input] - chat_body[messages] # responses_body[model] - chat_body[model] # responses_body[stream] - chat_body[stream] chat_body { model: responses_body.get(model, deepseek-chat), messages: [], stream: responses_body.get(stream, False), temperature: responses_body.get(temperature, 0.7), max_tokens: responses_body.get(max_tokens, 2048), } # 处理输入消息。Responses API 的 input 字段通常是字符串或消息数组。 input_data responses_body.get(input, ) if isinstance(input_data, str): # 如果是字符串当作一条用户消息 chat_body[messages].append({role: user, content: input_data}) elif isinstance(input_data, list): # 如果是数组尝试转换为 Chat 的 messages 格式 for msg in input_data: # 这里需要根据实际的 Responses 消息格式进行适配以下为通用处理 if isinstance(msg, dict): role msg.get(role, user) # Responses API 可能使用 content 或 text 字段 content msg.get(content) or msg.get(text) or if content: chat_body[messages].append({role: role, content: content}) # 清理可能的空消息 chat_body[messages] [m for m in chat_body[messages] if m.get(content)] # 如果转换后消息为空添加一个默认消息防止错误 if not chat_body[messages]: chat_body[messages].append({role: user, content: Hello}) return chat_body async def convert_chat_to_responses(chat_response, stream_modeFalse): 将 DeepSeek Chat Completions 响应转换为 Codex Responses API 响应。 if stream_mode: # 流式响应需要逐行转换 SSE 事件 # 这是一个简化版实际需要处理 data: {...} 格式 # 本示例返回原样流Codex 可能兼容。更复杂的转换需参考官方协议。 return chat_response else: # 非流式 JSON 响应 try: chat_data await chat_response.json() except: # 如果响应不是 JSON可能是错误信息直接返回 return chat_response # 构建 Responses 格式的响应 responses_data { output: [], model: chat_data.get(model, ), id: chat_data.get(id, ), } choice chat_data.get(choices, [{}])[0] message choice.get(message, {}) if message: responses_data[output].append({ type: message, role: message.get(role, assistant), content: message.get(content, ), }) return web.json_response(responses_data) async def proxy_handler(request): 处理所有来自 Codex 的代理请求。 path request.path if path in [/v1/responses, /responses]: # 1. 获取 Codex 的请求数据 try: req_data await request.json() if request.can_read_body else {} except: req_data {} # 2. 转换为 DeepSeek Chat API 格式 chat_body await convert_responses_to_chat(req_data) stream_mode chat_body.get(stream, False) # 3. 准备转发到 DeepSeek headers { Authorization: fBearer {DEEPSEEK_API_KEY}, Content-Type: application/json, } deepseek_url f{DEEPSEEK_BASE_URL}/chat/completions # 4. 发起请求 timeout ClientTimeout(total60) async with ClientSession(timeouttimeout) as session: async with session.post(deepseek_url, jsonchat_body, headersheaders) as deepseek_resp: # 5. 将 DeepSeek 的响应转换后返回给 Codex response await convert_chat_to_responses(deepseek_resp, stream_mode) return response else: # 处理其他路径例如模型列表查询 (Codex 可能会请求 /v1/models) if path in [/v1/models, /models]: # 返回一个模拟的模型列表让 Codex 识别 fake_models { object: list, data: [ { id: deepseek-chat, object: model, created: 1686935000, owned_by: deepseek }, { id: deepseek-coder, object: model, created: 1686935001, owned_by: deepseek } ] } return web.json_response(fake_models) return web.Response(textfProxy active. Requested path: {path}, status200) async def health_check(request): 健康检查端点。 return web.Response(textOK) async def init_app(): 初始化 Web 应用。 app web.Application() app.router.add_post(/v1/responses, proxy_handler) app.router.add_post(/responses, proxy_handler) app.router.add_get(/v1/models, proxy_handler) app.router.add_get(/models, proxy_handler) app.router.add_get(/health, health_check) return app def main(): 启动代理服务器。 print(f[INFO] Starting DeepSeek proxy server on {PROXY_HOST}:{PROXY_PORT}) print(f[INFO] Target API: {DEEPSEEK_BASE_URL}) print([INFO] Press CtrlC to stop the server.) # 验证 API Key 是否已配置 if DEEPSEEK_API_KEY.startswith(sk-your-): print([ERROR] Please edit deepseek_proxy.py and set your real DEEPSEEK_API_KEY!) return web.run_app(init_app(), hostPROXY_HOST, portPROXY_PORT) if __name__ __main__: main()关键操作找到代码开头的配置区域。将DEEPSEEK_API_KEY sk-your-deepseek-api-key-here中的字符串替换成你从 DeepSeek 平台获取的真实 API Key。可选如果你需要使用其他端口可以修改PROXY_PORT的值但要确保不与系统其他服务冲突。4.2 启动代理服务保存文件后在终端中进入该文件所在目录运行以下命令启动代理python deepseek_proxy.py如果一切正常你将看到类似以下的输出表示代理服务已在127.0.0.1:15721运行[INFO] Starting DeepSeek proxy server on 127.0.0.1:15721 [INFO] Target API: https://api.deepseek.com [INFO] Press CtrlC to stop the server. Running on http://127.0.0.1:15721 (Press CTRLC to quit)请保持这个终端窗口打开代理服务需要持续运行。你可以最小化它。5. 配置 Codex CLI 使用本地代理现在我们需要告诉 Codex CLI它的 API 端点是我们刚刚启动的本地代理。5.1 定位并编辑 Codex 配置文件根据你的操作系统找到 Codex 的配置文件Linux/macOS:~/.codex/config.tomlWindows:%USERPROFILE%\.codex\config.toml(例如C:\Users\YourName\.codex\config.toml)用文本编辑器如 VSCode、Notepad、Sublime Text 或系统自带的记事本打开这个文件。5.2 修改配置文件在config.toml文件中你需要找到或添加[api]部分并进行如下配置# ~/.codex/config.toml 示例配置 [api] # 将 API 地址指向我们本地运行的代理服务器 base_url http://127.0.0.1:15721/v1 # Codex 使用的 API 类型必须保持为 responses wire_api responses # 认证部分由于我们的代理脚本会自行添加 DeepSeek 的 API Key # 这里可以填写一个占位符或者如果你之前的配置里有 OpenAI 的 key可以注释或删除。 # 关键点是Codex 会发送这个 key 给代理但代理脚本会忽略它并使用自己配置的 key。 api_key dummy-key-or-your-old-openai-key # 占位符即可 # 可选配置模型目录如果Codex无法自动发现模型 # 我们的代理脚本提供了 /v1/models 端点来返回模拟的模型列表。 # 通常 Codex 会自动查询如果遇到问题可以尝试显式指定 # model_catalog_json /path/to/your/custom_model_catalog.json重点说明base_url: 必须设置为http://127.0.0.1:15721/v1。如果你的代理脚本使用了不同的端口请相应修改。wire_api: 必须保持为responses这是 Codex 客户端的协议我们的代理会处理转换。api_key: 这里填写的值不会被用于访问 DeepSeek。它只是 Codex 发起请求时携带的一个凭证。我们的代理脚本在转发请求时会使用脚本内硬编码的DEEPSEEK_API_KEY替换掉它。因此你可以填写任何字符串如dummy-key或者保留你之前用于其他服务的 key这不会有安全问题因为请求不会直接发往外部。5.3 重启 Codex CLI修改并保存config.toml后必须重启 Codex CLI。如果你之前已经在终端中运行了codex交互会话请退出通常按CtrlD或输入/exit然后重新运行codex命令启动一个新的会话。6. 功能测试与效果验证配置完成后我们通过几个步骤来验证代理是否工作正常。6.1 验证基础连接与模型列表在新的 Codex CLI 会话中首先尝试列出可用的模型/model如果代理工作正常Codex 会调用我们脚本中的/v1/models端点并显示类似以下的模型列表名称来自我们脚本中的模拟数据Available models: - deepseek-chat - deepseek-coder这表明 Codex 已经成功通过本地代理获取到了“模型”信息。6.2 发送测试请求现在发送一个简单的测试提示词Hello, who are you?或者用Python写一个快速排序函数。观察点Codex 终端你应该能看到 Codex 开始接收流式响应如果启用了流式输出并正常显示 DeepSeek 生成的回答。代理服务终端你应该能看到类似POST /v1/responses HTTP/1.1 200的日志输出表明请求被成功代理和转发。6.3 验证流式输出Codex 默认支持流式输出。确保你的对话是流畅的没有出现截断或乱码。如果流式输出有问题可能是代理脚本中的流式响应转换不够完善。对于基础使用我们提供的简化转换在多数情况下可以工作。6.4 进行多轮对话尝试进行多轮对话检查上下文是否能够正常保持。例如Q: 什么是Python的列表推导式 A: (等待DeepSeek回答) Q: 给我一个例子。观察第二次提问时Codex/代理是否将历史对话上下文正确地传递给了 DeepSeek。7. 接口 API 与进阶调用我们的本地代理本质上是一个标准的 HTTP 服务这意味着它不仅服务于 Codex CLI也可以被其他任何能够发送 HTTP 请求的工具调用用于测试或集成。7.1 直接调用代理 API 进行测试你可以使用curl命令来模拟 Codex 的请求直接测试代理curl -X POST http://127.0.0.1:15721/v1/responses \ -H Content-Type: application/json \ -H Authorization: Bearer dummy-key \ -d { model: deepseek-chat, input: 请用一句话介绍你自己。, stream: false }如果成功你会收到一个经过转换的、Codex Responses 格式的 JSON 响应。7.2 使用 Python 脚本调用你也可以编写 Python 脚本像使用普通 API 一样使用这个代理import requests import json proxy_url http://127.0.0.1:15721/v1/responses headers { Content-Type: application/json, Authorization: Bearer dummy-key # 这个key会被代理替换 } payload { model: deepseek-chat, input: 解释一下神经网络。, stream: False, temperature: 0.5, max_tokens: 500 } response requests.post(proxy_url, headersheaders, jsonpayload, timeout30) if response.status_code 200: result response.json() print(Response:, json.dumps(result, indent2, ensure_asciiFalse)) else: print(fError: {response.status_code}, response.text)7.3 处理批量任务对于批量处理任务建议在调用方你的脚本层面实现队列和重试机制而不是依赖这个简单的代理。例如你可以读取一个包含多个问题的文件。循环调用上述代理接口。为每个请求添加适当的延迟避免触发上游 API 的速率限制。实现错误重试逻辑如遇到网络超时或 5xx 错误时重试。将每个响应保存到独立的文件或数据库中。8. 资源占用与性能观察这个自建代理方案的优势之一就是资源消耗极低且透明可控。CPU 与内存代理脚本本身只是一个简单的 HTTP 转发服务不执行任何模型推理。在空闲时CPU 使用率接近 0%内存占用通常在 100 MB 以下。在转发请求时会有轻微的网络 I/O 和 JSON 解析开销但对系统性能影响微乎其微。网络延迟整个链路的延迟 本地网络延迟 (Codex - 本地代理) 代理处理延迟 你的网络到 DeepSeek API 的延迟 DeepSeek 处理延迟。由于前两部分都在本地延迟几乎可以忽略1ms。因此最终用户体验到的响应速度主要取决于你的网络连接到api.deepseek.com的速度以及 DeepSeek 服务的处理时间。稳定性服务的稳定性取决于两个因素本地代理脚本的稳定性只要 Python 进程不崩溃它就稳定。代码中包含了基本的错误处理对于常规使用是足够的。你的网络到 DeepSeek API 的稳定性这是主要变量。如果出现连接超时代理脚本会返回错误给 Codex。监控你可以直接观察运行代理的终端窗口所有进出的 HTTP 请求都会打印日志取决于aiohttp的默认日志级别。这是最直接的监控方式。9. 常见问题与排查方法在部署和使用过程中你可能会遇到以下问题。请根据现象按顺序排查。问题现象可能原因排查方式解决方案启动代理时提示端口被占用端口15721已被其他程序使用。1. 检查netstat -ano | findstr :15721(Win) 或lsof -i :15721(Mac/Linux)。2. 或尝试修改脚本中的PROXY_PORT为其他端口如15722并同步修改 Codexconfig.toml中的base_url。1. 终止占用端口的进程。2.推荐修改代理脚本和 Codex 配置使用一个空闲端口。Codex 启动时报错或无法连接1. 代理服务未运行。2.config.toml中的base_url配置错误。3. 系统防火墙/安全软件阻止了连接。1. 确认代理脚本的终端是否在运行且无报错。2. 检查config.toml文件确保base_url的 IP、端口和路径 (/v1) 完全正确。3. 尝试用浏览器或curl访问http://127.0.0.1:15721/health看是否返回OK。1. 启动代理服务。2. 修正config.toml。3. 临时关闭防火墙或添加入站规则允许本地回环地址 (127.0.0.1) 的通信。/model命令不显示模型或报错1. 代理的/v1/models端点未正确响应。2. Codex 缓存了旧的模型信息。1. 访问http://127.0.0.1:15721/v1/models查看返回的 JSON 是否正常。2. 完全退出 Codex CLI 并重新启动。1. 检查代理脚本中/v1/models路由部分的代码是否正确。2. 重启 Codex。Codex 能连接但请求后无响应或超时1. DeepSeek API Key 无效或余额不足。2. 网络无法访问api.deepseek.com。3. 代理脚本的请求转换逻辑有误。1. 去 DeepSeek 平台检查 API Key 状态和余额。2. 在终端用ping api.deepseek.com或curl -I https://api.deepseek.com测试网络连通性。3. 查看代理脚本终端的详细错误日志。1. 更换有效且有余额的 API Key并更新脚本中的DEEPSEEK_API_KEY。2. 检查本地网络设置、代理或 hosts 文件。3. 根据错误日志调整convert_responses_to_chat或convert_chat_to_responses函数。流式输出中断或显示异常代理脚本对 Server-Sent Events (SSE) 流的转换不完整导致 Codex 无法正确解析。观察代理日志看转发流式请求时是否出错。对比直接调用 DeepSeek API 的原始流和经过代理后的流数据差异。这是本简化方案的一个潜在难点。需要深入研究 OpenAI Responses API 和 Chat Completions API 的 SSE 事件格式并实现精确的映射。对于非流式请求 (stream: false)则没有此问题。多轮对话上下文丢失代理脚本在转换请求时没有正确处理或传递历史消息数组。检查convert_responses_to_chat函数中处理input数组的逻辑。打印转换前后的消息内容进行对比。完善convert_responses_to_chat函数确保它能正确地将 Codex 传递的完整对话历史可能是一个消息对象数组转换为 DeepSeek Chat API 所需的messages数组格式。10. 最佳实践与使用建议为了让这个自建代理方案运行得更稳定、更安全建议遵循以下实践API Key 管理切勿将写有真实 API Key 的脚本上传到 GitHub 等公开仓库。可以考虑将 API Key 存储在环境变量中让脚本从环境变量读取。import os DEEPSEEK_API_KEY os.getenv(DEEPSEEK_API_KEY, default-key-if-not-set)然后在启动脚本前设置环境变量# Linux/macOS export DEEPSEEK_API_KEYyour_real_key_here python deepseek_proxy.py # Windows (PowerShell) $env:DEEPSEEK_API_KEYyour_real_key_here python deepseek_proxy.py进程守护对于长期使用建议使用进程守护工具如systemd(Linux)、launchd(macOS)、nssm(Windows)将代理脚本作为后台服务运行并设置开机自启和崩溃重启。日志记录当前的脚本只有基础输出。对于生产环境应该配置更完善的日志记录将请求、响应、错误信息写入文件便于后期排查问题。可以使用 Python 标准的logging模块。配置化将监听端口、目标 API 地址等配置项提取到外部配置文件如config.json或config.yaml中避免每次修改都要动代码。协议兼容性本文提供的脚本是一个最小可行实现 (MVP)重点在于演示原理。OpenAI 的 Responses API 和 Chat Completions API 的字段映射可能更复杂特别是对于工具调用function calling、推理过程reasoning等高级特性。如果你需要完全兼容需要仔细对照两者的官方文档完善转换函数。备用方案这个自建代理是 CC Switch 的“平替”它给了你最大的控制权和避开了网络下载问题。但如果未来 CC Switch 有了更便捷的获取方式或者你找到了其他稳定的第三方客户端依然可以切换回去。只需将 Codex 的config.toml中的base_url改回对应的地址即可。通过以上步骤你已经成功搭建了一个不依赖 CC Switch 或 Codex、完全自主控制的 Codex-to-DeepSeek 本地代理桥梁。这个方案将复杂的协议转换和网络问题隔离在本地让你能更专注于使用 Codex CLI 进行高效的开发工作。如果在实践中遇到本文未覆盖的特定问题深入分析代理脚本的日志和 Codex 的错误信息往往是解决问题的关键。