4、基础推理:加载模型、单次推理、流式输出、参数调优
好,咱们进入正题。前面几章我们把环境搭好了,也把 vLLM 的核心架构捋了一遍。现在,是时候让模型真正跑起来了。
这一章,我会带你走一遍基础推理的完整流程。从加载模型开始,到单次推理,再到流式输出,最后聊聊参数调优。说白了,就是让你能立刻上手,把模型用起来。
4.1 加载模型:没那么简单
加载模型,听起来就是一行代码的事。但我在项目中踩过不少坑,这里给你提个醒。
max_model_len 和 gpu_memory_utilization。
我个人习惯用 LLM 类来加载模型。它封装了大部分细节,用起来很顺手。看代码:
from vllm import LLM, SamplingParams
# 加载模型
llm = LLM(
model="Qwen/Qwen2.5-7B-Instruct",
tensor_parallel_size=1, # 单卡就用1
max_model_len=4096, # 限制最大上下文长度
gpu_memory_utilization=0.9, # 显存利用率
trust_remote_code=True # 有些模型需要这个
)
这里有几个关键点:
- tensor_parallel_size:如果你有多张卡,可以设成 2、4 等。vLLM 会自动做张量并行。
- max_model_len:我建议设小一点。比如 4096,既能满足大部分场景,又不会把显存撑爆。
- gpu_memory_utilization:默认是 0.9。如果你还要跑其他任务,可以降到 0.7。
4.2 单次推理:最简单的调用
模型加载好了,接下来就是推理。单次推理,说白了就是给模型一个输入,它给你一个输出。
看这个例子:
# 准备输入
prompts = ["什么是人工智能?"]
# 设置采样参数
sampling_params = SamplingParams(
temperature=0.7,
max_tokens=512,
top_p=0.9
)
# 执行推理
outputs = llm.generate(prompts, sampling_params)
# 打印结果
for output in outputs:
print(output.outputs[0].text)
嗯,这里要注意:llm.generate 返回的是一个列表。即使你只传了一个 prompt,它也会返回一个列表。所以要用 outputs[0] 来取结果。
我曾经犯过一个低级错误:直接打印 outputs,结果看到一堆对象地址,还以为模型坏了。后来才发现要取 .outputs[0].text。
4.3 流式输出:让用户不再等待
单次推理有个问题:如果模型生成的内容很长,用户要等很久才能看到结果。流式输出就是为了解决这个问题。
vLLM 支持两种流式方式:
- 同步流式:用
generate方法,设置stream=True - 异步流式:用
AsyncLLMEngine,配合asyncio
我个人更推荐同步流式,因为它简单,而且大多数场景够用了。看代码:
from vllm import LLM, SamplingParams
llm = LLM(model="Qwen/Qwen2.5-7B-Instruct")
sampling_params = SamplingParams(temperature=0.7, max_tokens=1024)
# 流式输出
for output in llm.generate("讲个笑话", sampling_params, stream=True):
# output 是一个 RequestOutput 对象
if output.outputs[0].text:
print(output.outputs[0].text, end="", flush=True)
这里的关键是 stream=True。vLLM 会逐 token 返回结果。你想想看,用户看到文字一个字一个字地蹦出来,体验是不是好很多?
output.outputs[0].text 是增量文本,不是完整结果。所以你要用 end="" 来拼接,而不是每次都换行。
4.4 参数调优:控制模型的行为
模型推理时,有几个参数能显著影响输出质量。我重点讲两个:max_tokens 和 temperature。
4.4.1 max_tokens:控制输出长度
max_tokens 决定了模型最多生成多少个 token。注意,是 token,不是汉字。一般来说,一个汉字对应 1-2 个 token。
| 场景 | 推荐 max_tokens | 说明 |
|---|---|---|
| 短问答 | 128-256 | 比如“今天天气怎么样” |
| 中等长度 | 512-1024 | 比如写一段代码或邮件 |
| 长文本生成 | 2048-4096 | 比如写文章或报告 |
我建议不要设得太大。一方面,显存占用会线性增长;另一方面,模型生成太长容易跑偏。我在项目中遇到过,设了 4096,结果模型写到后面开始胡言乱语。
4.4.2 temperature:控制随机性
temperature 控制模型输出的随机性。值越高,输出越多样;值越低,输出越确定。
- temperature=0:完全确定,每次输出都一样。适合代码生成、数学计算。
- temperature=0.7:平衡模式。适合大多数对话场景。
- temperature=1.0:高随机性。适合创意写作、头脑风暴。
top_k、top_p 同时使用。如果你设置了 temperature,就不要设 top_k 和 top_p。否则模型行为会变得不可控。
我曾经犯过一个错:把 temperature 设成 2.0,结果模型输出了一堆乱码。后来查文档才知道,temperature 一般建议在 0-1 之间。超过 1 会让概率分布过于平滑,模型几乎是在随机选词。
4.5 完整示例:一个可运行的脚本
说了这么多,不如直接给你一个完整的脚本。你复制到本地就能跑:
from vllm import LLM, SamplingParams
def main():
# 1. 加载模型
print("正在加载模型...")
llm = LLM(
model="Qwen/Qwen2.5-7B-Instruct",
max_model_len=2048,
gpu_memory_utilization=0.8
)
# 2. 设置参数
sampling_params = SamplingParams(
temperature=0.7,
max_tokens=512,
top_p=0.9
)
# 3. 单次推理
prompts = ["用Python写一个快速排序算法"]
outputs = llm.generate(prompts, sampling_params)
print("单次推理结果:")
print(outputs[0].outputs[0].text)
# 4. 流式输出
print("\n流式输出结果:")
for output in llm.generate(prompts, sampling_params, stream=True):
if output.outputs[0].text:
print(output.outputs[0].text, end="", flush=True)
if __name__ == "__main__":
main()
这个脚本涵盖了加载模型、单次推理、流式输出三个核心步骤。你跑一遍,就能直观感受到 vLLM 的推理速度。
4.6 知识体系图
为了让你更直观地理解本章内容,我画了一张流程图:
这张图清晰地展示了推理流程:加载模型 → 设置参数 → 选择流式或单次 → 输出结果。你跟着这个流程走,基本不会出错。
公众号:蓝海资料掘金营,微信deep3321