Skip to content

vllm_omni.diffusion.models.lance.lance_transformer

Lance transformer pieces.

The Lance LLM is BAGEL's Qwen2-MoT transformer verbatim — the released Lance_3B checkpoint uses the identical *_moe_gen / q_norm / vae2llm / llm2vae / time_embedder / latent_pos_embed layout, so Bagel / Qwen2MoTForCausalLM / Qwen2MoTConfig / NaiveCache are re-exported unchanged. Only the understanding ViT differs (Qwen2.5-VL vision instead of SigLIP) and the video path adds a 3D latent position embedding.

This module also provides :class:LanceBagel, a thin :class:Bagel subclass that overrides the two ViT entry points to consume Qwen2.5-VL's packed pixel_values + image_grid_thw layout directly (BAGEL itself assumes SigLIP-style (C, H, W) tensors that get patchified inside the model).

NOTE ON mRoPE: Lance's backbone is Qwen2.5-VL and its understanding / video paths use multimodal RoPE (mrope_section=[16,24,24]). BAGEL's BagelRotaryEmbedding is plain 1-D RoPE on scalar position ids. For the text2img generation path Lance assigns scalar positions (the gen latent block shares a single rope position, same as BAGEL), so the reused rotary is correct there. Full mRoPE for the x2t / video understanding path is a follow-up — see LancePositionEmbedding3D.

LANCE_SECONDS_PER_GRID module-attribute

LANCE_SECONDS_PER_GRID = 1.0

LANCE_TOKENS_PER_SECOND module-attribute

LANCE_TOKENS_PER_SECOND = 2

LANCE_VIDEO_BUCKET_STRIDE module-attribute

LANCE_VIDEO_BUCKET_STRIDE = 16

LANCE_VIDEO_MAX_DURATION module-attribute

LANCE_VIDEO_MAX_DURATION = 6.0

LANCE_VIDEO_SAMPLE_FPS module-attribute

LANCE_VIDEO_SAMPLE_FPS = 12

LANCE_VIDEO_TEMPORAL_STRIDE module-attribute

LANCE_VIDEO_TEMPORAL_STRIDE = 4

LANCE_VIDEO_VAE_DIVISIBLE_CROP module-attribute

LANCE_VIDEO_VAE_DIVISIBLE_CROP = 16

LANCE_VIDEO_VAE_RESOLUTION module-attribute

LANCE_VIDEO_VAE_RESOLUTION = 640

LANCE_VIDEO_VIT_DIVISIBLE_CROP module-attribute

LANCE_VIDEO_VIT_DIVISIBLE_CROP = 28

LANCE_VIDEO_VIT_RESOLUTION module-attribute

LANCE_VIDEO_VIT_RESOLUTION = 616

LANCE_VIT_ASPECT_RATIOS module-attribute

LANCE_VIT_ASPECT_RATIOS = (
    "21:9",
    "16:9",
    "4:3",
    "1:1",
    "3:4",
    "9:16",
)

LANCE_VIT_BUCKET_RESOLUTION module-attribute

LANCE_VIT_BUCKET_RESOLUTION = 672

LANCE_VIT_BUCKET_STRIDE module-attribute

LANCE_VIT_BUCKET_STRIDE = 16

LANCE_VIT_DIVISIBLE_CROP module-attribute

LANCE_VIT_DIVISIBLE_CROP = 28

LANCE_VIT_NORM_MEAN module-attribute

LANCE_VIT_NORM_MEAN = (0.48145466, 0.4578275, 0.40821073)

LANCE_VIT_NORM_STD module-attribute

LANCE_VIT_NORM_STD = (0.26862954, 0.26130258, 0.27577711)

LANCE_VIT_PATCH_SIZE module-attribute

LANCE_VIT_PATCH_SIZE = 14

LANCE_VIT_SPATIAL_MERGE module-attribute

LANCE_VIT_SPATIAL_MERGE = 2

LANCE_VIT_TEMPORAL_PATCH_SIZE module-attribute

LANCE_VIT_TEMPORAL_PATCH_SIZE = 2

Bagel

Bases: CFGParallelMixin, Module

base_model_prefix class-attribute instance-attribute

