1. 项目概述与核心定位1.1 这个项目到底解决什么问题第一次接触 litellm 是在一个多模型混用的项目里。当时团队同时接入了好几个不同厂商的大模型服务每个平台的接口规范、鉴权方式、返回结构都不一样代码里到处是 if-else 分支维护起来非常头疼。litellm 就是在这个背景下进入视野的——它本质上是一个统一的大模型调用中间层用一套 OpenAI 兼容的接口格式去对接市面上几乎所有主流的大模型服务。说白了它的核心价值就一句话让你用同一套代码调用不同厂商的模型。你不需要为每个平台单独写适配层不需要记住每家的参数命名差异也不需要为切换模型而重构业务逻辑。改一个模型名称字符串就能从一家服务切到另一家。这个项目适合谁我认为三类人最需要它一是做 AI 应用开发的工程师尤其是需要在多个模型之间做对比测试或动态路由的场景二是搭建内部 AI 网关的运维或平台团队需要统一管理密钥、限流、计费三是做研究和实验的开发者想快速在不同模型上跑同一套评测逻辑。哪怕你只是个人开发者想在自己的小工具里灵活切换模型litellm 也能省掉大量重复劳动。1.2 为什么是“统一接口”这个思路大模型服务这个领域过去两年最大的特点就是碎片化。每家厂商的 API 设计哲学不同有的用messages数组有的用prompt字符串有的返回choices[0].message.content有的返回output.text流式输出的 SSE 格式也各有各的写法。如果每个都单独适配代码量会随着接入模型数量线性增长。litellm 选择的做法是以 OpenAI 的接口规范为事实标准。这个选择很务实——OpenAI 的接口格式目前是业界最广泛被模仿和兼容的大量现有工具链、SDK、框架都围绕它构建。litellm 把其他厂商的接口“翻译”成这个格式相当于在混乱中建立了一个公约数。你学会一套调用方式就能覆盖绝大多数模型。这个设计思路的好处是迁移成本极低。你现有的基于 OpenAI SDK 写的代码只需要把base_url指向 litellm 的代理地址把模型名改成对应的标识其余几乎不用动。对于已经在用 OpenAI 接口的团队来说接入成本接近于零。1.3 核心能力全景litellm 的能力可以分成几个层次来理解。最基础的是统一调用支持上百种模型的标准化调用包括各大云厂商的商用模型和本地部署的开源模型。往上一层是代理网关提供一个独立的服务进程对外暴露 OpenAI 兼容的 HTTP 接口内部做路由、鉴权、限流、日志。再往上是成本追踪与预算控制能记录每次调用的 token 消耗和费用支持设置预算上限。还有负载均衡与故障转移同一个模型可以配置多个后端自动做权重分配和失败重试。这些能力组合起来litellm 就不只是一个 SDK 了而是一个轻量级的 AI 基础设施层。小团队可以用它快速统一调用入口大团队可以用它做多租户的模型网关。我见过不少公司把它当作内部 AI 平台的底座上面再叠加自己的业务逻辑。2. 核心架构与关键设计解析2.1 两层架构SDK 与 Proxylitellm 的架构分两个独立但互补的部分理解这个区分很重要因为很多人一开始会混淆。第一层是 Python SDK。你pip install litellm之后直接在代码里import litellm然后调用litellm.completion()就能发请求。这一层适合嵌入到你的应用代码里轻量、直接不需要额外起服务。它的工作方式是在运行时把统一的参数转换成目标厂商需要的格式发出去再把响应转换回统一格式。第二层是 Proxy Server。这是一个独立的服务通常用litellm --config config.yaml启动对外暴露一个 HTTP 端口。你的应用不直接调用各家模型而是把请求发给这个代理代理再转发。这一层适合多服务共享、集中管理密钥、统一审计的场景。两者的关系是Proxy 内部其实也是用 SDK 来发请求的只是外面包了一层 HTTP 服务和配置管理。所以你先搞懂 SDK 的调用逻辑Proxy 的配置就很容易理解了。2.2 模型路由的命名规则litellm 用前缀加模型名的方式来标识目标模型这个设计是整个项目的关键机制。格式大致是provider/model-name比如openai/gpt-4o、anthropic/claude-3-5-sonnet、azure/your-deployment、ollama/llama3这样。这个前缀决定了 litellm 用哪套转换逻辑、走哪个 API 端点、用哪个环境变量里的密钥。比如看到anthropic/前缀它就知道要去读ANTHROPIC_API_KEY把请求发到 Anthropic 的端点并按 Anthropic 的格式组装参数。注意模型名的拼写必须和 litellm 内部维护的映射表一致写错了会直接报“不支持的模型”。遇到不确定的模型名最稳妥的办法是查官方文档的模型列表或者用litellm.model_list打印当前版本支持的所有模型。对于自部署的模型比如用 Ollama 或 vLLM 起的服务前缀后面跟的是你本地的模型标识同时需要在参数里指定api_base指向你的服务地址。这种灵活性让 litellm 既能对接云服务也能对接私有部署。2.3 配置驱动的代理设计Proxy 的核心是一份 YAML 配置文件里面定义了模型列表、路由策略、密钥管理、限流规则等。这种配置驱动的设计好处是运维友好——改配置重启服务就能调整行为不需要改代码。一份典型的配置里model_list是核心每一项定义一个可用的模型包括它的对外名称、实际的后端模型、API 密钥来源、API 地址等。router_settings控制路由行为比如重试次数、超时时间、负载均衡策略。general_settings管全局的比如主密钥、数据库连接。我个人的经验是配置文件的组织要按环境分离。开发环境用一份配置生产环境用另一份通过环境变量注入密钥配置文件本身不进版本库或者只进脱敏版本。这样既方便管理又避免密钥泄露。2.4 成本追踪的实现逻辑成本追踪是 litellm 很实用的一个功能它的原理是内置了一张模型价格表记录了每个模型的输入输出 token 单价。每次调用完成后它根据实际消耗的 token 数乘以单价算出这次调用的费用。这个费用数据可以写到日志、回调或者数据库里。Proxy 模式下如果配置了数据库还能按用户、按密钥、按时间段做聚合统计。对于需要做成本分摊或者预算控制的团队这个功能省去了自己搭建计费系统的麻烦。提示内置价格表可能滞后于厂商调价如果对费用精度要求高建议定期核对官方价格必要时在配置里手动覆盖单价。我就遇到过某模型降价后litellm 内置价格还没更新的情况导致统计偏高。3. 实操部署与核心环节实现3.1 环境准备与安装先从最基础的 SDK 安装说起。Python 环境建议 3.8 以上用虚拟环境隔离依赖。python -m venv venv source venv/bin/activate pip install litellm如果你要用 Proxy 功能安装时带上额外依赖pip install litellm[proxy]这个[proxy]会装上 FastAPI、Uvicorn 等 Web 服务需要的包。安装完成后可以用litellm --version确认版本。密钥的管理我强烈建议用环境变量不要硬编码在代码或配置里。比如export OPENAI_API_KEYyour-key-here export ANTHROPIC_API_KEYyour-key-herelitellm 会自动读取这些约定俗成的环境变量名。不同厂商对应的变量名在官方文档里有完整列表配置前先确认清楚。3.2 SDK 直接调用实操最简单的调用长这样import litellm response litellm.completion( modelopenai/gpt-4o, messages[ {role: user, content: 用一句话解释什么是统一接口} ] ) print(response.choices[0].message.content)想换成另一个厂商的模型只改model参数response litellm.completion( modelanthropic/claude-3-5-sonnet-20241022, messages[ {role: user, content: 用一句话解释什么是统一接口} ] )其余代码完全不用动。这就是统一接口的威力。流式输出也支持加个streamTrueresponse litellm.completion( modelopenai/gpt-4o, messages[{role: user, content: 写一段关于秋天的散文}], streamTrue ) for chunk in response: delta chunk.choices[0].delta.content if delta: print(delta, end, flushTrue)注意不同厂商的流式返回在细节上可能有差异比如有的会在最后一个 chunk 里带 usage 信息有的不带。litellm 尽量做了统一但涉及 usage 统计时建议实测确认目标模型的行为。3.3 Proxy 服务搭建全流程Proxy 的搭建分几步。先写配置文件config.yamlmodel_list: - model_name: gpt-4o litellm_params: model: openai/gpt-4o api_key: os.environ/OPENAI_API_KEY - model_name: claude-sonnet litellm_params: model: anthropic/claude-3-5-sonnet-20241022 api_key: os.environ/ANTHROPIC_API_KEY general_settings: master_key: sk-your-master-key litellm_settings: drop_params: true这里model_name是对外暴露的名称客户端调用时用这个litellm_params.model是实际的后端模型。os.environ/前缀表示从环境变量读取密钥避免明文。启动服务litellm --config config.yaml --port 4000服务起来后客户端就可以用 OpenAI SDK 来调用了只需要把base_url指向代理from openai import OpenAI client OpenAI( api_keysk-your-master-key, base_urlhttp://localhost:4000 ) response client.chat.completions.create( modelgpt-4o, messages[{role: user, content: 你好}] )注意这里用的是标准的 OpenAI SDKmodel填的是配置文件里的model_name。代理收到请求后根据名称找到对应的后端配置转发出去。3.4 负载均衡与故障转移配置生产环境里同一个模型往往要配多个后端来提高可用性。比如你有两个 OpenAI 的密钥想轮询使用model_list: - model_name: gpt-4o litellm_params: model: openai/gpt-4o api_key: os.environ/OPENAI_API_KEY_1 - model_name: gpt-4o litellm_params: model: openai/gpt-4o api_key: os.environ/OPENAI_API_KEY_2 router_settings: routing_strategy: simple-shuffle num_retries: 3 timeout: 30两个条目用了相同的model_namelitellm 会自动把它们当作同一个模型的两个后端。simple-shuffle策略会随机分配请求num_retries控制失败重试次数。路由策略还有几个选项值得了解。least-busy会把请求发给当前负载最低的后端适合后端性能不均的场景。latency-based-routing根据历史延迟选择最快的后端适合对响应速度敏感的应用。选择哪种取决于你的实际瓶颈在哪里。实操心得故障转移的重试次数不要设太高。我一开始设了 5 次结果某个后端整体不可用时请求会卡很久才失败。后来改成 2 到 3 次配合合理的超时整体体验好很多。重试次数和超时时间要一起调单独调一个效果不好。3.5 成本追踪与预算控制落地开启成本追踪需要在配置里指定回调litellm_settings: success_callback: [langfuse] failure_callback: [langfuse]或者写到数据库general_settings: database_url: os.environ/DATABASE_URL数据库模式下每次调用的详细信息都会落库包括模型、token 数、费用、耗时、用户标识等。之后可以用 SQL 做各种维度的统计。预算控制通过max_budget参数实现可以设在密钥级别或用户级别。超过预算后后续请求会被拒绝。这个功能对于给不同团队分配额度、防止意外超支很实用。4. 常见问题与排查技巧实录4.1 调用报错排查速查表实际用下来遇到的问题大多集中在几类。我整理了一张速查表报错现象可能原因排查方向不支持的模型模型名前缀或拼写错误核对官方模型列表确认前缀鉴权失败密钥未设置或变量名不对检查环境变量名是否匹配连接超时api_base 配置错误或网络不通确认服务地址和端口可达参数被忽略目标模型不支持该参数开启 drop_params 自动丢弃流式中断超时设置过短调大 timeout 或检查网络费用统计为零模型不在价格表内手动配置单价或更新版本这张表覆盖了我遇到的大部分情况。排查时按“先看报错信息再查配置最后测网络”的顺序走效率最高。4.2 参数兼容性处理不同模型支持的参数不一样。比如有的模型支持temperature但不支持top_p有的支持max_tokens但字段名不同。litellm 做了大量转换工作但不可能覆盖所有情况。遇到参数不兼容时drop_params: true这个设置很有用它会自动丢弃目标模型不支持的参数而不是报错。代价是这些参数静默失效可能影响输出效果。所以我的建议是开发阶段先关掉 drop_params让不兼容的参数暴露出来确认哪些参数真正生效上线前再打开保证服务稳定性。对于确实需要但 litellm 没自动转换的参数可以用extra_body透传response litellm.completion( modelopenai/gpt-4o, messages[{role: user, content: 测试}], extra_body{custom_param: value} )这个参数会原样塞进请求体适合对接一些厂商的特有功能。4.3 性能与并发调优litellm 本身是异步友好的Proxy 基于 FastAPI天然支持高并发。但实际吞吐量受限于后端模型服务的能力。调优时关注几个点。一是连接池。频繁调用时复用 HTTP 连接能显著降低延迟。litellm 内部用了 httpx默认会维护连接池一般不用手动调但如果并发特别高可以适当调大池子大小。二是超时设置。不同模型的响应时间差异很大统一设一个超时值往往不合适。可以在模型级别单独配置超时给慢模型更长的容忍时间。三是批处理。如果业务允许把多个请求合并成一次调用比如用支持批处理的接口能大幅提升吞吐。litellm 对部分厂商的批处理接口有支持具体看文档。踩过的坑有一次压测时发现 QPS 上不去排查半天发现是某个后端模型的并发限制卡住了。litellm 的重试机制在这种情况下会不断重试反而加剧拥堵。后来给这个后端单独设了较低的并发上限问题解决。所以后端的能力上限要如实配置不要指望中间层能变魔术。4.4 日志与可观测性生产环境一定要开日志。litellm 支持多种回调可以对接常见的可观测性平台。日志里最有价值的信息是请求的模型、耗时、token 消耗、是否命中缓存、是否重试。我习惯把成功和失败的日志分开处理。成功日志用于成本分析和性能监控失败日志用于告警和排查。失败日志里要特别关注错误类型是鉴权问题、限流问题还是模型本身的问题处理方式完全不同。如果日志量很大建议做采样或者只记录关键字段避免存储成本失控。全量记录详细请求体在排查时有用但长期存储性价比不高。5. 进阶用法与扩展思路5.1 自定义回调与钩子litellm 提供了回调机制允许在请求前后插入自定义逻辑。这个能力可以用来做很多事比如给请求打标签、做内容审核、记录自定义指标。写一个自定义回调类实现async_log_success_event等方法然后在配置里注册。我见过有人用它做敏感词过滤在请求发出前拦截不合规的内容也有人用它做 A/B 测试按比例把请求分到不同模型。这个扩展点的价值在于把通用能力和业务逻辑解耦。litellm 负责调用和路由你的业务逻辑通过回调注入两边互不干扰。5.2 多租户与密钥管理给多个团队或客户提供服务时密钥管理是个绕不开的问题。litellm 支持生成子密钥每个子密钥可以绑定不同的预算、模型权限、有效期。通过管理接口创建子密钥curl -X POST http://localhost:4000/key/generate \ -H Authorization: Bearer sk-your-master-key \ -H Content-Type: application/json \ -d {models: [gpt-4o], max_budget: 100}返回的子密钥只能访问指定的模型且总消费不超过 100。这种机制让资源分配变得可控也方便追踪每个租户的使用情况。提示子密钥的预算单位要和你的计费口径一致。litellm 默认按美元计如果你的业务用其他货币或积分体系需要在回调里做换算。5.3 缓存策略降低重复成本很多场景下相同的请求会被重复发送。litellm 支持缓存命中缓存时直接返回结果不消耗后端 token。缓存可以配置在内存、Redis 或其他后端。对于问答类应用如果问题重复率高缓存能省下可观的费用。配置方式是在litellm_settings里指定cache和cache_params。不过缓存要谨慎使用。对于需要实时性或者结果有随机性的场景缓存可能导致返回过时或重复的答案。我的做法是只对确定性强的请求开缓存比如固定的知识查询对生成类请求保持关闭。5.4 与现有工具链的集成litellm 的 OpenAI 兼容接口意味着它能无缝接入大量现有工具。比如各种基于 OpenAI 接口的客户端、评测框架、Agent 框架只要支持自定义base_url就能指向 litellm 代理。这个特性在搭建评测流水线时特别有用。你可以用同一套评测代码通过切换模型名跑遍所有候选模型结果格式统一对比起来很方便。省去了为每个模型写适配脚本的功夫。我在实际项目里把 litellm 当作模型层的抽象上层业务代码完全不感知具体用的是哪家模型。这样模型选型变化时业务代码零改动只需要调整配置。这种解耦带来的灵活性在模型快速迭代的当下价值非常大。最后分享一个小技巧litellm 的版本更新比较频繁新模型支持往往很快跟进。建议定期升级但升级前先在测试环境验证确认现有配置和调用不受影响。我一般会关注 release notes 里的 breaking changes提前做好适配。