vLLM的介绍
vLLM的核心特性:
最先进的服务吞吐量
使用PageAttention高效管理注意力键和值的内存
量化:GPTQ,AWQ,INT4,INT8和FP8
VLLM的灵活性和易用性体现在以下方面:
具有高吞吐量服务以及各种解码算法,包括并行采样,束搜索等
支持张量并行和流水线并行的分布式推理
提供与OpenAI兼容的API服务器
支持很多显卡:NVIDIA GPU、AMD CPU和GPU、Intel GPU和CPU、PowerPC CPU、TPU及AWS Neuron
前缀缓存支持
支持多LoRA
基础
量化
量化是将模型中的 高精度参数(如 FP32)转为低位宽整数或浮点数(如 INT4、INT8、FP8) 的过程,以达到:
-
减少模型大小
-
降低显存占用
-
加速推理速度
-
提升部署效率(尤其在边缘设备)
方法 | 全称 / 意义 | 类型 | 是否需训练 | 简要说明 |
---|---|---|---|---|
INT8 | 8-bit Integer Quant. | 权重+激活量化 | ❌(PTQ)或 ✅(QAT) | 最基础,兼容性好,精度较高,速度/压缩比适中 |
INT4 | 4-bit Integer Quant. | 权重量化 | ❌(PTQ) | 更小显存,损失更大,适合结合 GPTQ/AWQ 使用 |
FP8 | 8-bit Floating Point | 权重+激活量化 | ✅(需训练支持) | 精度高于 INT8,部署需硬件支持(如 H100) |
GPTQ | GPT Quantization | 权重量化(INT4) | ❌(Post-training) | 自动通道选择,适合大模型,兼顾速度与精度 |
AWQ | Activation-aware Weight Quantization | 权重量化(INT4) | ❌(Post-training) | 感知激活分布,专为 LLM 优化,精度更好 |
AWQ(Activation-aware Weight Quantization)是一种 后训练量化(Post-Training Quantization, PTQ) 方法,它的核心创新在于:
-
分析每层神经元激活分布
-
对不同通道的权重做“有选择的”量化
-
避免激活和权重之间的量化误差共振(量化时考虑激活值),保持模型性能
误差共振:量化权重引入的误差与激活值在某些层发生耦合或放大效应,导致模型输出误差显著放大,从而严重影响整体推理精度的现象。
例如:假设模型某一层的激活值比较大且集中(例如都是正数),此时:
-
如果权重量化误差也呈现某种集中偏向(比如整体偏负);
-
乘积操作就可能系统性偏离真实输出;
-
偏差在下一层继续放大,最终影响整个推理精度。
这在 LLM 中尤为严重,因为 LLM 的结构深、层数多,误差一层层累积,可能导致模型完全输出错误的回答。
KV Cache
KV Cache 就是 Transformer 中**注意力机制(Self-Attention)**模块中,每一层的 Key(K)和 Value(V)向量的缓存,它可以在每一步生成时重复使用,而不用重新计算前面所有的 K/V。
-
前一步生成 token 的 K/V 会被缓存起来。
-
下一步只需计算
-
当前 token 的 Q,再用之前缓存的 K/V 来做注意力计算。
-
效果:每一步只计算一次 Q,大大减少了计算和内存开销。
优势:提升速度、降低资源占用、支持长文本生成、易于实现(大多数框架(如 Transformers、vLLM)都有内置支持)
优化:
PagedAttention(vLLM)
-
把 KV Cache 分页管理(像虚拟内存页表),支持多用户并发、动态上下文切换
FlashAttention
- 利用 CUDA kernel 和序列并行优化注意力计算,也有专门版本支持 KV Cache。
使用:use_cache=True # 开启 KV Cache
估算GPU资源
推理(Inference)与训练(Training)两部分之和
每个参数所占内存:
-
float32(默认):每个参数 4 Bytes
-
float16(混合精度训练):每个参数 2 Bytes
-
int8/in4(量化推理):每个参数 1 Byte
显存估算公式(粗略):
显存(MB)≈参数量(B)×4(FP16)+KV缓存大小(基于长上下文)+其他缓存
例如:总参数量:0.6B(6亿参数);上下文长度(Context Length):32,768 tokens(超长上下文)
推理总显存需求估算(FP16):
-
模型参数:0.6B × 2 Bytes ≈ 1.2 GB
-
KV 缓存:~1 GB
-
其他激活缓存、临时变量等:~1 GB
推理最低显存需求:约 3–4 GB(FP16)
训练资源预估
训练比推理显存需求高很多,主要因为:
-
需要存储梯度、前向激活值
-
反向传播时显存翻倍
-
长上下文会加重 attention 的计算开销
粗略训练显存估算:
1. 参数模型体积(FP16):
-
0.6B × 2 Bytes = 1.2 GB
2. 激活值 + 梯度缓存(训练中需占 2-4 倍模型体积)
Batch size 越大,显存占用越高
最终估算:
训练所需单卡显存 ≈ 30–40GB+(保守估计)
安装vLLM
建议使用uv,地址:GPU - vLLM
uv pip install "vllm[cuda]"
##这个命令会自动选择适合你的 CUDA 版本的 prebuilt 版本(12.1 及以上)
Docker部署
- 将需要下载的大模型下载到对应的项目中
- 编写配置文件Dockerfile
获取镜像:https://hub.docker.com/search?q=&type=image
# 基础镜像,带CUDA 12.1 + cuDNN + Python 3.10(我们后面升级Python)
FROM pytorch/pytorch:2.2.0-cuda12.1-cudnn8-runtimeENV DEBIAN_FRONTEND=noninteractive
# 安装Python 3.11及相关工具
RUN apt-get update && apt-get install -y software-properties-common \&& add-apt-repository ppa:deadsnakes/ppa \&& apt-get update && apt-get install -y \python3.11 python3.11-distutils python3.11-venv python3-pip curl \&& rm -rf /var/lib/apt/lists/*# 设置python3指向python3.11
RUN update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.11 1# 升级pip,安装对应PyTorch和vllm
RUN python3 -m pip install --upgrade pip# 重新安装兼容CUDA 12.1的PyTorch,避免版本冲突(覆盖基础镜像的PyTorch)
RUN python3 -m pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121# 安装vLLM
RUN python3 -m pip install vllm# 创建工作目录
WORKDIR /app# 拷贝启动脚本
COPY entrypoint.sh /app/entrypoint.sh
RUN chmod +x /app/entrypoint.sh# 挂载模型目录
VOLUME ["/qwen"]# 开放8000端口
EXPOSE 8000# 启动命令
CMD ["/app/entrypoint.sh"]
3. 编写shell脚本文件
#!/bin/bash
# 启动 vLLM OpenAI 兼容 API 服务,加载挂载的本地模型路径python3 -m vllm.entrypoints.openai.api_server \--model /qwen \--tokenizer /qwen \--served-model-name Qwen-3 \--host 0.0.0.0 \--port 8000
4. 构建镜像运行
## 构建镜像DOCKER_BUILDKIT=1 docker build -f [本地磁盘上的 Dockerfile 文件所在位置] -t qwen-vllm:latest .
## 最后的路径参数表示构建上下文目录,Docker从这里找文件构建镜像 .代表当前目录
## -t 给镜像打标签(tag)<镜像名>:<标签>##查看镜像
docker images# 删除容器
docker rm {容器名称}## 运行容器
docker run -d --gpus '"device=1"' -p 8000:8000 \-v /home/featurize/qwen:/qwen \--name qwen-vllm-container1 \qwen-vllm:latest
#-v:表示把本地 /home/featurize/qwen 目录挂载到容器里的 /qwen
#--name:给容器起名字
#qwen-vllm:latest--镜像名
#-d :让容器在后台运行
#-p 8000:8000--把宿主机(本机)的 8000 端口,映射到容器内的 8000 端口##持续监听日志:
docker logs -f qwen-vllm-container1
##退出日志的持续监听
Ctrl + C
参数:DOCKER_BUILDKIT
是 Docker 提供的一个环境变量,用来控制是否启用 BuildKit 构建引擎
-
DOCKER_BUILDKIT=1 表示启用 Docker 的 BuildKit 功能。
-
DOCKER_BUILDKIT=0 或不设置则使用传统的 Docker 构建引擎。
BuildKit 是 Docker 官方推出的一个更高效、更灵活的镜像构建引擎,具备以下优势:
-
并行构建:能够并行执行 Dockerfile 中的多条命令,提高构建速度。
-
更好的缓存管理:缓存机制更智能,减少重复构建时间。
-
更小的镜像层:生成的镜像层更合理,减少镜像体积。
-
内置更强大的语法支持:支持更复杂的 Dockerfile 语法,比如
--mount=type=cache
等。 -
安全隔离:提高构建过程的安全性。
测试
方式一:curl
curl -X POST http://localhost:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{"model":"Qwen-3","messages":[{"role":"user","content":"你好"}]}'
方式二:python
import requests
import jsondef chat_with_model(prompt, model_name="Qwen-3", server_url="http://localhost:8000/v1/chat/completions"):headers = {"Content-Type": "application/json",}data = {"model": model_name,"messages": [{"role": "user", "content": prompt}]}response = requests.post(server_url, headers=headers, data=json.dumps(data))if response.status_code == 200:res_json = response.json()answer = res_json.get("choices", [{}])[0].get("message", {}).get("content", "")return answerelse:return f"Error: {response.status_code} - {response.text}"if __name__ == "__main__":prompt = "你好,今天天气怎么样"reply = chat_with_model(prompt)print("模型回复:", reply)
Fast API封装
#示例 test.py
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
import httpxapp = FastAPI()# 请求输入格式
class ChatRequest(BaseModel):prompt: strtemperature: float = 0.7max_tokens: int = 512# 响应格式可自定义
class ChatResponse(BaseModel):response: str# 本地大模型的 API 地址
LLM_API_URL = "http://localhost:8000/v1/chat/completions"@app.post("/api/chat", response_model=ChatResponse)
async def chat_with_model(req: ChatRequest):# 转换为大模型 API 所需要的格式(假设你在用 OpenAI 格式接口)payload = {"model": "your-model-name", # 视情况设置或移除"messages": [{"role": "user", "content": req.prompt}],"temperature": req.temperature,"max_tokens": req.max_tokens}try:async with httpx.AsyncClient() as client:response = await client.post(LLM_API_URL, json=payload, timeout=60.0)response.raise_for_status()data = response.json()# 从大模型返回中提取内容(OpenAI 格式)reply_text = data['choices'][0]['message']['content']return ChatResponse(response=reply_text)except Exception as e:raise HTTPException(status_code=500, detail=str(e))
运行
uvicorn test:app --host 0.0.0.0 --port 9000 --reload
#test:app-模块名:变量名 是告诉 Uvicorn 去哪里找 FastAPI 实例来运行服务。
测试
curl -X POST http://localhost:9000/api/chat \
-H "Content-Type: application/json" \
-d '{"prompt": "你好,请介绍一下你自己", "temperature": 0.7, "max_tokens": 200}'
大模型量化
AWQ:https://github.com/casper-hansen/AutoAWQ
python -m awq.entry \--model_path /home/featurize/qwen \ --w_bit 4 \ --q_group_size 128 \ --q_backend real \ --dump_quant quant_cache/qwen3-awq-int4.pt