base_model_prefix = 'bagel'

config instance-attribute

config = config

config_class class-attribute instance-attribute

config_class = BagelConfig

connector instance-attribute

connector = MLPconnector(
    self.vit_hidden_size,
    self.hidden_size,
    config.connector_act,
    quant_config=quant_config,
    prefix=f"{prefix}.connector",
)

get_flattened_position_ids instance-attribute

get_flattened_position_ids = (
    get_flattened_position_ids_extrapolate
)

hidden_size instance-attribute

hidden_size = config.llm_config.hidden_size

language_model instance-attribute

language_model = language_model

latent_channel instance-attribute

latent_channel = config.vae_config.z_channels

latent_downsample instance-attribute

latent_downsample = (
    config.vae_config.downsample * config.latent_patch_size
)

latent_patch_size instance-attribute

latent_patch_size = config.latent_patch_size

latent_pos_embed instance-attribute

latent_pos_embed = PositionEmbedding(
    self.max_latent_size, self.hidden_size
)

llm2vae instance-attribute

llm2vae = nn.Linear(
    self.hidden_size, self.patch_latent_dim
)

max_latent_size instance-attribute

max_latent_size = config.max_latent_size

num_heads instance-attribute

num_heads = config.llm_config.num_attention_heads

parallel_config instance-attribute

parallel_config = parallel_config

patch_latent_dim instance-attribute

patch_latent_dim = (
    self.latent_patch_size**2 * self.latent_channel
)

time_embedder instance-attribute

time_embedder = TimestepEmbedder(self.hidden_size)

timestep_shift instance-attribute

timestep_shift = config.timestep_shift

use_moe instance-attribute

use_moe = 'Mo' in config.llm_config.layer_module

vae2llm instance-attribute

vae2llm = nn.Linear(
    self.patch_latent_dim, self.hidden_size
)

vit_hidden_size instance-attribute

vit_hidden_size = config.vit_config.hidden_size

vit_max_num_patch_per_side instance-attribute

vit_max_num_patch_per_side = (
    config.vit_max_num_patch_per_side
)

vit_model instance-attribute

vit_model = vit_model

vit_patch_size instance-attribute

vit_patch_size = config.vit_config.patch_size

vit_pos_embed instance-attribute

vit_pos_embed = PositionEmbedding(
    self.vit_max_num_patch_per_side, self.hidden_size
)

combine_multi_branch_cfg_noise

combine_multi_branch_cfg_noise(
    predictions: list[Tensor],
    true_cfg_scale: dict[str, Any],
    cfg_normalize: bool = False,
) -> Tensor

Combine gen/text/img branch velocities via Bagel's renorm CFG.

predictions[0] is the gen branch, [1] the text-CFG branch, and [2] (when present) the image-CFG branch. cfg_normalize is unused because renormalization is folded into _combine_cfg itself.

forward

forward(
    x_t: Tensor,
    timestep: Tensor,
    packed_vae_token_indexes: LongTensor,
    packed_vae_position_ids: LongTensor,
    packed_text_ids: LongTensor,
    packed_text_indexes: LongTensor,
    packed_position_ids: LongTensor,
    packed_seqlens: IntTensor,
    past_key_values: NaiveCache,
    cfg_renorm_min: float = 0.0,
    cfg_renorm_type: str = "global",
    cfg_text_scale: float = 1.0,
    cfg_img_scale: float = 1.0,
    cfg_branch_pids: list[Tensor] | None = None,
    cfg_branch_caches: list[NaiveCache] | None = None,
    cfg_vae_lengths: list[int] | None = None,
    cfg_text_scales: list[float] | None = None,
    cfg_img_scales: list[float] | None = None,
)

forward_cache_update_text

forward_cache_update_text(
    past_key_values: NaiveCache,
    packed_text_ids: IntTensor,
    packed_text_position_ids: LongTensor,
    text_token_lens: LongTensor,
)

forward_cache_update_vae

