[Bug]: Dynamic NTK RoPE scaling is wrong

用户在 vLLM 推理框架中加载 nomic-embed-text-v1 等嵌入模型时触发问题。该模型官方支持 8192 上下文长度,但 vLLM 仅支持 2048。问题源于 vLLM 中 DynamicNTKScalingRotaryEmbedding 实现的计算公式错误。可能受影响的范围包括所有

[Bug]: Dynamic NTK RoPE scaling is wrong

[Bug]: Dynamic NTK RoPE scaling is wrong

快速结论:该报错通常发生在使用 vLLM 加载依赖 Dynamic NTK RoPE scaling 的模型(如 nomic-ai/nomic-embed-text-v1)时,因实现公式错误导致计算结果与预期不符,进而影响长上下文支持。优先排查 vLLM 版本是否已包含修复(PR #41277)。

问题场景

用户在 vLLM 推理框架中加载 nomic-embed-text-v1 等嵌入模型时触发问题。该模型官方支持 8192 上下文长度,但 vLLM 仅支持 2048。问题源于 vLLM 中 DynamicNTKScalingRotaryEmbedding 实现的计算公式错误。可能受影响的范围包括所有依赖 Dynamic NTK scaling 的模型(如 NomicBert、Snowflake Arctic-embed 系列)。

报错原文

Bug: Dynamic NTK RoPE scaling is wrong
The original formula: (α * current sequence length / original model context length) - (α - 1)
Current vLLM implementation (dynamic_ntk_scaling_rope.py):
    max_len = self.max_position_embeddings * self.scaling_factor
    base = self.base * (
        (self.scaling_factor * max_len / self.max_position_embeddings)
        - (self.scaling_factor - 1)
    )
Substituted: (α * α) - (α - 1)  →  constant, independent of sequence length

原因分析

vLLM 中 DynamicNTKScalingRotaryEmbedding 的实现错误地将原始公式中的 max_len 定义带入,导致计算出的 base 值变为仅与 scaling_factor (α) 相关的常量,完全不受当前序列长度影响。根据原始论文和社区参考实现(如 Reddit 讨论、arxiv 2402.01613),正确公式应在序列长度变化时动态调整 base,而 vLLM 的实现将其“固化”了。

此错误对短序列(序列长度 ≤ max_position_embeddings)影响较小(可能只导致 2048)时,错误公式会产生错误的旋转频率,从而阻止模型正确利用长上下文能力。

环境排查

  • vLLM 版本:确认是否 < 0.4.0(或已包含 PR #41277 修复的版本)。
  • 模型配置:检查模型中 rope_scaling 的类型是否为 dynamic,以及 rope_thetascaling_factor 的值。
  • 参考实现:对比 HuggingFace 参考实现中的公式(如 modeling_hf_nomic_bert.py 第639行、1413行),确认其使用 seqlen 而非 max_len 参与计算。

解决步骤

  1. 升级 vLLM:将 vLLM 更新至包含 PR #41277 修复的版本(该 PR 已合并并固定此问题)。
  2. 手动补丁(临时方案):编辑 vllm/model_executor/layers/rotary_embedding/dynamic_ntk_scaling_rope.py,将公式修正为:
    base = self.base * (
        (self.scaling_factor * seqlen / self.max_position_embeddings) - (self.scaling_factor - 1)
    ) ** (self.dim / (self.dim - 2))

    并移除对 max_len = self.max_position_embeddings * self.scaling_factor 的依赖。

  3. 若使用 nomic-embed-text-v1:注意 vLLM 当前并未对 NomicBert 模型使用 DynamicNTKScalingRotaryEmbedding,而是使用 NomicBertRotaryEmbedding(仅在上下文扩展时切换到 NomicBertDynamicNTKRotaryEmbedding)。如果用户遇到 8K 上下文支持问题,建议先用 sentence-transformers 的参考代码验证模型本身对长上下文的支持。

验证方法

使用超过 2048 token 的输入序列测试 nomic-embed-text-v1 模型,比较原始 vLLM 和修复后版本生成的 embedding 差异。正确实现应能处理更长上下文并产生与论文一致的 embedding;错误实现则无法利用动态缩放,导致长序列性能退化。可运行 MTEB 基准测试对比原始上下文长度(2048)和扩展上下文(8192)的结果。

参考来源

vllm-project/vllm #41236(原始 Issue)

vllm-project/vllm PR #41277(修复 PR)

HuggingFace NomicBert 参考实现(正确公式)

GamsGo AI

AI 工具推荐

想把多个 AI 模型放在一个入口?

GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。

了解 GamsGo AI

推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。

celebrityanime
celebrityanime
文章: 10504

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注