Prhub

#48850 [Bugfix][LoRA] Add embedding_modules for Qwen3.5 CausalLM

原始 PR 作者 Agoni-02 合并时间 2026-08-19 12:55 文件变更 1 提交数 8 评论 7 代码增减 +5 / -0

执行摘要

为 Qwen3.5 注册 LoRA embedding_modules,修复 embedding 目标适配器加载失败

Issue #48934 报告了 Qwen3.5 CausalLM 因缺少 embedding_modules 导致 embed_tokens / lm_head 的 LoRA 适配器加载失败;PR body 明确指出『Qwen3_5ForCausalLMBase implements SupportsLoRA but did not define embedding_modules. Loading a PEFT adapter whose target_modules include embed_tokens / lm_head fails unexpected-module validation in LoRAModel.from_local_checkpoint』,且同系列 Qwen3 / Qwen3-MoE 可正常工作,属于同族模型契约不一致的补齐。

值得快速浏览的教科书式最小修复:它直观展示了 vLLM LoRA 的 embedding_modules 契约如何参与 PEFT adapter 的加载校验。若后续开发新模型 LoRA 支持,可直接复用该模式,并建议顺手补一个仓库内单测防止再次遗漏。

讨论亮点

本 PR 评审过程没有技术争论,核心讨论集中在流程层面:

  • 作者 Agoni-02 为首次贡献者,因新贡献者门禁(0 个已合并 PR)无法触发 pre-run-check,在 PR 评论中请求维护者(sighingnow、vadiklyutiy、jeejeelee)添加 ready 标签。
  • 维护者 jeejeelee 回复『Sorry for the delayed response』后直接批准,并以 /ci run 触发 Buildkite CI;CI 通过后带 verified 标签完成合并,无遗留未解决疑虑。

实现拆解

本次变更共 1 个文件、+5/-0 行,实现步骤拆解如下:

  1. 变更入口:在 vllm/model_executor/models/qwen3_5.pyQwen3_5ForCausalLMBase 类体中新增 embedding_modules 类属性,位置紧邻 packed_modules_mapping 声明,位于类继承声明之后。
  2. 契约内容:映射键为 PEFT 适配器中常见的 LoRA 目标模块名,embed_tokens 映射到 vLLM 的输入 embedding 包装器 input_embeddingslm_head 映射到输出 embedding 包装器 output_embeddings;该映射逐字对齐 Qwen3ForCausalLM / Qwen3MoeForCausalLM 的既有实现。
  3. 链路作用Qwen3_5ForCausalLMBase 已实现 SupportsLoRA,LoRA 校验依赖该映射判定 adapter 的 target_modules 是否属于模型预期模块集合。此前缺失该映射时,from_local_checkpoint 会把 embed_tokens / lm_head 判为 unexpected-module 并抛 ValueError,与 Qwen3 家族行为不一致。注册后 PEFT embedding LoRA 在 enable_lora=True 场景下可正常加载。
  4. 测试与配套:本 PR 未新增仓库内单元测试,作者给出手动验证路径(ruff check / ruff format --check 通过,加载带 embed_tokens / lm_head 的 LoRA 确认不再抛错);维护者触发 Buildkite CI #84536 在 head commit 7cb8e198 上运行通过,PR 带 verified 标签合入。
文件 模块 状态 重要度
vllm/model_executor/models/qwen3_5.py 模型定义 modified 5.34

关键符号

embedding_modules

关键源码片段

vllm/model_executor/models/qwen3_5.py data-contract

唯一变更文件:在 Qwen3_5ForCausalLMBase 类上新增 embedding_modules 类属性,把 PEFT 的 embed_tokens / lm_head LoRA 目标映射到 vLLM 的 input_embeddings / output_embeddings 包装器,修复 LoRA 加载时的 unexpected-module 校验失败。

class Qwen3_5ForCausalLMBase(
    nn.Module,
    HasInnerState,
    IsHybrid,
    SupportsEagle3,
    SupportsLoRA,
    SupportsMRoPE,
    SupportsPP,
):
    # 现有的融合投影映射,用于把 HF 权重名称映射到 vLLM 的融合层。
    packed_modules_mapping = {
        "qkv_proj": ["q_proj", "k_proj", "v_proj"],
        "gate_up_proj": ["gate_proj", "up_proj"],
        # GDN 融合投影。
        "in_proj_qkvz": ["in_proj_qkv", "in_proj_z"],
        "in_proj_ba": ["in_proj_b", "in_proj_a"],
    }
​
    # 本 PR 新增:把 PEFT adapter 的 embed / lm_head LoRA 目标名映射到
    # vLLM 的 embedding 包装器(输入嵌入 / 输出嵌入)。该映射与
    # Qwen3ForCausalLM / Qwen3MoeForCausalLM 完全一致。
    # 缺失时,`target_modules` 里的 embed_tokens / lm_head 会在
    # LoRAModel.from_local_checkpoint 的 unexpected-module 校验中被拒绝。
    embedding_modules = {
        "embed_tokens": "input_embeddings",
        "lm_head": "output_embeddings",
    }

评论区精华

新贡献者 pre-run-check 门禁阻塞 other

作者 Agoni-02 作为首次贡献者(0 个合并 PR)无法触发 pre-run-check,在 PR 评论中请求维护者添加 ready 标签以推进 CI。

结论:维护者 jeejeelee 触发 /ci run,Buildkite CI #84536 在 head commit 7cb8e198 上运行。 · 已解决

CI 验证与合并 测试

jeejeelee 批准前以 /ci run 触发完整 CI,PR 随后被标记为 verified 并合入 main。

结论:CI 通过,PR 合并完成,无技术性 review 争议。 · 已解决

风险与影响

风险极低,但存在以下可注意的点:

  • 缺少自动化测试覆盖:本 PR 唯一变更文件为源码文件,没有新增直接单测,验证依赖作者手动 e2e 与现有 LoRA 测试的间接覆盖;若后续 PEFT adapter 使用带前缀的命名(如 model.embed_tokens),仍可能触发同类校验问题。
  • 兼容性:新增的是纯类级 dict,不改任何计算路径、权重加载或量化逻辑;enable_lora=False 或 adapter 不含 embedding 目标时行为完全不变,不存在回归风险。
  • 数据契约一致性:映射与 Qwen3 逐字对齐,若未来 PEFT 侧命名(如 lm_head 替换为 output_embeddings)发生变化,需要同步更新。
  • 性能 / 安全:无相关改动。

影响面聚焦在 Qwen3.5 系列(CausalLM 基底)的 LoRA 用户:此前 target_modules 包含 embed_tokens / lm_head 的 PEFT 适配器在引擎初始化阶段直接失败;修复后与 Qwen3 / Qwen3-MoE 行为对齐,无需任何迁移或配置变更即可生效。对不使用 embedding LoRA 的用户无感知,对一个 5 行数据契约补齐而言影响范围与程度都较小。

缺少自动化测试覆盖 LoRA 数据契约对齐

关联 Issue

#48934 [Bug]: Qwen3.5 CausalLM missing embedding_modules breaks LoRA on embed_tokens/lm_head

完整报告

参与讨论