forward_cache_update_vae(
    vae_model,
    past_key_values: NaiveCache,
    padded_images: Tensor,
    patchified_vae_latent_shapes: list,
    packed_vae_position_ids: LongTensor,
    packed_timesteps: Tensor,
    packed_vae_token_indexes: LongTensor,
    packed_text_ids: LongTensor,
    packed_text_indexes: LongTensor,
    packed_position_ids: LongTensor,
    packed_seqlens: IntTensor,
)

forward_cache_update_vit

forward_cache_update_vit(
    past_key_values: NaiveCache,
    packed_text_ids: LongTensor,
    packed_text_indexes: LongTensor,
    packed_vit_tokens: Tensor,
    packed_vit_token_indexes: LongTensor,
    packed_vit_position_ids: LongTensor,
    vit_token_seqlens: IntTensor,
    packed_position_ids: LongTensor,
    packed_seqlens: IntTensor,
)

forward_single_branch

forward_single_branch(
    x_t: Tensor,
    timestep: Tensor,
    packed_vae_token_indexes: LongTensor,
    packed_vae_position_ids: LongTensor,
    packed_text_ids: LongTensor,
    packed_text_indexes: LongTensor,
    packed_position_ids: LongTensor,
    packed_seqlens: IntTensor,
    past_key_values: NaiveCache,
) -> Tensor

Run a single-branch forward pass (no CFG batching).

Used by CFG parallel mode where each rank computes one branch. Returns the velocity v_t for the given branch. Supports Ulysses / Ring SP when parallel_config.sequence_parallel_size > 1.

generate_image

generate_image(
    packed_text_ids: LongTensor,
    packed_text_indexes: LongTensor,
    packed_init_noises: Tensor,
    packed_vae_position_ids: LongTensor,
    packed_vae_token_indexes: LongTensor,
    packed_seqlens: IntTensor,
    packed_position_ids: LongTensor,
    past_key_values: NaiveCache,
    num_timesteps: int = 24,
    timestep_shift: float = 1.0,
    cfg_renorm_min: float = 0.0,
    cfg_renorm_type: str = "global",
    cfg_interval: tuple[float, float] = [0, 1],
    cfg_text_scale: float = 1.0,
    cfg_text_packed_position_ids: LongTensor | None = None,
    cfg_text_past_key_values: NaiveCache | None = None,
    cfg_img_scale: float = 1.0,
    cfg_img_packed_position_ids: LongTensor | None = None,
    cfg_img_past_key_values: NaiveCache | None = None,
    return_trajectory_latents: bool = False,
    scheduler: object | None = None,
    scheduler_kwargs: dict | None = None,
    frame_condition_token_indexes: LongTensor | None = None,
)

generate_text

generate_text(
    past_key_values: NaiveCache,
    packed_start_tokens: LongTensor,
    packed_query_position_ids: LongTensor,
    max_length: int,
    do_sample: bool = False,
    temperature: float = 1.0,
    end_token_id: int | None = None,
)

Autoregressive text generation (ported from original BAGEL).

Decodes tokens one at a time, appending to past_key_values until max_length is reached or end_token_id is generated.

predict_noise

predict_noise(**kwargs) -> Tensor

Single-branch velocity prediction for CFGParallelMixin.

Each CFG branch differs only by packed_position_ids and past_key_values (carried in kwargs); the heavy lifting is the per-branch forward_single_branch pass.

prepare_denoise_schedule

prepare_denoise_schedule(
    x_t: Tensor, num_timesteps: int, timestep_shift: float
) -> tuple[Tensor, Tensor]

Build BAGEL's flow-matching timesteps and per-step deltas.

prepare_input

prepare_input(
    curr_kvlens, curr_rope, image_sizes, new_token_ids=None
)

prepare_prompts

prepare_prompts(
    curr_kvlens,
    curr_rope,
    prompts,
    tokenizer,
    new_token_ids,
)

prepare_start_tokens

prepare_start_tokens(curr_kvlens, curr_rope, new_token_ids)

Prepare start tokens for autoregressive text generation.

Ported from the original BAGEL Bagel.prepare_start_tokens.

prepare_vae_images

prepare_vae_images(
    curr_kvlens,
    curr_rope,
    images,
    transforms,
    new_token_ids,
    timestep=0,
)

prepare_vae_latent

prepare_vae_latent(
    curr_kvlens, curr_rope, image_sizes, new_token_ids
)

