在 Codex CLI 中使用 GLM-5.1 模型:完整配置指南
本文详细记录如何将智谱 GLM-5.1 模型接入 OpenAI Codex CLI,涵盖代理服务搭建、配置文件编写、密钥管理与一键启动脚本,助你在本地环境中无缝切换至国产大模型。
1. 背景与原理
Codex CLI 原生支持 OpenAI Responses API 协议,而智谱 GLM 系列模型使用的是 Chat Completions API 协议。两者在请求/响应格式、流式事件结构上存在差异,因此需要一个本地代理服务将 Codex 发出的 Responses API 请求转换为智谱兼容的 Chat Completions 请求,并将响应转译回 Responses API 格式。
整体架构如下:
Codex CLI ──(Responses API)──▶ 本地代理 (127.0.0.1:8787) ──(Chat Completions API)──▶ 智谱 API
◀──(SSE 流)── ◀──(SSE 流)──
2. 环境要求
| 依赖 | 最低版本 | 说明 |
|---|---|---|
| Node.js | ≥ 22 | Codex CLI 运行时 |
| Python | ≥ 3.10 | 代理服务运行时 |
| pip | 最新 | Python 包管理 |
| curl | 任意 | 健康检查与调试 |
安装 Codex CLI:
npm install -g @openai/codex
验证安装:
codex --version
# 期望输出类似:codex-cli 0.125.0
3. 获取智谱 API Key
- 访问 智谱开放平台,注册并登录。
- 进入「API Keys」页面,创建新的 API Key。
- 复制 Key 并妥善保管,后续步骤将使用。
4. 搭建本地代理服务
4.1 项目结构
codex-glm-proxy/
├── app.py # FastAPI 代理主程序
├── requirements.txt # Python 依赖
├── run.sh # 手动启动脚本
└── README.md
4.2 Python 依赖
requirements.txt:
fastapi>=0.115,<1.0
uvicorn[standard]>=0.30,<1.0
httpx>=0.27,<1.0
安装依赖:
cd codex-glm-proxy
python3 -m venv .venv
.venv/bin/pip install -r requirements.txt
4.3 代理核心逻辑(app.py)
代理服务的核心职责:
- 请求转换:将 Codex 发出的 Responses API 请求体转换为智谱 Chat Completions 格式
- 流式转发:将智谱返回的 Chat Completions SSE 流转译为 Responses API SSE 事件序列
- Usage 字段归一化:将智谱的
prompt_tokens/completion_tokens映射为 Codex 期望的input_tokens/output_tokens/total_tokens - Function Call 支持:处理工具调用场景下的消息格式转换
关键代码片段——请求体转换:
def to_chat_messages(input_field, instructions=None):
messages = []
if instructions:
messages.append({"role": "system", "content": instructions})
if isinstance(input_field, str):
messages.append({"role": "user", "content": input_field})
return messages
if isinstance(input_field, list):
for item in input_field:
if not isinstance(item, dict):
continue
item_type = item.get("type")
if item_type == "message":
role = item.get("role", "user")
if role == "developer":
role = "system"
messages.append({"role": role, "content": _flatten_text(item.get("content", ""))})
elif item_type == "function_call_output":
# 工具调用结果转译
call_id = item.get("call_id", item.get("id", ""))
call_meta = _CALL_REGISTRY.get(call_id)
if call_meta:
messages.append({
"role": "assistant",
"content": "",
"tool_calls": [{
"id": call_id,
"type": "function",
"function": {
"name": call_meta.get("name", ""),
"arguments": call_meta.get("arguments", "{}"),
},
}],
})
messages.append({
"role": "tool",
"tool_call_id": call_id,
"content": str(item.get("output", "")),
})
return messages
关键代码片段——Usage 归一化:
def _normalize_usage_for_responses(usage) -> dict:
if not isinstance(usage, dict):
usage = {}
out = dict(usage)
inp = out.get("input_tokens") or out.get("prompt_tokens")
outp = out.get("output_tokens") or out.get("completion_tokens")
inp_i = int(inp) if inp is not None else 0
outp_i = int(outp) if outp is not None else 0
tot = out.get("total_tokens")
tot_i = int(tot) if tot is not None else inp_i + outp_i
out["input_tokens"] = inp_i
out["output_tokens"] = outp_i
out["total_tokens"] = tot_i
return out
关键代码片段——流式事件转译:
# 将智谱 Chat Completions 的 SSE 事件转换为 Codex 期望的 Responses API 事件序列
yield 'data: ' + json.dumps({"type": "response.created", ...}) + '\n\n'
yield 'data: ' + json.dumps({"type": "response.in_progress", ...}) + '\n\n'
yield 'data: ' + json.dumps({"type": "response.output_item.added", ...}) + '\n\n'
yield 'data: ' + json.dumps({"type": "response.content_part.added", ...}) + '\n\n'
yield 'data: ' + json.dumps({"type": "response.output_text.delta", "delta": text, ...}) + '\n\n'
yield 'data: ' + json.dumps({"type": "response.output_text.done", ...}) + '\n\n'
yield 'data: ' + json.dumps({"type": "response.content_part.done", ...}) + '\n\n'
yield 'data: ' + json.dumps({"type": "response.output_item.done", ...}) + '\n\n'
yield 'data: ' + json.dumps({"type": "response.completed", "response": response_obj}) + '\n\n'
yield 'data: [DONE]\n\n'
4.4 健康检查端点
代理提供 /health 端点,供启动脚本确认服务状态:
@app.get("/health")
async def health():
return {"status": "ok", "has_key": bool(os.getenv("ZHIPU_API_KEY", "").strip())}
4.5 手动启动代理
export ZHIPU_API_KEY="your_api_key_here"
cd codex-glm-proxy
../.venv/bin/python -m uvicorn app:app --host 127.0.0.1 --port 8787
验证代理运行:
curl http://127.0.0.1:8787/health
# 期望输出:{"status":"ok","has_key":true}
5. Codex CLI 配置
5.1 主配置文件
编辑 ~/.codex/config.toml:
# 模型设置
model = "glm-5.1"
model_provider = "glm_proxy"
model_reasoning_effort = "medium"
# 自定义 Provider 定义
[model_providers.glm_proxy]
name = "GLM Local Proxy"
base_url = "http://127.0.0.1:8787/v1"
wire_api = "responses" # 关键:指定使用 Responses API 协议
requires_openai_auth = false # 无需 OpenAI 认证
配置项详解:
| 字段 | 值 | 说明 |
|---|---|---|
model | "glm-5.1" | 传递给代理的模型名称,代理会原样转发至智谱 API |
model_provider | "glm_proxy" | 对应 [model_providers.glm_proxy] 的键名 |
wire_api | "responses" | 告知 Codex 使用 Responses API 格式发送请求 |
base_url | "http://127.0.0.1:8787/v1" | 代理服务地址,Codex 会在后面拼接 /responses |
requires_openai_auth | false | 设为 false 后 Codex 不要求 OpenAI Key |
5.2 密钥管理
创建 ~/.codex/auto.json 存放智谱 API Key(此文件不应提交至版本控制):
{
"GLM_API_KEY": "your_zhipu_api_key_here",
"auth_mode": "local"
}
⚠️ 安全提示:
auto.json包含敏感凭据,务必将其加入.gitignore。
5.3 用户级指令(可选)
编辑 ~/.codex/instructions.md 可自定义 AI 行为偏好:
# User-level instructions
## Code and architecture
- Use first-principles thinking when analyzing problems.
- Follow DRY, KISS, SOLID, and YAGNI when coding.
- Keep functions under ~500 lines; split when necessary.
## Language and communication
- Communicate with the user in their preferred language.
6. 一键启动脚本
手动先启动代理再启动 Codex 比较繁琐,推荐使用一键启动脚本 ~/.codex/scripts/codex-with-auto-json.sh:
#!/usr/bin/env bash
set -euo pipefail
CODEX_HOME="${CODEX_HOME:-$HOME/.codex}"
AUTO_JSON="${CODEX_HOME}/auto.json"
PROXY_DIR="$HOME/Project/codex_project/custdown_test/codex-glm-proxy"
PROXY_HOST="127.0.0.1"
PROXY_PORT="8787"
PROXY_HEALTH_URL="http://${PROXY_HOST}:${PROXY_PORT}/health"
PROXY_LOG="$CODEX_HOME/log/proxy.log"
PROXY_AUTO_RESTART="${PROXY_AUTO_RESTART:-1}"
# 1. 从 auto.json 加载 GLM_API_KEY
if [[ -f "$AUTO_JSON" ]]; then
GLM_KEY="$(python3 -c "
import json, os
p = os.path.expanduser('~/.codex/auto.json')
try:
with open(p, encoding='utf-8') as f:
d = json.load(f)
print((d.get('GLM_API_KEY') or '').strip())
except Exception:
print('')
")"
if [[ -n "$GLM_KEY" ]]; then
export GLM_API_KEY="$GLM_KEY"
export ZHIPU_API_KEY="$GLM_KEY"
fi
fi
# 2. 检查 Key 是否存在
if [[ -z "${ZHIPU_API_KEY:-}" ]]; then
echo "GLM key is empty. Put GLM_API_KEY into ~/.codex/auto.json"
exit 1
fi
# 3. 确保代理虚拟环境就绪
if [[ ! -x "$PROXY_DIR/.venv/bin/python" ]]; then
python3 -m venv "$PROXY_DIR/.venv"
"$PROXY_DIR/.venv/bin/pip" install -r "$PROXY_DIR/requirements.txt"
fi
# 4. 自动重启代理(确保最新代码生效)
if [[ "$PROXY_AUTO_RESTART" == "1" ]]; then
pkill -f "uvicorn app:app --host $PROXY_HOST --port $PROXY_PORT" >/dev/null 2>&1 || true
ZHIPU_API_KEY="$ZHIPU_API_KEY" nohup "$PROXY_DIR/.venv/bin/python" -m uvicorn app:app \
--host "$PROXY_HOST" --port "$PROXY_PORT" --app-dir "$PROXY_DIR" \
>> "$PROXY_LOG" 2>&1 &
# 等待代理就绪
for _ in {1..16}; do
sleep 0.5
curl -fsS "$PROXY_HEALTH_URL" >/dev/null 2>&1 && break
done
fi
# 5. 设置环境变量后启动 Codex
export GLM_PROXY_DUMMY_KEY="ok"
exec codex "$@"
使用方式:
chmod +x ~/.codex/scripts/codex-with-auto-json.sh
# 启动交互式会话
~/.codex/scripts/codex-with-auto-json.sh
# 或执行单条指令
~/.codex/scripts/codex-with-auto-json.sh exec "解释 main.c 的逻辑"
可将该脚本路径加入
PATH或创建 alias 以简化调用。
7. 完整目录结构总览
~/.codex/
├── config.toml # 主配置:模型 & Provider
├── auto.json # 密钥(GLM_API_KEY)
├── instructions.md # 用户级 AI 指令
├── AGENTS.md # 项目级 AI 指令
├── scripts/
│ └── codex-with-auto-json.sh # 一键启动脚本
├── log/
│ └── proxy.log # 代理运行日志
└── ...
codex-glm-proxy/
├── app.py # 代理服务主程序
├── requirements.txt # Python 依赖
├── run.sh # 手动启动脚本
├── .venv/ # Python 虚拟环境
└── README.md
8. 常见问题排查
| 问题 | 原因 | 解决方案 |
|---|---|---|
Proxy failed to start | Python 虚拟环境未就绪 | 手动运行 python3 -m venv .venv && .venv/bin/pip install -r requirements.txt |
Proxy protocol self-check failed | 代理返回的事件格式不符合 Codex 解析预期 | 检查 app.py 中 response.completed 事件是否包含 input_tokens / output_tokens / total_tokens |
GLM key is empty | auto.json 中缺少 GLM_API_KEY | 编辑 ~/.codex/auto.json,填入有效 Key |
| Codex 启动后无响应 | 代理未运行或端口被占用 | 运行 curl http://127.0.0.1:8787/health 确认代理状态 |
| 流式输出中断 | 智谱 API 限流 | 代理内置 1.2s 节流,必要时调大 _throttle_upstream 参数 |
9. 总结
通过搭建一个轻量的本地 FastAPI 代理,我们实现了 Codex CLI 与智谱 GLM-5.1 模型的无缝对接。核心思路是:
- 协议适配:Responses API ↔ Chat Completions API 双向转换
- 流式转译:智谱 SSE 事件 → Codex SSE 事件序列
- 字段归一化:Usage 字段名映射
- 一键启动:自动加载密钥、启动代理、验证健康状态
这套方案不仅适用于 GLM-5.1,也可扩展至任何兼容 Chat Completions API 的模型服务(如 DeepSeek、Qwen 等),只需修改代理中的上游 API 地址和模型名即可。
本文基于 Codex CLI v0.125.0 与智谱 GLM-5.1 验证通过,环境为 Linux / Node.js 22 / Python 3.10+。
实战教程&spm=1001.2101.3001.5002&articleId=160631840&d=1&t=3&u=ea27bbee381b47708656c75d2155d0bc)
743

被折叠的 条评论
为什么被折叠?



