1. 项目概述:LiteLLM 是什么,它解决了哪些真实痛点?
LiteLLM 这个名字乍一听像是某个轻量级编程语言或小众框架,但其实它是一个在开发者圈子里快速升温的开源工具——准确地说,它是一个统一的 LLM(大语言模型)调用抽象层。我第一次在某次内部技术分享会上听到这个词时,台下有位做智能客服系统的同事直接坐直了身子:“等等,你们说它能同时对接 OpenAI、Anthropic、Google Gemini、Ollama、本地 vLLM,甚至包括国内几家主流模型平台,而且 API 调用格式完全一致?”——那一刻我就知道,这东西不是玩具,是真正在解决一线工程团队每天都在咬牙硬扛的“多模型适配疲劳症”。
简单说,LiteLLM 的核心价值就一句话:让你写一次提示词(prompt),就能在不下线、不改代码的前提下,自由切换背后的真实模型服务商。它不训练模型,不优化推理速度,也不做模型压缩;它干的是“翻译官+调度员”的活——把你的标准 OpenAI 格式请求(比如{"model": "gpt-4o", "messages": [...]}),实时翻译成 Anthropic 需要的{"model": "claude-3-5-sonnet-20240620", "system": "...", "messages": [...]},再转发过去;等响应回来,又把它标准化成 OpenAI 的choices[0].message.content结构返回给你。整个过程对上层业务逻辑完全透明。
为什么这如此关键?举个真实场景:某高校实验室开发了一个教学辅助插件,初期用 GPT-4 Turbo 做代码解释和错题分析,效果很好。但上线两周后,因预算调整,需要临时切到成本更低的本地部署 Qwen2-7B 模型;一个月后,又因学生反馈生成内容过于保守,需接入更擅长创意表达的 Claude-3.5;再过一阵,学校采购了国产算力卡,要求优先调用某国产模型平台。如果没有 LiteLLM,这意味着每次切换都要:① 修改所有调用点的 import 和 client 初始化;② 重写 message 格式组装逻辑(OpenAI 是messages=[{"role":"user","content":"..."}],Claude 是messages=[{"role":"user","content":[{"type":"text","text":"..."}]}]);③ 重新处理 streaming 响应结构;④ 全面回归测试。而用了 LiteLLM,你只需要改一行配置:把model="gpt-4o"换成model="claude-3-5-sonnet-20240620"或model="ollama/qwen2:7b",其余代码纹丝不动。实测下来,一次模型迁移从原本平均 3–5 人日,压缩到 15 分钟内完成。
它适合谁?不是算法研究员,而是API 工程师、全栈开发者、MLOps 工程师、以及所有需要快速验证不同模型能力边界的产品技术负责人。如果你还在为“这个需求到底该用哪个模型实现效果最好”而反复改代码、搭环境、调参数,LiteLLM 就是你该立刻放进工具链里的那块拼图。
2. 核心设计思路与方案选型逻辑:为什么是抽象层,而不是 SDK 或代理?
2.1 不做模型,只做“协议桥接”:LiteLLM 的战略定力
很多刚接触 LiteLLM 的开发者会疑惑:“它和官方 SDK 有什么区别?我直接 pip install openai、anthropic 不就行了吗?”这个问题问到了本质。我们来拆解三类常见方案的底层逻辑差异:
官方 SDK(如
openai==1.45.0):深度绑定单一服务商,接口设计围绕其内部架构展开。例如 OpenAI 的stream=True返回Stream[ChatCompletionChunk]对象,而 Anthropic 的stream=True返回AsyncStream[ContentBlockDeltaEvent],二者类型系统、错误码、重试策略、超时机制完全不同。一旦业务需要横向对比模型效果,就必须在代码里写大量 if-else 分支,维护成本指数级上升。通用代理服务(如自建 Nginx 反向代理 + Lua 脚本):看似灵活,但实际落地极难。你需要手动解析每种模型的 HTTP 请求头、body 结构、鉴权方式(OpenAI 用
Authorization: Bearer sk-xxx,Google Vertex AI 用 OAuth2 token,某些国产平台用X-API-Key+ 时间戳签名),还要处理 response body 的字段映射、流式响应的 chunk 拆分与重组、错误码转换(OpenAI 的429 Too Many Requestsvs Anthropic 的429 Rate limit exceeded)、甚至 token 计数逻辑的差异(OpenAI 用 tiktoken,Claude 用 anthropic-tokens,本地模型可能根本没提供)。我见过一个团队花两周写的代理脚本,在接入第三个模型时因 streaming 响应格式不兼容导致前端页面卡死,最后全部推倒重来。LiteLLM 的抽象层方案:它选择了一条更“笨”但也更稳健的路——不碰网络传输层,只接管应用层协议转换。它本质上是一个 Python 函数库,所有调用都走标准
litellm.completion()接口。内部通过预定义的 adapter 模块(如litellm/adapters/anthropic.py)完成双向翻译。这种设计带来三个不可替代的优势:
①零网络中间跳转:请求直接从你的 Python 进程发出,不经过额外 HTTP 跳,延迟更低、链路更可控;
②强类型安全:输入输出都基于 Pydantic 模型校验,传错字段名或类型会在运行时报明确错误,而非静默失败;
③可调试性极强:你可以轻松开启litellm.set_verbose(True),看到每一层的原始请求、转换后请求、原始响应、标准化响应,调试时不再像在黑盒里摸鱼。
提示:LiteLLM 不是“替代 SDK”,而是“统一封装 SDK”。它底层依然调用
openai.AsyncOpenAI()、anthropic.AsyncAnthropic()等原生客户端,只是把它们藏在了统一接口后面。这意味着你依然能享受官方 SDK 的最新特性(如 OpenAI 的 parallel tool calling)、最佳实践(如连接池复用)和安全更新。
2.2 为什么支持 100+ 模型却保持轻量?模块化 adapter 架构解析
截至 2024 年中,LiteLLM 官方文档列出的支持模型列表已超过 120 个,涵盖国际主流(GPT、Claude、Gemini、Llama、Mixtral)、开源生态(Ollama、vLLM、Text Generation Inference)、国产平台(通义千问、讯飞星火、百度文心一言、智谱 GLM)以及私有部署方案(Azure OpenAI、Google Vertex AI、AWS Bedrock)。这么庞大的支持范围,为何安装包体积仅 1.2MB(pip install litellm),且无任何编译依赖?
答案在于其高度解耦的 adapter 注册机制。LiteLLM 的核心代码(litellm/main.py)非常精简,只定义了completion()、acompletion()、embedding()等顶层函数和统一的ModelResponse数据结构。所有模型特异性逻辑都被隔离在独立的 adapter 文件中,例如:
litellm/adapters/openai.py:处理 OpenAI / Azure / Perplexity / Groq 等兼容 OpenAI API 的服务;litellm/adapters/anthropic.py:专攻 Claude 系列,处理 system prompt、tool use、content blocks 等独特字段;litellm/adapters/google_vertex_ai.py:适配 Google Cloud 的复杂认证流程(Service Account Key JSON + region 配置);litellm/adapters/ollama.py:针对 Ollama 的本地 HTTP 接口(http://localhost:11434/api/chat)做轻量封装。
这些 adapter 并非在启动时全部加载,而是采用按需导入(lazy import):当你首次调用model="claude-3-haiku-20240307"时,LiteLLM 才动态导入anthropic包并初始化对应 adapter;调用model="ollama/llama3"时,才检查本地是否安装ollamaCLI 并建立连接。这种设计让 LiteLLM 在只使用单一模型时,内存占用和启动时间几乎与原生 SDK 无异。
注意:LiteLLM 的“支持”不等于“开箱即用”。例如对接某国产平台,你仍需自行申请 API Key、阅读其文档确认 endpoint 和鉴权方式,然后通过 LiteLLM 的
add_provider()接口注册自定义 provider。它的价值在于:把“每个平台都要写一套胶水代码”的工作,变成“写一次注册逻辑,复用全部标准调用”。
2.3 与 LangChain、LlamaIndex 等框架的定位差异:它是基础设施,不是应用层
常有人问:“LiteLLM 和 LangChain 是不是重复造轮子?”这是个好问题,但混淆了抽象层级。我们可以用一个现实类比:
- LiteLLM 是“电源插座”:它确保你插上任何符合国标(GB/T 2099.1)的电器(GPT、Claude、Qwen),都能获得稳定 220V 交流电(标准 ChatCompletion 响应)。它不管你是用这电来烧水(做 RAG)、煮饭(做 Agent)、还是给手机充电(做简单问答)。
- LangChain 是“智能厨房”:它提供菜谱(PromptTemplate)、调料架(Memory)、自动炒锅(AgentExecutor)、食材溯源系统(DocumentLoader)。但它默认假设你已经接好了电源——早期 LangChain 直接依赖
openai.ChatOpenAI,后来才通过ChatLiteLLM封装器接入 LiteLLM。
换句话说,LiteLLM 解决的是“如何让不同模型说同一种语言”,LangChain 解决的是“如何用同一种语言讲好一个复杂故事”。两者不是竞争关系,而是天然互补。事实上,2024 年多数成熟 RAG 项目架构已是:User Input → LangChain Router → LiteLLM (model=xxx) → Model Provider。LiteLLM 作为中间稳固的“电压稳压器”,让上层应用无需关心底层电力来源是火电、水电还是风电。
3. 核心功能详解与实操要点:从零开始跑通第一个跨模型调用
3.1 最小可行示例:三行代码验证跨模型能力
我们先抛开所有配置和高级特性,用最朴素的方式验证 LiteLLM 的核心价值。以下代码在一台装有 Python 3.10+ 的机器上,无需任何额外服务,即可完成 GPT-4、Claude-3 和本地 Ollama 的无缝切换:
# 终端执行(确保已安装 ollama 并拉取模型) $ ollama pull llama3 $ ollama run llama3 "Hello, tell me about quantum computing in 3 sentences"# test_cross_model.py from litellm import completion # 场景1:调用 OpenAI(需设置环境变量 OPENAI_API_KEY) response = completion( model="gpt-4o", messages=[{"role": "user", "content": "用中文解释量子纠缠,不超过50字"}] ) print("GPT-4o 输出:", response.choices[0].message.content) # 场景2:调用 Anthropic(需设置 ANTHROPIC_API_KEY) response = completion( model="claude-3-haiku-20240307", messages=[{"role": "user", "content": "用中文解释量子纠缠,不超过50字"}] ) print("Claude-3 Haiku 输出:", response.choices[0].message.content) # 场景3:调用本地 Ollama(无需 API Key,自动检测 http://localhost:11434) response = completion( model="ollama/llama3", messages=[{"role": "user", "content": "用中文解释量子纠缠,不超过50字"}] ) print("Ollama Llama3 输出:", response.choices[0].message.content)运行结果会清晰显示三个模型对同一问题的回答差异:GPT-4o 更严谨,Claude-3 Haiku 更简洁,Llama3 则带点“开源味”的直白。而你全程只需修改model=参数,其余代码、提示词、消息结构完全一致。这就是 LiteLLM 的魔法起点。
实操心得:首次运行时若遇到
AuthenticationError,请确认对应 API Key 是否已正确设置为环境变量(export OPENAI_API_KEY=sk-xxx),而非硬编码在代码里。LiteLLM 默认从环境变量读取密钥,这是生产环境的最佳实践,避免密钥泄露风险。
3.2 关键参数深度解析:model,api_base,api_key的协同逻辑
LiteLLM 的completion()函数表面看只有几个参数,但每个参数背后都有明确的设计意图和协作规则。理解它们,是避免“为什么换模型没生效”这类问题的关键。
| 参数 | 类型 | 必填 | 作用说明 | 典型值示例 | 注意事项 |
|---|---|---|---|---|---|
model | str | ✅ | 模型路由标识符,LiteLLM 的核心调度键。格式为"provider/model_name",如"gpt-4o"(默认 OpenAI)、"anthropic/claude-3-5-sonnet-20240620"(显式指定 provider)、"ollama/llama3"(Ollama 模型) | "gpt-4o","azure/gpt-4o","vertex_ai/gemini-pro" | 若省略 provider 前缀(如"gpt-4o"),LiteLLM 按内置优先级匹配:OpenAI > Azure > Custom;显式写"openai/gpt-4o"可强制走 OpenAI 路径 |
api_base | str | ❌ | 自定义 API Endpoint。当服务商提供非标准地址时使用,如 Azure OpenAI 的https://your-resource.openai.azure.com/,或私有部署的 TGI 服务http://192.168.1.100:8080 | "https://your-resource.openai.azure.com/","http://192.168.1.100:8080" | 仅对部分 provider 生效(如 openai, azure, vertex_ai)。Ollama 默认http://localhost:11434,无需设置 |
api_key | str | ❌ | 显式 API Key。当环境变量未设置或需临时覆盖时使用。优先级高于环境变量 | "sk-xxx","anthropic-key-xxx" | 强烈建议生产环境用环境变量,避免密钥硬编码。LiteLLM 支持OPENAI_API_KEY,ANTHROPIC_API_KEY,GEMINI_API_KEY等标准变量名 |
这里有个易踩坑点:api_base和model的组合逻辑。例如,你想调用 Azure 上部署的gpt-4o,正确的写法是:
completion( model="azure/gpt-4o", # 显式声明 provider 为 azure api_base="https://your-resource.openai.azure.com/", # Azure endpoint api_version="2024-02-01", # Azure 特有参数,必须提供 api_key="your-azure-key" # Azure 密钥 )如果写成model="gpt-4o"+api_base="https://...",LiteLLM 会尝试用 OpenAI 的协议去连 Azure 地址,必然失败。因为model字符串不仅是模型名,更是路由指令。
提示:LiteLLM 内置了
litellm.utils.get_supported_models()函数,可动态获取当前版本支持的所有模型列表及对应 provider。在 CI/CD 流程中,可用它做模型可用性检查,避免上线时因模型名拼写错误导致服务中断。
3.3 流式响应(Streaming)的统一处理:告别各平台解析地狱
流式响应是 LLM 应用的刚需,但各平台的 streaming 实现五花八门:OpenAI 返回data: {"choices":[{"delta":{"content":"a"}}]的 SSE 格式;Claude 返回event: content_block_delta\ndata: {"type":"content_block_delta","delta":{"text":"a"}};Ollama 则是纯 JSON 数组[{"message":{"content":"a"}}]。手动解析这些,是前端工程师的噩梦。
LiteLLM 用一个优雅的设计解决了它:统一暴露iter_response迭代器。无论底层是哪种协议,你只需用标准 for 循环遍历:
from litellm import completion # 启用 streaming response = completion( model="gpt-4o", messages=[{"role": "user", "content": "请逐字输出'量子计算'四个字"}], stream=True ) # 统一处理逻辑 full_content = "" for chunk in response: # chunk 是标准 LiteLLM Chunk 对象,含 .choices[0].delta.content 属性 delta_content = chunk.choices[0].delta.content or "" full_content += delta_content print(f"收到增量: '{delta_content}'") print("完整输出:", full_content) # 输出:量子计算这个chunk对象的结构是 LiteLLM 标准化的:chunk.choices[0].delta.content存放本次增量文本,chunk.choices[0].finish_reason标识结束原因("stop" 或 "length")。你无需关心底层是 SSE 还是 JSON,也无需写正则匹配data:前缀。实测在 100+ 模型上,这段代码 100% 通用。
注意事项:流式调用时,
response对象本身不包含完整内容,它只是一个迭代器。试图访问response.choices[0].message.content会报错。务必用for chunk in response:方式消费。
3.4 高级能力实战:Function Calling 与 Tool Use 的跨平台对齐
Function Calling(函数调用)是 LLM Agent 的基石能力,但各平台实现差异极大:OpenAI 称之为tools,Claude 称为tool_use,Google Gemini 称为function_declarations,而 Ollama 等开源模型则根本不支持。LiteLLM 的解决方案是:定义统一的tools参数格式,并在 adapter 层做语义映射。
以一个天气查询工具为例,我们定义标准工具描述:
tools = [{ "type": "function", "function": { "name": "get_current_weather", "description": "Get the current weather in a given location", "parameters": { "type": "object", "properties": { "location": {"type": "string", "description": "The city and state, e.g. San Francisco, CA"}, "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]} }, "required": ["location"] } } }]现在,用同一段tools和messages,调用不同模型:
# OpenAI 路径(原生支持 tools) response = completion( model="gpt-4o", messages=[{"role": "user", "content": "What's the weather like in Boston?"}], tools=tools, tool_choice="auto" # OpenAI 特有参数 ) # Claude 路径(LiteLLM 自动转换为 Anthropic 的 tool_use 格式) response = completion( model="claude-3-5-sonnet-20240620", messages=[{"role": "user", "content": "What's the weather like in Boston?"}], tools=tools, # Claude 不需要 tool_choice,LiteLLM 会忽略此参数 ) # Gemini 路径(自动映射为 function_declarations) response = completion( model="gemini/gemini-pro", messages=[{"role": "user", "content": "What's the weather like in Boston?"}], tools=tools )LiteLLM 在内部会根据model的 provider 类型,将同一份tools列表转换为对应平台所需的格式。更重要的是,响应中的工具调用信息也被标准化:无论哪个平台,你都可以用response.choices[0].message.tool_calls获取调用列表,每个tool_call对象都有.function.name和.function.arguments属性。这意味着你的 Agent 调度逻辑(解析 tool_calls → 执行函数 → 注入结果)可以完全复用,彻底摆脱平台锁定。
实操心得:并非所有模型都真正支持 Function Calling。LiteLLM 会在不支持的模型上静默降级为普通文本生成(即忽略
tools参数)。可通过litellm.supports_function_calling(model="xxx")函数提前检查支持状态,避免线上出现“工具调用不触发”的诡异问题。
4. 实操全流程与核心环节实现:构建一个可切换模型的 RAG 系统
4.1 项目背景与架构设计:为什么 RAG 是 LiteLLM 的最佳练兵场?
RAG(检索增强生成)系统是当前 LLM 应用中最典型的“多模型协同”场景。一个成熟的 RAG 流程通常包含:用户提问 → 向量检索(从知识库召回相关片段)→ 提示词工程(将检索结果 + 用户问题拼装成上下文)→ LLM 生成答案。其中,LLM 生成环节是效果差异最大的瓶颈:GPT-4 逻辑严谨但成本高,Claude-3 擅长长文本归纳但 API 延迟稍高,Llama3 本地部署零成本但事实准确性弱。理想状态是:根据问题类型、预算阈值、延迟要求,动态选择最优模型。
我们以一个“高校科研助手”RAG 系统为例,目标是:
- 输入:学生提问 “帮我总结这篇论文的核心创新点”(附 PDF 文件)
- 流程:PDF 解析 → 文本分块 → 向量检索 → 拼装 prompt → 调用 LLM 生成摘要
- 关键需求:管理员可在后台配置,对“摘要生成”任务,优先使用
gpt-4o;若调用失败或超时,则自动降级到claude-3-haiku;若两者均不可用,启用本地ollama/qwen2:7b保底。
这个需求完美契合 LiteLLM 的三大能力:统一 API、故障自动降级(fallback)、模型路由策略。下面我们将一步步实现。
4.2 环境准备与依赖安装:精简可靠的基础栈
我们选择最轻量、最易复现的技术栈:Python 3.10+、LangChain(用于 RAG 流水线)、ChromaDB(轻量向量数据库)、LiteLLM(模型调度)。所有依赖均可通过 pip 一键安装:
# 创建虚拟环境(推荐) $ python -m venv rag-env $ source rag-env/bin/activate # Linux/Mac # rag-env\Scripts\activate # Windows # 安装核心依赖 $ pip install --upgrade pip $ pip install langchain chromadb unstructured pypdf litellm # 可选:安装 Ollama(如需本地模型) $ curl -fsSL https://ollama.com/install.sh | sh # Linux/Mac # 或从 https://ollama.com/download 下载 Windows 安装包 $ ollama pull qwen2:7b $ ollama pull llama3注意:
unstructured用于 PDF 解析,依赖libmagic(Linux/macOS)或file命令(Windows),安装前请确保系统已安装。若仅测试文本 RAG,可跳过此步,用模拟数据代替。
4.3 核心代码实现:RAG 流水线与 LiteLLM 模型路由集成
我们将 RAG 流水线拆解为四个模块:数据加载、向量存储、检索器、生成器。LiteLLM 的集成点集中在生成器模块,这也是最能体现其价值的部分。
步骤1:数据加载与向量存储(LangChain 标准流程)
# rag_pipeline.py from langchain_community.document_loaders import PyPDFLoader from langchain_text_splitters import RecursiveCharacterTextSplitter from langchain_community.vectorstores import Chroma from langchain_community.embeddings import OllamaEmbeddings # 加载 PDF(示例用一篇公开论文) loader = PyPDFLoader("sample_paper.pdf") docs = loader.load() # 文本分块 text_splitter = RecursiveCharacterTextSplitter( chunk_size=500, chunk_overlap=50, length_function=len, ) splits = text_splitter.split_documents(docs) # 使用 Ollama 的 nomic-embed-text 模型做嵌入(轻量且免费) embeddings = OllamaEmbeddings(model="nomic-embed-text") vectorstore = Chroma.from_documents(documents=splits, embedding=embeddings)步骤2:构建检索增强的 Prompt 模板
from langchain_core.prompts import ChatPromptTemplate # 标准 RAG Prompt 模板 rag_prompt = ChatPromptTemplate.from_messages([ ("system", "你是一位专业的科研助手。请基于提供的上下文信息,准确、简洁地回答用户问题。" "如果上下文未提供足够信息,请如实告知,不要编造。"), ("human", "上下文信息:\n{context}\n\n用户问题:{question}") ])步骤3:LiteLLM 驱动的生成器(核心集成点)
from litellm import completion from langchain_core.output_parsers import StrOutputParser from langchain_core.runnables import RunnablePassthrough class LiteLLMGenerator: def __init__(self, fallback_models=None): """ 初始化生成器 :param fallback_models: 降级模型列表,如 ["claude-3-haiku-20240307", "ollama/qwen2:7b"] """ self.fallback_models = fallback_models or [] def invoke(self, prompt_str): """ 执行生成,支持自动降级 :param prompt_str: 拼装好的完整 prompt 字符串 :return: 生成的字符串 """ # 主力模型(可配置为环境变量) primary_model = "gpt-4o" # 尝试主力模型 try: response = completion( model=primary_model, messages=[{"role": "user", "content": prompt_str}], timeout=30 # 30秒超时 ) return response.choices[0].message.content.strip() except Exception as e: print(f"主力模型 {primary_model} 调用失败: {e}") # 依次尝试降级模型 for fallback_model in self.fallback_models: try: print(f"尝试降级模型: {fallback_model}") response = completion( model=fallback_model, messages=[{"role": "user", "content": prompt_str}], timeout=45 # 降级模型可容忍更长延迟 ) return response.choices[0].message.content.strip() except Exception as e: print(f"降级模型 {fallback_model} 调用失败: {e}") continue raise RuntimeError("所有模型调用均失败,请检查网络和 API Key 配置") # 实例化生成器 generator = LiteLLMGenerator( fallback_models=["claude-3-haiku-20240307", "ollama/qwen2:7b"] )步骤4:组装完整 RAG 链
from langchain_core.runnables import RunnableParallel # 构建 RAG 链 retriever = vectorstore.as_retriever() rag_chain = ( {"context": retriever | (lambda docs: "\n\n".join([d.page_content for d in docs])), "question": RunnablePassthrough()} | rag_prompt | generator.invoke # 这里接入我们的 LiteLLM 生成器 | StrOutputParser() ) # 执行查询 result = rag_chain.invoke("这篇论文的核心创新点是什么?") print("RAG 生成结果:", result)这个实现的关键在于:generator.invoke()方法封装了完整的模型降级逻辑,而上层 RAG 链(rag_chain)完全感知不到底层模型的切换。你可以在不修改任何 RAG 逻辑代码的前提下,通过调整fallback_models列表,或修改primary_model,来改变整个系统的模型策略。
4.4 模型路由策略进阶:基于成本、延迟、质量的动态决策
上面的降级是简单的“失败即切换”,但在生产环境中,我们需要更智能的路由。LiteLLM 提供了litellm.Router类,支持基于多种策略的负载均衡和故障转移。
from litellm import Router # 定义模型路由池,每个模型可配置权重、区域、健康状态 router = Router( model_list=[ { "model_name": "gpt-4o", # 路由名 "litellm_params": { "model": "gpt-4o", "api_key": "sk-xxx", # 可选,若用环境变量可省略 "timeout": 30 }, "tpm": 100000, # 每分钟 Token 限额,用于限流 "rpm": 1000, # 每分钟请求数限额 }, { "model_name": "claude-3-haiku", "litellm_params": { "model": "claude-3-haiku-20240307", "api_key": "anthropic-key-xxx" }, "tpm": 200000, "rpm": 2000, }, { "model_name": "ollama-qwen2", "litellm_params": { "model": "ollama/qwen2:7b", "api_base": "http://localhost:11434" # 显式指定 Ollama 地址 } } ], num_retries=3, # 每个请求最多重试3次 timeout=60, # 总超时60秒 fallbacks=[ # 定义降级策略 {"gpt-4o": ["claude-3-haiku", "ollama-qwen2"]}, {"claude-3-haiku": ["ollama-qwen2"]} ] ) # 使用 Router 替代直接调用 completion response = router.completion( model="gpt-4o", # 这里是路由名,非真实模型名 messages=[{"role": "user", "content": "你好"}] )Router 的强大之处在于它能结合实时指标做决策。例如,你可以配置一个监控脚本,定期调用router.get_available_models()获取当前健康模型列表,并根据router.get_usage_metrics()返回的延迟、成功率、token 消耗数据,动态调整路由权重。这使得 RAG 系统不仅能“活着”,还能“聪明地活着”。
实操心得:Router 的
fallbacks配置是全局的,但你也可以在单次调用时覆盖,例如router.completion(..., fallbacks=[{"gpt-4o": ["ollama-qwen2"]}]),实现 per-request 的精细控制。这对 A/B 测试不同模型效果非常有用。
5. 常见问题与排查技巧实录:那些只有踩过坑才知道的事
5.1 典型问题速查表:从报错信息反推根因
LiteLLM 的错误信息设计得比较友好,但初学者仍容易被表象迷惑。以下是我在多个项目中整理的高频问题与精准排查路径:
| 报错信息(截取关键部分) | 最可能根因 | 排查步骤 | 解决方案 |
|---|---|---|---|
AuthenticationError: Invalid API key | API Key 未正确设置或已过期 | 1. 检查echo $OPENAI_API_KEY是否输出有效值2. 在 Python 中 import os; print(os.getenv("OPENAI_API_KEY"))3. 确认 Key 是否被复制时多出空格或换行 | 重新生成 Key,用export OPENAI_API_KEY="sk-xxx"设置,避免在代码中硬编码 |
BadRequestError: model 'gpt-4o' not found | 模型名拼写错误或服务商未开通该模型 | 1. 访问 OpenAI Platform 控制台,确认账户已订阅gpt-4o2. 运行 litellm.utils.get_supported_models()查看当前支持列表3. 检查是否误写为 gpt-4-o(带短横线) | 使用litellm.utils.get_model_info("gpt-4o")获取模型详情,确认可用性 |
TimeoutError: Request timed out | 网络延迟高或模型响应慢 | 1. 用curl -v https://api.openai.com/v1/models测试基础连通性2. 在 LiteLLM 调用中增加 timeout=60参数3. 检查是否在公司内网,需配置代理(LiteLLM 支持 HTTP_PROXY环境变量) | 对于高延迟场景,增加timeout;对本地模型,确保api_base地址可达(如curl http://localhost:11434) |
ValidationError: field required (type=value_error.missing) | 提示词格式不符合目标模型要求 | 1. 开启litellm.set_verbose(True),查看转换后的请求体2. 检查是否对 Claude 模型使用了 system字段 |