Skip to content

speculators.models.utils

Functions:

flatten_rope_parameters

flatten_rope_parameters(
    config: PretrainedConfig,
) -> PretrainedConfig

Flatten nested per-layer-type rope_parameters for rotary embedding init.

Models like Laguna store separate rope configs per layer type (sliding_attention, full_attention). Rotary embedding classes expect a flat dict with rope_type/rope_theta at the top level. This helper selects the sliding_attention variant when nested parameters are detected and returns a deep-copied config; otherwise returns the original unchanged.

Source code in speculators/models/utils.py
def flatten_rope_parameters(config: PretrainedConfig) -> PretrainedConfig:
    """Flatten nested per-layer-type ``rope_parameters`` for rotary embedding init.

    Models like Laguna store separate rope configs per layer type
    (``sliding_attention``, ``full_attention``). Rotary embedding classes expect
    a flat dict with ``rope_type``/``rope_theta`` at the top level. This helper
    selects the ``sliding_attention`` variant when nested parameters are detected
    and returns a deep-copied config; otherwise returns the original unchanged.
    """
    rope_params = getattr(config, "rope_parameters", None)
    if not rope_params or "sliding_attention" not in rope_params:
        return config
    config = deepcopy(config)
    config.rope_parameters = rope_params["sliding_attention"]
    return config

resolve_draft_intermediate_size

resolve_draft_intermediate_size(
    verifier_config: PretrainedConfig,
) -> int

Resolve a dense draft MLP intermediate_size from a verifier config.

The draft is an independent small dense decoder, so its FFN width is a design choice rather than something to reconcile with the verifier's routed capacity:

  • Dense verifiers expose intermediate_size directly; the draft mirrors it.
  • MoE verifiers have no dense intermediate_size (their FFN is a routed set of small experts), so the draft falls back to the widely used 3 * hidden_size gated-MLP ratio -- the Qwen3 dense convention that the dflash draft decoder follows. Pass --draft-config to set it explicitly instead.

Raises:

  • ValueError –

    when the verifier config exposes neither intermediate_size nor hidden_size (degenerate config; pass --draft-config).

Source code in speculators/models/utils.py
def resolve_draft_intermediate_size(verifier_config: PretrainedConfig) -> int:
    """Resolve a dense draft MLP ``intermediate_size`` from a verifier config.

    The draft is an independent small *dense* decoder, so its FFN width is a design
    choice rather than something to reconcile with the verifier's routed capacity:

    * Dense verifiers expose ``intermediate_size`` directly; the draft mirrors it.
    * MoE verifiers have no dense ``intermediate_size`` (their FFN is a routed set of
      small experts), so the draft falls back to the widely used ``3 * hidden_size``
      gated-MLP ratio -- the Qwen3 dense convention that the dflash draft decoder
      follows. Pass ``--draft-config`` to set it explicitly instead.

    :raises ValueError: when the verifier config exposes neither ``intermediate_size``
        nor ``hidden_size`` (degenerate config; pass ``--draft-config``).
    """
    dense = getattr(verifier_config, "intermediate_size", None)
    if dense is not None:
        return int(dense)

    hidden_size = getattr(verifier_config, "hidden_size", None)
    if hidden_size is None:
        raise ValueError(
            "Verifier config exposes neither `intermediate_size` nor `hidden_size`, "
            "so a draft intermediate_size cannot be inferred. Pass --draft-config to "
            "set the draft architecture explicitly."
        )

    intermediate_size = 3 * int(hidden_size)
    warnings.warn(
        "Verifier config has no dense intermediate_size (likely MoE); using draft "
        f"intermediate_size={intermediate_size} (3 x hidden_size = {hidden_size}). "
        "Pass --draft-config to override.",
        stacklevel=3,
    )
    return intermediate_size

resolve_verifier_norm_class

resolve_verifier_norm_class(config) -> type

The RMSNorm class matching the verifier's final-norm weight convention.

The frozen verifier_norm must apply the same gain convention the verifier was trained under (x * (1 + w) for the Gemma/Qwen3.5 families, x * w otherwise), or the reconstructed verifier targets are silently mis-scaled.

Source code in speculators/models/utils.py
def resolve_verifier_norm_class(config) -> type:
    """The RMSNorm class matching the verifier's final-norm weight convention.

    The frozen ``verifier_norm`` must apply the same gain convention the
    verifier was trained under (`x * (1 + w)` for the Gemma/Qwen3.5
    families, `x * w` otherwise), or the reconstructed verifier targets
    are silently mis-scaled.
    """
    if uses_gemma_style_final_norm(config):
        return Gemma3RMSNorm
    return Qwen3RMSNorm

uses_gemma_style_final_norm

uses_gemma_style_final_norm(config) -> bool

Whether the verifier's final norm applies gain 1 + w (not w).

Source code in speculators/models/utils.py
def uses_gemma_style_final_norm(config) -> bool:
    """Whether the verifier's final norm applies gain ``1 + w`` (not ``w``)."""
    verifier = getattr(getattr(config, "speculators_config", None), "verifier", None)
    name_or_path = getattr(verifier, "name_or_path", None)
    if not name_or_path:
        return False
    model_type = _verifier_model_type(name_or_path)
    return model_type is not None and model_type in GEMMA_STYLE_FINAL_NORM_MODEL_TYPES