离线批处理基础:离线推理的概念

离线批处理,说白了就是「批量干活」。

我刚开始接触大模型时,总觉得在线服务才是王道。后来发现,很多场景根本不需要实时响应。比如数据分析、内容审核、批量翻译——这些任务你等个几秒甚至几分钟都无所谓。

离线推理的核心就一句话:把数据准备好,让模型一次性处理完。没有网络延迟,没有并发压力,你只需要关心吞吐量和成本。

嗯,这里要注意:离线不等于低效。恰恰相反,离线批处理往往能榨干 GPU 的每一分算力。

离线推理 vs 在线推理

维度离线推理在线推理
响应时间秒级到分钟级毫秒级
吞吐量高(批量处理)低(单条处理)
资源利用率低(有闲置)
适用场景数据分析、批量生成聊天机器人、实时翻译

使用 LLM 类加载模型

vLLM 里加载模型,核心就是 LLM 这个类。我个人习惯把它叫做「模型管家」——你给它一个模型名字,它帮你搞定一切。

from vllm import LLM

# 加载模型
llm = LLM(model="Qwen/Qwen2.5-7B-Instruct")

就这么简单?对,就这么简单。但背后 vLLM 做了很多事:

  • 自动检测 GPU 显存
  • 分配 KV cache 空间
  • 启用 PagedAttention 优化
  • 自动选择量化方式(如果有)

我在项目中遇到过一个问题:显存不够用。后来发现,vLLM 默认会预留一部分显存给 KV cache。你可以通过 gpu_memory_utilization 参数调整:

llm = LLM(
    model="Qwen/Qwen2.5-7B-Instruct",
    gpu_memory_utilization=0.9  # 默认0.9,可以调到0.95
)

注意:别把 gpu_memory_utilization 设成 1.0。我曾经这么干过,结果模型加载到一半直接 OOM。留点余量给系统和其他进程,安全第一。

单条文本生成

模型加载好了,接下来就是生成。单条文本生成是最基础的操作:

# 单条生成
output = llm.generate("请用一句话介绍深度学习")
print(output[0].outputs[0].text)

你可能会问:为什么返回的是一个列表?因为 vLLM 的设计哲学就是「一切皆批处理」。即使你只传一条文本,它也会包装成列表处理。

输出的结构是这样的:

# output 是一个 RequestOutput 对象列表
# 每个 RequestOutput 包含:
#   - request_id: 请求ID
#   - prompt: 输入文本
#   - outputs: CompletionOutput 列表
#       - text: 生成的文本
#       - token_ids: 生成的 token ID 列表
#       - cumulative_logprob: 累计对数概率

我记得第一次用的时候,被这个嵌套结构搞晕了。后来写了个小工具函数:

def get_text(output):
    return output[0].outputs[0].text

print(get_text(output))

批量文本生成

离线批处理的精髓来了。批量生成,说白了就是一次喂给模型多条文本:

prompts = [
    "什么是机器学习?",
    "解释一下 Transformer 架构",
    "Python 和 Java 有什么区别?",
    "写一首关于秋天的诗",
    "如何优化数据库查询?"
]

outputs = llm.generate(prompts)

for i, output in enumerate(outputs):
    print(f"问题 {i+1}: {prompts[i]}")
    print(f"回答: {output.outputs[0].text}")
    print("-" * 50)

你想想看,如果一条一条处理,每次都要重新加载模型、分配显存。批量处理就不一样了——vLLM 会把多条请求合并成一个 batch,一次性喂给 GPU。

经验之谈:批量大小不是越大越好。我试过把 1000 条文本一次性丢进去,结果显存爆了。建议先小批量测试,比如 16 条、32 条,逐步增加。vLLM 会自动做动态批处理,但你得给它留够空间。

理解生成参数

生成参数,说白了就是控制模型「怎么说话」的旋钮。我重点讲三个最常用的:temperaturetop_pmax_tokens

temperature:控制随机性

temperature 的取值范围是 0 到 2(甚至更高)。它控制模型输出的「冒险程度」:

  • 低温度(0.1 - 0.3):输出保守、确定性强。适合事实性问答、代码生成。
  • 中温度(0.7 - 0.9):输出有创意但不过分。适合对话、故事生成。
  • 高温度(1.0 以上):输出随机性强,可能跑偏。适合创意写作、头脑风暴。

