☰
LMDeploy 离线推理 Pipeline 实战指南:从 Hello World 到 PPL 计算与多后端配置
2026/9/27 10:31:03 网站建设 项目流程
  • 人工智能
  • 大模型
  • 模型推理服务
  • 推理引擎
  • 本地部署
  • 模型量化

【免费下载链接】lmdeploy

LMDeploy is a toolkit for compressing, deploying, and serving LLMs.

项目地址:https://gitcode.com/gh_mirrors/lm/lmdeploy
点击查看免费下载

LMDeploy 的pipeline是一套面向离线推理场景的 Python 高层 API,它屏蔽了 TurboMind 与 PyTorch 两种后端、张量并行、KV cache 管理等底层细节,让开发者可以用几行代码完成批量对话、流式生成、logits/hidden states 提取、困惑度(PPL)评估、LoRA 推理等任务。本篇以官方文档 docs/zh_cn/llm/pipeline.md 为骨架,结合仓库源码逐例讲解 API 用法与参数语义,帮助读者快速在自己的脚本中落地可复现的离线推理方案。

1. 认识 Pipeline:一次调用,多请求批量推理

pipeline的入口封装位于 lmdeploy/pipeline.py,Pipeline类对外暴露的核心方法包括:

  • __call__(等价于infer):非流式批量推理;
  • stream_infer:流式批量推理,返回迭代器;
  • chat:带 session 管理的多轮对话;
  • get_logits/get_ppl:面向打分与评估场景的专用接口;
  • close:显式释放资源(也支持with语句自动释放)。

其内部会先通过autoget_backend_config(见 lmdeploy/archs.py)自动判断模型该走 TurboMind 还是 PyTorch 后端:若模型不满足 TurboMind 的supported_models列表,或 TurboMind 未被编译,都会自动回退到 PyTorch 引擎。之后由get_task根据模型架构识别是纯文本 LLM(AsyncEngine)还是视觉语言模型(VLAsyncEngine),例如 InternVL、Qwen2.5-VL、Gemma3 等多模态架构会在 lmdeploy/archs.py#L84-L113 的check_vl_llm中被识别为 VLM 任务。

1.1 "Hello, world" 示例

from lmdeploy import pipeline pipe = pipeline('internlm/internlm2_5-7b-chat') response = pipe(['Hi, pls intro yourself', 'Shanghai is']) print(response)

