vLLM

我们建议您在部署 Qwen 时尝试使用 vLLM。它易于使用,且具有最先进的服务吞吐量、高效的注意力键值内存管理(通过PagedAttention实现)、连续批处理输入请求、优化的CUDA内核等功能。要了解更多关于vLLM的信息,请参阅 论文文档

环境配置

默认情况下,你可以通过 pip 在新环境中安装 vllm

pip install "vllm>=0.8.5"

请留意预构建的vllmtorch和其CUDA版本有强依赖。请查看vLLM官方文档中的注意事项以获取有关安装的帮助。

API 服务

借助vLLM,构建一个与OpenAI API兼容的API服务十分简便,该服务可以作为实现OpenAI API协议的服务器进行部署。默认情况下,它将在 http://localhost:8000 启动服务器。您可以通过 --host--port 参数来自定义地址。请按照以下所示运行命令:

vllm serve Qwen/Qwen3-8B

默认情况下,如果模型未指向有效的本地目录,它将从 Hugging Face Hub 下载模型文件。要从 ModelScope 下载模型,请在运行上述命令之前设置以下内容:

export VLLM_USE_MODELSCOPE=true

对于使用张量并行的分布式推理,操作非常简单:

vllm serve Qwen/Qwen3-8B --tensor-parallel-size 4

上述命令将在 4 块 GPU 上使用张量并行。您应根据需求调整 GPU 的数量。

基本用法

然后,您可以利用 create chat interface 来与Qwen进行对话:

curl http://localhost:8000/v1/chat/completions -H "Content-Type: application/json" -d '{
  "model": "Qwen/Qwen3-8B",
  "messages": [
    {"role": "user", "content": "Give me a short introduction to large language models."}
  ],
  "temperature": 0.6,
  "top_p": 0.95,
  "top_k": 20,
  "max_tokens": 32768
}'

或者您可以如下面所示使用 openai Python SDK中的 API 客户端:

from openai import OpenAI
# Set OpenAI's API key and API base to use vLLM's API server.
openai_api_key = "EMPTY"
openai_api_base = "http://localhost:8000/v1"

client = OpenAI(
    api_key=openai_api_key,
    base_url=openai_api_base,
)

chat_response = client.chat.completions.create(
    model="Qwen/Qwen3-8B",
    messages=[
        {"role": "user", "content": "Give me a short introduction to large language models."},
    ],
    max_tokens=32768,
    temperature=0.6,
    top_p=0.95,
    extra_body={
        "top_k": 20,
    },
)
print("Chat response:", chat_response)

小技巧

vllm 将使用模型文件中 generation_config.json 的采样参数。

虽然默认的采样参数在大多数情况下适用于思考模式,但建议根据您的应用调整采样参数,并始终将采样参数传递给 API。

思考与非思考模式

Qwen3 模型会在回复前进行思考。这种行为可以通过硬开关(完全禁用思考)或软开关(模型遵循用户关于是否应该思考的指令)来控制。

硬开关在 vLLM 中可以通过以下 API 调用配置使用。要禁用思考,请使用

curl http://localhost:8000/v1/chat/completions -H "Content-Type: application/json" -d '{
  "model": "Qwen/Qwen3-8B",
  "messages": [
    {"role": "user", "content": "Give me a short introduction to large language models."}
  ],
  "temperature": 0.7,
  "top_p": 0.8,
  "top_k": 20,
  "max_tokens": 8192,
  "presence_penalty": 1.5,
  "chat_template_kwargs": {"enable_thinking": false}
}'

或者您可以如下面所示使用 openai Python SDK中的 API 客户端:

from openai import OpenAI
# Set OpenAI's API key and API base to use vLLM's API server.
openai_api_key = "EMPTY"
openai_api_base = "http://localhost:8000/v1"

client = OpenAI(
    api_key=openai_api_key,
    base_url=openai_api_base,
)

