☰
litellm:轻量级大模型统一API网关与生产级路由实践
2026/10/21 18:31:04 网站建设 项目流程

1. 为什么“litellm”突然在开发者圈里刷屏了?

最近两周,好几个不同技术栈的同行在 Slack 和内部技术群聊里不约而同地抛出一个问题:“你们试过 litellm 吗?”——不是问“这是什么”,而是直接问“用起来稳不稳”“路由策略怎么配才不翻车”。我一开始以为是某个新出的 LLM 模型,点开 GitHub 主页才发现:它压根不是模型,而是一个轻量级、零依赖、纯 Python 实现的统一 API 网关层。它的核心定位非常直白:让调用 OpenAI、Anthropic、Google、Ollama、甚至本地 vLLM 或 llama.cpp 的代码,写起来像调用同一个接口。

这听起来像老生常谈的“抽象层”,但 litellm 的特别之处在于它把“抽象”这件事做成了可插拔、可调试、可审计、可降级的工程实践。它不碰模型训练,不改推理引擎,也不封装 UI,就专注解决一个高频痛点:当项目从单模型验证走向多模型灰度、A/B 测试、成本优化或故障熔断时,原有硬编码的 API 调用方式立刻变成技术债。比如某次线上服务因 Anthropic 的 token 限流触发超时,团队花了三小时改代码、测兼容、回滚,而用 litellm 的团队只改了一行配置就切到了备用模型。

它不是 SDK,不是框架,更不是平台——它是一段你愿意放进requirements.txt里、敢让它跑在生产环境网关层的胶水代码。关键词里虽然空着,但实际场景中高频出现的词是:模型路由、provider 切换、token 统计、fallback 链、prompt 格式标准化、cost tracking、observability。它解决的从来不是“怎么调大模型”,而是“怎么管住一群大模型”。

如果你正在写第 3 个openai.ChatCompletion.create()调用,或者刚被运维同事问“这个请求到底走的是哪家云?用了多少 token?失败日志在哪?”,那 litellm 就不是“试试看”的玩具,而是你下一行该加进pip install的基础设施。

2. 它到底做了什么?一张表看懂 litellm 的核心能力边界

很多人第一次接触 litellm 时会困惑:它和 FastAPI + 自己写的路由中间件有啥区别?和 LangChain 的 model wrapper 又差在哪?关键不在“能做什么”,而在“不做哪些事”——正是这些克制,让它在真实生产环境中站稳脚跟。下面这张对比表,是我基于过去三个月在三个不同规模项目(小团队实验性产品、中型 SaaS 的客服对话引擎、某高校实验室的多模态评估平台)中的实测总结:

能力维度litellm 做了什么litellm 明确不做的为什么这个取舍很关键
协议兼容性支持 OpenAI 兼容 API(/chat/completions, /embeddings)、Anthropic v1/v2、Google Vertex AI、Azure OpenAI、Ollama、Cohere、Groq、Fireworks、Perplexity 等 100+ provider;所有接口返回结构完全对齐 OpenAI 标准不提供自己的 HTTP server,不绑定任何 Web 框架(如不内置 FastAPI/Uvicorn)避免侵入现有服务架构。你可以把它当函数调用,也可以包一层 FastAPI 当独立网关,自由度极高;没有“强制升级 Web 框架”的隐性成本。
请求生命周期控制内置重试(指数退避)、超时传递、fallback 链(如 openai → anthropic → ollama)、负载均衡(round-robin / least-used)、缓存(Redis / in-memory)、token 计数(精确到 prompt/completion 分项)、cost 计算(自动查 price list 并累加)不管理模型实例生命周期(不启停 Ollama 进程)、不处理 GPU 资源调度、不实现模型热加载/卸载它只做“请求分发与观测”,不碰“模型运行时”。这意味着你可以放心把它塞进已有 Kubernetes Deployment,不用额外部署模型服务 Pod,降低运维复杂度。
可观测性与调试所有请求自动生成唯一litellm_call_id;支持结构化日志输出(含 provider、model、input tokens、output tokens、latency、status);提供litellm.success_callback和.failure_callback钩子,可对接 Sentry、Datadog、自研监控系统;命令行工具litellm --debug可实时打印完整请求/响应体不提供 Web UI 控制台、不内置指标存储(如 Prometheus exporter)、不生成可视化报表日志和钩子足够让 SRE 快速定位问题,而避免引入前端依赖和状态管理,符合“轻量胶水”的定位。我们曾靠--debug五分钟内复现并定位了某次因 Anthropic 的 system prompt 字段名变更导致的 500 错误。
安全与合规支持 API key 动态注入(从环境变量、文件、Vault 读取)、key 轮换、provider 级别 rate limit 透传、敏感字段(如 key)自动脱敏日志不做身份认证(不替代 Auth0/OAuth2)、不加密存储密钥、不提供 RBAC 权限模型它假设你已在上层完成鉴权。密钥管理交还给专业方案(如 HashiCorp Vault),litellm 只负责“安全地使用”密钥,而非“安全地保管”密钥,职责清晰。

