Prhub

#39575 Add Jina Embeddings v5 model support (fixes #38633)

vllm-project/vllm · 作者 Roy214 · 合并时间 2026-04-16 14:37

分析状态 已生成
文件变更 7提交数 12 · 评论 10
代码增减 +218 / -10
feature model v1 pooling

执行摘要

新增 Jina Embeddings v5 模型支持,基于 Qwen3-0.6B-Base 并合并 LoRA 适配器。

Issue #38633报告用户尝试部署jinaai/jina-embeddings-v5-text-small模型时,出现Model architectures ['JinaEmbeddingsV5Model'] are not supported错误,并提示需要peft包。PR body明确说明目的是添加该模型支持以修复此问题,使用户能够通过vLLM服务该模型。

该PR值得精读,特别是JinaEmbeddingsV5Model类中LoRA适配器加载和合并的实现,展示了如何在模型加载时处理适配器权重而避免运行时依赖。关注load_weights方法的设计决策和权重匹配逻辑。

讨论亮点

review讨论中,gemini-code-assist[bot]指出了load_weights实现的关键缺陷:通过调用self.model.load_weights而非super().load_weights,可能跳过模型外部权重(如lm_head),导致加载不完整,建议使用前缀无关的匹配方法优化LoRA合并。noooop建议将新增的jina_embeddings_v5.pytest_jina_v5.py合并到现有文件中以减少文件数量。作者最终采纳了这些建议,合并了文件并修复了实现,PR获得批准。

实现拆解

  1. 新增模型实现:在vllm/model_executor/models/jina.py中新增JinaEmbeddingsV5Model类,继承自Qwen3ForCausalLM,并实现load_weights方法。添加辅助函数_load_adapter_build_lora_pairs,用于从Hugging Face仓库加载LoRA适配器配置和权重,并在加载时合并到基础权重中,避免运行时依赖peft。
  2. 注册模型:在vllm/model_executor/models/registry.py_EMBEDDING_MODELS字典中添加"JinaEmbeddingsV5Model": ("jina", "JinaEmbeddingsV5Model")条目,使系统能够识别该模型架构。
  3. 更新测试套件
    • tests/models/language/pooling_mteb_test/test_jina.py中添加新模型的测试配置,包括MTEB分数、架构类型等。
    • 修改tests/models/language/pooling_mteb_test/mteb_embed_utils.py,新增HfMtebEncoder类以支持Hugging Face模型编码,并扩展VllmMtebEncoder以支持提示前缀。
  4. 配套调整
    • 更新docs/models/pooling_models/embed.md文档,添加JinaEmbeddingsV5Model的说明。
    • 修改tests/conftest.py中的HfRunner类,添加revision参数以支持模型版本控制。
文件 模块 状态 重要度
vllm/model_executor/models/jina.py 模型实现 modified 8.88
tests/models/language/pooling_mteb_test/test_jina.py 测试套件 modified 5.81
vllm/model_executor/models/registry.py 注册表 modified 4.96
tests/models/language/pooling_mteb_test/mteb_embed_utils.py 测试工具 modified 6.03
tests/models/registry.py 测试注册 modified 3.8
tests/conftest.py 测试配置 modified 3.31
docs/models/pooling_models/embed.md 文档 modified 2.28
vllm/model_executor/models/jina.py core-logic

核心模型实现文件,新增了 JinaEmbeddingsV5Model 类和适配器加载逻辑,是实现变更的入口。

def _load_adapter(
    model: str,
    task: str,
    revision: str | None,
) -> tuple[dict, dict[str, torch.Tensor]] | None:
    """从本地路径或HF仓库加载适配器配置和权重。    返回 (adapter_config, adapter_weights) 或 None(如果未找到)。
    """
    config_bytes = get_hf_file_bytes(
        f"adapters/{task}/adapter_config.json", # 从HF仓库获取适配器配置文件
        model,
        revision,
    )
    if config_bytes is None:
        return None # 适配器不存在时返回None
​
    adapter_config = json.loads(config_bytes) # 解析JSON配置