prepare_vae_latent_cfg

prepare_vae_latent_cfg(curr_kvlens, curr_rope, image_sizes)

prepare_vit_images

prepare_vit_images(
    curr_kvlens,
    curr_rope,
    images,
    transforms,
    new_token_ids,
)

BaseNavitOutputWithPast dataclass

Bases: ModelOutput

packed_query_sequence class-attribute instance-attribute

packed_query_sequence: FloatTensor = None

past_key_values class-attribute instance-attribute

past_key_values: NaiveCache | None = None

LanceBagel

Bases: Bagel

Bagel subclass with Lance-specific ViT handling.

The released Lance checkpoint pairs BAGEL's Qwen2-MoT trunk with the Qwen2.5-VL vision tower (whose merger already projects to LLM hidden_size and which carries its own rotary positional encoding). Two BAGEL assumptions therefore break for Lance:

  1. prepare_vit_images calls transforms(image) -> (C, H, W) and then patchify(...); Lance's image processor returns (num_patches_flat, patch_features) + image_grid_thw already.
  2. forward_cache_update_vit adds a connector projection plus a 2-D vit_pos_embed that has no checkpoint weights and would also double-count the ViT's own positional encoding.

This subclass overrides exactly those two methods. Everything else — LLM trunk, VAE flow, generation loop, forward_cache_update_text / forward_cache_update_vae — is reused unchanged.

forward_cache_update_vae

forward_cache_update_vae(
    vae_model,
    past_key_values,
    padded_images=None,
    patchified_vae_latent_shapes=None,
    packed_vae_position_ids=None,
    packed_timesteps=None,
    packed_vae_token_indexes=None,
    packed_text_ids=None,
    packed_text_indexes=None,
    packed_position_ids=None,
    packed_seqlens=None,
    packed_indexes=None,
    key_values_lens=None,
    packed_key_value_indexes=None,
    precomputed_latent=None,
)

Lance-native VAE prefill that actually scatters the encoded latents into the LLM query sequence.

:meth:Bagel.forward_cache_update_vae in vllm-omni computes packed_latent = vae2llm(...) + time_embed + pos_embed and then passes only packed_text_ids to the LLM — the VAE embeddings never enter the query sequence (the LLM builds it from embed_tokens(packed_text_ids) which is just the 2 framing tokens). The mismatch between query_lens = [num_vae + 2] and the resulting 2-token sequence is what crashes the gather inside attention.

We scatter both pieces explicitly: text framing tokens at packed_text_indexes and the VAE latent embeddings at packed_vae_token_indexes, producing a full-length (sum(packed_seqlens), hidden) sequence the LLM can attend over. Empty prep data (legacy x2t / x2t_video no-op path) is short-circuited.

forward_cache_update_vit

forward_cache_update_vit(*args, **kwargs)

prepare_prompts

prepare_prompts(*args, **kwargs)

prepare_start_tokens

prepare_start_tokens(*args, **kwargs)

prepare_vae_images

prepare_vae_images(
    curr_kvlens,
    curr_rope,
    images,
    transforms,
    new_token_ids,
    timestep=0,
)

VAE prefill router.

  • When images is non-empty (image_edit / video_edit path on the image side): delegate to :meth:_lance_native_prepare_vae_images which emits Lance's 3-D mRoPE positions and a real VAE prefill, letting BAGEL's parent image_edit flow handle the rest.
  • When images is empty (t2i / x2t paths): short-circuit with the no-op output, mirroring BAGEL's "no image to prefill" sentinel.

prepare_vae_latent

prepare_vae_latent(
    curr_kvlens, curr_rope, image_sizes, new_token_ids
)

prepare_vae_latent_cfg

prepare_vae_latent_cfg(curr_kvlens, curr_rope, image_sizes)

prepare_video_latent

prepare_video_latent(
    curr_kvlens, curr_rope, video_shapes, new_token_ids
)

3-D analogue of :meth:prepare_vae_latent.

