llm_proxy_pro
v1.0.0
Published
Multi-provider LLM proxy for claude code / codex with load balancing, failover and training-data recording
Readme
llm_proxy
面向 Claude Code / Codex 等客户端的 LLM 代理。零 npm 依赖,纯 Node.js(>= 18,依赖内置 fetch)实现。
功能简介
- 多 provider 配置:一个 config.json 里配置多个上游 OpenAI 兼容 provider。
- 负载均衡:provider 的每个
api_key是一个独立槽位(slot),多个 key = 同一模型多倍并发。 - 故障切换(failover)与自动恢复:上游超时/报错自动切到下一个槽位/模型,故障槽位后台重试恢复。
- 全宕报警:所有槽位不可用时向 stderr 输出
⚠ ALL PROVIDERS DOWN(去重,恢复后重置)并返回 HTTP 503。 - 训练数据记录:每个成功请求记录一条 OpenAI fine-tune 格式的 JSONL(
data/sessions-YYYYMMDD.jsonl)。 - 协议转换:Anthropic
/v1/messages⇄ OpenAI/v1/chat/completions双向转换,含 SSE 流式。
config.json 说明
对象形式(推荐,见 config.example.json):
{
"port": 8787,
"timeout_ms": 300000,
"providers": [
{
"name": "provider-a",
"base_url": "https://your-provider.example.com",
"api_keys": ["sk-your-key-1", "sk-your-key-2"],
"models": ["model-a", "model-b"]
}
]
}也兼容 llm-proxy-py 的数组形式(顶层直接是 provider 数组,此时 port/timeout_ms 用默认值或 CLI 指定)。
字段说明:
| 字段 | 说明 |
|---|---|
| port | 监听端口,默认 8787(CLI --port 可覆盖) |
| timeout_ms | 上游读写超时,默认 300000(5 分钟);0 表示不限制 |
| providers[].name | provider 名称(用于训练数据 metadata),缺省用 base_url |
| providers[].base_url | 上游 OpenAI 兼容地址(会自动去掉尾部 /) |
| providers[].api_keys | key 数组;每个 key 是一个独立槽位,多 key = 该模型更高并发 |
| providers[].models | 该 provider 提供的模型列表;必须显式列出,不会调用上游 /v1/models 自动发现 |
启动方式
# 方式一:npx(推荐)
CONFIG_FILE=config.json npx llm_proxy@latest
# 方式二:本地运行
node bin/llm-proxy.js --config config.json- CLI 参数:
--port <n>、--host <addr>、--config <file>(也可用环境变量CONFIG_FILE,默认config.json)。 - 默认监听
127.0.0.1:8787。 - 环境变量
DATA_DIR可覆盖训练数据目录,默认data/。
客户端接入
代理的鉴权很简单:客户端带的 key 只要求非空,实际用哪个上游 key 由代理的槽位调度决定。
Claude Code(走 Anthropic 协议 /v1/messages,由代理转换为 OpenAI):
export ANTHROPIC_BASE_URL=http://127.0.0.1:8787
export ANTHROPIC_API_KEY=sk-anything # 任意非空即可Codex(走 OpenAI 协议 /v1/chat/completions):
export OPENAI_BASE_URL=http://127.0.0.1:8787/v1
export OPENAI_API_KEY=sk-anything # 任意非空即可注意:Codex 还需在 ~/.codex/config.toml 中设置 wire_api = "chat":
wire_api = "chat"因为代理未实现 Responses API(/v1/responses),必须让 Codex 走 Chat Completions 协议。
端点列表
| 端点 | 说明 |
|---|---|
| POST /v1/chat/completions | OpenAI 协议透传(含 SSE 流式);响应中的 model 字段回显客户端请求名 |
| POST /v1/messages | Anthropic 协议,内部转换为 OpenAI 调用(含 SSE 流式) |
| GET /v1/models | 返回资源池中的模型列表(来自 config,非上游发现) |
| GET /health | 各槽位状态(IDLE/IN_USE/UNAVAILABLE)与 last_error |
注意:客户端请求里的 model 名仅用于回显,代理实际会从资源池中选择可用的真实模型转发。
训练数据格式
每个成功请求写入一行 JSONL,路径为 data/sessions-YYYYMMDD.jsonl(或 DATA_DIR 目录下),格式为 OpenAI fine-tune 格式:
{"messages":[{"role":"system","content":"..."},{"role":"user","content":"..."},{"role":"assistant","content":"..."}],"metadata":{"model":"上游真实模型","provider":"a","requested_model":"客户端请求名","endpoint":"chat","timestamp":"2026-09-18T04:00:00.000Z","usage":{"prompt_tokens":10,"completion_tokens":20}}}说明:
messages为完整对话(system/user/assistant),metadata记录上游真实模型、provider、客户端请求的模型名、端点、时间戳与 token 用量。- 只记录成功请求:失败请求、failover 中间尝试、上游断流(未收到
[DONE])均不记录。
故障切换行为
- 上游超时 / 连接错误 / 400 / 401 / 403 / 429 / 5xx → 该槽位标记为
UNAVAILABLE,请求自动切换到同模型的其他槽位,再切到其他模型。 - 不可用槽位会被持续重试,成功后自动恢复为
IDLE。 - 所有槽位均不可用时:向 stderr 输出
⚠ ALL PROVIDERS DOWN(连续报警去重,任一槽位恢复后重置),并向客户端返回 HTTP 503。
测试
npm test
# 或
node --test "test/*.test.js"