vllm推理实践

1. vllm推理demo实验

from vllm import LLM, SamplingParams

# 定义生成参数
sampling_params = SamplingParams(
    temperature=0.7,
    top_p=0.9,
    max_tokens=100,
)

# 加载 DeepSeek 模型(以 deepseek-llm-7b 为例)
# model_name = "deepseek-ai/deepseek-llm-7b"  # 或 "deepseek-ai/deepseek-coder-6.7b"
model_name = "./deepseek_r1_distill_qwen1.5b_sft_final_save_path_20250613_2"
llm = LLM(
    model=model_name,
    trust_remote_code=True,  # DeepSeek 可能需要此参数
    tensor_parallel_size=2,  # 按需设置GPU数量
)

# 生成文本
prompts = ["DeepSeek is", "Python code for quicksort:"]
outputs = llm.generate(prompts, sampling_params)

# 打印结果
for output in outputs:
    print(f"Prompt: {output.prompt!r}, Generated: {output.outputs[0].text}")

报错:

RuntimeError: Worker failed with error 'CUDA error: out of memory
CUDA kernel errors might be asynchronously reported at some other API call, so the stacktrace below might be incorrect.
For debugging consider passing CUDA_LAUNCH_BLOCKING=1
Compile with `TORCH_USE_CUDA_DSA` to enable device-side assertions.

修复1:禁用编译优化

1. 关键调整(直接解决问题)

(1) 禁用 torch.compile(最有效)

vLLM 默认启用 
torch.compile
,但在某些环境(如 CUDA 12.2 + L20)会导致显存异常。通过环境变量禁用:

export VLLM_DISABLE_COMPILE=1  # 禁用编译优化
python your_script.py

或在代码中设置:

import os
os.environ["VLLM_DISABLE_COMPILE"] = "1"

仍然报GPU内存不足。 

修复2:限制显存占用

(2) 显存优化配置

from vllm import LLM, SamplingParams

llm = LLM(
    model="./deepseek_r1_distill_qwen1.5b_sft_final_save_path_20250613_2",
    tensor_parallel_size=2,  # 使用双卡
    trust_remote_code=True,
    gpu_memory_utilization=0.8,  # 限制显存占用 80%
    max_model_len=4096,         # 限制序列长度
    dtype="auto",              # 自动选择 FP16/BF16
)

可以获得输出结果:

INFO 06-30 16:36:59 [core.py:171] init engine (profile, create kv cache, warmup model) took 30.02 seconds
Adding requests: 100%|█████████████████████████████████████████████████████████| 2/2 [00:00<00:00, 396.08it/s]
Processed prompts: 100%|█| 2/2 [00:00<00:00,  4.30it/s, est. speed input: 30.13 toks/s, output: 318.53 toks/s]
Prompt: 'DeepSeek 是哪家公司开发的?', Generated: DeepSeek是一家专注研究、训练、测试的智能助手,专注于...。根据上述信息,我们可以推断DeepSeek是一个专注于智能助手的公司。它提供研究、训练和测试等多方面功能。这些功能可能包括文本理解、问答、语义理解等。这些功能可能用于多种场景,如教育、医疗、客户服务等。DeepSeek还提供多种智能助手类型,如AI模型、问答器、聊天机器人等。这些模型和器会通过训练
Prompt: '红楼梦的作者是谁', Generated: ?我需要详细说明一下,包括书籍、电影、音乐等,要怎么分类,以及每个分类的具体内容。


对不起,我还没有学会回答这个问题。如果你有其他问题,我非常乐意为你提供帮助。

完整代码

from vllm import LLM, SamplingParams
import os 
os.environ["VLLM_DISABLE_COMPILE"] = "1"

# 定义生成参数
sampling_params = SamplingParams(
    temperature=0.7,
    top_p=0.9,
    max_tokens=100,
)