video_shapes is a list of (T, H, W) per request (RGB pixel space). We package one packed-init-noise tensor over T_lat × H_lat × W_lat latent tokens per video, plus 1-D indices into the 3-D position embedding table maintained by :class:LancePositionEmbedding3D (bagel.latent_pos_embed). Latent geometry:

  • spatial: H_lat = H // latent_downsample (=16 for Lance)
  • temporal: T_lat = (T - 1) // downsample_temporal + 1 (=4 for Wan2.2)
  • channels: latent_channel = 48

Position ids are flattened t * max_per_side² + h * max_per_side + w so they index directly into the (max_num_frames * max_per_side², hidden_size) table.

prepare_video_latent_cfg

prepare_video_latent_cfg(
    curr_kvlens, curr_rope, video_shapes
)

3-D analogue of :meth:prepare_vae_latent_cfg (CFG side).

Mirrors :meth:prepare_video_latent's mRoPE 3-D position layout EXACTLY, including the LANCE_TOKENS_PER_SECOND * LANCE_SECONDS_PER_GRID temporal scaling. Without that scaling, the cfg_text branch attends with different rope coordinates than the cond branch (and than upstream's get_rope_index), which makes cfg_text_v_t diverge from upstream and the CFG combination amplifies the error every denoise step.

prepare_vit_images

prepare_vit_images(
    curr_kvlens,
    curr_rope,
    images,
    transforms,
    new_token_ids,
)

prepare_vit_videos

prepare_vit_videos(
    curr_kvlens,
    curr_rope,
    videos,
    new_token_ids,
    precomputed_vit=None,
)

Multi-frame ViT prefill for the x2t_video / video_edit paths.

videos is a list of per-request video tensors / numpy arrays of shape (T, H, W, 3). By default the Qwen2-VL video processor is used to convert each video to (pixel_values_videos, video_grid_thw). For video_edit precision matching, the pipeline may pre-compute the upstream-style BucketResize output and pass it via precomputed_vit — a list of (pixel_values, grid_thw) per video, in which case the processor call is skipped.

LanceIdentityConnector

Bases: Module

No-op connector for Lance.

BAGEL's connector projects the ViT hidden size to the LLM hidden size. Qwen2.5-VL's vision tower (which Lance uses) already projects to the LLM hidden size internally via merger (out_hidden_size = hidden_size), and the released Lance safetensors carry no connector.* weights. We therefore plug in an Identity connector so forward_cache_update_vit keeps its existing call site without a separate code path.

forward

forward(x: Tensor) -> Tensor

LancePositionEmbedding3D

Bases: Module

Frozen 3-D sin-cos latent position embedding for the video path.

BAGEL only ships a 2-D PositionEmbedding (image latents). Lance's Lance_3B_Video checkpoint adds a temporal axis; this mirrors upstream modeling/lance/modeling_utils.py::PositionEmbedding3D. The image path uses t=1 and is numerically equivalent to the 2-D embedding.

hidden_size instance-attribute

hidden_size = hidden_size

max_num_frames instance-attribute

max_num_frames = max_num_frames

max_num_patch_per_side instance-attribute

max_num_patch_per_side = max_num_patch_per_side

pos_embed instance-attribute

pos_embed = nn.Parameter(
    torch.zeros(n, hidden_size), requires_grad=False
)

forward

forward(position_ids: Tensor) -> Tensor

LanceQwen2_5_VLNaViTWrapper

Bases: Module

Packed (NaViT-style) wrapper around the Qwen2.5-VL vision tower.

Bridges BAGEL's vit(packed_pixel_values, ...) -> [num_tokens, vit_hidden] surface to the HF Qwen2_5_VisionTransformerPretrainedModel which consumes (hidden_states, grid_thw). The packed call additionally needs a per-image image_grid_thw so non-square images (and the spatial-merge token count) line up — :class:LanceBagel stashes the grid on the wrapper before invoking the ViT.

config property

config

spatial_merge_size instance-attribute

spatial_merge_size = spatial_merge_size

vision_model instance-attribute

vision_model = getattr(vision_model, "visual", vision_model)

forward

forward(
    packed_pixel_values: Tensor,
    packed_flattened_position_ids: Tensor,
    cu_seqlens: Tensor,
    max_seqlen: int,
) -> Tensor

set_pending_grid_thw

set_pending_grid_thw(grid_thw: Tensor) -> None