​
    weights_bytes = get_hf_file_bytes(
        f"adapters/{task}/adapter_model.safetensors", # 获取适配器权重文件
        model,
        revision,
    )
    if weights_bytes is None:
        return None # 权重文件不存在时返回None
​
    adapter_weights = safetensors_load(weights_bytes) # 加载安全张量格式的权重
    return adapter_config, adapter_weights

关键符号

JinaEmbeddingsV5Model.__init__ _load_adapter _build_lora_pairs load_weights _merge_weights

评论区精华

load_weights 实现缺陷 正确性

gemini-code-assist[bot] 指出权重加载逻辑可能跳过非 self.model 属性中的权重,导致加载不完整,并建议使用 super().load_weights 和优化 LoRA 合并方法。

结论:作者应修复实现,采纳建议并优化代码。 · 已解决

文件合并建议 设计

noooop 建议将新增的 jina_embeddings_v5.py 和 test_jina_v5.py 合并到现有文件中,以减少文件数量,提升代码结构清晰度。

结论:作者采纳建议,合并了文件。 · 已解决

风险与影响

技术风险包括:1. 权重加载逻辑可能遗漏非self.model属性中的权重,导致模型参数不完整,影响推理正确性。2. LoRA适配器合并时的数值精度问题,可能引入微小误差。3. 测试覆盖依赖于预设的MTEB分数,若模型更新可能需调整分数。

对用户:现在可以直接使用vLLM部署jinaai/jina-embeddings-v5-text-small模型进行嵌入任务,支持检索、文本匹配、分类和聚类四种任务。对系统:扩展了vLLM的模型支持范围,新增了一个基于Qwen3的适配器合并模型。对团队:代码结构优化,合并了重复文件,减少了维护复杂度。

核心路径变更 权重加载缺陷 LoRA 合并精度

关联 Issue

#38633 [New Model]: JinaEmbeddingsV5Model

完整报告

执行摘要

本PR新增了对Jina Embeddings v5模型(jinaai/jina-embeddings-v5-text-small)的支持,通过实现一个基于Qwen3-0.6B-Base并合并任务特定LoRA适配器的模型类,解决了Issue #38633中报告的不支持问题。变更覆盖了模型实现、注册表、测试和文档,使用户能够通过vLLM直接部署该模型进行嵌入任务。

功能与动机

Issue #38633报告用户尝试部署jinaai/jina-embeddings-v5-text-small模型时,出现Model architectures ['JinaEmbeddingsV5Model'] are not supported错误,并提示需要peft包。PR body明确说明目的是添加该模型支持以修复此问题,使用户能够通过vLLM服务该模型,支持检索、文本匹配、分类和聚类四种任务。

实现拆解

  1. 新增模型实现:在vllm/model_executor/models/jina.py中新增JinaEmbeddingsV5Model类,继承自Qwen3ForCausalLM,并实现load_weights方法。添加辅助函数_load_adapter_build_lora_pairs,用于从Hugging Face仓库加载LoRA适配器配置和权重,并在加载时合并到基础权重中,避免运行时依赖peft。关键代码如下:
def _load_adapter(
    model: str,
    task: str,
    revision: str | None,
) -> tuple[dict, dict[str, torch.Tensor]] | None:
    """从本地路径或HF仓库加载适配器配置和权重。    返回 (adapter_config, adapter_weights) 或 None(如果未找到)。
    """
    config_bytes = get_hf_file_bytes(
        f"adapters/{task}/adapter_config.json", # 从HF仓库获取适配器配置文件
        model,
        revision,
    )
    if config_bytes is None:
        return None # 适配器不存在时返回None
​
    adapter_config = json.loads(config_bytes) # 解析JSON配置
​
    weights_bytes = get_hf_file_bytes(
        f"adapters/{task}/adapter_model.safetensors", # 获取适配器权重文件
        model,
        revision,
    )
    if weights_bytes is None:
        return None # 权重文件不存在时返回None
