RynnValue-8B / attention_impl.py
huangsiteng's picture
Upload folder using huggingface_hub
78d6a37 verified
Raw
History Blame Contribute Delete
2.84 kB
"""Custom eager attention with prediction slot isolation.
The R copies within a ``<value>`` / ``<relative_value>`` slot attend
bidirectionally to each other; cross-slot pred keys are invisible to all
other queries.
All extra tensors flow through HF's ``**kwargs`` pass-through from the
top-level ``forward()`` call down to the attention function.
"""
from typing import Optional
import torch
import torch.nn as nn
from transformers.models.qwen3_vl.modeling_qwen3_vl import repeat_kv
from transformers.modeling_utils import ALL_ATTENTION_FUNCTIONS
from transformers.masking_utils import ALL_MASK_ATTENTION_FUNCTIONS, eager_mask
from transformers.processing_utils import Unpack
from transformers.utils import TransformersKwargs
def pred_slot_isolated_eager(
module: nn.Module,
query: torch.Tensor,
key: torch.Tensor,
value: torch.Tensor,
attention_mask: Optional[torch.Tensor],
scaling: float,
dropout: float = 0.0,
is_pred_key: Optional[torch.Tensor] = None,
pred_slot_id: Optional[torch.Tensor] = None,
**kwargs: Unpack[TransformersKwargs],
):
key_states = repeat_kv(key, module.num_key_value_groups)
value_states = repeat_kv(value, module.num_key_value_groups)
B = query.shape[0]
L_q = query.shape[2]
L_k = key_states.shape[2]
mask_dtype = query.dtype
neg_inf = torch.finfo(mask_dtype).min
if attention_mask is not None:
add_mask = attention_mask[:, :, :, :L_k].to(mask_dtype).clone()
else:
add_mask = torch.zeros(B, 1, L_q, L_k, dtype=mask_dtype, device=query.device)
if is_pred_key is not None and is_pred_key.any():
if pred_slot_id is not None:
slot_q = pred_slot_id[:, :, None]
slot_k = pred_slot_id[:, None, :]
same_slot = (slot_q == slot_k) & (slot_q >= 0)
add_mask = add_mask.masked_fill(same_slot[:, None, :, :], 0.0)
pred_mask = is_pred_key[:, None, :] & ~same_slot
else:
# Decode step with KV cache: the new query is never a pred token,
# so every cached pred key must be masked.
pred_mask = is_pred_key[:, None, :].expand(B, L_q, L_k)
add_mask = add_mask.masked_fill(pred_mask[:, None, :, :], neg_inf)
attn_weights = torch.matmul(query, key_states.transpose(2, 3)) * scaling + add_mask
attn_weights = nn.functional.softmax(attn_weights, dim=-1, dtype=torch.float32).to(query.dtype)
attn_weights = nn.functional.dropout(attn_weights, p=dropout, training=module.training)
attn_output = torch.matmul(attn_weights, value_states)
attn_output = attn_output.transpose(1, 2).contiguous()
return attn_output, attn_weights
ALL_ATTENTION_FUNCTIONS["pred_slot_isolated_eager"] = pred_slot_isolated_eager
ALL_MASK_ATTENTION_FUNCTIONS._global_mapping["pred_slot_isolated_eager"] = eager_mask