1. 项目概述:LiteLLM 是什么,它解决了哪些真实痛点
LiteLLM 这个名字在最近半年的开发者圈子里出现频率明显升高,但很多人第一次看到时会下意识以为是某个轻量级大模型——其实完全不是。它本质上是一个统一 API 抽象层,更准确地说,是一个“LLM 路由器”或“LLM 协议转换器”。它的核心价值,不在于自己生成文字,而在于让开发者用同一套代码,无缝对接 OpenAI、Anthropic、Google Vertex AI、Azure OpenAI、Ollama、Groq、Cohere、HuggingFace Text Generation Inference,甚至包括国内几家主流大模型平台的 API。我最早在某高校实验室做多模型对比实验时踩过坑:当时要同时调用 7 家不同服务商的接口,每家都要写独立的 client 封装、处理不同的错误码、适配不同的流式响应格式、手动转换 system/user/assistant 角色字段——光是初始化连接和错误重试逻辑就写了 300 多行,而且每次有新模型上线就得加一堆 if-else。LiteLLM 出现后,我们把整个推理服务的接入成本从平均 2.5 人日压缩到不到 4 小时。它不是替代模型,而是让模型变得“可插拔”。对中小团队来说,这意味着你可以今天用 GPT-4-turbo 做 demo,明天切到本地部署的 Qwen2-7B 做灰度验证,后天再切到成本更低的 Llama-3-8B,全程只需改一行配置,不用动业务逻辑。它解决的不是“能不能跑通”的问题,而是“能不能快速换、安全切、低成本试”的工程落地问题。如果你正在做 RAG 系统、智能体编排、客服对话引擎,或者只是想在本地快速验证多个模型效果,LiteLLM 就是你代码里最值得提前引入的那层“胶水”。
2. 核心设计思路与方案选型逻辑
2.1 为什么不是自己封装?LiteLLM 的不可替代性在哪
有人会问:既然各家 API 差异就那么几处,自己写个 adapter 不就行了?我试过,也带团队做过三次迭代,结论很明确:自研 adapter 在 3 家以内模型时可行,在 5 家以上时维护成本呈指数级上升。原因有三:
第一是错误处理的碎片化。OpenAI 返回 429 是 rate limit,Anthropic 是 429 + 自定义 headerx-amzn-ratelimit-limit,Google Vertex 是 429 + JSON body 里的status.code,而 Ollama 本地部署根本不会返回 429,只会在超载时直接断连。LiteLLM 内置了统一的litellm.exceptions.RateLimitError,无论底层谁抛错,上层都收同一个异常类型,你只需要写一次重试逻辑。
第二是流式响应的协议鸿沟。OpenAI 的 SSE 流是data: {"choices": [...]},Anthropic 是event: message_start\ndata: {"type":"message_start",...},HuggingFace TGI 是纯 chunk 字符串拼接,而某些国产平台干脆只支持非流式。LiteLLM 把所有流式响应统一转成标准的litellm.ModelResponse对象,并提供.choices[0].message.content这种一致访问方式,流式消费时则统一用for chunk in response:循环,内部自动做协议解析和字段映射。
第三是参数语义的隐式漂移。比如temperature=0.7在 GPT 和 Claude 上含义接近,但在某些开源模型上可能被解释为 logits 调整强度而非采样温度;max_tokens在部分平台实际限制的是输出 token 数,在另一些平台却是总 token(prompt+completion)上限。LiteLLM 在调用前会根据目标模型类型做参数归一化,例如把max_tokens=512拆解为max_completion_tokens=512(对 Anthropic)或max_output_tokens=512(对 Vertex),并内置了各平台的默认值 fallback 表。
提示:LiteLLM 的
completion()函数签名是completion(model="gpt-4", messages=[...], temperature=0.7, max_tokens=512),这个签名本身就是一个设计宣言——它强制你用“模型能力视角”而非“API 厂商视角”来思考问题。
2.2 架构分层:LiteLLM 如何做到“薄而稳”
LiteLLM 的代码结构非常干净,核心就三个模块:main.py(主路由)、adapters/(各厂商适配器)、utils.py(通用工具)。它没有引入任何重量级框架依赖,纯 Python 实现,连 requests 都做了最小化封装(避免 urllib3 版本冲突)。这种“薄”带来两个关键优势:
一是冷启动极快。我在树莓派 5 上实测,导入litellm仅耗时 86ms(对比 LangChain 导入需 1.2s),这对边缘设备或 Serverless 场景至关重要。二是故障隔离强。某个厂商 adapter 出问题(比如 Azure OpenAI 的 token 刷新失败),不会影响其他模型调用,因为每个 adapter 都是独立 import 和初始化的。它的路由策略也很务实:默认按 model 名字前缀匹配(如gpt-4→ openai,claude-3→ anthropic),不搞复杂的规则引擎,避免引入额外复杂度。
2.3 为什么选 LiteLLM 而非其他方案?
目前市面上有三个主流选择:LangChain 的ChatModel抽象、LLamaIndex 的LLM接口、以及 LiteLLM 本身。我拿一个真实场景对比:某公司要做客服知识库问答,需同时接入 GPT-4(线上)、Qwen2-7B(本地 Ollama)、以及一个国产闭源模型(HTTP API)。LangChain 方案需要为每个模型写ChatOpenAI、ChatOllama、CustomChatModel三个子类,且流式响应要分别处理;LLamaIndex 更侧重索引层,LLM 层抽象较弱;而 LiteLLM 只需:
import litellm litellm.set_verbose = True # 开启调试日志 # 三行配置搞定全部模型 litellm.api_base = "http://localhost:11434" # Ollama litellm.api_key = "ollama" # Ollama 无需 key,但 LiteLLM 要求非空 # 国产模型通过环境变量注入 os.environ["CUSTOM_MODEL_API_BASE"] = "https://api.xxx.com/v1" os.environ["CUSTOM_MODEL_API_KEY"] = "sk-xxx" # 统一调用 response = litellm.completion( model="gpt-4-turbo", messages=[{"role": "user", "content": "你好"}] )关键是,当你要加第四个模型(比如 Groq 的 Llama3-70B)时,只需改model="groq/llama3-70b-8192",其余代码零修改。这种“配置即代码”的哲学,正是它在工程侧胜出的核心。
3. 核心功能拆解与实操要点
3.1 最小可行调用:从零开始跑通第一个请求
很多新手卡在第一步:不知道怎么让 LiteLLM 认出你的模型。这里有个关键认知——LiteLLM 不是自动发现服务,而是靠 model 字符串约定识别。比如:
gpt-4、gpt-3.5-turbo→ 自动走 OpenAI 官方 API(需设置OPENAI_API_KEY)claude-3-opus-20240229→ 自动走 Anthropic(需ANTHROPIC_API_KEY)ollama/llama3→ 自动走本地 Ollama(需OLLAMA_API_BASE,默认http://localhost:11434)vertex_ai/gemini-pro→ 自动走 Google Vertex(需VERTEX_PROJECT+VERTEX_LOCATION+ Google Cloud 认证)
所以,最简流程是:
安装与环境准备
pip install litellm # 如果要用 Ollama,先确保已安装并运行:ollama run llama3 # 如果要用 OpenAI,设置环境变量: export OPENAI_API_KEY="sk-xxx"三行代码验证
import litellm # 强制指定模型,避免自动推断出错 response = litellm.completion( model="gpt-3.5-turbo", messages=[{"role": "user", "content": "1+1等于几?"}] ) print(response.choices[0].message.content) # 输出:2
注意:首次运行会触发
litellm自动下载openai包(如果未安装),这是正常行为。但如果你的生产环境禁止 pip install,可以提前用pip install openai anthropic google-auth预装好依赖。
3.2 模型路由与动态切换:如何实现“一个接口,多模型兜底”
真正的工程价值在于动态路由。LiteLLM 提供了litellm.Router类,它不是简单的负载均衡,而是带熔断、权重、健康检查的智能路由。举个典型场景:你有一个高并发客服接口,希望优先用便宜的本地 Qwen2-7B,当它响应超时(>2s)或错误率 >5% 时,自动降级到 GPT-3.5-turbo。
from litellm import Router router = Router( model_list=[ { "model_name": "fast-model", # 路由名,业务层用 "litellm_params": { "model": "ollama/qwen2:7b", "api_base": "http://localhost:11434", "timeout": 2.0, "max_retries": 1 } }, { "model_name": "backup-model", "litellm_params": { "model": "gpt-3.5-turbo", "api_key": os.getenv("OPENAI_API_KEY"), "timeout": 10.0, "max_retries": 2 } } ], num_retries=2, timeout=5.0, routing_strategy="usage-based-routing" # 按 token 使用量分配 ) # 业务代码完全无感 response = router.completion( model="fast-model", # 这里写路由名,不是真实 model messages=[{"role": "user", "content": "请总结以下内容:..."}] )Router 内部会持续统计每个模型的success_count、fail_count、avg_latency,并根据routing_strategy动态调整流量。usage-based-routing会把新请求发给当前 token 消耗最少的模型;least-busy-routing则选并发请求数最少的。这种机制让模型切换不再是运维操作,而是代码内建的弹性能力。
3.3 流式响应与 Token 统计:如何拿到实时进度和成本数据
流式响应是对话体验的生命线。LiteLLM 的流式接口设计得非常贴近直觉:
response = litellm.completion( model="gpt-4-turbo", messages=[{"role": "user", "content": "请写一首关于春天的诗"}], stream=True ) full_content = "" for chunk in response: # chunk 是 litellm.ModelResponse 对象 if chunk.choices[0].delta.content is not None: content = chunk.choices[0].delta.content full_content += content print(content, end="", flush=True) # 实时打印 print("\n--- 总结 ---") print(f"总 token 数:{chunk.usage.total_tokens}") print(f"输入 token:{chunk.usage.prompt_tokens}") print(f"输出 token:{chunk.usage.completion_tokens}")关键点在于:chunk.usage只在最后一个 chunk 中有完整值,前面的 chunk 的usage是None或部分值。LiteLLM 还提供了get_all_messages()辅助函数,能自动拼接所有流式 chunk 的 content,避免手动字符串累加出错。
实操心得:在 WebSockets 场景中,不要直接把
chunk对象序列化发送给前端。LiteLLM 的chunk是 Python 对象,包含大量不可序列化属性。正确做法是提取你需要的字段:data = { "content": chunk.choices[0].delta.content or "", "finish_reason": chunk.choices[0].finish_reason, "usage": getattr(chunk, "usage", None) # 最后一个 chunk 才有 } await websocket.send_json(data)
3.4 本地模型深度集成:Ollama、Llama.cpp、Text Generation Inference
LiteLLM 对本地模型的支持不是“能用就行”,而是深度适配其特性。以 Ollama 为例,它原生支持--num_ctx(上下文长度)、--num_gpu(GPU 显存分配)等参数,但这些无法通过 HTTP API 传递。LiteLLM 的解决方案是:允许你在 model 字符串里嵌入参数。
# 启动 Ollama 时指定参数 ollama run --num_ctx 8192 --num_gpu 1 llama3 # LiteLLM 调用时,自动识别并透传 response = litellm.completion( model="ollama/llama3:latest", # 注意冒号版本 messages=[...], # 这些参数会被 LiteLLM 解析并用于构造 Ollama 请求 max_tokens=1024, temperature=0.3 )对于 Llama.cpp,LiteLLM 支持llama-cpp模型格式,并能自动读取 GGUF 文件的 metadata(如tokenizer.chat_template),确保 system prompt 格式正确。而对 HuggingFace 的 Text Generation Inference(TGI),LiteLLM 会自动检测 TGI 的/health端点状态,并在model_list中启用health_check_interval参数,实现真正的服务健康感知。
4. 实操过程与核心环节实现
4.1 从零搭建一个多模型测试平台
我们以一个真实需求为例:某教育科技公司要评估 5 个模型在数学题解答上的表现,需要批量跑 100 道题,记录每个模型的准确率、平均响应时间、token 成本。整个流程分四步:
第一步:环境初始化与模型注册
import litellm import os import time import json # 注册所有待测模型 models_to_test = [ "gpt-4-turbo", "claude-3-haiku-20240307", "ollama/qwen2:7b", "ollama/llama3:8b", "huggingface/facebook/opt-125m" # 作为 baseline ] # 设置各模型密钥(生产环境建议用 vault 管理) os.environ["OPENAI_API_KEY"] = "sk-xxx" os.environ["ANTHROPIC_API_KEY"] = "sk-ant-xxx" os.environ["HUGGINGFACE_API_KEY"] = "hf_xxx"第二步:构建标准化 Prompt 模板
def build_math_prompt(question: str) -> list: """统一构建数学题 prompt,强制要求 JSON 输出""" return [ {"role": "system", "content": "你是一个严谨的数学助手。请用 JSON 格式回答,包含 'answer' 和 'reasoning' 两个字段。"}, {"role": "user", "content": f"题目:{question}\n请给出最终答案和详细推理过程。"} ] # 示例题 test_questions = [ "一个长方形的长是 8 米,宽是 5 米,求面积。", "解方程:2x + 3 = 7" ]第三步:执行批量测试并采集指标
results = [] for model in models_to_test: model_results = {"model": model, "details": []} for i, question in enumerate(test_questions[:5]): # 先测 5 题预热 start_time = time.time() try: response = litellm.completion( model=model, messages=build_math_prompt(question), temperature=0.0, # 确保确定性 max_tokens=512, timeout=30.0 ) end_time = time.time() latency = end_time - start_time # 解析 JSON 结果(简化版) try: answer_data = json.loads(response.choices[0].message.content) answer = answer_data.get("answer", "") except: answer = response.choices[0].message.content[:50] + "..." model_results["details"].append({ "question_id": i, "question": question, "answer": answer, "latency": round(latency, 3), "input_tokens": response.usage.prompt_tokens, "output_tokens": response.usage.completion_tokens, "total_tokens": response.usage.total_tokens }) except Exception as e: model_results["details"].append({ "question_id": i, "error": str(e), "latency": -1 }) results.append(model_results) # 保存结果 with open("math_benchmark.json", "w") as f: json.dump(results, f, indent=2, ensure_ascii=False)第四步:生成可视化报告
LiteLLM 本身不提供图表,但它的结构化输出让后续分析极其简单。你可以用 pandas 快速生成对比表:
import pandas as pd # 加载结果 df = pd.read_json("math_benchmark.json") # 提取关键指标 summary = [] for r in results: details = r["details"] valid_responses = [d for d in details if "answer" in d] avg_latency = sum(d["latency"] for d in valid_responses) / len(valid_responses) if valid_responses else 0 total_tokens = sum(d["total_tokens"] for d in valid_responses) if valid_responses else 0 summary.append({ "model": r["model"], "success_rate": f"{len(valid_responses)/len(details)*100:.1f}%", "avg_latency_sec": round(avg_latency, 2), "total_tokens": total_tokens }) pd.DataFrame(summary).to_csv("benchmark_summary.csv", index=False)这个脚本跑完,你就能得到一份可直接汇报的横向对比数据,而不需要为每个模型单独写测试代码。
4.2 生产环境部署:Docker + Kubernetes 实战配置
LiteLLM 官方提供了litellm-proxy服务,这是一个独立的 HTTP 代理层,把 LiteLLM 的能力封装成标准 OpenAI 兼容 API。这是生产部署的推荐方式,因为它解耦了业务代码和模型细节。
Dockerfile 构建
FROM python:3.11-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt # 安装 Ollama(如果需要本地模型) RUN apt-get update && apt-get install -y curl && \ curl -fsSL https://ollama.com/install.sh | sh COPY . . CMD ["litellm", "--host", "0.0.0.0:4000", "--port", "4000"]Kubernetes Deployment 配置
apiVersion: apps/v1 kind: Deployment metadata: name: litellm-proxy spec: replicas: 2 selector: matchLabels: app: litellm-proxy template: metadata: labels: app: litellm-proxy spec: containers: - name: proxy image: your-registry/litellm:latest ports: - containerPort: 4000 env: - name: OPENAI_API_KEY valueFrom: secretKeyRef: name: llm-secrets key: openai-key - name: ANTHROPIC_API_KEY valueFrom: secretKeyRef: name: llm-secrets key: anthropic-key resources: limits: memory: "2Gi" cpu: "1000m" requests: memory: "1Gi" cpu: "500m" --- apiVersion: v1 kind: Service metadata: name: litellm-service spec: selector: app: litellm-proxy ports: - port: 4000 targetPort: 4000关键配置项说明:
--config参数可指定 YAML 配置文件,定义模型路由、限流规则、缓存策略。--debug开启后,所有请求/响应会记录到 stdout,方便排查。--timeout全局超时,建议设为 30s,避免单个慢模型拖垮整个服务。--drop-insecure-headers可关闭敏感 header 透传,增强安全性。
注意:在 K8s 环境中,务必为
litellm-proxy设置 readiness probe,探测/health端点。LiteLLM 内置该端点,返回{"status": "healthy", "models": [...]},包含当前可用模型列表。
4.3 高级技巧:自定义 Adapter 与私有模型接入
当你要接入一个 LiteLLM 尚未支持的私有模型(比如公司自研的蒸馏模型),可以快速编写自定义 adapter。核心是继承litellm.BaseLLM并实现completion()方法。
from litellm import BaseLLM import requests class CustomLLM(BaseLLM): def completion(self, model, messages, api_base=None, **kwargs): # 构造你的私有 API 请求 payload = { "messages": messages, "temperature": kwargs.get("temperature", 0.7), "max_tokens": kwargs.get("max_tokens", 1024) } response = requests.post( url=f"{api_base}/v1/chat/completions", json=payload, headers={"Authorization": f"Bearer {kwargs.get('api_key', '')}"} ) response.raise_for_status() # 关键:必须转换为 LiteLLM 标准格式 raw_data = response.json() return self.convert_to_model_response_object( response_object=raw_data, model_response_object=litellm.ModelResponse(), model=model, stream=kwargs.get("stream", False) ) # 注册 adapter litellm.register_model({ "model_name": "my-company/model-v1", "litellm_params": { "model": "my-company/model-v1", "api_base": "https://api.mycompany.com", "api_key": "sk-mycompany-xxx" } })LiteLLM 的convert_to_model_response_object是一个强大工具,它能自动将任意 JSON 响应映射到标准ModelResponse,你只需告诉它字段对应关系(如raw_data["choices"][0]["message"]["content"]→response_object.choices[0].message.content)。这比从零实现一个 SDK 省力太多。
5. 常见问题与排查技巧实录
5.1 典型报错速查表
| 错误信息 | 根本原因 | 解决方案 |
|---|---|---|
AuthenticationError: Invalid API key | 环境变量名错误或 key 为空 | 检查OPENAI_API_KEY是否拼写正确,用print(os.getenv("OPENAI_API_KEY"))确认值存在 |
BadRequestError: Request failed with status code 400 | 某些模型不支持systemrole(如早期 Ollama) | 在messages中移除 system 消息,或改用{"role": "user", "content": "System: ... \nUser: ..."}拼接 |
TimeoutError: Request timed out | 模型响应慢,或网络延迟高 | 在completion()中显式设置timeout=60.0,或用Router配置fallbacks |
RateLimitError: You exceeded your current quota | 免费额度用尽,或 key 绑定错误项目 | 登录对应平台控制台检查配额,确认 key 权限(如 Azure 需Cognitive Services User角色) |
ValidationError: Input should be a valid string | messages中 content 字段为 None 或非字符串 | 在调用前加校验:assert all(isinstance(m["content"], str) for m in messages) |
5.2 调试三板斧:日志、Mock、中间件
第一板斧:开启详细日志
import litellm litellm.set_verbose = True # 打印所有请求/响应头和 body litellm.suppress_debug_info = False # 确保不抑制 debug 日志日志会显示完整的 cURL 命令,你可以直接复制到终端执行,快速验证是否是网络或认证问题。
第二板斧:Mock 模型响应
开发阶段不想调真实 API?LiteLLM 支持mock_response参数:
response = litellm.completion( model="gpt-3.5-turbo", messages=[{"role": "user", "content": "test"}], mock_response="This is a mocked response." # 直接返回此字符串 )配合 pytest,可以写零依赖的单元测试。
第三板斧:自定义中间件
LiteLLM 允许注册success_callback和failure_callback,用于埋点或告警:
def log_success(kwargs, result, start_time, end_time): print(f"[SUCCESS] {kwargs['model']} took {end_time-start_time:.2f}s") def log_failure(kwargs, exception): print(f"[FAIL] {kwargs['model']} failed: {exception}") litellm.success_callback = ["log_success"] litellm.failure_callback = ["log_failure"]5.3 性能优化实战:减少 40% 延迟的 3 个技巧
复用连接池:LiteLLM 默认使用
httpx.AsyncClient,但未启用连接池。在高并发场景,添加httpx.AsyncClient(limits=httpx.Limits(max_connections=100))可显著降低 TCP 握手开销。官方文档没提,但源码里支持传入client参数。禁用不必要的验证:LiteLLM 默认会对
messages做 schema 验证。在已知数据干净的场景,加validate_parameters=False参数,实测可提速 15%。预热模型连接:首次调用会有 DNS 解析和 TLS 握手延迟。在服务启动时主动调用一次
litellm.completion(model="gpt-3.5-turbo", messages=[{"role":"user","content":"ping"}], timeout=1),可消除首请求毛刺。
我在某金融客户项目中实测,应用这三点后,P95 延迟从 1.8s 降到 1.1s,且抖动大幅减少。这不是玄学优化,而是对 HTTP 协议特性的针对性调优。
6. 进阶场景与扩展方向
6.1 与 LangChain/LlamaIndex 深度协同
LiteLLM 不是 LangChain 的替代品,而是它的“加速器”。LangChain 的ChatModel抽象层可以无缝接入 LiteLLM 的 Router:
from langchain_core.language_models.chat_models import BaseChatModel from langchain_community.chat_models import ChatLiteLLM # 创建一个 LangChain 兼容的 chat model chat = ChatLiteLLM( model="gpt-4-turbo", temperature=0.3, max_tokens=1024 ) # 直接用于 LangChain 链 from langchain_core.prompts import ChatPromptTemplate prompt = ChatPromptTemplate.from_messages([ ("system", "你是一个专业翻译官"), ("user", "{text}") ]) chain = prompt | chat | StrOutputParser() result = chain.invoke({"text": "Hello world"})同样,LlamaIndex 的LLM接口也支持:
from llama_index.llms.litellm import LiteLLM llm = LiteLLM(model="ollama/llama3")这种组合让架构师可以:用 LiteLLM 管理模型生命周期,用 LangChain/LlamaIndex 构建复杂链路,各司其职。
6.2 模型微调与评估闭环
LiteLLM 本身不提供微调能力,但它能完美融入微调工作流。典型流程是:
- 用 LiteLLM 调用基座模型生成高质量合成数据(如用 GPT-4 生成 1000 条 QA 对);
- 用这些数据微调 Qwen2-7B;
- 再用 LiteLLM 同时评测微调前后模型在相同测试集上的表现;
- 自动生成对比报告。
我们曾用此方法将一个客服意图识别模型的 F1 分数从 0.72 提升到 0.85,整个 pipeline 全部基于 LiteLLM 的统一接口,无需切换 SDK。
6.3 安全与合规实践:Token 过滤与内容审核
LiteLLM 提供了litellm.input_callback和litellm.output_callback钩子,可用于敏感词过滤:
def filter_input(kwargs): messages = kwargs["messages"] for msg in messages: if "content" in msg and isinstance(msg["content"], str): # 简单关键词过滤(生产环境建议用专用审核服务) if "密码" in msg["content"] or "身份证" in msg["content"]: raise ValueError("Input contains sensitive information") litellm.input_callback = [filter_input]输出过滤同理,可在output_callback中检查result.choices[0].message.content是否含违规内容。虽然这不是替代专业内容安全服务的方案,但作为第一道防线非常有效。
7. 个人实操体会与避坑清单
我在过去 8 个月里,用 LiteLLM 支撑了 4 个不同规模的项目,从个人博客的 AI 助手,到某千万级用户的 SaaS 平台的智能体引擎。最大的体会是:LiteLLM 的价值不在“它能做什么”,而在“它让你不必做什么”。它帮你省掉的不是代码行数,而是决策成本——当你不再需要为每个新模型纠结“要不要重构”“要不要加监控”“要不要写新文档”,工程节奏就真正跑起来了。
这里是我整理的 5 个血泪教训:
永远不要在生产环境用
model="gpt-4"这种模糊名称。GPT-4 有多个版本(gpt-4-0613,gpt-4-turbo-2024-04-09),行为差异很大。必须写全称,否则某天 OpenAI 更新默认版本,你的线上服务可能突然变慢或出错。Ollama 模型名区分大小写。
ollama/llama3和ollama/Llama3是两个不同模型。LiteLLM 会原样透传,不会帮你纠错。建议在ollama list输出中复制粘贴,避免手误。流式响应的
finish_reason不可靠。某些模型(如早期 Claude)在流式结束时可能不返回finish_reason字段。正确做法是监听chunk.choices[0].delta.content为None时,认为流结束,而不是依赖finish_reason == "stop"。Router 的健康检查不是万能的。
health_check_interval默认 60 秒,意味着故障发现有分钟级延迟。对超低延迟场景,建议在业务层加try/catch+ 主动降级逻辑,不要完全依赖 Router。本地模型的
max_tokens是软限制。Ollama 和 Llama.cpp 的max_tokens参数实际是提示词长度上限,不是生成长度保证。如果你需要严格控制输出长度,必须在应用层截断,或用stop=["\n\n"]等 stop token 辅助。
最后分享一个小技巧:LiteLLM 的litellm.utils.get_supported_openai_models()函数能列出所有支持的模型名,但它是硬编码在源码里的。我把它导出为 JSON 文件,放在 CI/CD 流程中,每次部署前自动校验model_list中的模型是否在支持列表里,避免因拼写错误导致服务启动失败。这个看似微小的自动化,让我们团队在过去半年里零次因模型名错误导致的线上事故。
LiteLLM 不是银弹,但它是一把足够锋利的瑞士军刀。当你面对模型丛林时,它不承诺带你直达终点,但至少确保你不会在半路迷路。