LanceZeroVitPosEmbed

Bases: Module

No-op positional embedding for Lance's ViT tokens.

BAGEL adds an extra 2-D sin-cos vit_pos_embed on top of the ViT output. Qwen2.5-VL's vision tower already carries its own (rotary) positional encoding, and the released Lance safetensors carry no vit_pos_embed.* weights. This module returns a broadcast-friendly zero so the addition in forward_cache_update_vit is a no-op without requiring a code-path branch.

forward

forward(position_ids: Tensor) -> Tensor

MLPconnector

Bases: Module

act instance-attribute

act = nn.GELU()

fc1 instance-attribute

fc1 = ColumnParallelLinear(
    input_dim,
    output_dim,
    bias=True,
    gather_output=False,
    quant_config=quant_config,
    prefix=f"{prefix}.fc1",
)

fc2 instance-attribute

fc2 = RowParallelLinear(
    output_dim,
    output_dim,
    bias=True,
    input_is_parallel=True,
    quant_config=quant_config,
    prefix=f"{prefix}.fc2",
)

forward

forward(x)

NaiveCache

key_cache instance-attribute

key_cache = {k: None for k in range(num_layers)}

key_values_lens instance-attribute

key_values_lens: list[int] | None = None

num_layers property

num_layers

seq_lens property

seq_lens

value_cache instance-attribute

value_cache = {k: None for k in range(num_layers)}

from_object classmethod

from_object(obj) -> NaiveCache

Convert a duck-typed cache (e.g., SimpleNamespace from KV transfer) to NaiveCache; in the future, we should find a better way to handle this, e.g., a model agnostic abstraction for key cache transfer instead of having this cache live in bagel.

NOTE: If a NaiveCache is provided, the object is just returned. Otherwise, we enumerate over the key/value cache values and map layer indices to the corresponding tensors.

merge staticmethod

merge(caches: Sequence[NaiveCache]) -> NaiveCache

Merge NaiveCaches into one for packed request/CFG attention.

Already-merged inputs keep their per-sequence lengths so nested request-by-CFG packing can split cache rows back out correctly.

split_with_zeros staticmethod

split_with_zeros(
    tensor: Tensor, lengths: Sequence[int]
) -> list[Tensor | None]

Split tensor by lengths, which may include 0 entries, e.g., for splitting cfg branches out, since text_cfg may have 0 kv length.

0 lengths will be replaced with None in the returned list.

PackedAttentionMoT

Bases: Module

Packed attention with Mixture-of-Tokens routing for understanding/generation.

Uses MoTQKVParallelLinear and MoTRowParallelLinear for tensor parallelism. Text and vae weights are held within the same MoT layer (text on self, vae on self.gen_exp). Token routing is driven by text_indices / vae_indices.

attn_causal instance-attribute

attn_causal = DiffusionAttention(
    num_heads=self.total_num_heads,
    head_size=self.head_dim,
    softmax_scale=1.0 / self.head_dim**0.5,
    causal=True,
    num_kv_heads=self.total_num_kv_heads,
)

attn_noncausal instance-attribute

attn_noncausal = DiffusionAttention(
    num_heads=self.total_num_heads,
    head_size=self.head_dim,
    softmax_scale=1.0 / self.head_dim**0.5,
    causal=False,
    num_kv_heads=self.total_num_kv_heads,
)

head_dim instance-attribute

head_dim = self.hidden_size // self.total_num_heads

hidden_size instance-attribute

hidden_size = config.hidden_size

k_norm instance-attribute

k_norm = MoTRMSNorm(
    self.head_dim, head_norm=True, eps=config.rms_norm_eps
)

kv_size instance-attribute

kv_size = self.num_kv_heads * self.head_dim

layer_idx instance-attribute

layer_idx = layer_idx

num_heads instance-attribute

num_heads = self.total_num_heads // tp_size

num_kv_heads instance-attribute