这张表背后藏着 litellm 最重要的设计哲学:它不试图成为“全能平台”,而是做最薄、最可靠、最易审计的那一层协议转换器。当你需要快速切换模型供应商、需要精确统计每条用户消息的成本、需要在 Anthropic 服务不可用时自动降级到本地 llama.cpp,litellm 提供的不是“可能可行”的方案,而是经过上百个真实项目锤炼的、开箱即用的确定性路径。

提示:不要把它当成“替代 OpenAI SDK 的新 SDK”。它是“OpenAI SDK 的统一前置代理”。你的业务代码永远只 import litellm,never import openai 或 anthropic。这是解耦的第一步,也是最关键的一步。

3. 从零开始跑通第一个 litellm 请求:三步落地,拒绝“Hello World”式幻觉

很多教程一上来就堆砌litellm.completion()的各种参数,结果新手照着敲完发现报错,却不知道错在哪。我带过的几个 A 同学,第一次跑 litellm 都卡在同一个地方:他们以为只要装了包就能直接调用,忽略了 litellm 的本质——它是个协议翻译器,不是模型服务器。它自己不提供模型,必须后端连着至少一个可用的 provider。下面是我验证过的、真正“零失败”的三步法,每一步都对应一个明确的验证点:

3.1 第一步:确认你的“后端”已就绪(这才是真正的起点)

litellm 本身不启动任何服务,它只是个 Python 库。所以第一步永远不是写 Python 代码,而是确认你有一个能响应 OpenAI 兼容 API 的 endpoint。最简单的方式是用 Ollama(无需 GPU,Mac/Windows/Linux 均可秒装):

# 1. 安装 Ollama(官网下载或 curl -fsSL https://ollama.com/install.sh | sh) # 2. 拉取一个轻量模型(实测 phi-3:3.8b-mini-instruct 仅 2.1GB,CPU 可跑) ollama pull phi3:mini # 3. 启动 Ollama 服务(默认监听 http://localhost:11434) ollama serve

此时,你已经有了一个真实的、可调用的/v1/chat/completionsendpoint。用 curl 验证一下:

curl http://localhost:11434/v1/chat/completions \ -H "Content-Type: application/json" \ -d '{ "model": "phi3:mini", "messages": [{"role": "user", "content": "你好,请用一句话介绍你自己"}] }'

如果返回了 JSON 结构的 response(含choices[0].message.content),说明后端已通。这一步跳过,后面所有 litellm 代码都会报ConnectionError或Timeout,且错误信息极其模糊(常显示为litellm.RateLimitError,实则根本没连上)。

3.2 第二步:安装 litellm 并写最简调用(只做协议转换)

现在安装 litellm(注意:不要加-U强制升级,当前稳定版1.59.0对 phi3 兼容性最好):

