如果你同时对接过三家以上大模型厂商的 API大概率体会过那种“每家都长得差不多每家都不一样”的憋屈。请求体里的字段名不同、认证方式不同、返回结构不同甚至同一个模型名在不同平台下的效果也天差地别。以前我的处理方式是在业务代码里堆一堆 if-else后来项目越来越多这种胶水代码成了最想删又最不敢删的部分。直到我开始用 litellm才把这块彻底从业务里剥了出去。litellm 是一个开源的 LLM 网关/代理简单说它把你的模型请求统一收口成一个业界常见的 chat/completions 风格 API后端再转发到各家模型服务。对调用方来说只需要知道一个地址、一个密钥、一种格式对平台方来说模型路由、成本统计、访问控制全部集中在一个点上。适合谁用后端开发者、AI 平台运维、想在公司内部做一套统一 AI 接入层的小团队甚至自己手里有好几个 API key 的个人玩家都能从中找到实用价值。1. 先搞清楚痛点为什么要“收口”1.1 一个真实场景三套 API 并存的日子我之前维护一个内部工具平台里面接了三个不同厂家的模型服务。起初只接一家代码很简单请求发出去JSON 返回解析 content 字段就完事。后来想对比不同模型的效果就接了第二家麻烦开始出现。第二家的认证方式不一样请求体里要求把历史消息放在一个嵌套结构里返回结果还多包了一层。为了统一我只能在服务层写适配函数。接第三家的时候问题彻底爆发。第三家的流式返回格式和前两家完全不同超时时间也短经常需要单独调参数。那段时间每次加新功能模型调用部分的代码改动量都超过业务逻辑本身。更难受的是前端同事想做一个对话测试页面需要同时调用三个接口每个接口的鉴权和传参方式都不一样开发效率直接被拖垮。1.2 litellm 的核心定位litellm 做的事本质上就是“流量收口”。它部署好后你只需要向 litellm 发起请求格式是统一的至于后端是哪家模型、用什么鉴权、怎么重试全部由 litellm 转发时处理。它的核心价值体现在四个层面格式统一调用方拿到的始终是同一种 API 结构参数名、返回结构、错误格式都标准化。路由集中不同业务线可以访问同一个网关由网关决定流量走哪个模型不用各自维护。密钥安全API key 不会散落在各个服务里统一存在 litellm 配置中。可观测性所有请求的 token 数、成本、延迟在一个地方统计方便做预算控制。最初我以为它只是一个“代理转发”用了一段时间才意识到真正的价值在于把模型接入变成配置项而不是代码。接新模型时不需要改业务代码改配置文件就能上线这意味着整个系统对模型变更的响应速度有了质的提升。2. 部署与配置五分钟跑起一个网关2.1 安装与依赖Python 环境就行litellm 是基于 Python 的所以机器上装好 Python 3.8 即可。我一般用虚拟环境避免污染系统环境python -m venv venv source venv/bin/activate # Windows 下是 venv\Scripts\activate然后安装带代理功能的包pip install litellm[proxy]这个命令会装好核心依赖。建议装到固定版本不要随手升级。我在生产环境吃过一次亏某次升级后配置文件中一个旧字段失效导致启动直接失败后来还是靠看 changelog 才解决。所以如果你是想稳定使用最好把版本号锁住例如pip install litellm[proxy]1.40.0。装完后命令行直接输入litellm就能看到帮助信息。默认端口是 4000改端口可以用--port。2.2 最小配置文件从 .env 到 config.yamllitellm 支持两种常见配置方式环境变量和 YAML 文件。我推荐用 YAML因为模型列表这种结构用 YAML 更直观。先在项目目录创建一个.env文件把各家的 API key 放进去export PROVIDER1_API_KEYsk-xxxx1 export PROVIDER2_API_KEYsk-xxxx2 export LITELLM_MASTER_KEYsk-liteLLM-master-key然后写一个最小config.yamlmodel_list: - model_name: assistant-a litellm_params: model: provider1/model-a api_key: os.environ/PROVIDER1_API_KEY - model_name: assistant-b litellm_params: model: provider2/model-b api_key: os.environ/PROVIDER2_API_KEY general_settings: master_key: os.environ/LITELLM_MASTER_KEY这里的model_name是对外暴露的模型别名业务方只需要知道这个别名。litellm_params里的model字段是真正的后端模型路径格式一般是“厂商名/模型名”。api_key可以直接写明文但更稳妥是通过os.environ/变量名引用环境变量。启动时用litellm --config config.yaml --port 4000看到类似Uvicorn running on http://0.0.0.0:4000的日志就说明网关起来了。这时候随便用一个 HTTP 客户端往http://localhost:4000/v1/chat/completions发请求只要模板和格式正确就能正常返回。2.3 路由规则与模型映射很多人在配置阶段会忽略路由直接写一个模型就完事。但实际项目里我建议一开始就想清楚“别名”和“真实模型”的映射关系。比如公司有两个业务线一个偏成本敏感一个偏效果优先那么可以在同一个model_name后面配多个真实模型并通过路由策略区分。litellm 支持按请求参数做路由。一个典型需求是不同租户走不同模型或者按用户级别分配模型。可以在model_list中给每个模型加tags然后在请求时通过metadata指定model_list: - model_name: assistant litellm_params: model: provider1/model-a api_key: os.environ/PROVIDER1_API_KEY tags: - premium - model_name: assistant litellm_params: model: provider2/model-b api_key: os.environ/PROVIDER2_API_KEY tags: - standard请求时带上{ model: assistant, messages: [...], metadata: { tags: [premium] } }这样网关会优先选择带premium标签的模型如果没有匹配的再回退到其他模型。这个能力很实用可以让你在不改业务代码的情况下动态调整模型分配策略。3. 核心功能解析不止是“转发”3.1 统一 API 格式把各家参数变成一套litellm 官方最亮眼的能力就是可以把不同厂商的请求转换成同一个格式。调用方只需要知道 chat/completions 这种标准格式litellm 会在内部完成映射。比如某些平台要求系统提示词用特定字段或者在multi_modal内容里有特殊格式这些细节都被封装了。我实际感受最深的是流式输出的统一。做对话应用时流式几乎不可避免。不同厂家的流式事件格式不一样有的用data:前缀有的分多个事件类型如果自己的服务暴露给前端很不稳定。litellm 会把后端流式输出统一转换成 OpenAI 风格的 SSE 格式前端只处理一种事件即可。这一点省了我大量适配工作。另外它还可以做 prompt 模板管理不过这需要额外配置。我不建议在网关注入太多业务模板保持简单更好因为模板一旦复杂调试成本会上升。3.2 成本追踪与预算限制项目账单不再糊涂做 AI 应用的人都知道大模型 API 费用是个让人头疼的问题。尤其多人共用一个 key、多个应用共享一个入口时月底账单根本分不清是哪个项目花的钱。litellm 内置了成本追踪可以为每个请求打上标记并记录 token 消耗。开启成本追踪需要配置数据库。我用的 SQLite轻量够用general_settings: database_url: sqlite:///litellm.db启动后litellm 会自动创建相关表。请求时会记录模型、token 数、成本估算、用户 ID 等信息。然后可以设置预算上限general_settings: max_budget: 100 # 美元所有请求累计 budget_duration: 30d也可以在用户维度设置预算比如某个内部应用每月只能花 20 美元。超了之后网关直接返回 429请求不会被转发到后端。这个功能对团队内部共享 API 场景帮助极大能有效避免“谁偷偷跑了个大任务月底账单爆掉”的情况。需要注意成本估算依赖于 litellm 内置的价格表如果新模型不在价格表里成本计算会不准。解决办法是在配置里手动补充cost_per_token参数或者在模型列表里指定价格信息。我一般对常用模型验证一下价格表确保不会差太多。3.3 多租户与密钥管理API Key 不会到处飞在没有网关的时候每个后端服务都要存一份厂商 API key一旦 key 需要轮换你得跑到所有机器上改。用 litellm 之后厂商 key 只存在网关配置里业务方不需要知道真实 key他们用的是 litellm 自己签发的虚拟 key。启动服务前先设置master_key这是管理员密钥。通过这个密钥调用虚拟 key 管理接口可以为每个项目生成一个独立的sk-xxxx格式的 key并给这个 key 绑定预算、速率限制、允许访问的模型范围。比如 A 项目只能用模型 aB 项目只能用模型 b互不干扰。我在实际项目中给三个团队各分配了一个虚拟 key团队 X 的 key 只能访问 assistant-a每分钟限 10 次。团队 Y 的 key 可以访问 assistant-a 和 assistant-b每天限 100 万 token。临时测试 key 有效期只有 1 天过期自动失效。这些配置都可以在管理接口或 dashboard 中完成。dashboard 是 litellm 自带的可视化界面启动时加--ui参数就能访问。界面虽然不算华丽但基础的管理功能都有适合不想敲命令行的同事用。3.4 fallback 与重试宕机时的容错策略另一个很容易被忽略但极其重要的功能是 fallback。后端模型服务不可能永远高可用有时候限流有时候超时有时候直接 5xx。为了让业务不受影响litellm 支持配置失败回退。配置 fallback 的方式是在请求参数里带上fallbacks或者通过 config 里的 router_settings 全局设置。我在 config 中常用的形式router_settings: fallbacks: - model_group: assistant-a fallback_model_group: assistant-b意思是如果assistant-a连续失败流量自动切到assistant-b。这样业务方感知到的只是响应变慢而不会直接拿到报错。还可以设置重试次数和超时时间router_settings: num_retries: 2 request_timeout: 30 allowed_fails: 1num_retries是重试次数allowed_fails是熔断阈值超过阈值后一段时间内不再向故障模型转发流量。这一套配置下来比自己在业务里写重试优雅得多。4. 常见问题与排查实录4.1 模型报 404 或 400多半是路径和参数问题我遇到过好几次代理正常启动但请求返回 404。排查发现问题是后端模型的路径写错了。不同厂商的模型命名不一样有些厂商要求“厂商名/模型名”有些则写成“deployment/模型名”。litellm 能不能正确识别取决于model字段的写法是否匹配它内置的厂商映射。如果你不确定可以先在 litellm 命令行里做一次测试比如用litellm --model provider/model --test看看是否能通。还有 400 错误常见原因是请求参数超出了后端模型的限制比如某模型不支持max_tokens这个字段或者把它写成了旧版本的名字。litellm 不会对所有参数做无损透传在转换过程中它有自己的参数名映射规则。遇到 400 时建议打开 debug 日志看看网关实际发给了后端什么请求体很快就能定位。4.2 Token 计数不准与上下文超限成本追踪依赖 token 计数。litellm 默认对不同厂商模型使用不同的 tokenizer但偶尔新模型 tokenizer 未内置计数会偏差很大。一个典型现象代理显示的 token 数远小于实际消耗导致成本估算过低。我踩过的坑是接了一个国内厂商的中文模型默认 tokenizer 按英文切分中文 token 数被严重低估预算控制完全失灵。解决办法是在模型配置里显式指定litellm_params中的max_tokens和输入长度限制必要时通过 litellm 的custom_tokenizer参数接一个自带的 tokenizer 实现。如果只是要一个粗略估算也可以手动在配置里填cost_per_token至少保证账单不会差太多。上下文超限是另一个高频问题。业务方在不知道上下文窗口上限的情况下一次性传了大量历史消息litellm 会原样透传给后端然后后端返回 context length exceeded。建议是在网关层直接开启请求截断或摘要逻辑但这涉及业务语义不适合通用处理。更务实的方案是在网关侧做 token 数量预检超过阈值直接返回友好提示而不是让后端报一堆堆栈信息。4.3 高并发下的性能与超时调优litellm 底层是 FastAPI异步能力不错。但默认参数不一定适合高并发场景。我之前用默认配置跑生产50 个并发请求时延迟明显上升甚至出现 timeout。检查后发现是数据库写入锁竞争导致SQLite 在写操作密集时性能受限。如果并发量不高SQLite 完全够用如果要支撑更大的并发建议切换到 PostgreSQL。配置里改 database_url 即可表结构会自动迁移。另外可以把请求日志和成本统计的写入改成异步队列避免业务请求被审计操作拖慢。但我暂时没有走到这一步单实例加 PostgreSQL 足够支撑公司内部几十人的使用规模。超时设置也要注意。后端模型如果响应很慢默认的超时可能不够。litellm 支持在litellm_params里设置timeout或者在请求层设置request_timeout。我在流式场景下特别把超时调大因为流式响应首字节时间虽然快但整个读取过程可能持续很久如果网关误判超时切断连接用户看到的是一半内容突然断掉。4.4 安全加固与合规注意点虽然没有网关也能接入模型但安全性很难把控。litellm 提供了一些基础缓解手段比如 IP 白名单、虚拟 key、预算限制。我还会在网关上再套一层内部认证中间件确保只有内网服务可以访问。另外需要注意防止 prompt 注入。如果业务方直接把用户输入透传给模型别人可以构造恶意文本让模型注入提示。这个不全是网关的活但 litellm 支持在请求进入时做 token 级前处理比如屏蔽特定敏感内容虽然不是万能但至少能挡住一部分明显攻击。合规方面还有个容易被忽略的点日志。litellm 默认会记录部分请求信息如果你处理的是用户隐私数据得考虑脱敏。我在生成环境里会关闭内容级别的日志只保留元信息例如模型名、token 数、调用者 ID不记录 prompt 和 completion 内容。这个设置在 config 里可以控制但不同版本字段有差异升级前一定要看文档。5. 我的一些实操心得用了 litellm 差不多一年多我最大的感受是它帮我省掉的不仅是最初的“if-else 适配”更是一种系统层面的复杂度转移。以前接新模型我要写代码、发版、测试现在只需要往配置文件里加两行重载配置业务代码一行不动。这种变化看似简单实际影响却很大团队迭代模型的频率更快了出错的概率也更低。我还建议如果你决定采用 litellm尽早把模型别名规范建立起来。比如统一用业务语义命名不要用厂商名加版本号。因为业务方只关心“我要一个能对话的模型”而不是“我要某厂的某个模型”好的别名设计可以让你后续调整模型时无感切换。另外litellm 的社区版本迭代速度很快新功能也很多但生产环境里我倾向于“稳”字优先。不要频繁追新先在测试环境跑一段时间确认没有回归再升级。最后分享一个小技巧在排查问题时用 curl 直接请求 litellm 接口加-v参数看完整响应头然后再对比直连后端模型服务的响应就能很快定位问题出在转换层还是后端层。这个方法我用了无数次几乎是排查 litellm 相关问题的第一手段。希望这篇东西能帮你少走一点弯路把这工具真正用起来。