chat_response = client.chat.completions.create(
    model="Qwen/Qwen3-8B",
    messages=[
        {"role": "user", "content": "Give me a short introduction to large language models."},
    ],
    max_tokens=8192,
    temperature=0.7,
    top_p=0.8,
    presence_penalty=1.5,
    extra_body={
        "top_k": 20, 
        "chat_template_kwargs": {"enable_thinking": False},
    },
)
print("Chat response:", chat_response)

备注

请注意,enable_thinking并非OpenAI API定义的参数,具体传入方式可能因推理框架不同而不同。

小技巧

要完全禁用思考,您可以在启动模型时使用自定义聊天模板

vllm serve Qwen/Qwen3-8B --chat-template ./qwen3_nonthinking.jinja

该聊天模板会阻止模型生成思考内容,即使用户通过 /think 指示模型这样做。

小技巧

建议为思考模式和非思考模式分别设置不同的采样参数。

解析思考内容

vLLM 支持将模型生成的思考内容解析为结构化消息:

vllm serve Qwen/Qwen3-8B --enable-reasoning --reasoning-parser deepseek_r1

自 vLLM 0.9.0 版本,也可以使用

vllm serve Qwen/Qwen3-8B --reasoning-parser qwen3

响应消息除了包含 content 字段外,还会有一个名为 reasoning_content 的字段,其中包含模型生成的思考内容。

备注

请注意,此功能与 OpenAI API 规范不一致。

重要

在 vLLM 0.8.5 版本中,enable_thinking=False 与此功能不兼容。如果需要向 API 传递 enable_thinking=False,则应禁用解析思考内容。此问题已在 vLLM 0.9.0 中通过 qwen3 思考解析器得到解决。

解析工具调用

vLLM 支持将模型生成的工具调用内容解析为结构化消息:

vllm serve Qwen/Qwen3-8B --enable-auto-tool-choice --tool-call-parser hermes

详细信息,请参阅函数调用的指南

结构化/JSON输出

vLLM 支持结构化/JSON 输出。请参照vLLM文档了解 guided_json 参数。此外,也建议在系统消息或用户提示中指示模型生成特定格式,避免仅依赖于推理参数配置。

部署量化模型

Qwen3 提供了两种类型的预量化模型:FP8 和 AWQ。

部署这些模型的命令与原始模型相同,只是名称有所更改:

# For FP8 quantized model
vllm serve Qwen/Qwen3-8B-FP8

# For AWQ quantized model
vllm serve Qwen/Qwen3-8B-AWQ

备注

Qwen3 的 FP8 模型采用分块 (block-wise) 量化,该功能支持在 compute capability > 8.9 的 NVIDIA GPU 上运行,即 Ada Lovelace、Hopper 及更新的 GPU,并以 w8a8 方式运行。

从 vLLM v0.9.0 开始,FP8 Marlin 已支持分块量化(以 w8a16 方式运行),您还可以在 Ampere 显卡上运行 Qwen3 FP8 模型。

备注

如果在部署 FP8 模型时遇到以下错误,这表明张量并行大小与模型权重不匹配:

File ".../vllm/vllm/model_executor/layers/quantization/fp8.py", line 477, in create_weights
    raise ValueError(
ValueError: The output_size of gate's and up's weight = 192 is not divisible by weight quantization block_n = 128.

目前,我们建议降低张量并行的程度,例如使用 --tensor-parallel-size 4,或者启用专家并行,例如使用 --tensor-parallel-size 8 --enable-expert-parallel

上下文长度

Qwen3 模型在预训练中的上下文长度最长为 32,768 个 token。为了处理显著超过 32,768 个 token 的上下文长度,应应用 RoPE 缩放技术。我们已经验证了 YaRN 的性能,这是一种增强模型长度外推的技术,可确保在长文本上的最佳性能。

vLLM 支持 YaRN,可以配置为

vllm serve Qwen/Qwen3-8B --rope-scaling '{"rope_type":"yarn","factor":4.0,"original_max_position_embeddings":32768}' --max-model-len 131072  

备注

vLLM 实现了静态 YaRN,这意味着无论输入长度如何,缩放因子都保持不变,这可能会对较短文本的性能产生影响。 我们建议仅在需要处理长上下文时添加 rope_scaling 配置。还建议根据需要调整 factor。例如,如果您的应用程序的典型上下文长度为 65,536 个 token,则最好将 factor 设置为 2.0。

备注

如果未指定 --max-model-lenconfig.json 中的默认 max_position_embeddings 被设置为 40,960,vLLM 将使用该值。此分配包括为输出保留 32,768 个 token,为典型提示保留 8,192 个 token,这足以应对大多数涉及短文本处理的场景,并为模型思考留出充足空间。如果平均上下文长度不超过 32,768 个 token,我们不建议在此场景中启用 YaRN,因为这可能会降低模型性能。

Python 库使用

vLLM 也可以直接用作 Python 库,这对离线批量推理非常方便,但缺少一些仅限 API 的功能,例如将模型生成解析为结构化消息。

以下展示了将 vLLM 用作库的基本用法:

from transformers import AutoTokenizer
from vllm import LLM, SamplingParams

# Initialize the tokenizer
tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen3-8B")

# Configurae the sampling parameters (for thinking mode)
sampling_params = SamplingParams(temperature=0.6, top_p=0.95, top_k=20, max_tokens=32768)

# Initialize the vLLM engine
llm = LLM(model="Qwen/Qwen3-8B")

# Prepare the input to the model
prompt = "Give me a short introduction to large language models."
messages = [
    {"role": "user", "content": prompt}
]
text = tokenizer.apply_chat_template(
    messages,
    tokenize=False,
    add_generation_prompt=True,
    enable_thinking=True,  # Set to False to strictly disable thinking
)

# Generate outputs
outputs = llm.generate([text], sampling_params)

# Print the outputs.
for output in outputs:
    prompt = output.prompt
    generated_text = output.outputs[0].text
    print(f"Prompt: {prompt!r}, Generated text: {generated_text!r}")

自 vLLM v0.9.0 开始,LLM.chat 支持 chat_template_kwargs 参数,因而也可以使用以下方法:

from vllm import LLM, SamplingParams

# Configurae the sampling parameters (for thinking mode)
sampling_params = SamplingParams(temperature=0.6, top_p=0.95, top_k=20, max_tokens=32768)

# Initialize the vLLM engine
llm = LLM(model="Qwen/Qwen3-8B")

# Prepare the input to the model
prompt = "Give me a short introduction to large language models."
messages = [
    {"role": "user", "content": prompt}
]

# Generate outputs
outputs = llm.chat(
    [messages], 
    sampling_params,
    chat_template_kwargs={"enable_thinking": True},  # Set to False to strictly disable thinking
)

# Print the outputs.
for output in outputs:
    prompt = output.prompt
    generated_text = output.outputs[0].text
    print(f"Prompt: {prompt!r}, Generated text: {generated_text!r}")

常见问题解答

您可能会遇到令人烦恼的OOM(内存溢出)问题。我们推荐您尝试两个参数进行修复。

  • 第一个参数是 --max-model-len 。我们提供的默认最大位置嵌入(max_position_embedding)为 40960 ,因此服务时的最大长度也是这个值,这会导致更高的内存需求。将此值适当减小通常有助于解决OOM问题。

  • 另一个您可以关注的参数是 --gpu-memory-utilization 。 vLLM将预分配该参数指定比例的显存。默认情况下,该值为 0.9。这也是为什么您发现一个vLLM服务总是占用大量内存的原因。如果你使用了eager模式(默认不是),您可以将其调高以应对OOM问题。反之,vLLM会使用CUDA Graphs,而CUDA Graphs会额外占用不受vLLM管理的显存;此时,您应当尝试降低--gpu-memory-utilization。如果还是无法解决,可以尝试--enforce-eager(这会影响推理效率)或缩小--max-model-len

有关 vLLM 的更多使用指南,请参阅 vLLM 的Qwen3 使用指南