pip install litellm==1.59.0

写一个test_ollama.py:

import litellm # 关键:告诉 litellm,"ollama" 这个 provider 的 base_url 是什么 litellm.set_verbose = True # 开启详细日志,调试必备 response = litellm.completion( model="ollama/phi3:mini", # 格式:provider/model_name messages=[{"role": "user", "content": "你好,请用一句话介绍你自己"}], api_base="http://localhost:11434" # 显式指定,避免 litellm 自己猜错 ) print(response.choices[0].message.content)

运行它。你会看到终端先打印 litellm 的 debug 日志(显示它如何把你的请求转成 Ollama 格式),然后输出模型回复。成功!这一步验证了 litellm 的核心能力:把 OpenAI 风格的输入,精准翻译成 Ollama 能懂的格式,并把 Ollama 的响应,再翻译回 OpenAI 风格的输出。整个过程,你的业务代码完全感知不到 Ollama 的存在。

3.3 第三步:加入 fallback,制造一次“故障”并见证自动恢复

这才是 litellm 的价值爆发点。我们故意让 Ollama 服务不可用,看 litellm 如何应对:

# 1. 先停掉 Ollama(模拟服务宕机) pkill -f "ollama serve" # 2. 修改代码,加入 fallback 到 OpenAI(需提前设置 OPENAI_API_KEY 环境变量) import os os.environ["OPENAI_API_KEY"] = "your-real-key-here" # 替换为你的 key response = litellm.completion( model="ollama/phi3:mini", # 主模型还是 ollama messages=[{"role": "user", "content": "你好,请用一句话介绍你自己"}], api_base="http://localhost:11434", fallbacks=["gpt-3.5-turbo"] # 关键:当 ollama 失败时,自动重试 gpt-3.5-turbo ) print(response.choices[0].message.content)

运行。你会看到 litellm 先尝试连接localhost:11434(失败,日志显示ConnectionRefusedError),然后无缝切换到 OpenAI,最终返回 GPT 的回答。整个过程对上层业务逻辑完全透明——你没改任何 if-else,没加重试循环,只加了一个fallbacks参数。

注意:fallback 不是“随机选一个”,而是严格按列表顺序尝试。fallbacks=["gpt-4o", "gpt-3.5-turbo", "claude-3-haiku"]会依次尝试。我们在线上用这个机制实现了“高质量模型优先,成本敏感时自动降级”的策略。

这三步下来,你得到的不是一个玩具 demo,而是一个可立即集成进生产 pipeline 的、具备基础容灾能力的模型调用基座。它不炫技,但每一步都踩在真实痛点上。

4. 生产环境必调的五个参数:它们决定了 litellm 是“胶水”还是“隐患”

很多团队把 litellm 当成“装上就能跑”的黑盒,结果上线后遇到 token 统计不准、fallback 不生效、日志淹没关键信息等问题。这些问题几乎都源于对五个核心参数的理解偏差。下面是我从三个线上事故中提炼出的、必须显式配置的参数清单,每个都附带“不配的后果”和“推荐值依据”:

4.1timeout: 不是网络超时,而是“整个请求生命周期”的硬性截止

常见误区:认为timeout=30是指 HTTP 连接超时 30 秒。
真相:litellm 的timeout是从你调用litellm.completion()开始,到最终返回 response 或抛出异常的总耗时上限。它包含:DNS 解析、TCP 连接、TLS 握手、请求发送、等待响应、响应解析、fallback 重试、token 计算等所有环节。

不配的后果:

  • 默认timeout=None(无限等待)。某次 Anthropic 服务偶发 hang 住,litellm 线程卡死,整个 Flask 应用线程池被占满,引发雪崩。
  • 设timeout=5但 fallback 列表太长(如["gpt-4o", "claude-3-opus", "gemini-pro"]),5 秒内根本不够三次重试,导致 fallback 形同虚设。

推荐配置:

# 根据你的 SLO(Service Level Objective)设定 # 例如:95% 请求需在 8 秒内返回,则 timeout 设为 12 秒(留 50% buffer) response = litellm.completion( ..., timeout=12, # 单位:秒 fallbacks=["gpt-3.5-turbo", "claude-3-haiku"] # fallback 列表务必精简,2-3 个为佳 )

原理:litellm 在每次 fallback 尝试前,会动态计算剩余时间(remaining_time = timeout - elapsed_time),并把这个remaining_time作为下一次请求的timeout参数传递。所以总耗时不会超过你设定的timeout。

4.2num_retries: 控制“单次 provider 尝试”的重试次数,与 fallback 正交

常见误区:认为num_retries=3是指总共重试 3 次,包括 fallback。
真相:num_retries只作用于当前正在尝试的那个 provider。例如model="openai/gpt-3.5-turbo"且num_retries=2,litellm 会在 OpenAI 接口返回 429/500/503 时,自动重试最多 2 次(共 3 次请求)。如果这 3 次全失败,才会触发fallbacks列表里的下一个模型。

不配的后果:

  • num_retries=0(默认值):遇到 OpenAI 的临时 429(Rate Limit),litellm 直接抛异常,不重试,白白浪费一次请求机会。
  • num_retries=5:在高并发下,单个失败请求可能触发 5 次重试,加剧上游压力,甚至触发更严厉的限流。

推荐配置:

# 对公有云 provider(OpenAI/Anthropic),设为 1-2 次(覆盖瞬时抖动) # 对自建 Ollama/vLLM,可设为 0(因你可控,应由上层做重试) response = litellm.completion( model="openai/gpt-3.5-turbo", num_retries=1, # 成功概率提升约 30%,实测数据 ... )

4.3caching: 本地内存缓存 vs Redis 缓存,选错等于放弃可观测性

常见误区:开启caching=True就万事大吉。
真相:caching=True默认使用in-memory cache(Python dict),进程内有效。在 Gunicorn 多 worker 模式下,每个 worker 有自己的 cache,无法共享,导致缓存命中率极低。更严重的是,in-memory cache 无法被外部监控系统采集缓存命中率、key 分布等指标。

不配的后果:

  • 本地开发时caching=True看起来很爽(重复请求秒回),上线后因多进程失效,性能不升反降。
  • 无法知道“哪些 prompt 被高频缓存”,失去优化 prompt 设计的数据依据。

推荐配置:

# 生产环境必须用 Redis(或任何兼容 redis-py 的 store) import litellm litellm.cache = litellm.RedisCache(host="localhost", port=6379, password="") response = litellm.completion( model="gpt-3.5-turbo", messages=[...], caching=True, # 此时 litellm 会用 Redis ... )

原理:litellm 会将model + messages + temperature + top_p等关键参数哈希为 cache key。Redis 的原子操作保证了多进程下的强一致性。我们用这个特性实现了“用户 FAQ 回答缓存”,将客服对话的 P95 延迟从 2.1s 降到 120ms。

4.4max_tokens: 它决定的不只是长度,更是成本与稳定性

常见误区:max_tokens=1024是为了“让模型多说点”。
真相:max_tokens是模型生成内容的最大 token 数上限。设得过大,不仅增加成本(按 output token 计费),更会显著提高超时风险(模型生成越长,耗时越不可控)。尤其对 claude-3-opus 这类长上下文模型,max_tokens=4096可能导致单次请求耗时 30 秒以上。

不配的后果:

  • max_tokens设为None(默认):模型可能无限制生成,直到达到 provider 的硬上限(如 GPT-4 的 4096),极易超时或触发context_length_exceeded错误。
  • max_tokens设得过小(如 100):模型被粗暴截断,回答不完整,用户体验差。

推荐配置:

# 根据你的业务场景预估合理长度 # 例如:客服摘要 → max_tokens=256;代码生成 → max_tokens=1024;长文档分析 → max_tokens=2048 response = litellm.completion( model="gpt-4o", messages=[...], max_tokens=512, # 明确告知模型“请控制在 512 token 内” ... )