为什么会这样?因为 temperature 影响的是 softmax 函数的「陡峭程度」。温度越低,概率分布越尖锐,模型越倾向于选最高概率的词。

from vllm import SamplingParams

# 低温度:确定性输出
params_deterministic = SamplingParams(temperature=0.1, max_tokens=100)

# 中温度:平衡输出
params_balanced = SamplingParams(temperature=0.7, max_tokens=100)

# 高温度:创意输出
params_creative = SamplingParams(temperature=1.2, max_tokens=100)

我的习惯:做代码生成时用 0.1,做文案生成时用 0.8。如果发现输出太死板,就调高一点;太发散,就调低一点。没有绝对正确的值,只有适合你场景的值。

top_p:核采样

top_p 是另一种控制随机性的方式。它做的事情是:只保留累积概率达到 p 的 top 词,然后重新归一化。

举个例子:假设模型预测下一个词的概率分布是:

  • "是":0.5
  • "为":0.3
  • "在":0.1
  • "有":0.05
  • "对":0.05

如果 top_p=0.9,那么只保留「是」「为」「在」这三个词(累积概率 0.9),其他词被丢弃。

我个人习惯把 top_ptemperature 搭配使用:

# 常用组合
params = SamplingParams(
    temperature=0.7,
    top_p=0.9,
    max_tokens=200
)

避坑指南:我曾经同时把 temperature 设得很高(1.5)又把 top_p 设得很低(0.5),结果模型输出乱七八糟。后来才明白,这两个参数是互补的——一个控制概率分布的「形状」,一个控制「候选词范围」。建议先固定一个,调另一个。

max_tokens:控制输出长度

max_tokens 是最直观的参数——限制模型最多生成多少个 token。

注意:token 不是字。中文里一个 token 大约 0.5-1 个字。所以 max_tokens=100 大概对应 50-100 个汉字。

# 短输出
params_short = SamplingParams(max_tokens=50)

# 中等输出
params_medium = SamplingParams(max_tokens=200)

# 长输出
params_long = SamplingParams(max_tokens=1024)

嗯,这里有个坑:max_tokens 设得太小,输出可能被截断;设得太大,浪费算力。我一般根据任务预估:

任务类型建议 max_tokens
短问答50 - 100
代码生成200 - 500
文章摘要100 - 300
长文本生成512 - 2048

完整示例:批量生成 + 参数控制

最后,给你一个完整的实战代码:

from vllm import LLM, SamplingParams

# 1. 加载模型
llm = LLM(
    model="Qwen/Qwen2.5-7B-Instruct",
    gpu_memory_utilization=0.9
)

# 2. 配置生成参数
sampling_params = SamplingParams(
    temperature=0.7,
    top_p=0.9,
    max_tokens=200
)

# 3. 准备批量数据
prompts = [
    "解释一下什么是注意力机制",
    "用 Python 写一个快速排序",
    "翻译成英文:今天天气真好",
    "写一段产品介绍:智能手表"
]

# 4. 批量生成
outputs = llm.generate(prompts, sampling_params)

# 5. 输出结果
for i, output in enumerate(outputs):
    print(f"输入: {prompts[i]}")
    print(f"输出: {output.outputs[0].text}")
    print("=" * 60)

核心要点回顾:

  • 离线批处理适合非实时场景,能最大化 GPU 利用率
  • LLM 类是 vLLM 的入口,加载模型只需一行代码
  • 单条和批量生成用同一个接口,vLLM 自动处理
  • temperature 控制随机性,top_p 控制候选范围,max_tokens 控制长度
  • 参数没有绝对正确值,根据场景调优
离线批处理核心流程 加载模型 LLM(model="...") 配置生成参数 temperature, top_p, max_tokens 准备批量数据 prompts = [...] 生成 生成参数详解 temperature 控制随机性 低 → 保守 高 → 创意 范围: 0 ~ 2 top_p 核采样 保留累积概率 达到 p 的候选词 范围: 0 ~ 1 max_tokens 控制输出长度 短 → 50-100 长 → 512-2048 注意 token 与字数

专注资料整理