跳过正文

Codex > DeepSeek V4 接入实战

·886 字·5 分钟
作者
王浩宇
记录服务器、虚拟化、网络和日常折腾。

为什么搞这个
#

DeepSeek V4 出来之后我一直在用,百万 token 上下文窗口意味着整个项目塞进去都不用分段。我就想:能不能让 Codex 吃 DeepSeek 的推理?

查了一圈,,发现有个开源项目,Moon Bridge 正好是干这事的。说白了就是个本地转发代理,把 Codex 的 OpenAI 格式请求翻译成 DeepSeek 能懂的话。

先看架构
#

项目目录 → Codex CLI ↔ Moon Bridge(本地:38440)↔ DeepSeek API

Moon Bridge 就是个协议转换器,跑在本地,不存任何数据。

准备工作
#

先确认环境:

node --version   # 需要 20+
go version       # 需要 1.25+

装 Codex:

npm install -g @openai/codex

DeepSeek 开放平台 搞个 API Key,存好。

配置 Moon Bridge
#

克隆项目:

git clone https://github.com/ZhiYi-R/moon-bridge.git
cd moon-bridge

根目录下建 config.yml

mode: "Transform"

server:
  addr: "127.0.0.1:38440"

models:
  deepseek-v4-pro:
    context_window: 1000000
    max_output_tokens: 384000
    default_reasoning_level: "high"
    supported_reasoning_levels:
      - effort: "high"
        description: "High reasoning effort"
      - effort: "xhigh"
        description: "Extra high reasoning effort"
    supports_reasoning_summaries: true
    default_reasoning_summary: "auto"
    extensions:
      deepseek_v4:
        enabled: true
  deepseek-v4-flash:
    context_window: 1000000
    max_output_tokens: 384000
    default_reasoning_level: "high"
    supported_reasoning_levels:
      - effort: "high"
        description: "High reasoning effort"
      - effort: "xhigh"
        description: "Extra high reasoning effort"
    supports_reasoning_summaries: true
    default_reasoning_summary: "auto"
    extensions:
      deepseek_v4:
        enabled: true

providers:
  deepseek:
    base_url: "https://api.deepseek.com/anthropic"
    api_key: "sk-你的key"      # ← 改成你的
    offers:
      - model: deepseek-v4-pro
      - model: deepseek-v4-flash

routes:
  moonbridge:
    model: deepseek-v4-pro    # 默认路由,后面可以在 Codex 里切换
    provider: deepseek

defaults:
  model: moonbridge
  max_tokens: 65536

踩坑提醒api_key 那行别漏了,我第一遍就漏了,查了半天 401。

启动
#

go run ./cmd/moonbridge --config config.yml

看到日志输出说明起来了。默认监听 127.0.0.1:38440,暴露的接口是 /v1/responses,跟 OpenAI 的 Responses API 格式一样。

别关这个终端,开个新窗口搞下一步。

生成 Codex 配置
#

CODEX_HOME_DIR="${CODEX_HOME:-$HOME/.codex}"
mkdir -p "$CODEX_HOME_DIR"

# 有老配置的话先备份
cp "$CODEX_HOME_DIR/config.toml" "$CODEX_HOME_DIR/config.toml.bak" 2>/dev/null || true

MODEL="$(go run ./cmd/moonbridge --config config.yml --print-codex-model)"
go run ./cmd/moonbridge \
  --config config.yml \
  --print-codex-config "$MODEL" \
  --codex-base-url "http://127.0.0.1:38440/v1" \
  --codex-home "$CODEX_HOME_DIR" \
  > "$CODEX_HOME_DIR/config.toml"

这步干了两个事:

  1. config.toml — Codex 的 provider 配置
  2. models_catalog.json — 模型能力描述,上下文窗口、推理档位这些

打开Codex进行测试 如果一切正常,Codex 发出的每个请求都会走 Moon Bridge → DeepSeek。

验证通没通
#

开第三个终端(是的,有点多):

# 看模型列表
curl http://127.0.0.1:38440/v1/models