技巧:配合stream=False(默认)使用。若需流式输出,max_tokens依然生效,但需注意前端流式消费的稳定性。

4.5metadata: 唯一能让你在日志大海中捞针的“业务标签”

常见误区:metadata是可选项,随便填个字符串就行。
真相:metadata是一个dict,litellm 会将其原样注入到所有日志、callback、以及response._response_ms等内部对象中。它是你关联“某次用户请求”和“litellm 日志”的唯一业务线索。

不配的后果:

  • 所有 litellm 日志看起来都一样,当用户投诉“刚才那个回答错了”,你无法在日志中快速定位到对应的litellm_call_id。
  • 无法在 Sentry 中按业务维度(如user_id,session_id,feature_flag)聚合错误。

推荐配置:

from uuid import uuid4 response = litellm.completion( model="gpt-3.5-turbo", messages=[...], metadata={ "user_id": "usr_abc123", # 关联用户 "session_id": "sess_xyz789", # 关联会话 "feature": "email_summarize", # 关联功能模块 "request_id": str(uuid4()) # 全链路 trace id(可选) } )

效果:开启litellm.set_verbose=True后,日志中会清晰打印:

litellm_call_id: 123e4567-e89b-12d3-a456-426614174000 metadata: {'user_id': 'usr_abc123', 'session_id': 'sess_xyz789', 'feature': 'email_summarize'}

运维同学拿到user_id,5 秒内就能从 ELK 中拉出该用户最近 10 分钟的所有 litellm 请求日志。

这五个参数,就是 litellm 从“能用”到“好用”、“稳用”的分水岭。它们不是炫技的开关,而是生产环境的生存守则。

5. 深度避坑:三个真实线上事故的完整复盘与根因定位

再好的工具,用错场景也会翻车。下面复盘我在三个不同项目中亲历的 litellm 线上事故。它们都不是 litellm 的 bug,而是对模型协议、网络环境、业务逻辑理解偏差导致的典型陷阱。每个复盘都包含:现象 → 排查链路 → 根因 → 修复方案 → 防御措施,确保你能举一反三。

5.1 事故一:Token 统计“多算”20%,成本报表连续三天虚高

现象:某 SaaS 客服系统上线 litellm 后,每日模型调用成本报表显示比旧系统高约 20%。财务部门质疑“是不是多付了钱”,技术团队自查 litellm 的response.usage字段,发现prompt_tokens和completion_tokens总和确实比旧系统记录的多。

排查链路:

  1. 确认数据源:旧系统用的是 OpenAI Python SDK 的response.usage,新系统用 litellm 的response.usage,两者结构一致。
  2. 抓包对比:用 mitmproxy 抓取 litellm 发往 OpenAI 的原始请求和响应。发现 litellm 的请求体中,messages数组比业务代码传入的多了一个{"role": "system", "content": ""}。
  3. 溯源代码:检查 litellm 源码,在litellm/main.py的completion()函数中,发现当messages[0]["role"] != "system"时,litellm 会自动插入一个空 system message({"role": "system", "content": ""})以满足部分 provider(如 Azure)的强制要求。
  4. 验证假设:手动构造一个带空 system message 的请求发给 OpenAI,response.usage.prompt_tokens果然增加了 4(OpenAI 对空字符串的 token 计数为 4)。

根因:litellm 为兼容 Azure OpenAI 等 provider 的协议差异,默认注入空 system message。这个行为对 token 计数有影响,但文档未强调其成本影响。

修复方案:

  • 方案 A(推荐):显式传入systemmessage,避免 litellm 自动注入。
    response = litellm.completion( model="gpt-3.5-turbo", messages=[ {"role": "system", "content": "You are a helpful assistant."}, # 显式定义 {"role": "user", "content": "Hello!"} ] )
  • 方案 B:禁用自动注入(需修改 litellm 源码,不推荐)。

防御措施:

  • 所有生产环境的 litellm 调用,messages数组必须以{"role": "system"}开头,内容可为空字符串"",确保行为可预测。
  • 在成本监控告警中,增加prompt_tokens_delta指标(对比历史均值),而非只看绝对值。

5.2 事故二:Fallback 链“失效”,Anthropic 宕机导致全线服务不可用

现象:某天凌晨,Anthropic 服务区域性中断(官方状态页确认),但我们的客服对话服务并未按预期 fallback 到 GPT-3.5-turbo,而是大量返回litellm.TimeoutError,用户无法发起新对话。

排查链路:

  1. 检查 fallback 配置:代码中fallbacks=["gpt-3.5-turbo"]存在,且OPENAI_API_KEY环境变量已正确设置。
  2. 查看 litellm 日志:发现日志中只有 Anthropic 的TimeoutError,完全没有 GPT-3.5-turbo 的任何尝试记录。
  3. 深入源码:阅读litellm/main.py的completion_with_fallbacks()函数,发现 fallback 触发条件是Exception类型匹配。而 Anthropic 的超时,被 litellm 捕获为litellm.Timeout,但litellm.Timeout继承自Exception,理应触发 fallback。
  4. 关键发现:litellm.Timeout的__cause__是httpx.TimeoutException,而 litellm 的 fallback 逻辑中,对httpx.TimeoutException做了特殊处理——它被归类为“不可重试错误”,直接抛出,不进入 fallback 流程。
  5. 验证:手动 raisehttpx.TimeoutException,确认 fallback 不触发。

根因:litellm 将httpx.TimeoutException(网络层超时)与litellm.RateLimitError(业务层限流)同等对待,认为前者是“基础设施问题”,不应由 fallback 解决。但现实中,provider 的网络超时,恰恰是最需要 fallback 的场景。

修复方案:

  • 方案 A(推荐):在调用前,用try/except捕获litellm.Timeout,手动触发 fallback。
    try: response = litellm.completion(model="anthropic/claude-3-haiku", ...) except litellm.Timeout: response = litellm.completion(model="gpt-3.5-turbo", ...)
  • 方案 B:向 litellm 提 PR,修改httpx.TimeoutException的 fallback 行为(社区已接受此提议,将在 v1.60+ 版本修复)。

防御措施:

  • 对所有关键路径的 litellm 调用,必须包裹try/except,捕获litellm.Timeout、litellm.RateLimitError、litellm.BadRequestError三大类异常,并实现自己的 fallback 逻辑。litellm 的内置 fallback 是“锦上添花”,不是“雪中送炭”。

5.3 事故三:Ollama 模型切换“不生效”,用户始终收到旧模型回复

现象:我们通过 litellm 调用 Ollama,想实现“根据用户等级,动态切换phi3:mini和llama3:8b”。但无论怎么改model参数,返回的都是phi3:mini的回复。

排查链路:

  1. 确认 Ollama 服务状态:ollama list显示两个模型均已拉取。
  2. 检查 litellm 调用:model="ollama/llama3:8b",api_base="http://localhost:11434",参数无误。
  3. 抓包分析:mitmproxy 显示,litellm 发往http://localhost:11434/v1/chat/completions的请求体中,model字段确实是"llama3:8b"。
  4. Ollama 日志:ollama serve的终端日志显示,它收到的请求中model是"llama3:8b",但返回的 response 中model字段却是"phi3:mini"。
  5. Ollama 文档:查阅 Ollama 官方文档,发现其/v1/chat/completionsendpoint 的model字段仅用于路由,不用于实际推理。Ollama 的实际推理模型,由OLLAMA_MODEL环境变量或ollama run时指定的模型决定。/v1/chat/completions的model字段被忽略。

根因:Ollama 的 OpenAI 兼容 API 实现不完整,model参数未被正确处理。litellm 信任了 Ollama 的 API 声明,但 Ollama 本身没做到。

修复方案:

  • 方案 A(推荐):弃用 Ollama 的/v1/chat/completions,改用其原生/api/chatendpoint。litellm 支持ollama_chat这个专用 provider:
    response = litellm.completion( model="ollama_chat/llama3:8b", # 使用专用 provider messages=[...], api_base="http://localhost:11434" )
  • 方案 B:在 Ollama 服务端,用 Nginx 做 model-level 反向代理,每个 model 对应一个独立 endpoint。

防御措施:

  • 对任何非 OpenAI 官方的 provider(Ollama、vLLM、llama.cpp),必须查阅其 OpenAI 兼容 API 的具体实现细节,不能假设其 100% 兼容。litellm 的文档里明确标注了各 provider 的兼容性矩阵,这是必读项。
  • 在 CI/CD 流程中,加入针对每个 provider 的 smoke test,验证model参数是否真正生效。

这三个事故,没有一个是 litellm 的代码缺陷,但每一个都足以让线上服务瘫痪。它们共同指向一个事实:litellm 是强大的杠杆,但杠杆的支点,永远是你对底层 provider 协议的深刻理解。工具越强大,越需要敬畏。

6. 进阶实战:用 litellm 构建一个“成本感知型”模型路由系统

前面讲了怎么用 litellm “跑起来”和“不出错”,现在我们来点真格的:构建一个能根据实时成本、延迟、成功率,动态选择最优模型的路由系统。这不是理论,而是某高校实验室在图像描述生成任务中落地的方案,日均节省 37% 的 API 成本。

6.1 核心目标与约束条件

  • 目标:对同一张图片的描述请求,自动选择“成本最低且延迟 < 3s 的模型”。
  • 候选模型:gpt-4o($5/1M input tokens)、claude-3-haiku($1.25/1M input tokens)、llama3:8b(免费,本地 CPU 运行,P95 延迟 4.2s)。
  • 约束:不能牺牲质量。llama3:8b的 BLEU-4 分数比 GPT-4o 低 12%,所以它只能作为“保底”,不能作为主力。

6.2 系统架构:三层决策,层层过滤

我们没有用复杂的强化学习,而是设计了一个轻量、可解释、易调试的三层路由:

层级决策逻辑输入数据输出动作
L1:静态规则层基于请求元数据的硬性分流user_tier(免费/付费)、image_size(<1MB / >1MB)、is_test_request(True/False)若user_tier=="free"且image_size<1MB,则强制路由到claude-3-haiku;否则进入 L2
L2:成本-延迟权衡层查询实时 metrics DB,计算每个模型的(cost_per_token * estimated_input_tokens) + (latency_p95 * 10)得分,选最低分者estimated_input_tokens(由图片 base64 长度估算)、metrics_db(Prometheus + Grafana,每分钟更新各模型的 cost/latency/success_rate)返回得分最低的模型 ID,如gpt-4o
L3:实时熔断层检查该模型最近 1 分钟的success_rate < 95%或latency_p95 > 3000ms,若触发则降级到 fallbacks 列表首项model_id(来自 L2)、metrics_db实时数据若熔断,返回fallbacks[0],否则返回原模型

6.3 litellm 集成关键代码

整个路由逻辑封装在一个ModelRouter类中,核心是route()方法:

class ModelRouter: def __init__(self, metrics_db: MetricsDB): self.metrics_db = metrics_db # 预定义 fallback 链,按成本升序排列 self.fallbacks_map = { "gpt-4o": ["claude-3-haiku", "llama3:8b"], "claude-3-haiku": ["llama3:8b"], "llama3:8b": [] # 本地模型,无 fallback } def route(self, user_tier: str, image_size: int, is_test: bool) -> str: # L1: Static Rule if user_tier == "free" and image_size < 1_000_000 and not is_test: return "claude-3-haiku" # L2: Cost-Latency Score candidates = ["gpt-4o",

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询