​
    adapter_weights = safetensors_load(weights_bytes) # 加载安全张量格式的权重
    return adapter_config, adapter_weights
  1. 注册模型:在vllm/model_executor/models/registry.py_EMBEDDING_MODELS字典中添加"JinaEmbeddingsV5Model": ("jina", "JinaEmbeddingsV5Model")条目,使系统能够识别该模型架构。
  2. 更新测试套件:在tests/models/language/pooling_mteb_test/test_jina.py中添加新模型的测试配置,包括MTEB分数和架构属性;修改tests/models/language/pooling_mteb_test/mteb_embed_utils.py,新增HfMtebEncoder类并扩展VllmMtebEncoder以支持提示前缀。测试配置示例如下:
EMBEDDING_MODELS = [
    EmbedModelInfo(
        "jinaai/jina-embeddings-v3",
        mteb_score=0.824413164,
        architecture="XLMRobertaModel",
        is_matryoshka=True,
        seq_pooling_type="MEAN",
        attn_type="encoder_only",
        is_prefix_caching_supported=False,
        is_chunked_prefill_supported=False,
    ),
    EmbedModelInfo( # 新增Jina v5模型测试配置
        "jinaai/jina-embeddings-v5-text-small",
        mteb_score=0.794535707854956,
        architecture="JinaEmbeddingsV5Model",
        seq_pooling_type="LAST",
        attn_type="decoder",
        is_prefix_caching_supported=True,
        is_chunked_prefill_supported=True,
    ),
]
  1. 配套调整:更新docs/models/pooling_models/embed.md文档,添加模型说明;修改tests/conftest.py中的HfRunner类,添加revision参数以支持模型版本控制。

关键源码片段

vllm/model_executor/models/jina.py

核心模型实现文件,新增了JinaEmbeddingsV5Model类和适配器加载逻辑,是实现变更的入口。

def _load_adapter(
    model: str,
    task: str,
    revision: str | None,
) -> tuple[dict, dict[str, torch.Tensor]] | None:
    """从本地路径或HF仓库加载适配器配置和权重。    返回 (adapter_config, adapter_weights) 或 None(如果未找到)。
    """
    config_bytes = get_hf_file_bytes(
        f"adapters/{task}/adapter_config.json", # 从HF仓库获取适配器配置文件
        model,
        revision,
    )
    if config_bytes is None:
        return None # 适配器不存在时返回None
​
    adapter_config = json.loads(config_bytes) # 解析JSON配置
​
    weights_bytes = get_hf_file_bytes(
        f"adapters/{task}/adapter_model.safetensors", # 获取适配器权重文件
        model,
        revision,
    )
    if weights_bytes is None:
        return None # 权重文件不存在时返回None
​
    adapter_weights = safetensors_load(weights_bytes) # 加载安全张量格式的权重
    return adapter_config, adapter_weights

评论区精华

  • 权重加载缺陷:gemini-code-assist[bot]指出load_weights实现可能跳过非self.model属性中的权重(如lm_head),建议使用super().load_weights并优化LoRA合并方法。作者最终采纳建议,修复了实现。

gemini-code-assist[bot]: “The load_weights implementation has several critical issues... By calling self.model.load_weights instead of super().load_weights, any weights defined in the JinaEmbeddingsV5Model... are skipped.”
- 文件合并优化:noooop建议将新增的jina_embeddings_v5.pytest_jina_v5.py合并到现有文件中,以减少文件数量。作者响应并执行了合并,提升了代码结构清晰度。

noooop: “Please merge this file with jina.py. There are already too many files in this folder; having one less file is always better.”

风险与影响

  • 技术风险:权重加载逻辑可能遗漏外部权重,导致模型参数不完整;LoRA适配器合并时可能引入数值精度误差;测试覆盖依赖于预设的MTEB分数,模型更新时可能需要调整。
  • 影响范围:对用户,现在可以直接部署Jina Embeddings v5模型进行嵌入任务;对系统,扩展了模型支持范围;对团队,代码结构优化减少了维护复杂度。

关联脉络

从近期历史PR看,本PR与#39747“Update registry for Nemotron-v3 VL Nano/Super”类似,都属于新增模型支持的功能扩展,反映了vLLM持续集成新模型的演进趋势。此外,Issue #38633直接关联,显示用户需求驱动了此变更。

参与讨论