LiteLLM 网关部署实战:从一条 pip 命令到虚拟 Key、预算和自动兜底

2 查看LiteLLMAI网关OpenAI兼容虚拟Key模型路由

把 LiteLLM 1.99.0 在本机从零装起来的完整记录:最小可用配置、启动验证、故意打挂主力模型看兜底、开后台发虚拟 Key 和预算,以及 pip install 'litellm[proxy]' 之后仍然缺 prisma 这类只有真装过才会遇到的坑。

这篇只讲一件事:把 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 SDKfrom litellm import completion,在你自己的代码里用统一写法调一百多家模型,进程内跑,不额外起服务。适合单个脚本、单个应用。
  • Proxy Server:一个独立进程,默认监听 4000 端口,对外暴露 OpenAI 兼容接口。所有客户端只认这一个地址,Key 治理、计费、限流、日志、路由都发生在这里。

判断标准很简单:只有一个调用方就用 SDK,两个以上调用方就上 Proxy。 本文讲的是 Proxy。

你的应用 G 脚本 / Notebook 聊天前端 / CLI 工具 OpenAI Anthropic 本地 Ollama 虚拟 Key · 预算 · 限流请求日志 · 用量统计

图 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 里全是思考过程。第一次遇到很容易误判成「网关没接通」。

LiteLLM 启动后浏览器打开根路径显示的 Swagger 文档页,左侧列出 chat/completions、embeddings、models 等 OpenAI 兼容端点

LiteLLM 启动后浏览器打开根路径显示的 Swagger 文档页,左侧列出 chat/completions、embeddings、models 等 OpenAI 兼容端点

图 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: 120

rpm 不只是限流,也是 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 的意义:给每个应用、每个成员发一把,各自带模型白名单、预算和频次上限,泄露了单独吊销,不牵连别人。

LiteLLM 管理后台 Virtual Keys 页面,列表里有一条 frontend-demo 的 Key,显示 Spend/Budget 为 0.00 of 5 美元,以及创建时间和预算重置日期

LiteLLM 管理后台 Virtual Keys 页面,列表里有一条 frontend-demo 的 Key,显示 Spend/Budget 为 0.00 of 5 美元,以及创建时间和预算重置日期

图 3:后台的 Virtual Keys 列表。刚才用 API 建的那把 Key 在这里能看到预算余量和重置时间,也可以直接在界面上建。

后台入口是 http://127.0.0.1:4000/ui。默认用户名 admin、密码是 master key;想换成别的,启动时加 UI_USERNAMEUI_PASSWORD 两个环境变量。

日志页是排障主战场

打了十几个请求之后,Logs 页面能看到每一条的耗时、TTFT、Key 别名、状态:

LiteLLM 管理后台 Request Logs 页面,十几条请求记录按时间倒序排列,多数为 Success,其中一条状态为 Failure,Key Alias 列显示 frontend-demo 与 litellm_proxy

LiteLLM 管理后台 Request Logs 页面,十几条请求记录按时间倒序排列,多数为 Success,其中一条状态为 Failure,Key Alias 列显示 frontend-demo 与 litellm_proxy

图 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_listmodel_info 里手写单价。别看到日志里成本是 0 就以为不花钱。

LiteLLM 管理后台 Models + Endpoints 页面,表格列出配置文件里加载的模型别名、对应的上游部署与所属提供商

LiteLLM 管理后台 Models + Endpoints 页面,表格列出配置文件里加载的模型别名、对应的上游部署与所属提供商

图 5:Models + Endpoints 页面。同一个别名下的多个部署会分行列出,确认「别名到底指向了谁」比读 YAML 直观。

六个容易踩的坑

  1. 别把 master key 发给应用。 master key 权限等同管理员,能建 Key、能改配置。应用一律用虚拟 Key。
  2. `STORE_MODEL_IN_DB=True` 和配置文件会打架。 开了之后在后台加的模型存在数据库里,重启不会被 YAML 覆盖;两边都改容易出现「配置文件里明明删了但还在」的困惑。选一边作为唯一来源。
  3. `JWT_SECRET` 之类的密钥要固定住。 让程序每次启动自动生成,重启一次所有人的登录态就没了。
  4. 超时要按最慢的模型设。 request_timeout 默认值对推理型模型偏紧,长思考链很容易被网关自己掐断,看起来像上游超时。
  5. 健康检查用 `/health/liveliness`,别用 `/`。 根路径是 Swagger 页面,任何时候都返回 200,拿它做探针等于没做。
  6. 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 网关的团队,直接加插件比多引入一个服务合理。

参考来源与核对方式

文中的命令输出、响应头和界面截图,均来自 2026-09-04 在本机跑通的那一次部署。版本号、内置价格表覆盖范围和 `[proxy]` extra 的依赖清单都属于易变信息,跟着新版本变化,照抄前先用 litellm --version 对一下自己装的是哪一版。