从零部署千问模型(二):使用vLLM部署高性能推理服务

前言

在上一篇《从零部署千问模型(一):Qwen模型简介与环境准备》中,我们完成了环境搭建和模型下载。本文将使用 vLLM 框架部署高性能推理服务,它支持连续批处理(Continuous Batching)、PagedAttention 内存优化和 OpenAI 兼容 API,是目前生产环境部署大模型的首选方案。

一、vLLM 简介

vLLM 是加州大学伯克利分校开源的高性能 LLM 推理引擎,核心优势包括:

  • PagedAttention:灵感来自操作系统的虚拟内存分页,将 KV Cache 分成固定大小的块(block),按需分配,显存利用率提升 60% 以上
  • 连续批处理:动态将多个请求合并处理,无需等待同一批次全部完成,吞吐量提升 2-4 倍
  • OpenAI 兼容 API:开箱即用的 /v1/chat/completions 接口,可直接对接现有应用
  • 量化推理:支持 AWQ、GPTQ、FP8 等多种量化方案
  • 张量并行:支持多 GPU 并行推理

二、安装 vLLM

确保已激活上一篇创建的 Conda 环境:

conda activate qwen

安装 vLLM(会自动安装依赖):

pip install vllm

如果安装过程中遇到编译问题,可以尝试指定 CUDA 版本:

pip install vllm --extra-index-url https://download.pytorch.org/whl/cu124

验证安装:

python -c "import vllm; print(f'vLLM version: {vllm.__version__}')"'

预期输出:

vLLM version: 0.6.x

三、启动推理服务

3.1 基础启动命令

vllm serve ./models/Qwen3-8B \
  --model ./models/Qwen3-8B \
  --served-model-name qwen3-8b \
  --host 0.0.0.0 \
  --port 8000 \
  --trust-remote-code

参数说明:

  • --model:模型文件路径
  • --served-model-name:API 中使用的模型名称(客户端调用时使用)
  • --host 0.0.0.0:监听所有网卡,允许外部访问
  • --port 8000:服务端口
  • --trust-remote-code:信任远程代码(Qwen 模型需要)

看到类似以下输出说明启动成功:

INFO 06-23 10:00:00 api_server.py:200] vLLM API server started on http://0.0.0.0:8000
INFO 06-23 10:00:00 api_server.py:201] Documentation: http://0.0.0.0:8000/docs
INFO 06-23 10:00:00 api_server.py:202] Metrics: http://0.0.0.0:8000/metrics

3.2 高级参数配置

针对不同场景,可以调整以下关键参数:

vllm serve ./models/Qwen3-8B \
  --served-model-name qwen3-8b \
  --host 0.0.0.0 \
  --port 8000 \
  --trust-remote-code \
  --dtype bfloat16 \
  --gpu-memory-utilization 0.90 \
  --max-model-len 32768 \
  --tensor-parallel-size 1 \
  --enforce-eager
参数说明推荐值
--dtype数据类型bfloat16(A100/H100)或 float16
--gpu-memory-utilizationGPU 显存使用比例0.85-0.95
--max-model-len最大上下文长度32768(根据显存调整)
--tensor-parallel-size张量并行 GPU 数1(单卡)/ 2(双卡)
--enforce-eager禁用 CUDA Graph(省显存)显存紧张时添加
--quantization量化方案awq / gptq / fp8
--max-num-seqs最大并发序列数128-256

3.3 使用量化模型(节省显存)

如果显存不足,可以使用 AWQ 量化版本,显存占用减少约 50%:

# 下载 AWQ 量化版本
modelscope download --model Qwen/Qwen3-8B-AWQ --local-dir ./models/Qwen3-8B-AWQ

# 启动量化模型
vllm serve ./models/Qwen3-8B-AWQ \
  --served-model-name qwen3-8b-awq \
  --host 0.0.0.0 \
  --port 8000 \
  --trust-remote-code \
  --quantization awq

四、测试 API 接口

4.1 Chat Completions 接口

curl -s http://localhost:8000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "qwen3-8b",
    "messages": [
      {"role": "system", "content": "你是一个运维专家。"},
      {"role": "user", "content": "如何查看Linux系统CPU使用率?"}
    ],
    "temperature": 0.7,
    "max_tokens": 512
  }' | python3 -m json.tool

预期返回:

{
  "id": "chat-abc123",
  "object": "chat.completion",
  "created": 1719500000,
  "model": "qwen3-8b",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "可以使用以下命令查看Linux系统CPU使用率:\n\n1. top命令:实时显示系统进程和资源使用情况\n2. htop命令:top的增强版,更直观\n3. mpstat命令:查看多核CPU使用情况\n4. sar命令:历史CPU使用率记录\n\n最常用的是 top 命令..."
      },
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 30,
    "completion_tokens": 128,
    "total_tokens": 158
  }
}

4.2 流式输出(Streaming)

curl -s http://localhost:8000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "qwen3-8b",
    "messages": [
      {"role": "user", "content": "写一个Python快排算法"}
    ],
    "stream": true,
    "max_tokens": 1024
  }'

响应将以 SSE(Server-Sent Events)格式逐 token 返回:

data: {"id":"chat-abc","object":"chat.completion.chunk","choices":[{"delta":{"content":"def"},"index":0}]}

data: {"id":"chat-abc","object":"chat.completion.chunk","choices":[{"delta":{"content":" quick"},"index":0}]}

data: {"id":"chat-abc","object":"chat.completion.chunk","choices":[{"delta":{"content":"sort"},"index":0}]}

data: [DONE]

4.3 Python SDK 调用

vLLM 完全兼容 OpenAI Python SDK,直接安装即可:

pip install openai
from openai import OpenAI

client = OpenAI(
    base_url="http://localhost:8000/v1",
    api_key="not-needed"  # vLLM 默认不需要 API Key
)

# 普通对话
response = client.chat.completions.create(
    model="qwen3-8b",
    messages=[
        {"role": "system", "content": "你是一个Python编程专家。"},
        {"role": "user", "content": "解释一下Python中的装饰器"}
    ],
    temperature=0.7,
    max_tokens=512
)
print(response.choices[0].message.content)

# 流式对话
print("\n--- 流式输出 ---")
stream = client.chat.completions.create(
    model="qwen3-8b",
    messages=[{"role": "user", "content": "写一首关于运维的诗"}],
    stream=True,
    max_tokens=256
)
for chunk in stream:
    content = chunk.choices[0].delta.content
    if content:
        print(content, end="", flush=True)
print()

五、Function Calling(工具调用)

Qwen3 原生支持 Function Calling,vLLM 也完整支持这一功能:

from openai import OpenAI
import json

client = OpenAI(base_url="http://localhost:8000/v1", api_key="not-needed")

# 定义工具函数
tools = [
    {
        "type": "function",
        "function": {
            "name": "get_weather",
            "description": "获取指定城市的天气信息",
            "parameters": {
                "type": "object",
                "properties": {
                    "city": {"type": "string", "description": "城市名称"},
                    "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}
                },
                "required": ["city"]
            }
        }
    }
]

# 第一轮对话:模型决定调用工具
response = client.chat.completions.create(
    model="qwen3-8b",
    messages=[{"role": "user", "content": "北京今天天气怎么样?"}],
    tools=tools
)

tool_call = response.choices[0].message.tool_calls[0]
print(f"模型请求调用: {tool_call.function.name}")
print(f"参数: {tool_call.function.arguments}")

# 模拟工具执行结果
weather_result = json.dumps({"city": "北京", "temp": "28°C", "condition": "晴"})

# 第二轮对话:将工具结果返回给模型
response2 = client.chat.completions.create(
    model="qwen3-8b",
    messages=[
        {"role": "user", "content": "北京今天天气怎么样?"},
        response.choices[0].message,
        {"role": "tool", "tool_call_id": tool_call.id, "content": weather_result}
    ],
    tools=tools
)
print(f"\n最终回复: {response2.choices[0].message.content}")

六、生产环境配置

6.1 使用 Systemd 管理服务

sudo tee /etc/systemd/system/vllm-qwen.service > /dev/null << 'EOF'
[Unit]
Description=vLLM Qwen3-8B Service
After=network.target

[Service]
Type=simple
User=root
WorkingDirectory=/root
Environment="PATH=/root/miniconda3/envs/qwen/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
ExecStart=/root/miniconda3/envs/qwen/bin/vllm serve /root/models/Qwen3-8B \
    --served-model-name qwen3-8b \
    --host 0.0.0.0 \
    --port 8000 \
    --trust-remote-code \
    --gpu-memory-utilization 0.90 \
    --max-model-len 32768
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable vllm-qwen
sudo systemctl start vllm-qwen

# 查看状态
sudo systemctl status vllm-qwen

# 查看日志
journalctl -u vllm-qwen -f

6.2 Nginx 反向代理 + HTTPS

sudo tee /etc/nginx/sites-available/vllm-api > /dev/null << 'EOF'
server {
    listen 443 ssl;
    server_name llm.example.com;

    ssl_certificate     /etc/nginx/ssl/cert.pem;
    ssl_certificate_key /etc/nginx/ssl/key.pem;

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        # SSE 流式输出支持
        proxy_buffering off;
        proxy_cache off;
        proxy_read_timeout 300s;
    }
}
EOF

sudo ln -sf /etc/nginx/sites-available/vllm-api /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx

6.3 性能压测

使用 vLLM 自带的基准测试工具评估性能:

# 安装压测工具
pip install datasets

# 运行基准测试
python -m vllm.entrypoints.openai.bench_serving \
    --backend vllm \
    --base-url http://localhost:8000 \
    --model qwen3-8b \
    --num-prompts 100 \
    --request-rate 10

关注以下指标:

  • Throughput (tokens/s):每秒生成的 token 数,越高越好
  • TTFT (Time To First Token):首 token 延迟,越低越好
  • ITL (Inter-Token Latency):token 间延迟

七、常见问题排查

Q1:OOM(显存不足)

  • 降低 --gpu-memory-utilization(如 0.80)
  • 减小 --max-model-len(如 8192)
  • 使用 AWQ/GPTQ 量化版本
  • 添加 --enforce-eager 禁用 CUDA Graph
  • 减小 --max-num-seqs(如 64)

Q2:启动报错 trust-remote-code

# 确保添加了该参数
--trust-remote-code

# 或者升级 transformers
pip install --upgrade transformers

Q3:流式输出中断

检查 Nginx 配置中是否关闭了缓冲:proxy_buffering off;,并增大超时时间 proxy_read_timeout 300s;

八、总结

本文使用 vLLM 成功部署了 Qwen3-8B 高性能推理服务,核心收获:

  • ✅ 理解了 vLLM 的核心优势(PagedAttention、连续批处理)
  • ✅ 掌握了 vLLM 的安装与服务启动
  • ✅ 学会了 OpenAI 兼容 API 的调用方式(curl + Python SDK)
  • ✅ 实现了 Function Calling 工具调用
  • ✅ 配置了 Systemd 服务管理和 Nginx 反向代理

下一篇将介绍使用 Ollama 快速部署千问模型,适合个人开发者和轻量场景,一键拉取模型、自动管理,更加简单易用。

参考资料

发表回复

后才能评论