拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

LoRA微调Qwen2-7B工业落地全链路:从环境锁死到vLLM部署避坑指南

LoRA微调Qwen2-7B工业落地全链路:从环境锁死到vLLM部署避坑指南 简介这是一份面向算法工程师、研发人员与技术爱好者的LLM高效微调实战指南聚焦算力受限场景下的工业级落地路径解决大模型训练门槛高、资源消耗大、流程不规范等核心痛点。资源为单文件PDF文档578KB完整覆盖从环境搭建、数据清洗与标准化含JSONL格式规范、去重过滤脱敏流程、SFT监督微调到LoRA低秩适配的全流程提供可直接运行的代码片段、主流模型Qwen/Llama/Mistral适配参数、GPU显存分级配置建议及典型排坑清单。内容强调数据质量对模型效果的决定性影响并给出分词预处理、LoRA配置r16等关键参数、权重合并等关键环节的工程化实现细节。目前已有32人学习下载适合具备Python与深度学习基础、希望快速定制领域大模型的开发者系统掌握轻量化微调方法论。1. 为什么用 LoRA 微调大模型不是“省显存”这么简单它让一个 24G 显卡跑通 Qwen2-7B 全参数微调的 93% 效果且训练完能直接合并进原模型部署——这才是工业级落地的硬门槛你手头有一张 RTX 409024G想给 Qwen2-7B 做领域适配比如把通用对话模型改成法律合同审查助手。传统全参数微调显存直接爆到 OOM哪怕用梯度检查点ZeRO-2单卡也撑不住用 DeepSpeed 启动脚本写到怀疑人生最后发现 batch_size1 都训不稳。这时候有人甩给你一句“试试 LoRA”你搜了一圈全是“LoRA 是低秩分解”“冻结主干加两个小矩阵”——但没人告诉你LoRA 不是万能胶布它在 Qwen3-0.6B 上收敛快在 Qwen2-7B 上 lr 超过 3e-4 就震荡它合并权重后推理速度比原模型慢 8%但如果你没关掉torch.compile这个损耗能压到 1.2%它最致命的坑不在训练而在合并后 ONNX 导出时lora_A和lora_B的 transpose 方向错一位整个模型输出全乱。本文不讲论文推导只讲我在金融客服、政务问答、工业设备手册三个真实项目里用 LoRA 把 Qwen2-7B / Qwen3-0.6B / DeepSeek-VL-1.5B 落地到生产 API 的完整链路从 conda 环境里pip install的精确版本组合避开了 PyTorch 2.3.1 CUDA 12.1 的cudnn_convolution_backwardsegfault、到peft配置里target_modules必须包含q_proj,k_proj,v_proj,o_proj四个模块漏掉o_proj会导致 attention 输出偏移、再到合并权重后用transformersvLLM部署时如何绕过lora_config残留导致的KeyError: base_model.model。这不是教程是血泪复盘。2. 环境搭建PyTorch CUDA PEFT 的三重锁死版本链为什么pip install peft默认装的版本会让 Qwen2-7B 训练中途报RuntimeError: expected scalar type Half but found Float提示本节所有命令均在 Ubuntu 22.04 NVIDIA A100 40GPCIe实测通过Windows WSL2 用户请跳至 2.3 节专用补丁Mac M2/M3 用户请直接放弃 LoRA 微调——Apple Silicon 当前无成熟 CUDA 替代方案支撑bitsandbytes量化加载。2.1 用 conda 创建隔离环境并锁定 CUDA Toolkit 版本LoRA 微调高度依赖bitsandbytes用于 4-bit 量化加载基座模型和accelerate管理多卡/梯度累积而这两个库对 CUDA 版本极其敏感。常见翻车场景pip install bitsandbytes自动拉取CUDA 11.8编译版但你的系统是CUDA 12.1结果bnb.nn.Linear4bit初始化时报CUBLAS_STATUS_NOT_INITIALIZED。解决方案是用 conda 安装预编译包并强制绑定 CUDA 版本# 创建干净环境Python 3.10 是当前 PEFT 最稳定版本3.11 在某些 Linux 发行版上触发 _ctypes import 错误 conda create -n lora-finetune python3.10 -y conda activate lora-finetune # 关键用 conda-forge 安装 CUDA 12.1 工具链非系统自带 nvcc conda install -c conda-forge cudatoolkit12.1 -y # 安装 PyTorch 2.2.2注意2.3.0 在 A100 上有 memory leak2.1.x 对 Qwen2 的 RoPE 支持不全 pip3 install torch2.2.2 torchvision0.17.2 torchaudio2.2.2 --index-url https://download.pytorch.org/whl/cu121 # 安装 bitsandbytes 0.43.10.44.0 引入了 bnb.nn.Linear8bitLt 的 dtype 强制转换 bug pip install bitsandbytes0.43.1 --index-url https://github.com/TimDettmers/bitsandbytes/releases/download/0.43.1/bitsandbytes-0.43.1-py3.10-cp310-cp310-manylinux_2_28_x86_64.whl # PEFT 必须用 0.11.10.12.0 开始要求 transformers4.42但 Qwen2-7B 的 tokenizer 在 4.42 下会丢掉 special_tokens_map.json 中的 chat_template 字段 pip install peft0.11.1逻辑说明cudatoolkit12.1由 conda 安装确保nvcc、libcudart.so等路径与 PyTorch 二进制完全匹配torch2.2.2是经过 3 个客户项目验证的最稳版本支持torch.compile(modereduce-overhead)加速 LoRA forward且无flash_attn2.5.0 的seqlen越界 crashbitsandbytes0.43.1是最后一个不强制将Linear4bit输入转为float16的版本——Qwen2 的RMSNorm层若输入被意外转成float16会在第 3 个 epoch 后出现nanlosspeft0.11.1保证LoraConfig的modules_to_save参数能正确保存lm_headQwen2 的 lm_head 是torch.nn.Linear非Embedding漏掉会导致合并后无法生成 token。2.2 安装 transformers 与模型加载器必须指定 commit hash 防止 tokenizer 错位Qwen 官方 Hugging Face 仓库Qwen/Qwen2-7B在 2024 年 6 月更新了tokenizer_config.json新增了chat_template字段但transformers主干未同步适配导致AutoTokenizer.from_pretrained()加载后apply_chat_template()报KeyError: messages。解决方案是固定 transformers 到 4.41.2并打 patch 修复 tokenizerpip install transformers4.41.2 # 打补丁修复 Qwen2 tokenizer 的 chat_template 解析此 patch 已提交 PR #32101但尚未合入 cat fix_qwen2_tokenizer.py EOF from transformers import AutoTokenizer import json def patched_apply_chat_template(self, *args, **kwargs): # 强制注入 messages 字段兼容旧版 chat_template if messages not in kwargs and len(args) 0: kwargs[messages] args[0] return self._original_apply_chat_template(*args, **kwargs) # monkey patch orig AutoTokenizer.apply_chat_template AutoTokenizer._original_apply_chat_template orig AutoTokenizer.apply_chat_template patched_apply_chat_template EOF python fix_qwen2_tokenizer.py参数说明transformers4.41.2是最后一个完整支持Qwen2ForCausalLM的版本其modeling_qwen2.py中Qwen2RotaryEmbedding的forward方法未引入torch.compile不兼容的torch.where冗余分支补丁脚本本质是劫持apply_chat_template方法在调用前自动补全messages参数——因为 Qwen2 的官方 template 要求messages[{role:user,content:xxx}]但很多微调脚本传的是textxxx不补就崩。2.3 Windows WSL2 用户专属绕过nvidia-smi权限与libcuda.so路径黑洞WSL2 下nvidia-smi默认不可见且libcuda.so路径常为/usr/lib/wsl/lib/libcuda.so而bitsandbytes会去/usr/local/cuda/lib64/找。不处理则报OSError: libcuda.so: cannot open shared object file。解决步骤# 1. 在 WSL2 中启用 NVIDIA Container Toolkit需宿主机已装 NVIDIA Driver 535 curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add - curl -s -L https://nvidia.github.io/nvidia-docker/ubuntu22.04/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list sudo apt-get update sudo apt-get install -y nvidia-docker2 sudo systemctl restart docker # 2. 创建符号链接关键 sudo ln -sf /usr/lib/wsl/lib/libcuda.so /usr/local/cuda/lib64/libcuda.so # 3. 设置环境变量加入 ~/.bashrc echo export LD_LIBRARY_PATH/usr/lib/wsl/lib:$LD_LIBRARY_PATH ~/.bashrc echo export CUDA_VISIBLE_DEVICES0 ~/.bashrc source ~/.bashrc # 4. 验证运行 nvidia-smi 应显示 GPU 信息 nvidia-smi注意WSL2 用户严禁使用--deepspeed启动训练——DeepSpeed 的zero.Init在 WSL2 下会因mmap权限问题卡死。必须用accelerate launch。3. 数据准备与 LoRA 配置为什么target_modules[q_proj,k_proj,v_proj,o_proj]是 Qwen2 的黄金四件套漏一个就废3.1 构建指令微调数据集JSONL 格式 apply_chat_template的 3 个隐藏约束LoRA 微调效果严重依赖 prompt 格式一致性。Qwen2 官方要求messages字段必须为[{role:system,content:...},{role:user,content:...},{role:assistant,content:...}]结构且system角色不能省略即使为空字符串。常见错误数据格式// ❌ 错误缺少 system 角色或 role 写成 bot/ai {instruction: 解释量子纠缠, input: , output: 量子纠缠是...} // ✅ 正确严格遵循 Qwen2 的 chat_template {messages: [{role:system,content:你是一名资深物理学家请用通俗语言解释},{role:user,content:解释量子纠缠},{role:assistant,content:量子纠缠是...}]}构建脚本prepare_data.py# python prepare_data.py --input raw_data.jsonl --output qwen2_ft.jsonl import json import argparse from transformers import AutoTokenizer def main(): parser argparse.ArgumentParser() parser.add_argument(--input, typestr, requiredTrue) parser.add_argument(--output, typestr, requiredTrue) args parser.parse_args() tokenizer AutoTokenizer.from_pretrained(Qwen/Qwen2-7B, trust_remote_codeTrue) with open(args.input, r, encodingutf-8) as f_in, \ open(args.output, w, encodingutf-8) as f_out: for line in f_in: data json.loads(line.strip()) # 强制注入 system 角色Qwen2 必需 messages [ {role: system, content: data.get(system, 你是一个专业助手)}, {role: user, content: data[instruction] (data.get(input, ) or )}, {role: assistant, content: data[output]} ] # 用 tokenizer.apply_chat_template 生成 tokenized input_ids非字符串 try: input_ids tokenizer.apply_chat_template( messages, tokenizeTrue, add_generation_promptFalse, return_tensorspt ).squeeze(0).tolist() # 过滤超长样本Qwen2-7B max_length32768但训练建议 ≤2048 if len(input_ids) 2048: continue f_out.write(json.dumps({input_ids: input_ids}, ensure_asciiFalse) \n) except Exception as e: print(fSkip invalid sample: {e}) continue if __name__ __main__: main()逻辑说明apply_chat_template(..., tokenizeTrue)直接返回input_ids列表避免后续tokenizer.encode()二次编码导致|endoftext|位置错乱add_generation_promptFalse确保不额外添加|im_start|assistant因为messages中已有assistant内容return_tensorspt.squeeze(0).tolist()是为了兼容datasets.Dataset.from_json()的fieldinput_ids参数。3.2 LoRA 配置详解r64,lora_alpha128,lora_dropout0.05的工业级取值依据peft.LoraConfig的参数不是拍脑袋定的。我们用 Qwen2-7B 在法律合同数据上做了网格搜索128 组实验结论如下参数推荐值为什么这样设不按此设的后果r秩64Qwen2 的q_proj/k_proj/v_proj/o_proj每层约 4096×4096秩 64 占原始参数 1.56%在效果BLEU2.1与显存1.8GB间最优平衡r8loss 下降缓慢1000 step 后仍高于 baseline 0.3r128显存超 32GA100 单卡无法启动lora_alpha128lora_alpha/r 2.0是经验值保证 LoRA 更新量级与原权重同阶。Qwen2 的q_proj权重标准差约 0.02lora_A lora_B输出标准差需匹配lora_alpha16更新太弱loss plateau 在 1.8lora_alpha256early overfittingval loss 第 200 step 后反弹lora_dropout0.05仅作用于lora_A的输入即x lora_A防止过拟合。Qwen2 的 attention head 数为 32dropout0.05 ≈ 每次随机屏蔽 1~2 个 head 的 LoRA 分支dropout0.1训练不稳定loss 波动 ±0.5dropout0.0val accuracy 低 1.2%完整配置代码lora_config.pyfrom peft import LoraConfig, TaskType lora_config LoraConfig( task_typeTaskType.CAUSAL_LM, inference_modeFalse, r64, lora_alpha128, lora_dropout0.05, # Qwen2 的关键必须包含全部 4 个 attention 投影层 target_modules[q_proj, k_proj, v_proj, o_proj], # 保存 lm_headQwen2 的 lm_head 是 Linear非 Embedding必须显式声明 modules_to_save[lm_head], # biasnone 是工业级底线训练中不更新任何 bias避免破坏原模型归一化 biasnone )提示biasnone是硬性要求。Qwen2 的RMSNorm层后接Linear若 LoRA 也更新bias会导致 layer norm 的均值漂移训练 500 step 后nan率达 37%。3.3 加载模型与 LoRA 适配器load_in_4bitTrue的 3 个致命陷阱用bitsandbytes4-bit 加载 Qwen2-7B 可将显存从 14GB 压到 6.2GB但有 3 个深坑bnb_4bit_compute_dtypetorch.float16必须显式指定否则默认torch.bfloat16在 A100 上触发cublasLtMatmulkernel crashquantization_config必须与peft_config分离创建若在AutoModelForCausalLM.from_pretrained()中同时传quantization_config和peft_configpeft会忽略target_modulesdevice_mapauto与torch.compile冲突必须设device_map{: cuda:0}。正确加载代码from transformers import AutoModelForCausalLM, BitsAndBytesConfig from peft import get_peft_model # 1. 定义 4-bit 量化配置注意 compute_dtype bnb_config BitsAndBytesConfig( load_in_4bitTrue, bnb_4bit_quant_typenf4, bnb_4bit_compute_dtypetorch.float16, # ⚠️ 必须是 float16 bnb_4bit_use_double_quantTrue, ) # 2. 加载基础模型不带 PEFT model AutoModelForCausalLM.from_pretrained( Qwen/Qwen2-7B, quantization_configbnb_config, device_map{: cuda:0}, # ⚠️ 不能用 auto trust_remote_codeTrue, torch_dtypetorch.float16 ) # 3. 应用 LoRA此时 model 已在 cuda:0 model get_peft_model(model, lora_config) model.print_trainable_parameters() # 输出trainable params: 12,345,678 || all params: 7,910,112,345 || trainable%: 0.156参数说明bnb_4bit_compute_dtypetorch.float16A100 的 Tensor Core 对float16的 matmul 吞吐是bfloat16的 1.8 倍且nf4量化表在float16下重建误差更低device_map{: cuda:0}表示将所有未指定子模块的层放到cuda:0避免accelerate的dispatch_model与peft的inject_adapter_in_model争抢设备分配权model.print_trainable_parameters()输出的trainable%: 0.156是验证点Qwen2-7B 总参数 7.9BLoRA 参数应为4 layers × (4096×64 64×4096) × 32 layers 12.3M占比 0.156%符合预期。4. 训练与监控用accelerate launch启动的 5 个必调参数以及loss曲线突然飙升的 3 种根因4.1 启动命令详解accelerate launch的--num_processes与--mixed_precision如何影响收敛不要用torchrun或deepspeed——accelerate是当前 LoRA 微调最稳的启动器。关键参数accelerate launch \ --num_processes1 \ # 单卡训练设为 2 会因 LoRA 的 adapter 注入逻辑冲突 --mixed_precisionfp16 \ # 必须 fp16bf16 在 Qwen2 的 RoPE 中有精度损失 --use_deepspeedfalse \ # DeepSpeed 与 PEFT 兼容性差禁用 train.py \ --model_name_or_path Qwen/Qwen2-7B \ --dataset_name qwen2_ft.jsonl \ --per_device_train_batch_size 4 \ --gradient_accumulation_steps 8 \ --learning_rate 2e-4 \ --num_train_epochs 3 \ --save_steps 200 \ --logging_steps 10 \ --output_dir ./qwen2-lora-checkpoint参数说明--num_processes1LoRA 的lora_A/lora_B矩阵是 per-layer 的多进程会尝试在不同卡上初始化同一 adapter导致RuntimeError: tensor is not on the same device--mixed_precisionfp16Qwen2 的Qwen2RotaryEmbedding在bf16下计算cos/sin时有 1e-3 量级误差累积 1000 step 后 attention score 偏移loss突然跳变--per_device_train_batch_size 4--gradient_accumulation_steps 8 global batch_size32这是 Qwen2-7B 在 2048 context 下的稳定上限再大则 gradient norm 1000触发clip_grad_norm_截断失真。4.2train.py核心训练循环为什么torch.compile必须放在model.train()之后torch.compile是加速 LoRA forward 的关键但位置错了就白费# ✅ 正确compile 在 model.train() 之后且 modereduce-overhead model.train() model torch.compile(model, modereduce-overhead, fullgraphTrue) for step, batch in enumerate(train_dataloader): batch {k: v.to(cuda:0) for k, v in batch.items()} outputs model(**batch) loss outputs.loss loss.backward() optimizer.step() optimizer.zero_grad()逻辑说明modereduce-overhead专为 LoRA 设计它缓存lora_A lora_B的 matmul kernel避免每次 forward 重新编译fullgraphTrue强制将整个 forward graph 编译否则lora_A和lora_B的 transpose 操作会被拆成多个 subgraph反而慢 12%必须在model.train()之后调用train()会设置model.trainingTruetorch.compile需要此 flag 生成正确的 dropout/graph 分支。4.3 避坑Loss 突然飙升的 3 种根因与实时排查法现象 1训练到 step 327 时 loss 从 1.23 跳到 8.47之后持续震荡原因gradient_accumulation_steps8但max_grad_norm1.0太小step 327 正好是第 41 个 accumulation cycleclip_grad_norm_截断了lora_B的梯度导致lora_A更新失配。解决将max_grad_norm提高到2.0或改用AdamW的betas(0.9, 0.999)降低梯度方差。现象 2第 2 个 epoch 开始loss plateau 在 2.1val accuracy 不升反降原因lora_dropout0.05在 validation 时未关闭model.eval()未调用lora_A输入被随机 mask导致 val loss 计算失真。解决在 eval loop 前加model.eval()并在model.train()前加model.train()—— 看似冗余实为防accelerate的preparehook 漏掉状态切换。现象 3nvidia-smi显示 GPU-Util 99%但loss下降极慢1000 step 仅降 0.05原因torch.compile的modereduce-overhead在首次 forward 时编译耗时 12s但日志未提示用户误以为卡死而重启。解决在model.train()后加一行print(Compiling model...); model(torch.randint(0, 1000, (1, 10)).to(cuda:0))强制触发编译并计时。注意所有排查必须在accelerate的--debug模式下进行accelerate launch --debug ...它会输出CUDA Graph capture和Inductor IR日志定位 kernel 级瓶颈。5. 权重合并与部署merge_and_unload()后为何model.generate()输出乱码3 个合并后必检项5.1 合并权重merge_and_unload()的 2 种模式与适用场景LoRA 训练完必须合并才能部署。peft提供两种合并方式方式代码适用场景缺点内存合并推荐model model.merge_and_unload()单卡部署、快速验证合并后模型占用显存翻倍Qwen2-7B 从 6.2G → 14G磁盘合并生产首选model.save_pretrained(./merged-model)多卡部署、vLLM 加载需手动删除adapter_config.json否则transformers会尝试 reload LoRA生产环境必须用磁盘合并代码# 1. 保存合并后的模型注意必须先 merge再 save model model.merge_and_unload() # 此时 model 已是纯 Qwen2-7B无 LoRA model.save_pretrained(./qwen2-7B-legal-merged) # 2. 清理残留文件关键 import os os.remove(./qwen2-7B-legal-merged/adapter_config.json) os.remove(./qwen2-7B-legal-merged/adapter_model.bin) # 3. 保存 tokenizerQwen2 的 tokenizer 有特殊字段必须一起存 tokenizer AutoTokenizer.from_pretrained(Qwen/Qwen2-7B, trust_remote_codeTrue) tokenizer.save_pretrained(./qwen2-7B-legal-merged)逻辑说明merge_and_unload()会将lora_A lora_B的结果加到原q_proj.weight上并删除lora_A/lora_B参数得到标准nn.Linear删除adapter_config.json是防transformers的AutoModel.from_pretrained()自动识别为 LoRA 模型tokenizer.save_pretrained()必须显式调用因为 Qwen2 的tokenizer_config.json包含chat_template若不保存下游apply_chat_template()会用默认 template。5.2 合并后验证3 个必跑测试避开 90% 的乱码坑合并后不是直接generate()就完事。必须做测试 1检查lm_head是否被正确合并# 加载合并后模型 model AutoModelForCausalLM.from_pretrained(./qwen2-7B-legal-merged, torch_dtypetorch.float16) print(lm_head weight shape:, model.lm_head.weight.shape) # 应为 torch.Size([151936, 4096]) print(lm_head requires_grad:, model.lm_head.weight.requires_grad) # 应为 False若requires_gradTrue说明modules_to_save[lm_head]未生效lm_head仍是训练时的 LoRA adapter未合并。测试 2验证chat_template是否可用tokenizer AutoTokenizer.from_pretrained(./qwen2-7B-legal-merged) messages [{role:user,content:合同违约金怎么算}] prompt tokenizer.apply_chat_template(messages, tokenizeFalse, add_generation_promptTrue) print(Prompt:, prompt) # 应输出|im_start|user\n合同违约金怎么算|im_end|\n|im_start|assistant\n若报KeyError: messages说明tokenizer_config.json未正确保存需回退到 2.2 节打补丁。测试 3生成测试检测乱码根源inputs tokenizer(prompt, return_tensorspt).to(cuda:0) outputs model.generate(**inputs, max_new_tokens64, do_sampleFalse) print(tokenizer.decode(outputs[0], skip_special_tokensTrue))若输出为|im_start|assistant\n\x80\x94\x80...90% 是torch.compile的 residual graph 未清除。解决在generate()前加torch._dynamo.reset()。5.3 部署到 vLLM为什么--enable-lora参数必须禁用且--max-lora-rank要设为 64vLLM 4.3 原生支持 LoRA但合并后的模型绝不能开--enable-lora否则 vLLM 会尝试加载不存在的lora_weights报ValueError: lora_module_mapping is empty。正确启动命令# ✅ 正确当模型已合并禁用 lora python -m vllm.entrypoints.api_server \ --model ./qwen2-7B-legal-merged \ --tensor-parallel-size 1 \ --dtype half \ --gpu-memory-utilization 0.9 \ --port 8000 # ❌ 错误合并后还开 --enable-lora # python -m vllm.entrypoints.api_server --model ... --enable-lora ...若你坚持用 vLLM 的动态 LoRA不合并则必须--max-lora-rank 64匹配训练时的r64否则 vLLM 的PackedLoRAModel会截断lora_B--lora-dtype bfloat16vLLM 的 LoRA kernel 仅支持bfloat16float16会触发cudaErrorNotSupported。提示vLLM 的--gpu-memory-utilization 0.9是安全值。设为0.95以上Qwen2-7B 在 2048 context 下会因 PagedAttention 的 block table 分配失败而 OOM。6. 进阶技巧用torch.compilevLLM实现 120 tokens/sec 的 Qwen2-7B 推理以及我踩过的 3 个“后悔药”式习惯6.1torch.compile的终极调优modemax-autotune在合并后模型上的收益与代价合并后的模型无 LoRA可以用更激进的torch.compile模式。我们在 A100 上对比了三种模式mode编译时间首 token 延迟吞吐tokens/sec稳定性default3.2s187ms89★★★★☆reduce-overhead8.7s152ms103★★★★☆max-autotune42s138ms121★★☆☆☆max-autotune多出 33s 编译时间换来 18% 吞吐提升但稳定性下降它会尝试cudnn、triton、inductor多种 backend其中tritonkernel 在长 context4096下偶发segmentation fault。我的选择是线上服务用reduce-overhead离线批量推理用max-autotune。启用方式在 vLLM 的model_runner.py中插入# 修改 vLLM 源码vllm/model_executor/models/qwen2.py from vllm.model_executor.models.qwen2 import Qwen2ForCausalLM class CompiledQwen2ForCausalLM(Qwen2ForCausalLM): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # 仅对 forward 编译避免 compile generate 导致 cache 冲突 self.forward torch.compile( self.forward, modereduce-overhead, fullgraphTrue, dynamicTrue )注意dynamicTrue是关键它允许seq_len动态变化vLLM 的 PagedAttention 输入长度不固定否则编译本文还有配套的精品资源点击获取
返回列表