这篇只讲一件事:把 LiteLLM 这个开源 AI 网关在自己机器上真正跑起来,跑到能发虚拟 Key、能看到每条请求的日志、主力模型挂掉时能自动切到备用模型为止。选型层面的横向比较(LiteLLM 和 New API、One API 怎么选)在如何搭建自己的中转站点里已经写过,本文不重复,只做单个工具的落地。
下面的命令都在一台 Apple Silicon 的 macOS 上跑过一遍:Python 3.12 虚拟环境、LiteLLM 1.99.0(2026-09-01 发布的版本)、Homebrew 装的 PostgreSQL 16,上游用了本机 Ollama 的 qwen3.5:9b 加两把故意写坏的云端 Key。之所以特意留两把坏 Key,是因为兜底这种功能不真打挂一次,你永远不知道它到底有没有生效。
先分清 SDK 和 Proxy,这是两件事
LiteLLM 这个名字底下其实装着两个东西,很多人一上来就搞混:
- Python SDK:
from litellm import completion,在你自己的代码里用统一写法调一百多家模型,进程内跑,不额外起服务。适合单个脚本、单个应用。 - Proxy Server:一个独立进程,默认监听 4000 端口,对外暴露 OpenAI 兼容接口。所有客户端只认这一个地址,Key 治理、计费、限流、日志、路由都发生在这里。
判断标准很简单:只有一个调用方就用 SDK,两个以上调用方就上 Proxy。 本文讲的是 Proxy。
图 1:Proxy 模式下的位置。下游只需要记住一个 Base URL 和一把网关签发的 Key,上游厂商的原始 Key 只存在网关一处。
十分钟起一个能用的网关
装
官方 README 现在推荐 uv,但 pip 一样能用,而且更容易和现有项目环境对齐:
python3.12 -m venv .venv
./.venv/bin/pip install 'litellm[proxy]'
./.venv/bin/litellm --version装完确认一下版本,别只看文档:
LiteLLM: Current Version = 1.99.0如果只是想立刻试一下,一条命令就能起:litellm --model gpt-4o。但这种起法没有配置文件,什么都改不了,看完就该走配置文件路线。
写最小可用配置
新建 config.yaml。这一版刻意只写必要的东西:
model_list:
- model_name: qwen-local
litellm_params:
model: ollama_chat/qwen3.5:9b
api_base: http://127.0.0.1:11434
- model_name: gpt-4o
litellm_params:
model: openai/gpt-4o
api_key: os.environ/OPENAI_API_KEY
litellm_settings:
drop_params: true
request_timeout: 120
general_settings:
master_key: os.environ/LITELLM_MASTER_KEY三个点值得说清楚:
- `model_name` 是别名,`litellm_params.model` 才是真实路由目标。 下游只认别名,你换厂商、换型号,改这一行就行,调用方零改动。
- `os.environ/XXX` 是 LiteLLM 的取值语法,不是 shell 展开。密钥别写进 YAML,这个文件多半要进 Git。
- `drop_params: true` 建议默认开。 不同厂商支持的参数不一样,客户端传了个上游不认的字段,开着这个开关会自动丢掉而不是整条请求报错。
起服务并验证
LITELLM_MASTER_KEY=sk-demo-1234 \
OPENAI_API_KEY=sk-placeholder \
litellm --config config.yaml --port 4000启动日志末尾会把加载到的别名列出来,这是第一道检查:
LiteLLM: Proxy initialized with Config, Set models:
qwen-local
gpt-4o然后打两个请求。先看健康检查和模型列表:
curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:4000/health/liveliness
curl -s http://127.0.0.1:4000/v1/models -H "Authorization: Bearer sk-demo-1234"再打一次真正的对话,确认它是真转发而不是只返回了个空壳:
curl -s http://127.0.0.1:4000/v1/chat/completions \
-H "Authorization: Bearer sk-demo-1234" \
-H "Content-Type: application/json" \
-d '{
"model": "qwen-local",
"messages": [{"role": "user", "content": "用一句话说明 API 网关的作用"}],
"max_tokens": 800,
"reasoning_effort": "none"
}'本机 qwen3.5:9b 回的是:「API 网关作为系统的统一入口,负责集中管理所有 API 请求的认证、限流、路由转发和监控等跨服务逻辑,从而屏蔽后端复杂性并保障系统安全与稳定。」用量是 19 个输入 token、42 个输出。到这一步,网关就已经能用了。
顺带一提,用推理型模型做冒烟测试有个小陷阱:不加 reasoning_effort: "none" 的话,模型会把 max_tokens 全花在思考链上,content 返回空字符串,reasoning_content 里全是思考过程。第一次遇到很容易误判成「网关没接通」。
图 2:直接用浏览器打开 http://127.0.0.1:4000/,是一份自动生成的 Swagger 文档。排查「这个端点到底叫什么」比翻文档快。
把配置写成生产的样子
最小配置能跑,但离能用还差一段。真正要长期跑的配置,至少还得补三件事。
一个别名挂多个部署
同一个 model_name 可以写多次,LiteLLM 会把它们当成同一个模型组的多个部署,在其间做负载均衡和故障切换:
model_list:
- model_name: gpt-4o
litellm_params:
model: openai/gpt-4o
api_key: os.environ/OPENAI_API_KEY
rpm: 60
- model_name: gpt-4o
litellm_params:
model: azure/gpt-4o-eastus
api_base: os.environ/AZURE_API_BASE
api_key: os.environ/AZURE_API_KEY
api_version: "2024-10-21"
rpm: 120rpm 不只是限流,也是 usage-based-routing-v2 分配流量的依据——两个部署一个 60、一个 120,压力会按比例倾斜到配额更宽的那边。
路由策略和跨模型兜底
router_settings:
routing_strategy: usage-based-routing-v2
num_retries: 2
allowed_fails: 3
cooldown_time: 30
fallbacks:
- gpt-4o: ["claude-sonnet", "qwen-local"]这段的意思是:gpt-4o 这一组内部先重试 2 次;同一部署连错 3 次就冷却 30 秒不再派活;整组都不行,按顺序降级到 claude-sonnet,再不行落到本地 qwen-local。模型路由的价值就体现在最后这个本地兜底上——云端全挂的时候,至少还能返回点东西。
一定要真的打挂一次
配置写完不等于生效。把两把云端 Key 都换成无效值,然后请求 gpt-4o,看响应头:
curl -s -D - -o /dev/null http://127.0.0.1:4000/v1/chat/completions \
-H "Authorization: Bearer sk-demo-1234" \
-H "Content-Type: application/json" \
-d '{"model":"gpt-4o","messages":[{"role":"user","content":"只回答两个字:你好"}],"max_tokens":200,"reasoning_effort":"none"}'我这边拿到的是:
HTTP/1.1 200 OK
x-litellm-model-name: ollama_chat/qwen3.5:9b
x-litellm-model-group: qwen-local
x-litellm-model-api-base: http://127.0.0.1:11434
x-litellm-version: 1.99.0
x-litellm-attempted-retries: 0
x-litellm-attempted-fallbacks: 2
x-litellm-response-duration-ms: 437.109
x-litellm-overhead-duration-ms: 6.084请求方要的是 gpt-4o,实际答话的是本机 qwen——attempted-fallbacks: 2 说明降级链完整走了两跳。*这一组 `x-litellm-` 响应头是排障时最有用的东西**,比翻日志快得多:网关自身开销只占 6 毫秒,剩下的都是上游耗时,谁慢一目了然。
打开后台:虚拟 Key、预算和日志
到这里网关只有一把 master key,所有人共用,既分不清谁在花钱,也没法单独吊销。要解决这个,得给 LiteLLM 接一个 PostgreSQL。
先说那个只有真装过才会踩的坑
pip install 'litellm[proxy]' 装完之后配上 DATABASE_URL 启动,1.99.0 会直接崩:
LiteLLM Proxy:ERROR - Failed to import Prisma client: No module named 'prisma'
Exception: Unable to find Prisma binaries. Please run 'prisma generate' first.
ERROR: Application startup failed. Exiting.[proxy] 这个 extra 并不包含 prisma,得自己补,而且 prisma generate 必须在装好的 litellm 包目录里跑(schema.prisma 在那儿):
pip install prisma
cd .venv/lib/python3.12/site-packages/litellm/proxy
DATABASE_URL="postgresql://user@127.0.0.1:5432/litellm" prisma generate还有一个更细的:prisma generate 会调用 prisma-client-py 这个可执行文件,如果你的 venv 的 bin 不在 PATH 里,它会报 prisma-client-py: command not found 而不是缺依赖。把 venv 的 bin 加进 PATH 再跑就行。用官方 Docker 镜像的人遇不到这两条——镜像里已经 generate 过了。这也是为什么如果你不打算折腾 Python 环境,直接用镜像更省事。
补完再起,日志里会看到迁移自动跑完:
All migrations have been successfully applied.
prisma migrate deploy completed发一把带预算的 Key
后台的活也能用 API 干,写脚本更方便:
curl -s -X POST http://127.0.0.1:4000/key/generate \
-H "Authorization: Bearer sk-demo-1234" \
-H "Content-Type: application/json" \
-d '{
"key_alias": "frontend-demo",
"models": ["qwen-local"],
"max_budget": 5,
"budget_duration": "30d",
"rpm_limit": 20,
"metadata": {"team": "web"}
}'返回里带一把 sk- 开头的新 Key。拿它去调允许的模型正常,去调没授权的模型会被当场拦下:
{"error":{"message":"key not allowed to access model. This key can only access models=['qwen-local']. Tried to access claude-sonnet","type":"key_model_access_denied","param":"model","code":"403"}}这才是虚拟 API Key 的意义:给每个应用、每个成员发一把,各自带模型白名单、预算和频次上限,泄露了单独吊销,不牵连别人。
图 3:后台的 Virtual Keys 列表。刚才用 API 建的那把 Key 在这里能看到预算余量和重置时间,也可以直接在界面上建。
后台入口是 http://127.0.0.1:4000/ui。默认用户名 admin、密码是 master key;想换成别的,启动时加 UI_USERNAME 和 UI_PASSWORD 两个环境变量。
日志页是排障主战场
打了十几个请求之后,Logs 页面能看到每一条的耗时、TTFT、Key 别名、状态:
图 4:请求日志。中间那条 Failure 就是上面那次越权调用——权限拦截也会进日志,这对复盘「用户说调不通」很关键。
有一处要提前有心理准备:Cost 那一列可能一直是空的。LiteLLM 有一份内置价格表,本地模型和自定义部署不在表里,启动时会刷一堆这样的警告:
register_model: model=azure/gpt-4o-eastus not in built-in cost map and no prefix/region variant matched结果就是这些模型的成本按 0 计。要让成本统计有意义,得在 model_list 的 model_info 里手写单价。别看到日志里成本是 0 就以为不花钱。
图 5:Models + Endpoints 页面。同一个别名下的多个部署会分行列出,确认「别名到底指向了谁」比读 YAML 直观。
六个容易踩的坑
- 别把 master key 发给应用。 master key 权限等同管理员,能建 Key、能改配置。应用一律用虚拟 Key。
- `STORE_MODEL_IN_DB=True` 和配置文件会打架。 开了之后在后台加的模型存在数据库里,重启不会被 YAML 覆盖;两边都改容易出现「配置文件里明明删了但还在」的困惑。选一边作为唯一来源。
- `JWT_SECRET` 之类的密钥要固定住。 让程序每次启动自动生成,重启一次所有人的登录态就没了。
- 超时要按最慢的模型设。
request_timeout默认值对推理型模型偏紧,长思考链很容易被网关自己掐断,看起来像上游超时。 - 健康检查用 `/health/liveliness`,别用 `/`。 根路径是 Swagger 页面,任何时候都返回 200,拿它做探针等于没做。
- Cost 列为 0 不等于免费,见上一节。
谁适合用,谁可以跳过
适合:手上有两家以上模型供应商、需要给多个应用或多个同事分发访问权限、需要按团队归因成本、或者想在云端模型之外挂一个本地模型做兜底的人。LiteLLM 的强项是配置表达力——路由策略、重试、降级、预算这些都能在一个 YAML 里说清楚。
可以跳过:只有一个应用调一家模型的,直连官方 SDK 就够了,多一层网关只是多一个故障点;只想要个能聊天的网页界面的,装 Open WebUI 一类的前端更直接。
要注意的:LiteLLM 的迭代非常快,版本号一天能跳好几个小版本。生产环境务必锁定具体版本,别写 latest,也别指望网上半年前的配置片段还能原样跑通——本文里 prisma 那个坑就是版本相关的。
替代方案
- 官方 Docker 镜像:
ghcr.io/berriai/litellm,省掉 Python 环境和 prisma 的所有麻烦,团队部署优先选这个。 - New API / One API:中文界面、内置充值和分销,适合要给外部用户开账号的场景,配置表达力不如 LiteLLM。见中转站搭建指南。
- [OpenRouter](/tools/openrouter):不想自己维护任何东西,接受把请求交给第三方,它是最省事的托管选择。
- Kong / Higress 的 AI 插件:已经在用这些 API 网关的团队,直接加插件比多引入一个服务合理。
参考来源与核对方式
- BerriAI/LiteLLM 项目仓库 —— 功能说明、安装方式与配置字段。
- LiteLLM 官方文档 —— Proxy、Router 与虚拟 Key 的行为定义。
- PyPI · litellm —— 版本号与发布时间,本文核对时最新为 1.99.0(2026-09-01)。
文中的命令输出、响应头和界面截图,均来自 2026-09-04 在本机跑通的那一次部署。版本号、内置价格表覆盖范围和 `[proxy]` extra 的依赖清单都属于易变信息,跟着新版本变化,照抄前先用 litellm --version 对一下自己装的是哪一版。