litellm & vllm 说明文档
- 仓库地址
- LiteLLM & vLLM 服务管理系统
- LLM API 包装器使用文档
- FAQ
- vllm
- vllm中的
model_name到底应该指什么? - 如何判断每个模型应该部署到多少个GPU上?
- 日志中出现报错
RuntimeError: Bytes object is corrupted, checksum does not match.怎么办? max_num_seqs和max_num_batched_tokens应该如何设置?- 日志中出现
Error retrieving safetensors: Repo id must be in the form 'repo_name' or 'namespace/repo_name': ... Use repo_type argument if needed., retrying 1 of 2 (APIServer pid=3206581) ERROR 01-13 20:59:00怎么办? - 日志中出现
openai_harmony.HarmonyError: error downloading or loading vocab file: failed to download or load vocab file怎么办?
- vllm中的
- litellm
- litellm的优先级是怎么样的?
- 对于litellm来说,“失败”的具体定义是什么?
max_parallel_requests等参数怎么与调度机制进行协调的?max_parallel_requests和tpm/rpm的优先级是怎么样的?- litellm的日志文件中出现
ImportError: ... install httpx using pip install httpx[socks].怎么办? - 可以查询到litellm启动程序运行了,但是litellm的日志没有内容,而且健康测试失败,怎么办?
- 在日志文件中遇到了
Checking for hanging requests....怎么办? - 如果在运行的过程中,openai库报错
ReadERR和Connection Error怎么办?
- vllm
仓库地址
LiteLLM & vLLM 服务管理系统
这是一个基于 Shell 的自动化工具流,用于一键部署和管理 LiteLLM Proxy(作为统一网关)和 vLLM(作为推理后端)。支持多 GPU、多实例部署,并包含自动健康检查和日志管理功能。
1. 脚本概览
项目包含以下四个核心脚本:
| 脚本名 | 作用 | 说明 |
|---|---|---|
start-all.sh |
主入口脚本 | 负责环境检查、停止旧服务、依次启动 vLLM 和 LiteLLM,并输出服务地址。 |
stop_all.sh |
停止服务 | 查找并终止所有相关进程,支持交互式强制关闭。 |
start_litellm.sh |
启动 LiteLLM | 独立启动 Proxy,支持开发模式(development)和生产模式(production)。 |
start_vllm_instances.sh |
启动 vLLM | 根据配置文件并行启动多个 vLLM 实例,并等待端口就绪。 |
2. 环境要求
在运行脚本之前,请确保服务器满足以下要求:
- 操作系统: Linux (Bash shell)
- Python 环境: 建议使用 Conda 或 venv
- 依赖工具:
litellm:pip install litellmvllm:pip install vllm(如果启用 vLLM)yq: 必须安装,用于解析 YAML 配置文件curl: 用于健康检查- NVIDIA Drivers &
nvidia-smi(如果启用 vLLM)
3. 配置文件说明
脚本强依赖 YAML 配置文件。以下是配置文件的结构示例。
3.1 vLLM 配置文件 (vllm_config.yaml)
如果需要启动 vLLM 后端,你需要按照以下格式编写配置:
settings:
log_dir: "./logs/vllm" # vLLM 日志存放路径
instances:
- id: 1
model_name: "/path/to/model-A"
served_model_name: "model-a" # 可选,默认为 model_name,用于litellm路由的名字
gpus: "0,1" # 指定 CUDA_VISIBLE_DEVICES,即这个实例可见的GPU
port: 8000
tensor_parallel_size: 2 # 张量并行数,需要为矩阵的约数,并且尽量与GPU个数相同
# vllm也支持数据并行和流水线并行,但是在单节点多GPU的时候没必要流水线并行
max_model_len: 8192 # 一次请求可处理的最大上下文长度
gpu_memory_utilization: 0.90 # 控制vLLM实例可用的GPU显存比例,决定模型权重和KV cache等分配的总显存上限
max_num_seqs: 256 # 可选,默认 256
enable_chunked_prefill: true # 可选,默认 false
disable_log_requests: false # 可选,默认 false
- id: 2
model_name: "/path/to/model-B"
gpus: "2"
port: 8001
tensor_parallel_size: 1
3.2 LiteLLM 配置文件 (litellm_config.yaml)
标准的 LiteLLM 配置文件,需要将 api_base 指向 vLLM 的端口。详见官方文档。具体的调度机制见grok的回答
model_list:
- model_name: llm-judge-1
litellm_params:
model: hosted_vllm/Qwen/Qwen3-0.6B # 替换为你的模型名称(served_model_name)
api_base: http://localhost:8001/v1
max_parallel_requests: 200 # 👈 关键:每后端最大并发
rpm: 10000 # 每分钟请求限制(设高一点)
tpm: 10000000 # 每分钟 token 限制
timeout: 300 # 请求超时 (秒)
stream_timeout: 60 # 流式响应超时 (秒)
model_info:
id: "llm_judge-instance-1"
- model_name: llm-judge-2
litellm_params:
model: hosted_vllm/Qwen/Qwen3-0.6B
api_base: http://localhost:8002/v1
max_parallel_requests: 200
rpm: 10000
tpm: 10000000
timeout: 300
stream_timeout: 60
model_info:
id: "llm_judge-instance-2"
# ============================================================
# LiteLLM 核心设置
# ============================================================
litellm_settings:
drop_params: true # 自动移除不支持的参数
num_retries: 3 # 失败重试次数
request_timeout: 600 # 全局请求超时(根据https://github.com/BerriAI/litellm/discussions/9206,会覆盖每个后端的timeout)
set_verbose: true # 调试时设为 true
# ============================================================
# 路由器设置 (负载均衡)
# ============================================================
router_settings:
# ---- 路由策略选择 ----
# simple-shuffle: 随机负载均衡(推荐,同质化部署)
# least-busy: 选择最空闲的实例(流式请求多时使用)
# usage-based-routing-v2: 基于 TPM/RPM 使用量(有配额限制时)
# latency-based-routing: 选择延迟最低的(延迟敏感场景)
routing_strategy: least-busy
# ---- 并发控制 ----
default_max_parallel_requests: 200 # 每个后端默认最大并发
# ---- 重试与超时 ----
enable_pre_call_checks: true # 预调用检查
num_retries: 3 # 路由重试次数
timeout: 30 # 路由超时
retry_after: 5 # 重试间隔(秒)
# ---- Redis 配置(多 LiteLLM 实例时需要)----
# redis_host: localhost
# redis_port: 6379
# redis_password: ""
# ============================================================
# 通用设置
# ============================================================
# general_settings:
# master_key: sk-your-secret-key-1234 # API 认证密钥 (生产环境请更换)
# database_url: postgresql://user:password@localhost:5432/litellm # 可选数据库
# store_model_in_db: true
4. 使用指南
4.1 一键启动
使用 start-all.sh 可以处理所有流程。
仅启动 LiteLLM (连接已有后端):
./start-all.sh --litellm-config ./config/litellm_config.yaml
启动 vLLM + LiteLLM (完整链路):
./start-all.sh \
--vllm-config ./config/vllm_config.yaml \
--litellm-config ./config/litellm_config.yaml
保留当前运行的服务 (跳过停止步骤):
./start-all.sh \
--skip-stop \
--litellm-config ./config/litellm_config.yaml
4.2 停止服务
使用 stop_all.sh 清理进程。脚本会检查残留进程,如果正常关闭失败,会询问是否强制 kill -9。
./stop_all.sh
也可以使用stop_vllm.sh和stop_litellm.sh分别停止两样服务
4.3 单独使用子脚本
如果你需要调试或单独管理某个组件,可以直接调用子脚本。
单独启动 vLLM:
# 这将根据配置启动所有定义的实例并在后台运行
./start_vllm_instances.sh --config ./config/vllm_config.yaml
单独启动 LiteLLM:
# 开发模式 (单进程,详细 Debug 日志)
./start_litellm.sh -c ./config/litellm_config.yaml -p 4000 -m development
# 生产模式 (Gunicorn 多 Worker)
./start_litellm.sh -c ./config/litellm_config.yaml -p 4000 -m production -w 8
5. 日志管理
- LiteLLM 日志: 可以在
start_litellm.sh的开头直接配置,也可以在start_all.sh调用start_litellm.sh的时候传递参数 - vLLM 日志: 位于
vllm_config.yaml中配置的路径(例如./logs/vllm_instance_{ID}.log)。
6. 故障排查
- 脚本提示
yq: command not found:- 脚本依赖
yq解析 YAML。请参考环境要求部分进行安装。
- 脚本依赖
- vLLM 启动超时:
- 检查日志文件。常见原因是显存不足 (OOM) 或模型路径错误。
- 如果是大模型,加载时间较长,脚本默认等待 300秒。
- LiteLLM 健康检查失败:
- 检查端口是否被占用。
- 查看
litellm_logs下的日志,确认配置文件语法是否正确。
- 端口冲突:
- 确保配置文件中指定的端口(如 8000, 8001, 4000)未被其他服务占用。
7. 目录结构建议
为了让脚本正常工作,建议的项目结构如下:
.
├── scripts/
├ ├── start-all.sh
├ ├── stop_all.sh
├ ├── start_litellm.sh
├ ├── start_vllm_instances.sh
├── config/
│ ├── litellm_config.yaml
│ └── vllm_config.yaml
├── vllm_logs/ # 自动生成
└── litellm_logs/ # 自动生成
LLM API 包装器使用文档
该模块主要通过 ChatGPT 类提供与大模型交互的能力,并利用 Recorder 类自动记录调用消耗。
1. 环境准备 (Prerequisites)
在使用之前,必须设置以下环境变量,或者在初始化时作为参数传入(部分参数):
| 环境变量名 | 必填 | 描述 |
|---|---|---|
OPENAI_API_KEY |
否 | API 密钥。 |
OPENAI_API_BASE |
否 | API 基础 URL (Base URL)。 |
MODEL |
否 | 默认使用的模型名称 (如果在代码中未指定 llm_name,则读取此环境变量)。 |
2. 核心类:ChatGPT
ChatGPT 是主要的交互入口,负责管理对话上下文和发送请求。
2.1 初始化 (__init__)
chat_bot = ChatGPT(
llm_name="gpt-4",
system_prompt="你是一个助手",
llm_record_path="./logs/record.json"
)
参数说明:
| 参数名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
llm_name |
str |
None |
模型名称(如 x-ai/grok-4.1-fast)。若为 None,则尝试读取环境变量 MODEL。 |
system_prompt |
str |
None |
系统提示词(System Prompt)。 注意:如果模型名包含 "o1",此参数将被忽略(强制为 None)。 |
max_try_num |
int |
10 |
底层 API 请求失败时的最大重试次数(针对网络错误、API 报错)。 |
try_num |
int |
3 |
业务逻辑/解析失败时的最大重试次数(针对 chat 方法中的解析错误)。若最终失败,将抛出 AssertionError,建议用 try-except 块包裹调用。 |
enable_recorder |
bool |
False |
是否记录调用信息(Recoder会频繁加载json文件,如果不需要调用信息可以不启动) |
llm_record_path |
str |
None |
记录文件的路径。若为 None则报错。 |
detailed_record_num |
int |
0 |
记录详细日志(包含完整 usage 信息)的前 N 条数量。 |
api_base |
str |
None |
Base URL,如果没有指定,则从环境变量中读取 |
api_key |
str |
None |
如果没有指定,则从环境变量中读取 |
2.2 发送对话 (chat)
这是最常用的方法,它封装了重试逻辑和历史记录更新。
reply, rest = chat_bot.chat(
request="你好,请介绍一下你自己",
temperature=0.7
)
参数说明:
| 参数名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
request |
str | dict |
必填 | 用户的输入内容。可以是字符串,也可以是符合 OpenAI 格式的消息字典(可以是多模态)。 |
parse_func |
Callable |
default_parse_func |
自定义解析函数。用于处理 API 返回的 completion 对象。 |
save_history |
bool |
False |
是否将这次回复加入到上下文中 |
**kwargs |
- | - | 其他传递给 API 的参数,例如 temperature, response_format 等(具体见官方文档参数说明);以及extra_body |
注意一下OpenAI API调用失败和LLM chat 报错分别代表的错误是哪两个函数
2.3 重置对话 (reset_conversation)
清空当前的对话历史,重置为初始状态(仅包含 System Prompt)。
chat_bot.reset_conversation()
参数说明:
| 参数名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
conversation |
list |
None |
可选。如果传入列表,则将对话历史强制设置为该列表。否则重置为默认 System Prompt。 |
3. 辅助功能
3.1 自定义解析函数 (parse_func)
在 chat 方法中,你可以传入自定义的解析函数来处理复杂的返回结构。
函数签名:
def my_parse_func(completion):
# completion 是 OpenAI API 返回的原始对象
content = completion.choices[0].message.content
# 进行自定义处理...
return content, "extra_info" # 必须返回两个值
3.2 调用请求参数解析函数(generate_llm_params)
此函数在内部进行调用,不用手动调用
会自动处理大部分参数,使用者只管传参即可
特殊参数处理 (generate_llm_params):
- temperature: 如果模型名包含 "o1",
temperature会被强制设为1。 - response_format: 会被自动转换为 OpenAI 格式
{"type": ...}。如果模型包含 "o1",强制设为{"type": "text"}。
3.3 费用记录 (Recorder)
该类由 ChatGPT 内部自动调用。
- 它会在指定的 JSON 文件中累加
total_cost和total_count。
功能不完善,没有修复,有些提供商不会在completion中返回费用;同时异步同步的逻辑也没有处理好;还可能有一些其他的毛病
先别使用,保持enable_recorder为False
4.技巧杂记
- 遇到了openai库不支持的参数(比如
provider),可以写在extra_body里面 - 有个参数叫
n,可以在同一个completion中返回多次生成。completion.choices[i]中的i不能超过n减一 - 可以获取每个位置的token的概率分布,如下:
支持这个参数的模型比较少,如果返回是None不要大惊小怪,可能是模型不支持response = openai.OpenAI( base_url=self.api_base, api_key=self.api_key ).chat.completions.create( model="openai/gpt-4o", # 或其他支持的模型 messages=[{"role": "user", "content": "您的提示内容"}], logprobs=True, top_logprobs=5 # 获取每个位置概率最高的5个token ) - 当前的openrouter(2025.11.30),除了claude,都支持自动化的cache,就不用单独设置(gemini也可以选择单独设置);claude需要单独设置,但是目前不会,可以学一下
provider可以选择模型提供商,具体介绍见官方文档,里面有个参数require_parameters很有用,最好都加上- 使用的时候是
extra_body={"provider": {"require_parameters": True}} - 但是有个弊端就是满足参数的提供商可能会比较拥挤
- 使用的时候是
FAQ
vllm
vllm中的model_name到底应该指什么?
按照官方文档的说法,假设我们按照HF的写法,那么他会先到$HF_HUB_CACHE里面去找模型,如果没有找到缓存的话就去HF网站上面下载。但是有些时候不知道为什么会失效,此时就需要指定模型的具体路径,比如.../models--Qwen--Qwen3-0.6B/snapshots/c1899de289a04d12100db370d81485cdf75e47ca(注意要具体到哈希值)
同时为了不让模型的名字过于复杂,使用--served-model-name来进行模型命名
如何判断每个模型应该部署到多少个GPU上?
在部署大模型的时候,可以去huggingface的模型页面的Files and versions里面看看模型的总大小(比如Qwen3-235B-A22B是470GB),然后去判断需要几张卡,比如一张H200大约141GB,所以需要4张卡
当然有些模型的Files and versions有多个目录(比如gpt-oss-120b),此时很可能只需要下载根目录下的文件即可(可以问问AI),当然计算内存的话也是按照根目录下的文件计算,而不会计算进入子目录下的文件
日志中出现报错RuntimeError: Bytes object is corrupted, checksum does not match. 怎么办?
vLLM使用PyTorch的torch.compile功能进行模型编译,并将编译结果缓存在磁盘上。缓存文件损坏了,导致加载时校验和不匹配。此时删除缓存rm -rf /.cache/vllm/torch_compile_cache/然后重新启动即可
max_num_seqs和max_num_batched_tokens应该如何设置?
啊这个可太复杂了
https://github.com/vllm-project/vllm/issues/8185
https://github.com/vllm-project/vllm/issues/4044
https://github.com/vllm-project/vllm/issues/2492
https://github.com/vllm-project/vllm/blob/ba7ba35cdaeacb59860bad2691de190bd77ccd05/benchmarks/auto_tune.sh
https://docs.vllm.ai/en/latest/api/vllm/#vllm.EngineArgs
https://docs.vllm.ai/en/latest/api/vllm/config/scheduler/#vllm.config.scheduler.SchedulerConfig
https://aistudio.google.com/prompts/15Y-wptvaeDD_FN06Q5QgP57mnA2W7Nvt
https://grok.com/c/a0096ebe-0afc-4838-8ee5-a9c3d765d307?rid=8818f14b-5777-46a4-ace5-3bcdf56df4ec
推荐是使用下面的模板:
现在我正在用vllm部署Qwen/Qwen3-235B-A22B
我有八张H200,可以部署两个Qwen/Qwen3-235B-A22B,每个Qwen/Qwen3-235B-A22B占用4个H200
我预估接下来的请求的最大输入token数可以达到32K,所以我将`max_model_len`设置为了40960;当然这只是单条请求的最大token数,不是所有的请求都会这么长,事实上,达到最大token请求数的并不是非常多
同时我的`gpu_memory_utilization`设置为0.8
请你帮我估计一下,我的`max_num_batched_tokens`和`max_num_seqs`这两个参数应该如何设置才可以达到最佳的性能?
然后同时给多个AI,综合他们的答案即可
日志中出现Error retrieving safetensors: Repo id must be in the form 'repo_name' or 'namespace/repo_name': ... Use repo_type argument if needed., retrying 1 of 2 (APIServer pid=3206581) ERROR 01-13 20:59:00怎么办?
简单来说就是vllm把提供的model_name当成一个要在HF上去下载的模型名了,但是实际上可能是一个本地的路径,所以格式错误,可以忽略这个报错
日志中出现openai_harmony.HarmonyError: error downloading or loading vocab file: failed to download or load vocab file怎么办?
这是gpt-oss的特有问题,运行下面的命令即可
mkdir -p tiktoken_encodings
curl -L -o tiktoken_encodings/o200k_base.tiktoken "https://openaipublic.blob.core.windows.net/encodings/o200k_base.tiktoken"
curl -L -o tiktoken_encodings/cl100k_base.tiktoken "https://openaipublic.blob.core.windows.net/encodings/cl100k_base.tiktoken"
export TIKTOKEN_ENCODINGS_BASE=${PWD}/tiktoken_encodings
litellm
litellm的优先级是怎么样的?
首先根据order参数分组,然后在每一个组里面使用routing_strategy,最多尝试num_retries次,如果还不成功,就换到一个更高值的order的组里面进行重复请求
可以在每个实例的litellm_params中设置num_retries,也可以在router_settings和litellm_settings中设置,优先级依次降低
order的生效需要在router_strategy中设置enable_pre_call_checks: true
对于litellm来说,“失败”的具体定义是什么?
定义是,当请求得到一个结果,但是这个结果并不正常,那么就算一次失败
max_parallel_requests等参数怎么与调度机制进行协调的?
首先按照order分组,然后在最高等级的组进行路由分配,但是一个部署能够被分配的前提是max_parallel等限制要满足;如果这个组里所有的部署都无法被分配,那么请求会进入事件循环中进行等待(litellm的内部实现机制就是asyncio库),等到可以发送的时候再进行发送;当这个请求在这个组里被发送出去并且得到结果了之后,才会根据结果返回或者计入失败次数;当这个请求在当前组的失败次数满了之后,就会在更低级别的组中进行重复步骤;当所有组都尝试完毕之后,此请求返回失败
max_parallel_requests和tpm/rpm的优先级是怎么样的?
三者没有优先级关系,如果都设置了,那么都需要满足
如果只设置了max_parallel_requests,那么认为tpm/rpm是无限的
如果没有设置max_parallel_requests,那么只满足tpm/rpm(可以只设置一个)
litellm的日志文件中出现ImportError: ... install httpx using pip install httpx[socks].怎么办?
应该是使用了代理,要么关闭代理,要么照做pip install httpx[socks]
可以查询到litellm启动程序运行了,但是litellm的日志没有内容,而且健康测试失败,怎么办?
这大概率是因为litellm正在启动,而过早查看日志了。此时需要将等待时间调长,耐心等待
在日志文件中遇到了Checking for hanging requests....怎么办?
不用管,是正常的工作流程
如果在运行的过程中,openai库报错ReadERR和Connection Error怎么办?
我不知道litellm内部是怎么处理的,我感觉是TCP连接开太多了
在其他条件固定的情况下,如果要维持总并发数不变,遇到这种情况可以尝试降低进程数,提高semaphore,可以缓解
这大概是因为每个进程至少开一个TCP连接,但是同一进程的不同请求可以复用TCP连接,所以TCP连接就会变少

浙公网安备 33010602011771号