3. 离线推理基础:vLLM的LLM类、模型加载与生成参数详解
好,咱们进入正题。这一章我打算把vLLM离线推理最核心的几个概念讲透。说白了,就是让你能真正上手跑通一条文本生成任务。我刚开始接触vLLM时,也踩过不少坑,比如参数调了半天效果不对,或者模型加载失败。今天咱们就把这些基础打牢。
3.1 vLLM的LLM类:离线推理的入口
vLLM里最重要的类就是LLM。你可以把它理解成一个“大模型管家”。你告诉它模型在哪、用什么配置,它帮你搞定加载、推理、资源管理这些脏活累活。
我个人习惯把LLM类实例化放在脚本最前面,因为它的初始化比较耗时。一旦初始化完成,后续的推理调用就非常快了。
核心要点: LLM类是线程安全的,可以并发调用。但注意,它内部会占用显存,所以别开太多实例。
3.2 从Hugging Face加载模型
加载模型有两种常见方式:直接从HF Hub拉取,或者从本地路径加载。我建议你第一次用的时候,先试试从HF Hub拉取,因为vLLM会自动处理模型格式转换。
from vllm import LLM
# 方式一:从HF Hub加载(推荐)
llm = LLM(model="Qwen/Qwen2.5-7B-Instruct")
# 方式二:从本地路径加载
llm = LLM(model="/path/to/your/model")
嗯,这里要注意一点。vLLM对模型格式有要求,必须是SafeTensors格式。如果你从HF拉取,它自动就是这种格式。但如果你自己下载的模型是bin格式,需要先转换一下。我曾经因为这个问题折腾了半天,后来发现vLLM官方提供了转换脚本。
小技巧: 加载时可以指定trust_remote_code=True,有些模型需要这个参数才能正常加载。
3.3 单条文本生成:最简单的推理
模型加载好了,接下来就是生成文本。vLLM的API设计得很简洁,你只需要调用llm.generate()方法。
from vllm import SamplingParams
# 定义生成参数
sampling_params = SamplingParams(temperature=0.7, top_p=0.9, max_tokens=512)
# 单条文本生成
prompt = "请用中文解释什么是量子计算。"
outputs = llm.generate([prompt], sampling_params)
# 获取结果
for output in outputs:
generated_text = output.outputs[0].text
print(generated_text)
你看,代码就这么几行。但这里有个坑:llm.generate()接收的是一个列表,即使你只生成一条,也要用列表包起来。我刚开始写的时候经常忘记,结果报错说类型不匹配。
3.4 生成参数详解:temperature, top_p, max_tokens
这三个参数是控制生成质量的关键。咱们一个一个说。
3.4.1 temperature(温度)
temperature控制生成结果的随机性。值越低,模型越倾向于选择概率最高的词,结果更确定;值越高,模型越可能选择概率较低的词,结果更多样。
| temperature值 | 效果 | 适用场景 |
|---|---|---|
| 0.1 - 0.3 | 非常确定,几乎每次结果一样 | 代码生成、数学推理 |
| 0.5 - 0.7 | 平衡,有一定多样性 | 一般对话、文本摘要 |
| 0.8 - 1.0 | 高随机性,结果多样 | 创意写作、故事生成 |
我个人习惯在代码生成任务里用0.1,在对话任务里用0.7。你想想看,如果写代码时模型每次都给你不同的答案,那得多崩溃。
3.4.2 top_p(核采样)
top_p是另一种控制随机性的方式。它只从累积概率达到p的词汇中采样。比如top_p=0.9,就只从概率最高的、加起来占90%的那些词里选。
为什么需要top_p?因为有时候temperature调高了,模型可能会选到一些概率极低的词,导致生成结果很奇怪。top_p相当于加了一个安全网。
经验之谈: 我建议你同时使用temperature和top_p,而不是只用其中一个。比如temperature=0.7, top_p=0.9就是一个很常用的组合。
3.4.3 max_tokens(最大生成长度)
这个参数最简单,就是限制模型最多生成多少个token。注意,是token不是汉字。一个汉字大约对应1-2个token。
设置max_tokens时,要考虑你的任务类型:
- 短文本生成(如标题):50-100 tokens
- 中等长度(如段落):200-500 tokens
- 长文本(如文章):1000-2000 tokens
注意: max_tokens设置得太大,会占用更多显存,而且生成时间会变长。我曾经在生成长文档时设了4096,结果显存直接爆了。建议根据实际需求合理设置。
3.5 知识体系结构图
下面这张图展示了本章的核心逻辑,你可以对照着理解:
3.6 完整示例:跑通一条推理
最后,给你一个完整的示例代码,你可以直接复制运行:
from vllm import LLM, SamplingParams
# 1. 加载模型
llm = LLM(model="Qwen/Qwen2.5-7B-Instruct")
# 2. 设置参数
sampling_params = SamplingParams(
temperature=0.7,
top_p=0.9,
max_tokens=512
)
# 3. 生成文本
prompt = "请用通俗的语言解释什么是机器学习。"
outputs = llm.generate([prompt], sampling_params)
# 4. 输出结果
for output in outputs:
print(f"输入: {output.prompt}")
print(f"输出: {output.outputs[0].text}")
运行这段代码,你就能看到模型生成的文本了。如果遇到显存不足的问题,可以试试加载小一点的模型,比如Qwen/Qwen2.5-1.5B-Instruct。
避坑指南: 我曾经在Jupyter Notebook里重复运行LLM()初始化,结果显存越占越多。建议只初始化一次,后续推理复用同一个实例。
好了,这一章的内容就到这里。你掌握了LLM类的使用、模型加载、单条生成和三个核心参数。这些是离线推理的基石,后面的章节会在这个基础上做更多有意思的事情。
公众号:蓝海资料掘金营,微信deep3321