如果你只是自己一个人用,Ollama 跑 Hermes 完全够用。但如果你要做的是一个服务——比如给团队十几个人用,或者给你的应用提供 API 后端——Ollama 的单请求处理模式就有点扛不住了。
这时候你需要的是 vLLM。
vLLM 是什么,凭什么快
vLLM 的全称是 Virtual Large Language Model,UC Berkeley 团队搞的。它最核心的两个技术点:
PagedAttention:传统的 KV Cache 管理方式很浪费显存——每个请求预分配一大块连续内存,用不完的部分就空着。PagedAttention 借鉴了操作系统虚拟内存分页的思路,把 KV Cache 切成小块按需分配。显存利用率直接提升了好几倍。
Continuous Batching:传统方案是等一批请求凑齐了再一起处理,先到的请求得等后到的。vLLM 的做法更聪明——新请求随时插入当前批次,完成的请求随时退出。相当于一个动态的”滚动窗口”,吞吐量能提升 2-4 倍。
说人话就是:同样的 GPU,vLLM 能同时伺候更多的请求,每个请求的等待时间也更短。
环境准备
vLLM 对硬件有要求,先确认一下你的环境:
- NVIDIA GPU,至少 16GB 显存(跑 Hermes 3 8B)
- CUDA 12.1+
- Python 3.9-3.12
查看 GPU 信息:
1 | nvidia-smi |
确认 CUDA 版本:
1 | nvcc --version |
安装 vLLM
建议用 conda 或 venv 隔离环境:
1 | # 创建虚拟环境 |
安装过程会自动处理 PyTorch 和 CUDA 依赖。第一次装可能要等挺久,包比较大。
如果遇到网络问题,可以用清华源加速:
1 | pip install vllm -i https://pypi.tuna.tsinghua.edu.cn/simple |
启动 Hermes 推理服务
基础启动
最简单的启动方式:
1 | python -m vllm.entrypoints.openai.api_server \ |
第一次运行会从 HuggingFace 下载模型,大概 16GB。之后就走本地缓存了。
启动成功后你会看到类似的日志:
1 | INFO: Started server process [12345] |
验证服务
1 | # 查看可用模型 |
用 Python 调用
因为 vLLM 提供的是标准 OpenAI 兼容 API,所以代码跟调 OpenAI 几乎一样:
1 | from openai import OpenAI |
深入理解 Continuous Batching
这部分稍微展开讲一下,因为理解了这个才能做好性能调优。
传统的 Static Batching 大概是这么个流程:
1 | 请求A(100 tokens) ──────────> 完成 |
B 和 C 虽然生成完了,但得等 A 这个最长的搞完,整个批次才算完。GPU 有一大半时间在摸鱼。
Continuous Batching 的做法:
1 | 请求A(100 tokens) ──────────> 完成 |
B 完成后,它的 GPU 资源立刻释放给新的请求 D。没有空等,没有浪费。
vLLM 在这个基础上又做了优化——它可以在每一步 token 生成之后检查是否有请求完成或新请求加入,粒度细到了 iteration level。
性能调优参数详解
关键参数
1 | python -m vllm.entrypoints.openai.api_server \ |
逐个解释:
–tensor-parallel-size:张量并行数,等于你要用几张 GPU。单卡填 1,双卡填 2,以此类推。注意不是所有模型都支持任意并行数。
–max-model-len:最大上下文长度。Hermes 3 原生支持 128K,但设太大会吃更多显存。根据实际需求设置,8192 对大部分场景够用了。
–max-num-batched-tokens:每个 iteration 处理的最大 token 总数。设大了吞吐高但延迟也会上去,需要根据你的显存和场景权衡。
–max-num-seqs:最大并发序列数,也就是同时处理多少个请求。默认 256,如果显存紧张可以调小。
–gpu-memory-utilization:GPU 显存使用率上限。默认 0.9,留 10% 给系统。如果你的 GPU 只跑这一个服务,可以调到 0.95。
–enforce-eager:禁用 CUDA Graph。CUDA Graph 启动快但占额外显存。显存紧张时加上这个参数。
量化部署
显存实在不够?上量化:
1 | # AWQ 量化版本(需要先下载对应模型) |
AWQ 量化大概能把显存需求减少一半,质量损失很小。
多 GPU 部署
如果你有多张卡:
1 | # 2卡张量并行 |
多卡并行不仅能处理更大的模型,还能显著提升吞吐量。不过通信开销也会上来,两张卡不是简单的 2 倍速。
生产环境部署建议
用 systemd 管理服务
1 | cat > /etc/systemd/system/vllm-hermes.service << 'EOF' |
加个 Nginx 反代
1 | upstream vllm_backend { |
监控
vLLM 自带了 Prometheus metrics endpoint:
1 | curl http://localhost:8000/metrics |
关键指标:
vllm:num_requests_running:正在处理的请求数vllm:num_requests_waiting:排队中的请求数vllm:gpu_cache_usage_perc:GPU KV Cache 使用率vllm:avg_generation_throughput_toks_per_s:平均生成速度
压测一下
用 vLLM 自带的 benchmark 工具跑一下看看性能:
1 | python -m vllm.entrypoints.openai.bench_serving \ |
在单张 A100 80GB 上跑 Hermes 3 8B,大概能跑到 2000+ tokens/s 的吞吐量,50 个并发请求无压力。这个数字比 Ollama 高了不止一个量级。
常见问题排查
Q: 启动时报 CUDA out of memory?
几个方向:
- 减小
--max-model-len,比如从 8192 降到 4096 - 加上
--enforce-eager禁用 CUDA Graph - 降低
--gpu-memory-utilization到 0.85 - 用量化模型
Q: 模型下载失败或者很慢?
HuggingFace 在国内访问经常不稳定。可以用镜像:
1 | export HF_ENDPOINT=https://hf-mirror.com |
或者手动下载模型到本地,然后指定本地路径:
1 | python -m vllm.entrypoints.openai.api_server \ |
Q: 返回结果质量不如 Ollama?
可能是聊天模板没正确加载。vLLM 通常会自动读取模型仓库里的 chat_template,但有时需要手动指定:
1 | python -m vllm.entrypoints.openai.api_server \ |
Hermes 3 用的是 ChatML 格式,确保模板匹配。
Q: 多用户同时访问时部分请求超时?
调整以下参数:
1 | --max-num-seqs 128 # 增加并发数 |
同时注意 Nginx 反代的超时设置也要调大。
Docker 部署
如果你不想手动管理 Python 环境,可以直接用 vLLM 的官方 Docker 镜像:
1 | docker run --runtime nvidia --gpus all \ |
Docker 方式的好处是环境完全隔离,不用担心依赖冲突。--ipc=host 参数是必须的,因为 vLLM 用共享内存做进程间通信。
用 Docker Compose 组织多个服务:
1 | version: '3.8' |
和其他方案的对比
| 特性 | Ollama | vLLM | TGI |
|---|---|---|---|
| 上手难度 | 最低 | 中等 | 中等 |
| 单请求延迟 | 低 | 低 | 低 |
| 高并发吞吐 | 一般 | 很强 | 强 |
| 显存效率 | 一般 | 很高 | 高 |
| 生态整合 | 好 | 好 | 好 |
| 适用场景 | 个人/开发 | 生产服务 | 生产服务 |
选择很清楚:开发阶段用 Ollama,上线了切 vLLM。
后续可以做的事
vLLM 把推理服务跑起来之后,你可以:
在 cocoloop 社区里也有人分享过在不同 GPU 上跑 vLLM 的性能数据,可以去参考一下。
vLLM + Hermes 这套方案在生产环境里经过了不少验证。如果你要认真做一个面向用户的 AI 服务,这大概是目前最靠谱的开源自部署方案之一。