# 发条测试
curl http://127.0.0.1:38440/v1/responses \
  -H "Content-Type: application/json" \
  -d '{
    "model": "moonbridge",
    "input": "泥嚎 deepseek",
    "max_output_tokens": 1024
  }'

同时看 Moon Bridge 的终端,应该有 POST /v1/responses 的日志。

推理档位
#

DeepSeek V4 支持多档推理,写复杂逻辑的时候挺有用。在配置里已经预置了两档:

  • high — 日常够用
  • xhigh — 需要深度推理的时候开
curl http://127.0.0.1:38440/v1/responses \
  -H "Content-Type: application/json" \
  -d '{
    "model": "moonbridge",
    "input": "输入的内容",
    "reasoning": {"effort": "high"},
    "max_output_tokens": 4096
  }'

踩坑记录
#

问题原因怎么搞
connection refusedMoon Bridge 没启动或端口不对config.ymlserver.addr,确认进程活着
Codex 不认模型models_catalog.json重新跑配置生成那一步
field provider not found配置格式老了用新格式:顶层 providers / models / routes / defaults
401API Key 不对检查 key 配没配对
402账户没钱了去 DeepSeek 开放平台充值
图片传不进去视觉功能要额外配置要么配 Kimi 的视觉 Provider,要么关掉 visual 扩展

一点感受
#

用了一周,说几个感受:

  1. V4 Flash 写日常代码完全够用,响应速度比 Pro 快不少,大部分场景不需要上 Pro
  2. 百万上下文是真的香,之前用别的模型经常写到一半忘了前面的上下文,DeepSeek 这边基本没遇到
  3. Moon Bridge 很稳,跑了几天没崩过,日志也干净
  4. 唯一不爽的是要多开一个终端,不过我已经写成脚本一键启动了(mac),也不算事

总的来说,这套组合的成本大概只有直接走 OpenAI 的十分之一,实际体验没啥差别。如果你是独立开发者或者小团队,很值得折腾一下。


start script
#

#!/bin/bash

# 一键启动 Codex + Moon Bridge + DeepSeek V4
#
# 用法:
#   ./start-codex-with-deepseek.sh [项目目录]
#
# 如果省略项目目录,默认当前目录。
#

set -e

PROJECT_DIR="${1:-$(pwd)}"
MOON_BRIDGE_DIR="${MOON_BRIDGE_DIR:-$HOME/moon-bridge}"
DEEPSEEK_API_KEY="${DEEPSEEK_API_KEY:-}"

# ── 颜色 ──
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'

log()  { echo -e "${GREEN}[✓]${NC} $1"; }
warn() { echo -e "${YELLOW}[!]${NC} $1"; }
err()  { echo -e "${RED}[✗]${NC} $1"; }

# ── 检查依赖 ──
check_deps() {
  command -v node >/dev/null 2>&1 || { err "需要 Node.js 18+"; exit 1; }
  command -v go >/dev/null 2>&1   || { err "需要 Go 1.25+"; exit 1; }
  command -v codex >/dev/null 2>&1|| { err "需要 Codex CLI,装一下:npm install -g @openai/codex"; exit 1; }
  log "依赖检查通过"
}

