Appearance
开源模型端到端部署指南
将开源大模型从 Hugging Face Hub 部署到生产环境,需要经过下载、量化、Serving 和监控四个关键环节。本指南提供每一步的实操路径。
概述
开源模型部署的核心挑战:
- 显存限制:大模型参数动辄数十 GB,需要量化或分布式策略
- 吞吐优化:单用户延迟 vs 多用户并发,需要 Continuous Batching
- 服务稳定性:模型加载慢、推理易 OOM,需要完善的监控和降级
- 多模型管理:不同任务需要不同模型,需要统一路由和调度
本指南覆盖从单卡本地部署到 Kubernetes 集群的完整路径。
1. 模型下载与加载
1.1 从 Hugging Face Hub 下载
命令行工具:
bash
# 安装
pip install huggingface-hub
# 下载整个模型仓库
huggingface-cli download meta-llama/Llama-2-7b-hf \
--local-dir ./models/llama2-7b \
--local-dir-use-symlinks False
# 只下载特定文件
huggingface-cli download meta-llama/Llama-2-7b-hf \
model.safetensors.index.json \
--local-dir ./models/llama2-7bPython API:
python
from huggingface_hub import snapshot_download
snapshot_download(
repo_id="meta-llama/Llama-2-7b-hf",
local_dir="./models/llama2-7b",
local_dir_use_symlinks=False,
resume_download=True, # 断点续传
)1.2 离线环境部署
bash
# 有网络环境:预下载到本地
export HF_DATASETS_OFFLINE=1
export TRANSFORMERS_OFFLINE=1
# 代码中强制本地加载
model = AutoModelForCausalLM.from_pretrained(
"./models/llama2-7b",
local_files_only=True,
)1.3 私有模型与认证
bash
# 登录 Hugging Face
huggingface-cli login
# 或使用 Access Token
export HF_TOKEN=hf_xxx2. 模型量化
量化是将模型权重从高精度(FP32/FP16)转换为低精度(INT8/INT4),显著减少显存占用。
2.1 量化方案对比
| 方案 | 精度 | 显存节省 | 速度影响 | 适用场景 |
|---|---|---|---|---|
| FP16/BF16 | 16-bit | 基准 | 基准 | 通用 |
| GPTQ | 4-bit | ~75% | -10~20% | GPU 推理 |
| AWQ | 4-bit | ~75% | 优于 GPTQ | GPU 推理 |
| GGUF | 2-8-bit | 50-87% | CPU 友好 | 边缘/CPU |
| BNF (bitsandbytes) | 8/4-bit | ~50-75% | -10% | 训练+推理 |
2.2 GPTQ 量化
python
from transformers import AutoModelForCausalLM, GPTQConfig
# 配置 GPTQ 量化
quantization_config = GPTQConfig(
bits=4,
group_size=128,
desc_act=False, # 是否按激活顺序排列
dataset="c4", # 校准数据集
)
# 量化并保存
model = AutoModelForCausalLM.from_pretrained(
"meta-llama/Llama-2-7b-hf",
quantization_config=quantization_config,
device_map="auto",
)
model.save_pretrained("./models/llama2-7b-gptq")2.3 AWQ 量化
bash
# 安装 AutoAWQ
pip install autoawq
# 量化
from awq import AutoAWQForCausalLM
model = AutoAWQForCausalLM.from_pretrained(
"meta-llama/Llama-2-7b-hf",
use_cache=False,
)
model.quantize(
tokenizer=tokenizer,
quant_config={"zero_point": True, "q_group_size": 128, "w_bit": 4}
)
model.save_quantized("./models/llama2-7b-awq")2.4 GGUF 转换(用于 llama.cpp)
bash
# 克隆 llama.cpp
git clone https://github.com/ggerganov/llama.cpp
cd llama.cpp
# 转换 Hugging Face 模型为 GGUF
python convert_hf_to_gguf.py \
../models/llama2-7b \
--outfile ../models/llama2-7b-f16.gguf \
--outtype f16
# 量化 GGUF(Q4_K_M 推荐)
./llama-quantize \
../models/llama2-7b-f16.gguf \
../models/llama2-7b-q4_k_m.gguf \
Q4_K_MGGUF 量化类型选择:
| 类型 | 大小 | 质量 | 推荐场景 |
|---|---|---|---|
| Q4_0 | 最小 | 一般 | 极速推理 |
| Q4_K_M | 小 | 好 | 推荐通用 |
| Q5_K_M | 中等 | 很好 | 质量优先 |
| Q8_0 | 较大 | 接近无损 | 高精度需求 |
3. Serving 方案
3.1 方案选择决策树
有 GPU?
├── 是 → 需要高吞吐?
│ ├── 是 → vLLM / TGI
│ └── 否 → Ollama / Transformers
└── 否 → 边缘/CPU 部署?
├── 是 → llama.cpp
└── 否 → Ollama (CPU 模式)3.2 vLLM(高吞吐 GPU 推理)
vLLM 基于 PagedAttention 算法,通过非连续 KV Cache 管理实现高吞吐推理。
安装与启动:
bash
# 安装
pip install vllm
# 启动 OpenAI-compatible API 服务
python -m vllm.entrypoints.openai.api_server \
--model meta-llama/Llama-2-7b-hf \
--tensor-parallel-size 1 \
--dtype bfloat16 \
--max-model-len 4096 \
--port 8000Docker 部署:
bash
docker run --runtime nvidia --gpus all \
-v ~/.cache/huggingface:/root/.cache/huggingface \
-p 8000:8000 \
vllm/vllm-openai:latest \
--model meta-llama/Llama-2-7b-hf调用示例:
python
from openai import OpenAI
client = OpenAI(base_url="http://localhost:8000/v1", api_key="dummy")
response = client.chat.completions.create(
model="meta-llama/Llama-2-7b-hf",
messages=[{"role": "user", "content": "你好"}],
temperature=0.7,
)
print(response.choices[0].message.content)关键参数:
| 参数 | 说明 | 建议 |
|---|---|---|
--tensor-parallel-size | GPU 数量 | 单卡=1,多卡=N |
--max-model-len | 最大序列长度 | 根据模型和显存调整 |
--dtype | 数据类型 | bfloat16 / float16 |
--quantization | 量化方式 | awq / gptq / fp8 |
--gpu-memory-utilization | GPU 显存利用率 | 0.9(留余量) |
3.3 llama.cpp(边缘/CPU 推理)
纯 C/C++ 实现,零依赖,支持多平台。
编译:
bash
cd llama.cpp
# CPU 版本
make
# CUDA 版本
make LLAMA_CUDA=1
# Metal (Apple Silicon)
make LLAMA_METAL=1启动 Server:
bash
./server \
-m ../models/llama2-7b-q4_k_m.gguf \
-c 4096 \
--host 0.0.0.0 \
--port 8080 \
-ngl 35 # GPU 层数(Metal/CUDA)Python 绑定:
python
from llama_cpp import Llama
llm = Llama(
model_path="./models/llama2-7b-q4_k_m.gguf",
n_ctx=4096,
n_gpu_layers=35, # offload 到 GPU 的层数
)
output = llm(
"Q: 什么是量子计算?\nA: ",
max_tokens=256,
temperature=0.7,
)
print(output["choices"][0]["text"])3.4 TGI(Hugging Face 官方)
bash
# Docker 启动
docker run --gpus all --shm-size 1g -p 8080:80 \
-v ~/.cache/huggingface:/data \
ghcr.io/huggingface/text-generation-inference:latest \
--model-id meta-llama/Llama-2-7b-hf \
--quantize gptq3.5 Ollama(一键本地运行)
bash
# 安装
curl -fsSL https://ollama.com/install.sh | sh
# 运行模型
ollama run llama3
# 导入自定义模型(GGUF)
# 创建 Modelfile
cat > Modelfile <<EOF
FROM ./models/llama2-7b-q4_k_m.gguf
PARAMETER temperature 0.7
PARAMETER num_ctx 4096
SYSTEM 你是一位专业的技术助手
EOF
ollama create my-model -f Modelfile
ollama run my-model4. 监控与运维
4.1 关键监控指标
| 指标 | 说明 | 告警阈值 |
|---|---|---|
| TTFT (Time To First Token) | 首 token 延迟 | > 2s |
| TPOT (Time Per Output Token) | 每 token 生成时间 | > 100ms |
| Throughput | 每秒生成 token 数 | 低于基线 20% |
| Queue Length | 等待队列长度 | > 10 |
| GPU Memory | GPU 显存使用率 | > 90% |
| KV Cache Usage | KV Cache 使用率 | > 95% |
| Error Rate | 请求错误率 | > 1% |
4.2 vLLM 监控
vLLM 内置 Prometheus metrics:
bash
# Metrics 端点
curl http://localhost:8000/metrics
# 关键指标
vllm:time_to_first_token_seconds
vllm:time_per_output_token_seconds
vllm:e2e_request_latency_seconds
vllm:request_queue_time_seconds
vllm:gpu_cache_usage_perc
vllm:num_requests_running
vllm:num_requests_waitingGrafana Dashboard 配置:
yaml
# docker-compose.yml
services:
prometheus:
image: prom/prometheus
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
ports:
- "9090:9090"
grafana:
image: grafana/grafana
ports:
- "3000:3000"4.3 日志与追踪
python
# OpenTelemetry 集成
from opentelemetry import trace
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
tracer = trace.get_tracer(__name__)
with tracer.start_as_current_span("llm-inference") as span:
span.set_attribute("model", "llama2-7b")
span.set_attribute("input_tokens", len(input_ids))
output = model.generate(input_ids)
span.set_attribute("output_tokens", len(output))
span.set_attribute("latency_ms", latency)5. 负载均衡与扩缩容
5.1 多实例负载均衡
Nginx 配置:
nginx
upstream vllm_backend {
least_conn; # 最少连接数策略
server localhost:8000;
server localhost:8001;
server localhost:8002;
}
server {
listen 80;
location /v1/ {
proxy_pass http://vllm_backend/v1/;
proxy_set_header Host $host;
proxy_read_timeout 300s;
}
}5.2 Kubernetes 自动扩缩容
yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: vllm-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: vllm-deployment
minReplicas: 1
maxReplicas: 5
metrics:
- type: Pods
pods:
metric:
name: vllm_num_requests_waiting
target:
type: AverageValue
averageValue: "5"5.3 KServe 模型服务
yaml
apiVersion: serving.kserve.io/v1beta1
kind: InferenceService
metadata:
name: llama2-7b
spec:
predictor:
containers:
- name: kserve-container
image: vllm/vllm-openai:latest
args:
- --model
- meta-llama/Llama-2-7b-hf
resources:
limits:
nvidia.com/gpu: 16. API 网关与路由
6.1 LiteLLM(统一多模型接入)
python
from litellm import completion
# 统一调用不同后端
response = completion(
model="vllm/llama2-7b", # 或 "openai/gpt-4", "ollama/llama3"
messages=[{"role": "user", "content": "你好"}],
api_base="http://localhost:8000",
)6.2 请求路由策略
| 策略 | 说明 | 适用场景 |
|---|---|---|
| 轮询 | 依次分发到各实例 | 实例性能一致 |
| 最少连接 | 分发到当前连接最少的实例 | 请求处理时间差异大 |
| 智能路由 | 根据模型能力/成本选择后端 | 多模型混合部署 |
| 会话保持 | 同一用户路由到同一实例 | 有状态对话 |
参考资源
- vLLM 文档: docs.vllm.ai
- llama.cpp: GitHub
- TGI 文档: Hugging Face
- Ollama: GitHub
- TensorRT-LLM: NVIDIA
- KServe: 官网
相关页面
- 模型部署与推理优化指南 — 模型部署与推理优化
- Model Quantization — 模型量化技术详解
- Fine-tuning — 大模型微调实操指南
- vLLM — vLLM 实体页面
- llama.cpp — llama.cpp 实体页面
- 推理框架深度对比 — 推理框架深度对比
- Edge vs Cloud Inference — 边缘 vs 云端推理对比