一个本地 HTTP 反向代理,用于拦截发往 OpenAI / Anthropic API 的请求,按用户配置的映射关系替换 model 字段,同时对响应中的 model 字段做反向还原,使客户端始终看到自己发送的别名。支持流式(SSE)和非流式两种响应模式。
- 请求中的
model别名 → 真实模型名(转发给上游) - 响应中的真实模型名 → 原别名(返回给客户端)
- 流式响应(SSE)逐行转换,零内存缓冲
- 同时支持 OpenAI 和 Anthropic API 格式
- 可选请求 / 响应日志,异步写入不影响性能
- 非 JSON 请求体(multipart 等)原样透传
需要 Bun v1.0+。
bun installbun run src/index.ts \
--port 3000 \
--target https://api.openai.com \
--map mcs-5:claude-sonnet-4-6 \
--map mcs-3:claude-haiku-4-5bun run src/index.ts --config config.json配置文件格式(参考 config.example.json):
{
"port": 3000,
"target": "https://api.openai.com",
"mappings": {
"mcs-5": "claude-sonnet-4-6",
"mcs-3": "claude-haiku-4-5"
}
}CLI 参数优先级高于配置文件。
# 日志写入默认目录 ./logs/
bun run src/index.ts --config config.json --log
# 指定日志目录(自动开启日志)
bun run src/index.ts --config config.json --log-dir /tmp/proxy-logs日志文件:
requests.log— 客户端原始请求(model 字段为客户端发送的别名)responses.log— 上游返回的完整响应(model 字段已还原为别名)
bun devbun build --compile 可将项目及 Bun 运行时一起打包为单个可执行文件,目标机器无需安装 Bun 或 Node.js。
bun run build
# 输出:dist/model-proxy在任意平台上均可交叉编译,无需目标环境:
# macOS arm64(Apple Silicon)
bun build --compile --minify --target=bun-darwin-arm64 src/index.ts --outfile dist/model-proxy-macos-arm64
# macOS x64(Intel)
bun build --compile --minify --target=bun-darwin-x64 src/index.ts --outfile dist/model-proxy-macos-x64
# Linux x64
bun build --compile --minify --target=bun-linux-x64 src/index.ts --outfile dist/model-proxy-linux-x64
# Linux arm64
bun build --compile --minify --target=bun-linux-arm64 src/index.ts --outfile dist/model-proxy-linux-arm64
# Windows x64
bun build --compile --minify --target=bun-windows-x64 src/index.ts --outfile dist/model-proxy-windows-x64.exe# 赋予执行权限(Linux / macOS)
chmod +x dist/model-proxy
# 通过 CLI 参数运行
./dist/model-proxy --port 3000 --target https://api.openai.com --map mcs-5:claude-sonnet-4-6
# 通过配置文件运行
./dist/model-proxy --config config.jsonWindows:
.\dist\model-proxy-windows-x64.exe --config config.json| 参数 | 说明 | 默认值 |
|---|---|---|
--port <n> |
本地监听端口 | 3000 |
--target <url> |
上游 API 地址 | 必填 |
--map <alias>:<model> |
模型映射,可多次使用 | — |
--config <path> |
JSON 配置文件路径 | — |
--log |
开启请求 / 响应日志 | 关闭 |
--log-dir <path> |
日志目录(自动开启日志) | ./logs |
客户端 代理 上游 API
│ │ │
│── POST /v1/chat/... ────>│ │
│ model: "mcs-5" │── model: "claude-sonnet-4-6" ──>│
│ │ │
│ │<── model: "claude-sonnet-4-6" ──│
│<── model: "mcs-5" ───────│ │
代理使用 TransformStream 逐块处理 SSE 数据,通过行缓冲确保跨 chunk 边界的行完整性。
- OpenAI:替换每条
data:JSON 中的顶层model字段,data: [DONE]原样透传 - Anthropic:仅替换
message_start事件中的data.message.model,其他事件类型直接透传,避免不必要的 JSON 解析
根据请求路径自动区分 API 格式:
/v1/messages→ Anthropic- 其他路径 → OpenAI 兼容格式
import OpenAI from "openai";
const client = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
baseURL: "http://localhost:3000/v1", // 指向本地代理
});
const response = await client.chat.completions.create({
model: "mcs-5", // 发送别名,代理自动转换
messages: [{ role: "user", content: "Hello" }],
});
console.log(response.model); // "mcs-5"(别名被还原)import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic({
apiKey: process.env.ANTHROPIC_API_KEY,
baseURL: "http://localhost:3000", // 指向本地代理
});
const message = await client.messages.create({
model: "mcs-5",
max_tokens: 1024,
messages: [{ role: "user", content: "Hello" }],
});
console.log(message.model); // "mcs-5"src/
├── index.ts # 入口:加载配置,启动 Bun.serve
├── config.ts # CLI 参数和 JSON 配置文件解析
├── proxy.ts # HTTP 代理逻辑(流式 + 非流式)
├── transform.ts # model 字段替换(请求、响应、SSE)
└── logger.ts # 异步日志写入(串行队列)