# ── 检查/拉取 Moon Bridge ──
setup_moon_bridge() {
  if [ ! -d "$MOON_BRIDGE_DIR" ]; then
    log "克隆 Moon Bridge 到 $MOON_BRIDGE_DIR"
    git clone https://github.com/ZhiYi-R/moon-bridge.git "$MOON_BRIDGE_DIR"
  else
    log "Moon Bridge 已存在,跳过克隆"
  fi

  # 写 config.yml(如果不存在)
  if [ ! -f "$MOON_BRIDGE_DIR/config.yml" ]; then
    log "生成 config.yml"
    cat > "$MOON_BRIDGE_DIR/config.yml" <<EOF
mode: "Transform"

server:
  addr: "127.0.0.1:38440"

models:
  deepseek-v4-pro:
    context_window: 1000000
    max_output_tokens: 384000
    default_reasoning_level: "high"
    supported_reasoning_levels:
      - effort: "high"
        description: "High reasoning effort"
      - effort: "xhigh"
        description: "Extra high reasoning effort"
    supports_reasoning_summaries: true
    default_reasoning_summary: "auto"
    extensions:
      deepseek_v4:
        enabled: true
  deepseek-v4-flash:
    context_window: 1000000
    max_output_tokens: 384000
    default_reasoning_level: "high"
    supported_reasoning_levels:
      - effort: "high"
        description: "High reasoning effort"
      - effort: "xhigh"
        description: "Extra high reasoning effort"
    supports_reasoning_summaries: true
    default_reasoning_summary: "auto"
    extensions:
      deepseek_v4:
        enabled: true

providers:
  deepseek:
    base_url: "https://api.deepseek.com/anthropic"
    api_key: "$DEEPSEEK_API_KEY"
    offers:
      - model: deepseek-v4-pro
      - model: deepseek-v4-flash

routes:
  moonbridge:
    model: deepseek-v4-pro
    provider: deepseek

defaults:
  model: moonbridge
  max_tokens: 65536
EOF
  fi

  # 检查 API Key
  if grep -q 'sk-you' "$MOON_BRIDGE_DIR/config.yml" 2>/dev/null; then
    err "config.yml 里的 API Key 还是占位符 sk-you…-key,请改成你的 DeepSeek Key"
    err "设置环境变量:export DEEPSEEK_API_KEY=sk-xxx,然后重新运行"
    exit 1
  fi
  log "Moon Bridge 配置就绪"
}

# ── 启动 Moon Bridge ──
start_moon_bridge() {
  if lsof -i :38440 >/dev/null 2>&1; then
    warn "38440 端口已被占用,Moon Bridge 可能已经在跑"
    return
  fi

  log "启动 Moon Bridge(监听 :38440)"
  cd "$MOON_BRIDGE_DIR"
  go run ./cmd/moonbridge --config config.yml &
  MOON_PID=$!
  cd - >/dev/null

  # 等它起来
  for i in $(seq 1 10); do
    if lsof -i :38440 >/dev/null 2>&1; then
      log "Moon Bridge 已就绪"
      return
    fi
    sleep 1
  done

  err "Moon Bridge 启动超时,检查日志"
  exit 1
}

# ── 生成 Codex 配置 ──
gen_codex_config() {
  local codex_home="${CODEX_HOME:-$HOME/.codex}"
  mkdir -p "$codex_home"

  # 备份
  [ -f "$codex_home/config.toml" ] && cp "$codex_home/config.toml" "$codex_home/config.toml.bak"

  local model
  model="$(cd "$MOON_BRIDGE_DIR" && go run ./cmd/moonbridge --config config.yml --print-codex-model)"

  (cd "$MOON_BRIDGE_DIR" && go run ./cmd/moonbridge \
    --config config.yml \
    --print-codex-config "$model" \
    --codex-base-url "http://127.0.0.1:38440/v1" \
    --codex-home "$codex_home" \
    > "$codex_home/config.toml")

  log "Codex 配置已生成到 $codex_home/config.toml"
}

# ── 启动 Codex ──
start_codex() {
  if [ ! -d "$PROJECT_DIR" ]; then
    err "项目目录不存在:$PROJECT_DIR"
    exit 1
  fi

  log "进入项目目录:$PROJECT_DIR"
  cd "$PROJECT_DIR"
  log "启动 Codex(按 Ctrl+C 退出)"
  echo ""
  codex
}

# ── 清理 ──
cleanup() {
  if [ -n "$MOON_PID" ]; then
    warn "关闭 Moon Bridge (PID $MOON_PID)"
    kill "$MOON_PID" 2>/dev/null || true
  fi
}
trap cleanup EXIT

# ── 开始 ──
echo ""
echo "╔══════════════════════════════════════╗"
echo "║   Codex + DeepSeek 一键启动         ║"
echo "╚══════════════════════════════════════╝"
echo ""

check_deps
setup_moon_bridge
start_moon_bridge
gen_codex_config
start_codex

相关链接: