一个不到 15MB 的 Go 二进制,让你把 OpenAI、Anthropic、Azure、Ollama 全部塞进一个 localhost:18080 里。


为什么需要这个东西?

事情很简单:我的机器上跑着好几个 LLM API 的客户端——OpenCode、Claude Code、自己写的脚本、前端调试工具。每个都要配置不同的 base_urlapi_keymodel,而且这几个值散落在 ~/.config/opencode.json、环境变量、.env 文件、脚本硬编码里……

改一个后端地址,六七个地方都要动。

更烦的是,有些工具只支持 OpenAI 协议,有些只支持 Anthropic。你的后端是 Anthropic 但客户端只认 OpenAI?对不起,调不通。

LLM API Proxy 就是来解决这个问题的——一个端口,双协议,所有后端统一入口


一句话说清楚它是干嘛的

你所有的 API 客户端 → localhost:18080 → 任意后端(OpenAI/Anthropic/Ollama/Azure)

再直白点:你在客户端把 base_url 全部改成 http://localhost:18080/v1,配一个统一的 API Key,然后后端随便换、随便加,客户端一行代码不用改。

当然,他还有一个作用,就是吧所有Agent的请求都记录到你的数据库中,方便你研究AI的思考过程。🤭


架构就是个透明代理

curl / OpenCode / Claude Code
         │
         ▼
  ┌─────────────────────┐
  │  LLM API Proxy      │
  │                     │
  │  /v1/chat/completions──→ OpenAI 后端 (mimo / DeepSeek / Ollama)
  │  /v1/messages       ──→ Anthropic 后端 (Claude)
  │  /v1/models         ──→ 透传
  │  /v1/embeddings     ──→ 透传
  │                     │
  │  ✅ 全量日志 → MongoDB
  └─────────────────────┘

不解析请求、不改模型参数、不做协议魔法转换。透明转发,就跟 nginx 反代一样,只是它同时支持两种 LLM 协议。


核心设计原则

1. 按协议路由,不做翻译

这是跟其他 LLM 代理最大的区别。常见的网关类项目喜欢做 OpenAI ↔ Anthropic 协议互译——把 /v1/messages 的 Anthropic 请求翻译成 /v1/chat/completions 再发给 OpenAI 后端。

我们这个不行。protocol: "anthropic" 的后端就是原样透传——Anthropic 格式进去,Anthropic 格式出来,零损耗。

为什么?第一,协议翻译必然丢字段(Anthropic 的 system 是顶层字段、stop_reason 语义不同、thinking 块没对应物)。第二,翻译本身是额外开销,你代理在中间做 JSON 重写,延迟直接上去。

简单说:后端是什么协议就用什么协议直通,不装聪明。

2. 多后端动态切换

配置文件里可以挂任意多个后端,每个带上协议标签:

backends:
  - name: "mimo"
    base_url: "https://token-plan-cn.xiaomimimo.com/v1"
    protocol: "openai"
    default: true

  - name: "claude"
    base_url: "https://api.anthropic.com"
    protocol: "anthropic"
    api_key: "sk-ant-xxxx"

  - name: "ollama"
    base_url: "http://localhost:11434/v1"
    protocol: "openai"

运行时通过 X-Backend 请求头切换,不用重启服务:

# 切到 Ollama
curl http://localhost:18080/v1/chat/completions \
  -H "X-Backend: ollama" \
  -d '{"model":"llama3","messages":[{"role":"user","content":"hi"}]}'

3. MongoDB 可选的日志系统

每次 API 调用自动记录到 MongoDB:请求体、响应体、耗时、状态码、后端名、客户端 IP。Authorization 自动脱敏。

关键设计:MongoDB 挂了不影响代理服务。启动时连不上就降级,日志写入变成 no-op,服务照常跑。你不需要为了跑个代理还要维护一个数据库实例。

// MongoDB 查询——按后端统计调用量
db.api_logs.aggregate([{$group: {_id: "$backend_name", count: {$sum: 1}}}])

// 查看慢请求
db.api_logs.find({duration_ms: {$gte: 10000}}).sort({timestamp: -1})

技术实现

Go 标准库 net/http/httputil.ReverseProxy,没用什么花哨框架。核心文件三个:

llm-proxy/
├── main.go                    # 入口 + 路由注册
├── internal/
│   ├── config/config.go       # YAML 配置加载 + 协议默认值
│   ├── handler/proxy.go       # 反向代理核心 + 日志捕获
│   ├── handler/anthropic.go   # Anthropic 端点处理
│   └── store/mongo.go         # MongoDB 存储层

编译出来一个 15MB 左右的二进制,无运行时依赖,直接丢服务器上 ./llm-proxy 就跑。

几个实现细节:

  • 流式 SSE —— captureResponseWriter 包装了 http.ResponseWriter,非流式完整捕获 body,流式从 data: 行中拼接 content 字段存库

  • 路径不重复拼接 —— base_url 里的 /v1 不会跟客户端请求的 /v1 拼成 /v1/v1,反向代理的 Director 里做了 TrimPrefix

  • Host 头重写 —— req.Host 在 Director 中显式设为后端 Host,避免 Go net/http 默认行为把 Host 设成目标 URL 而非请求原始 Host,导致 WAF 403

  • Anthropic 鉴权 —— 直透传模式用 x-api-key,不走 Authorization: Bearer

  • nil-safe 存储 —— MongoStore.InsertLog() 零接收器直接 return,主程序就算没连上 MongoDB 也不 panic


Claude Code 集成

很多人用 Claude Code 做开发。配置方式就一行:

export ANTHROPIC_BASE_URL="http://localhost:18080/v1"
export ANTHROPIC_API_KEY="sk-proxy-demo-key-2024"

然后 claude 命令的所有请求都走代理,后端可以随时切换到任何兼容服务。


跟其他方案的区别

特性

LLM API Proxy

one-api

LiteLLM

二进制大小

~15MB

~50MB+

~200MB+ (Python)

运行时依赖

MySQL + Redis

Python + pip

多协议支持

OpenAI + Anthropic

OpenAI only

多协议但做翻译

协议处理

透明透传

透明透传

格式翻译

日志存储

MongoDB(可选)

MySQL

多种

配置方式

YAML 单文件

Web UI

YAML + 环境变量

LLM API Proxy 的定位很清晰:极简、透明、可靠。不提供 Web 管理界面,不走数据库依赖,不在中间做协议转换。就是一台反向代理,做得非常纯粹。


快速上手

# 1. 克隆
git clone https://gitee.com/yang_davip/llm-proxy.git
cd llm-proxy

# 2. 编辑配置
vim config.yaml  # 填入你的后端地址和 API Key

# 3. 编译启动
go build -o llm-proxy . && ./llm-proxy

# 4. 测试
curl http://localhost:18080/health
curl -X POST http://localhost:18080/v1/chat/completions \
  -H "Authorization: Bearer sk-proxy-demo-key-2024" \
  -d '{"model":"mimo-v2.5-pro","messages":[{"role":"user","content":"hi"}]}'

启动后把你要用的所有工具的 base_url 全部指向 http://localhost:18080/v1,后端随便换。


后续

项目在 Gitee 上开源:yang_davip/llm-proxy

TODO 列表里还有几个想做的:

  • 请求重试 + 限流熔断

  • /metrics 端点(Prometheus 格式)

  • 请求级缓存(相同 prompt 直接返回缓存结果)

  • Docker 一键部署

欢迎 Issue 和 PR。


写于 2026 年 6 月的一个下午。