几点说明:

  • pipeline的第一个参数可以是 Hugging Face 上的模型 ID,也可以是本地模型目录。当传入的路径本地不存在时,Pipeline.__init__会调用get_model自动下载权重(见 lmdeploy/pipeline.py#L63-L67)。
  • 传入的是一个字符串列表,infer内部会将其统一转换为 OpenAI 风格的 messages 格式后再提交引擎(见 lmdeploy/pipeline.py#L117-L119)。
  • 单条 prompt 返回单个Response对象;prompt 列表则返回Response列表。Response定义在 lmdeploy/messages.py#L666-L701,包含text、generate_token_len、input_token_len、finish_reason、token_ids、logits、last_hidden_state等字段。

1.2 更精细的批量控制

infer的参数中,gen_config既可以是一个GenerationConfig(对所有请求生效),也可以是与其长度一致的GenerationConfig列表(逐请求定制);use_tqdm=True会显示进度条。这一点在Pipeline._request_generator中做了显式校验,当gen_config列表长度与 prompt 数不一致时会抛出ValueError(见 lmdeploy/pipeline.py#L363-L372)。

2. KV cache 显存占比:理解cache_max_entry_count

在 "Hello, world" 示例中,pipeline 默认会为推理过程中产生的 KV cache 预留一定比例的显存,比例由TurbomindEngineConfig.cache_max_entry_count控制。LMDeploy 在研发过程中,这一策略发生过变更:

  1. v0.2.0 <= lmdeploy <= v0.2.1:默认比例为0.5,表示占用GPU 总显存的 50% 用于 KV cache。对 7B 模型而言,若显存小于 40G 很容易 OOM。遇到 OOM 时,可按如下方式调低占比:

    from lmdeploy import pipeline, TurbomindEngineConfig # 将 k/v cache 占比调整为总显存的 20% backend_config = TurbomindEngineConfig(cache_max_entry_count=0.2) pipe = pipeline('internlm/internlm2_5-7b-chat', backend_config=backend_config) response = pipe(['Hi, pls intro yourself', 'Shanghai is']) print(response)
  2. lmdeploy > v0.2.1(当前版本):分配策略改为从空闲显存中按比例为 KV cache 开辟空间,默认值调整为0.8。若仍遇到 OOM,按同样的方式减少比例值即可。

从当前仓库源码可以确认这一行为:在 lmdeploy/messages.py#L305-L314 的TurbomindEngineConfig文档注释中明确写道——cache_max_entry_count表示 KV cache 所占 GPU 内存比例,v0.2.1 之后默认为0.8,指空闲显存的比例;当传入大于 0 的整数时,它还可以被解释为 KV block 的总数量(此时按 block 计数而不是按比例)。PytorchEngineConfig同样持有该字段,默认值也是0.8(见 lmdeploy/messages.py#L555),但它的取值范围被校验在0 < cache_max_entry_count < 1(见 lmdeploy/messages.py#L608-L609),即 PyTorch 后端只接受比例值。

在 TurboMind 端,该比例最终会换算为 KV block 数量传入 C++ 引擎:ec.cache_max_block_count = engine_config.cache_max_entry_count(见 lmdeploy/turbomind/turbomind.py#L248)。而 PyTorch 后端则在 executor 中按空闲显存计算可用 KV cache 大小:available_mems = [int((free_mem - runtime_cache_size) * cache_max_entry_count) ...](见 lmdeploy/pytorch/engine/executor/base.py#L222-L234),可以看到它会先从空闲显存中扣除运行时缓存,再乘比例。

3. 多卡并行:设置张量并行tp

TurboMind 与 PyTorch 后端都支持张量并行(tensor parallelism),通过TurbomindEngineConfig(tp=2)即可将模型切分到 2 张 GPU 上:

from lmdeploy import pipeline, TurbomindEngineConfig backend_config = TurbomindEngineConfig(tp=2) pipe = pipeline('internlm/internlm2_5-7b-chat', backend_config=backend_config) response = pipe(['Hi, pls intro yourself', 'Shanghai is']) print(response)

从源码看,TurbomindEngineConfig的并行维度不仅限于tp,还包括dp(数据并行)、cp(上下文并行)、ep(专家并行)以及attn_tp_size、mlp_tp_size、nnodes、node_rank、dist_init_addr等多机多卡相关字段(见 lmdeploy/messages.py#L381-L395),多机场景可配合dist_init_addr指定分布式初始化地址。PytorchEngineConfig也提供tp、dp、ep与distributed_executor_backend(可选uni、mp、ray三种分布式执行后端,见 lmdeploy/messages.py#L460-L546),满足从单机多卡到多机 Ray 集群的部署需求。

4. 采样参数:GenerationConfig全面解析

GenerationConfig在 lmdeploy/messages.py#L78-L201 中定义,是控制生成行为的核心配置。文档示例:

from lmdeploy import pipeline, GenerationConfig, TurbomindEngineConfig backend_config = TurbomindEngineConfig(tp=2) gen_config = GenerationConfig(top_p=0.8, top_k=40, temperature=0.8, max_new_tokens=1024) pipe = pipeline('internlm/internlm2_5-7b-chat', backend_config=backend_config) response = pipe(['Hi, pls intro yourself', 'Shanghai is'], gen_config=gen_config) print(response)

常用参数与默认值(来自源码字段定义):

参数默认值说明
max_new_tokens512单次生成的最大 token 数
do_sampleFalse是否采样,False时走贪心解码
top_p1.0核采样概率质量,取值范围[0, 1]
top_k50候选 token 数,须为非负整数
min_p0.0最小概率阈值(按最可能 token 概率缩放),典型取值0.01~0.2
temperature0.8采样温度,取值范围[0, 2]
repetition_penalty1.0重复惩罚,大于 1 抑制重复
ignore_eosFalse是否忽略 EOS token
stop_words/stop_token_idsNone停止词 / 停止 token,命中即终止生成且不计入输出
bad_words/bad_token_idsNone禁止生成的词 / token
min_new_tokensNone最少生成的 token 数
skip_special_tokensTrue解码时是否移除特殊 token
random_seedNone采样随机种子,用于可复现实验
response_formatNone结构化输出,支持json_schema、regex_schema、XGrammar 结构标签

__post_init__中会对这些参数做合法性校验,例如temperature必须在[0, 2]、top_p必须在[0, 1](见 lmdeploy/messages.py#L259-L273),非法值会在构造时直接断言失败。stop_words/bad_words字符串会在推理前由 tokenizer 转换为 token id 并合并进stop_token_ids/bad_token_ids,同时自动追加 tokenizer 的eos_token_id与模型 generation_config 中的 EOS id(见 lmdeploy/messages.py#L219-L257)。

5. 使用 OpenAI 格式的 prompt

除纯字符串外,pipeline 原生支持 OpenAI 风格的 messages 列表,便于携带role语义:

from lmdeploy import pipeline, GenerationConfig, TurbomindEngineConfig backend_config = TurbomindEngineConfig(tp=2) gen_config = GenerationConfig(top_p=0.8, top_k=40, temperature=0.8, max_new_tokens=1024) pipe = pipeline('internlm/internlm2_5-7b-chat', backend_config=backend_config) prompts = [[{ 'role': 'user', 'content': 'Hi, pls intro yourself' }], [{ 'role': 'user', 'content': 'Shanghai is' }]] response = pipe(prompts, gen_config=gen_config) print(response)

从实现上看,MultimodalProcessor.format_prompts会统一将字符串、dict或 messages 嵌套列表规范化为标准格式,之后引擎会依据模型对应的 chat template 把 messages 拼装为完整的 prompt(见 lmdeploy/pipeline.py#L169-L177)。这意味着你可以在同一个批次里混用不同形式的输入,由 pipeline 负责归一化。

6. 流式输出:stream_infer

将pipe(...)换成pipe.stream_infer(...),即可逐 token 获取结果:

from lmdeploy import pipeline, GenerationConfig, TurbomindEngineConfig backend_config = TurbomindEngineConfig(tp=2) gen_config = GenerationConfig(top_p=0.8, top_k=40, temperature=0.8, max_new_tokens=1024) pipe = pipeline('internlm/internlm2_5-7b-chat', backend_config=backend_config) prompts = [[{ 'role': 'user', 'content': 'Hi, pls intro yourself' }], [{ 'role': 'user', 'content': 'Shanghai is' }]] for item in pipe.stream_infer(prompts, gen_config=gen_config): print(item)

流式模式下每次迭代产出一个Response对象。它的底层是异步事件循环驱动的:Pipeline会启动一个后台_EventLoopThread运行 asyncio 事件循环,请求在循环中经AsyncEngine.preprocess与AsyncEngine.generate处理,结果通过Queue回传到同步调用方(见 lmdeploy/pipeline.py#L384-L448),因此对调用方来说是简单的同步迭代器。当某个请求发生RequestError时,流中会返回一个finish_reason='error'且带error_code、error_message的Response,方便业务层做容错处理(见 lmdeploy/pipeline.py#L395-L416)。

7. 提取生成 token 的 logits 与最后一层 hidden states

pipeline 支持把模型推理过程中的中间结果透传出来,这对 logits 分析、奖励模型、后续精排等场景非常有用。

获取生成 token 的 logits:

from lmdeploy import pipeline, GenerationConfig pipe = pipeline('internlm/internlm2_5-7b-chat') gen_config=GenerationConfig(output_logits='generation', max_new_tokens=10) response = pipe(['Hi, pls intro yourself', 'Shanghai is'], gen_config=gen_config) logits = [x.logits for x in response]

获取生成 token 最后一层的 hidden states:

from lmdeploy import pipeline, GenerationConfig pipe = pipeline('internlm/internlm2_5-7b-chat') gen_config=GenerationConfig(output_last_hidden_state='generation', max_new_tokens=10) response = pipe(['Hi, pls intro yourself', 'Shanghai is'], gen_config=gen_config) hidden_states = [x.last_hidden_state for x in response]

GenerationConfig中output_logits与output_last_hidden_state的可选值均为'all'或'generation'(见 lmdeploy/messages.py#L200-L201):'generation'只返回生成 token 的结果,'all'则覆盖包括输入在内的全部位置。获取到的logits、last_hidden_state会分别填充到Response.logits与Response.last_hidden_state字段(见 lmdeploy/messages.py#L693-L694)。需要注意的是,这两个开关会带来额外的显存与计算开销,实际使用时建议仅在需要的推理步开启,并配合较小的max_new_tokens。

8. 计算 PPL(困惑度)

pipeline 提供get_ppl与get_logits两个面向评估的接口,可以直接对一段 token 序列打分:

from transformers import AutoTokenizer from lmdeploy import pipeline model_repoid_or_path = 'internlm/internlm2_5-7b-chat' pipe = pipeline(model_repoid_or_path) tokenizer = AutoTokenizer.from_pretrained(model_repoid_or_path, trust_remote_code=True) messages = [ {"role": "user", "content": "Hello, how are you?"}, ] input_ids = tokenizer.apply_chat_template(messages) # logits is a list of tensor logits = pipe.get_logits(input_ids) print(logits) # ppl is a list of float numbers ppl = pipe.get_ppl(input_ids) print(ppl)

使用注意(原文档明确给出):

  • 当input_ids过长时,可能出现 OOM 错误,请小心使用;
  • get_ppl返回的是cross entropy loss,即返回前没有执行exp操作,若要得到严格意义上的 perplexity 需要自行对结果取指数。

从源码可以进一步了解其实现细节:Pipeline.get_ppl对每个输入序列调用引擎的async_get_ppl,支持传入单条list[int]或批量list[list[int]](见 lmdeploy/pipeline.py#L288-L312)。在 lmdeploy/serve/core/async_engine.py#L932-L972 中可以看到:

  • 位置i的 logits 用于预测位置i+1的 token,因此输入至少要包含 2 个 token 才能计算(num_scored = len(input_ids) - 1);
  • 开启 prefix caching 或投机采样(speculative decoding)时,async_get_ppl会直接抛出ValueError拒绝执行;
  • 引擎以GenerationConfig(max_new_tokens=1, return_ppl=True, top_k=1)运行一次前向,拿到未归一化的交叉熵和ce_loss,再除以可打分的 token 数得到平均 loss。

get_logits内部则使用output_logits='all'逐 token 提取整个输入序列的 logits(见 lmdeploy/serve/core/async_engine.py#L896-L930),可用于奖励模型、数据筛选等自定义打分逻辑。此外,针对 InternLM2/Qwen2 架构的奖励模型,Pipeline.get_reward_score还提供了直接获取 reward score 的快捷入口(见 lmdeploy/pipeline.py#L265-L286)。

9. 使用 PyTorchEngine

TurboMind 之外,pipeline 支持通过PytorchEngineConfig切换到纯 PyTorch 后端。使用前需要先安装 Triton:

pip install triton>=2.1.0
from lmdeploy import pipeline, GenerationConfig, PytorchEngineConfig backend_config = PytorchEngineConfig(session_len=2048) gen_config = GenerationConfig(top_p=0.8, top_k=40, temperature=0.8, max_new_tokens=1024) pipe = pipeline('internlm/internlm2_5-7b-chat', backend_config=backend_config) prompts = [[{ 'role': 'user', 'content': 'Hi, pls intro yourself' }], [{ 'role': 'user', 'content': 'Shanghai is' }]] response = pipe(prompts, gen_config=gen_config) print(response)

PytorchEngineConfig的核心配置项(见 lmdeploy/messages.py#L451-L598):

  • session_len:最大会话长度,None时由引擎自动推导;
  • max_batch_size:最大 batch,缺省时按设备自动设置;
  • cache_max_entry_count:KV cache 占空闲显存比例,默认0.8;
  • block_size:paging cache block 大小,默认64;kernel_block_size必须是不小于 16 的 2 的幂且能被block_size整除;
  • quant_policy:KV cache 量化策略,4/8/16/17分别对应 INT4/INT8/FP8/FP8_E5M2(枚举定义见 lmdeploy/messages.py#L20-L27);
  • device_type:支持cuda、ascend、maca、camb;
  • adapters:LoRA adapter 配置(见下文);
  • enable_prefix_caching:前缀缓存开关;
  • eager_mode:是否关闭 CUDA graph 的 eager 模式;
  • thread_safe:多线程环境下是否使用线程安全实例;
  • distributed_executor_backend:分布式执行后端,可选uni/mp/ray;
  • enable_mp_engine:多进程模式运行引擎。

另外,即使没有显式指定PytorchEngineConfig,当模型不被 TurboMind 支持时,pipeline 也会自动回退到 PyTorch 后端,因此 PyTorchEngine 实际是所有新架构模型的默认兜底路径。

10. LoRA 模型推理

PyTorch 后端支持加载多个 LoRA adapter 并在推理时按需切换。通过PytorchEngineConfig.adapters传入一个{adapter 名: 权重路径/模型 ID}的字典,调用时用adapter_name指定使用哪一个:

from lmdeploy import pipeline, GenerationConfig, PytorchEngineConfig backend_config = PytorchEngineConfig(session_len=2048, adapters=dict(lora_name_1='chenchi/lora-chatglm2-6b-guodegang')) gen_config = GenerationConfig(top_p=0.8, top_k=40, temperature=0.8, max_new_tokens=1024) pipe = pipeline('THUDM/chatglm2-6b', backend_config=backend_config) prompts = [[{ 'role': 'user', 'content': '您猜怎么着' }]] response = pipe(prompts, gen_config=gen_config, adapter_name='lora_name_1') print(response)

adapters字段类型为dict[str, str](见 lmdeploy/messages.py#L561),支持同时注册多个 LoRA,推理时通过infer/stream_infer的adapter_name参数动态选择。如果 LoRA 权重带有对应的对话模板,可以先将其注册到 LMDeploy,然后把对话模板名直接作为adapter_name使用。

11. 释放 pipeline 资源

Pipeline内部持有 GPU 显存、后台事件循环线程与引擎实例,使用完毕后应当释放。两种方式:

from lmdeploy import pipeline # 方式一:with 语句自动释放 with pipeline('internlm/internlm2_5-7b-chat') as pipe: response = pipe(['Hi, pls intro yourself', 'Shanghai is']) print(response)
# 方式二:显式调用 close() pipe = pipeline('internlm/internlm2_5-7b-chat') ... pipe.close()

with语句依赖Pipeline.__enter__/__exit__实现,退出时自动调用close()(见 lmdeploy/pipeline.py#L320-L324);close()会依次关闭内部事件循环线程与异步引擎(见 lmdeploy/pipeline.py#L179-L182)。在多轮实验、批量跑评测等长驻进程中,及时释放 pipeline 能避免显存碎片化与句柄泄漏。

12. 常见问题(FAQ)

RuntimeError: An attempt has been made to start a new process before the current process has finished its bootstrapping phase

当tp>1且使用 PyTorch 后端时,引擎会拉起多进程(或依赖多进程初始化)。如果脚本直接以顶层代码方式执行,子进程可能在主进程完成 bootstrap 前被创建从而触发该错误。解决办法是确保 Python 脚本以if __name__ == '__main__':作为入口:

if __name__ == '__main__': # 初始化 pipeline 并执行推理 ...

这样可以保证初始化代码只在主程序执行,而不会在每个新创建的进程/线程中被重复执行。

自定义对话模板

pipeline 依据模型对应的 chat template 将 messages 拼装为输入。需要自定义时,参考自定义对话模板:可编写一个 JSON 模板文件(定义system、user、assistant等字段的拼接规则),通过 CLI 的--chat-template参数或ChatTemplateConfig接口传入,也可以用lmdeploy提供的注册机制将模板注册后按名字引用。

LoRA 模板注册

若 LoRA 权重有对应的对话模板,可先将模板注册到 LMDeploy,之后直接用模板名作为adapter_name调用,无需每次显式传入完整模板配置。

13. 与多模态、长文本场景的衔接

尽管本文聚焦 LLM 离线推理,理解Pipeline的架构对扩展场景同样重要:get_task会根据架构自动选择VLAsyncEngine处理视觉语言模型(如 InternVL、Qwen2.5-VL、Gemma3 等,见 lmdeploy/archs.py#L116-L131),此时infer支持传入(prompt, image)元组形式的多模态输入;PytorchEngineConfig.session_len配合长上下文配置可支持长序列推理。pipeline的接口形态保持一致,切换模型只需更换model_path与backend_config,这正是离线推理 API 设计的主要价值——用统一入口覆盖不同架构、不同后端、不同输入模态。

14. 小结

  • pipeline是 LMDeploy 面向离线推理的统一入口,自动选择 TurboMind/PyTorch 后端,支持批量、流式、多模态输入;
  • 显存紧张时优先检查并调低cache_max_entry_count(当前默认取空闲显存的 0.8,TurboMind 也支持按 block 数指定);
  • GenerationConfig覆盖采样、停止词、结构化输出等全量生成控制,参数合法性在构造时即被校验;
  • output_logits/output_last_hidden_state/get_ppl/get_logits为评估与后处理场景提供了直接从引擎取中间结果的能力;
  • 多卡场景使用tp(以及dp/ep/cp),PyTorch 后端还支持 LoRA、Ray 分布式执行与多进程模式;
  • 记得用with或close()释放 pipeline,多进程推理请使用if __name__ == '__main__':保护入口。

如需查阅更完整的 API 文档,可阅读仓库内的 docs/zh_cn/api/pipeline.rst;想深入理解后端差异,可进一步阅读 docs/zh_cn/inference/turbomind.md 与 docs/zh_cn/inference/pytorch.md。

  • 人工智能
  • 大模型
  • 模型推理服务
  • 推理引擎
  • 本地部署
  • 模型量化

【免费下载链接】lmdeploy

LMDeploy is a toolkit for compressing, deploying, and serving LLMs.

项目地址:https://gitcode.com/gh_mirrors/lm/lmdeploy
点击查看免费下载

相关推荐

上一篇:3小时从零到动:如何亲手打造你的智能轮腿机器人?
下一篇:如何用549元打造FOC轮腿平衡机器人:开源DIY完整指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询