num_kv_heads = max(1, self.total_num_kv_heads // tp_size)

o_proj instance-attribute

o_proj = MoTRowParallelLinear(
    input_size=self.total_num_heads * self.head_dim,
    output_size=self.hidden_size,
    bias=False,
    quant_config=quant_config,
    prefix=f"{prefix}.o_proj",
)

parallel_config instance-attribute

parallel_config = parallel_config

q_norm instance-attribute

q_norm = MoTRMSNorm(
    self.head_dim, head_norm=True, eps=config.rms_norm_eps
)

q_size instance-attribute

q_size = self.num_heads * self.head_dim

qkv_proj instance-attribute

qkv_proj = MoTQKVParallelLinear(
    self.hidden_size,
    self.head_dim,
    self.total_num_heads,
    self.total_num_kv_heads,
    bias=True,
    vae_bias=True,
    quant_config=quant_config,
    prefix=f"{prefix}.qkv_proj",
)

rotary_op instance-attribute

rotary_op = RotaryEmbedding(is_neox_style=True)

total_num_heads instance-attribute

total_num_heads = config.num_attention_heads

total_num_kv_heads instance-attribute

total_num_kv_heads = config.num_key_value_heads

forward

forward(
    packed_query_sequence: Tensor,
    query_lens: Tensor,
    packed_query_position_embeddings: Tensor,
    past_key_values: NaiveCache | None = None,
    update_past_key_values=True,
    is_causal=True,
    mode="und",
    packed_vae_token_indexes=None,
    packed_text_indexes=None,
)

PositionEmbedding

Bases: Module

hidden_size instance-attribute

hidden_size = hidden_size

max_num_patch_per_side instance-attribute

max_num_patch_per_side = max_num_patch_per_side

pos_embed instance-attribute

pos_embed = nn.Parameter(
    torch.zeros(max_num_patch_per_side**2, hidden_size),
    requires_grad=False,
)

forward

forward(position_ids)

Qwen2MoTConfig

Bases: Qwen2Config

Configuration for Qwen2MoT (Mixture of Tokens) model.

This is fundamentally different from Qwen2, hence the distinct name.

keys_to_ignore_at_inference class-attribute instance-attribute

keys_to_ignore_at_inference = ['past_key_values']

layer_module instance-attribute

layer_module = layer_module

model_type class-attribute instance-attribute

model_type = 'qwen2_mot'

qk_norm instance-attribute

qk_norm = qk_norm

Qwen2MoTDecoderLayer

Bases: Module

hidden_size instance-attribute

hidden_size = config.hidden_size

input_layernorm instance-attribute

input_layernorm = MoTRMSNorm(
    config.hidden_size, eps=config.rms_norm_eps
)

layer_idx instance-attribute

layer_idx = layer_idx

mlp instance-attribute

mlp = BagelMLP(
    config.hidden_size,
    config.intermediate_size,
    config.hidden_act,
    quant_config=quant_config,
    prefix=f"{prefix}.mlp",
)

mlp_moe_gen instance-attribute

mlp_moe_gen = BagelMLP(
    config.hidden_size,
    config.intermediate_size,
    config.hidden_act,
    quant_config=quant_config,
    prefix=f"{prefix}.mlp_moe_gen",
)

post_attention_layernorm instance-attribute

post_attention_layernorm = MoTRMSNorm(
    config.hidden_size, eps=config.rms_norm_eps
)

self_attn instance-attribute

self_attn = attn_module(
    config,
    layer_idx,
    parallel_config=parallel_config,
    quant_config=quant_config,
    prefix=f"{prefix}.self_attn",
)

forward

forward(
    hidden_states: Tensor,
    encoder_hidden_states: Tensor | None = None,
    packed_query_sequence: Tensor | None = None,
    query_lens: Tensor = None,
    packed_query_position_embeddings: Tensor = None,
    past_key_values: NaiveCache | None = None,
    update_past_key_values=True,
    is_causal=True,
    mode="und",
    packed_vae_token_indexes=None,
    packed_text_indexes=None,
) -> BaseNavitOutputWithPast

Qwen2MoTForCausalLM

Bases: Qwen2PreTrainedModel

lm_head instance-attribute

lm_head = nn.Linear(
    config.hidden_size, config.vocab_size, bias=False
)

model instance-attribute

model = Qwen2MoTModel(
    config,
    parallel_config=parallel_config,
    quant_config=quant_config,
    prefix=f"{prefix}.model",
)

vocab_size instance-attribute

vocab_size = config.vocab_size

forward

forward(
    packed_query_sequence: Tensor | None = None,
    query_lens: Tensor | None = None,
    packed_query_position_ids: Tensor | None = None,
    past_key_values: NaiveCache | None = None,
    update_past_key_values=True,
    is_causal=True,
    mode="und",
    packed_vae_token_indexes=None,
    packed_text_indexes=None,
    packed_text_ids: Tensor | None = None,
    return_embeddings_only: bool = False,
) -> BaseNavitOutputWithPast

get_decoder

get_decoder()

get_input_embeddings

get_input_embeddings()

get_output_embeddings

get_output_embeddings()

load_weights

load_weights(
    weights: Iterable[tuple[str, Tensor]],
) -> set[str]

Load weights for MoT parallel layers.

Stacked parameter remapping (checkpoint name → model parameter): - q/k/v_proj → qkv_proj (text, shard q/k/v) - q/k/v_proj_moe_gen → qkv_proj.gen_exp (gen, shard q/k/v)

Direct remapping (no shard dimension): - o_proj_moe_gen → o_proj.gen_exp - {norm}_moe_gen.weight → {norm}.gen_weight (all MoTRMSNorm layers)

Text norm weights (input_layernorm.weight, q_norm.weight, etc.) and other names (embed_tokens, lm_head) pass through unchanged.

set_decoder

set_decoder(decoder)

set_input_embeddings

set_input_embeddings(value)

set_output_embeddings

set_output_embeddings(new_embeddings)

Qwen2MoTModel

Bases: Qwen2PreTrainedModel

embed_tokens instance-attribute

embed_tokens = VocabParallelEmbedding(
    config.vocab_size, config.hidden_size
)

layers instance-attribute

layers = nn.ModuleList(
    [
        Qwen2MoTDecoderLayer(
            config,
            layer_idx,
            attn_module=PackedAttentionMoT,
            parallel_config=parallel_config,
            quant_config=quant_config,
            prefix=f"{prefix}.layers.{layer_idx}",
        )
        for layer_idx in range(config.num_hidden_layers)
    ]
)

norm instance-attribute

norm = MoTRMSNorm(
    config.hidden_size, eps=config.rms_norm_eps
)

padding_idx instance-attribute

padding_idx = config.pad_token_id

rotary_emb instance-attribute

rotary_emb = BagelRotaryEmbedding(config=config)

use_moe instance-attribute

use_moe = 'Mo' in config.layer_module

vocab_size instance-attribute

vocab_size = config.vocab_size

forward

forward(
    packed_query_sequence: Tensor | None = None,
    query_lens: Tensor | None = None,
    packed_query_position_ids: Tensor | None = None,
    past_key_values: NaiveCache | None = None,
    update_past_key_values=True,
    is_causal=True,
    mode="und",
    packed_vae_token_indexes=None,
    packed_text_indexes=None,
    packed_text_ids: Tensor | None = None,
    return_embeddings_only: bool = False,
) -> BaseNavitOutputWithPast

TimestepEmbedder

Bases: Module

Embeds scalar timesteps into vector representations.

frequency_embedding_size instance-attribute

frequency_embedding_size = frequency_embedding_size

mlp instance-attribute

mlp = nn.Sequential(
    nn.Linear(
        frequency_embedding_size, hidden_size, bias=True
    ),
    nn.SiLU(),
    nn.Linear(hidden_size, hidden_size, bias=True),
)

forward

forward(t)

get_3d_sincos_pos_embed

get_3d_sincos_pos_embed(
    embed_dim: int, t: int, h: int, w: int
) -> ndarray

get_3d_sincos_pos_embed_from_grid

get_3d_sincos_pos_embed_from_grid(
    embed_dim: int, grid: ndarray
) -> ndarray

3-D sin-cos positional embedding (t, h, w), matching the upstream Lance modeling/lance/modeling_utils.py dimension split exactly.

patchify

patchify(imgs, p)

imgs: (N, 3, H, W) or (3, H, W) x: (N, L, patch_size2 *3) or (L, patch_size2 *3)