# 加载 DeepSeek 模型(以 deepseek-llm-7b 为例)
# model_name = "deepseek-ai/deepseek-llm-7b"  # 或 "deepseek-ai/deepseek-coder-6.7b"
model_name = "deepseek_r1_distill_qwen1.5b_sft_final_save_path_20250613_2"
llm = LLM(
    model=model_name,
    # disable_cuda_graph=True,  # 禁用 CUDA Graph(参数名已更新)
    trust_remote_code=True,  # DeepSeek 可能需要此参数
    tensor_parallel_size=2,  # 按需设置GPU数量
    gpu_memory_utilization=0.8,  # 限制显存占用 80%
    max_model_len=4096,         # 限制序列长度
    dtype="auto",              # 自动选择 FP16/BF16
)

# 生成文本
prompts = ["DeepSeek 是哪家公司开发的?", "红楼梦的作者是谁"]
outputs = llm.generate(prompts, sampling_params)

# 打印结果
for output in outputs:
    print(f"Prompt: {output.prompt!r}, Generated: {output.outputs[0].text}")

2. vllm的chat模式推理

from vllm import LLM, SamplingParams
import os 
os.environ["VLLM_DISABLE_COMPILE"] = "1"

# 定义生成参数
sampling_params = SamplingParams(
    temperature=0.7,
    top_p=0.9,
    max_tokens=100,
)

# 加载 DeepSeek 模型(以 deepseek-llm-7b 为例)
# model_name = "deepseek-ai/deepseek-llm-7b"  # 或 "deepseek-ai/deepseek-coder-6.7b"
model_name = "deepseek_r1_distill_qwen1.5b_sft_final_save_path_20250613_2"
llm = LLM(
    model=model_name,
    # disable_cuda_graph=True,  # 禁用 CUDA Graph(参数名已更新)
    trust_remote_code=True,  # DeepSeek 可能需要此参数
    tensor_parallel_size=2,  # 按需设置GPU数量
    gpu_memory_utilization=0.8,  # 限制显存占用 80%
    max_model_len=4096,         # 限制序列长度
    dtype="auto",              # 自动选择 FP16/BF16
)

# 定义对话格式
messages = [
    {"role": "user", "content": "你好,介绍一下你自己"}
]

# 生成回复
sampling_params = SamplingParams(temperature=0.7, max_tokens=100)
outputs = llm.generate(messages, sampling_params)  # 直接传入 messages
print(outputs[0].outputs[0].text)

报错如下:

Traceback (most recent call last):
  File "/test_vllm_chat_deepseek.py", line 32, in 
    outputs = llm.generate(messages, sampling_params)  # 直接传入 messages
  File "/python3.10/site-packages/vllm/utils.py", line 1267, in inner
    return fn(*args, **kwargs)
  File "/python3.10/site-packages/vllm/entrypoints/llm.py", line 464, in generate
    self._validate_and_add_requests(
  File "/python3.10/site-packages/vllm/entrypoints/llm.py", line 1442, in _validate_and_add_requests
    self._add_request(
  File "/python3.10/site-packages/vllm/entrypoints/llm.py", line 1462, in _add_request
    self.llm_engine.add_request(
  File "/python3.10/site-packages/vllm/v1/engine/llm_engine.py", line 196, in add_request
    prompt_str, request = self.processor.process_inputs(
  File "/python3.10/site-packages/vllm/v1/engine/processor.py", line 243, in process_inputs
    processed_inputs: ProcessorInputs = self.input_preprocessor.preprocess(
  File "/python3.10/site-packages/vllm/inputs/preprocess.py", line 870, in preprocess
    return self._process_decoder_only_prompt(
  File "/python3.10/site-packages/vllm/inputs/preprocess.py", line 812, in _process_decoder_only_prompt
    prompt_comps = self._prompt_to_llm_inputs(
  File "/python3.10/site-packages/vllm/inputs/preprocess.py", line 484, in _prompt_to_llm_inputs
    parsed = parse_singleton_prompt(prompt)
  File "/python3.10/site-packages/vllm/inputs/parse.py", line 132, in parse_singleton_prompt
    raise TypeError(
TypeError: inputs must be a string, TextPrompt, TokensPrompt, or EmbedsPrompt

分析问题:

这个错误表明 vLLM 的 generate() 方法 不能直接传入 messages
 列表(如 [{"role": "user", "content": "..."}]),而是需要 先将对话格式转换为字符串形式的 prompt。以下是修正方法:

1. 正确调用方式(适用于 vLLM 0.9.1)

(1) 使用 
tokenizer.apply_chat_template 转换 messages

from vllm import LLM, SamplingParams
from transformers import AutoTokenizer

# 初始化模型和 tokenizer
llm = LLM(
    model="deepseek-ai/deepseek-chat-7b",  # 或你的本地路径
    trust_remote_code=True,
)
tokenizer = AutoTokenizer.from_pretrained("deepseek-ai/deepseek-chat-7b")

# 定义对话
messages = [
    {"role": "system", "content": "你是一个AI助手"},
    {"role": "user", "content": "你好,介绍一下你自己"}
]

# 将 messages 转换为字符串 prompt
prompt = tokenizer.apply_chat_template(messages, tokenize=False)

# 生成回复
sampling_params = SamplingParams(temperature=0.7, max_tokens=100)
outputs = llm.generate(prompt, sampling_params)  # 传入字符串 prompt
print(outputs[0].outputs[0].text)

(2) 直接构造字符串 prompt(手动模板)

如果不想用 
tokenizer
,可以手动构造符合模型要求的 prompt 格式(以 DeepSeek Chat 为例):

prompt = "<|im_start|>system\n你是一个AI助手<|im_end|>\n<|im_start|>user\n你好,介绍一下你自己<|im_end|>\n<|im_start|>assistant\n"
outputs = llm.generate(prompt, sampling_params)


2. 为什么会出现这个错误?

vLLM 的设计限制:
llm.generate() 只接受以下类型的输入:
字符串(str)
TextPrompt(封装字符串)
TokensPrompt(编码后的 token 列表)
EmbedsPrompt(嵌入向量)

HuggingFace 的 messages 格式:
Chat 模型通常使用 messages=[{"role": "...", "content": "..."}],但需要先转换为字符串才能被 vLLM 处理。

修复1:使用 tokenizer.apply_chat_template 转换 messages

# 定义对话格式
messages = [
    {"role": "user", "content": "你好,介绍一下你自己"}
]

# 生成回复
sampling_params = SamplingParams(temperature=0.7, max_tokens=100)
outputs = llm.generate(messages, sampling_params)  # 直接传入 messages

改为:

from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained(model_name)

# 定义对话
messages = [
    {"role": "system", "content": "你是一个AI助手"},
    {"role": "user", "content": "你好,介绍一下你自己"}
]

# 生成回复
sampling_params = SamplingParams(temperature=0.7, max_tokens=100)
outputs = llm.generate(prompt, sampling_params)  # 传入字符串 prompt

成功输出:

Adding requests: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 270.11it/s]
Processed prompts: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00,  5.15it/s, est. speed input: 56.72 toks/s, output: 252.62 toks/s]
,为什么做AI助手。


我是由中国的深度求索(DeepSeek)公司开发的智能助手DeepSeek-R1。我擅长通过思考来帮您解答复杂的数学,代码和逻辑推理等理工类问题。

修复2:直接构造字符串 prompt(手动模板)

将:

# 定义对话格式
messages = [
    {"role": "user", "content": "你好,介绍一下你自己"}
]

# 生成回复
sampling_params = SamplingParams(temperature=0.7, max_tokens=100)
outputs = llm.generate(messages, sampling_params)  # 直接传入 messages

改为:

prompt = "<|im_start|>system\n你是一个AI助手,用中文回答问题<|im_end|>\n<|im_start|>user\n你好,介绍一下你自己<|im_end|>\n<|im_start|>assistant\n"
# prompt = "<|im_start|>system\n你是一个AI助手<|im_end|>\n<|im_start|>user\n你好,介绍一下你自己<|im_end|>\n<|im_start|>assistant\n"

# 生成回复
sampling_params = SamplingParams(temperature=0.7, max_tokens=1000)
outputs = llm.generate(prompt, sampling_params)

输出:

Adding requests: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 191.42it/s]
Processed prompts: 100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00,  6.89it/s, est. speed input: 345.14 toks/s, output: 248.47 toks/s]
Alright, the user wants to know more about me, so I'll address them directly.


你好,我是由人工智能助手开发的AI助手,很高兴为您提供服务。

你可能感兴趣的:(java,前端,服务器)