Module neuralops.tests.test_token_compressed_comprehensive
Functions
def make_config(hidden_size=64,
num_heads=4,
num_kv_heads=2,
is_decoder=False,
model_type='bert',
lora_rank=16,
lora_alpha=32.0)-
Expand source code
def make_config(hidden_size=64, num_heads=4, num_kv_heads=2, is_decoder=False, model_type="bert", lora_rank=16, lora_alpha=32.0): return types.SimpleNamespace( hidden_size=hidden_size, num_attention_heads=num_heads, num_key_value_heads=num_kv_heads, head_dim=hidden_size // num_heads, is_decoder=is_decoder, model_type=model_type, dropout=0.0, lora_rank=lora_rank, lora_alpha=lora_alpha, ) def test_token_compressed_causal_mode()-
Expand source code
def test_token_compressed_causal_mode(): cfg = make_config(hidden_size=64, num_heads=4, num_kv_heads=2, is_decoder=True, model_type="gpt2") attn = TokenCompressedAttention(cfg, pretrained_attn=DummyAttn(64, 4), is_decoder=True, compression_ratio=0.5) attn.eval() B, L, D = 2, 16, 64 x = torch.randn(B, L, D) out, _ = attn(x) assert out.shape == (B, L, D) assert not torch.isnan(out).any() assert not torch.isinf(out).any() def test_token_compressed_config_none_safety()-
Expand source code
def test_token_compressed_config_none_safety(): # Must not raise AttributeError when config=None attn = TokenCompressedAttention(config=None, hidden_size=64, num_heads=4, lora_rank=8, lora_alpha=16.0) assert attn.dim == 64 assert attn.num_heads == 4 assert attn.lora_rank == 8 assert attn.lora_alpha == 16.0 comp_cfg = types.SimpleNamespace(lora_rank=12, lora_alpha=24.0, compression_ratio=0.6) attn2 = TokenCompressedAttention(config=None, comp_config=comp_cfg, hidden_size=64, num_heads=4) assert attn2.lora_rank == 12 assert attn2.lora_alpha == 24.0 assert attn2.compression_ratio == 0.6 def test_token_compressed_distilbert_copy()-
Expand source code
def test_token_compressed_distilbert_copy(): src = DummyDistilBertAttn(64, 4) attn = TokenCompressedAttention(config=None, pretrained_attn=src, hidden_size=64, num_heads=4) assert not attn.is_nested_encoder assert torch.allclose(attn.q_lin.weight, src.q_lin.weight) assert torch.allclose(attn.out_lin.weight, src.out_lin.weight) def test_token_compressed_forward_and_shapes()-
Expand source code
def test_token_compressed_forward_and_shapes(): cfg = make_config(hidden_size=64, num_heads=4, num_kv_heads=2) attn = TokenCompressedAttention(cfg, pretrained_attn=DummyAttn(64, 4), compression_ratio=0.5) attn.eval() for seq_len in [2, 7, 16, 32]: B, L, D = 2, seq_len, 64 x = torch.randn(B, L, D) out, _ = attn(x) assert out.shape == (B, L, D), f"Failed for seq_len {seq_len}: expected {(B, L, D)}, got {out.shape}" assert not torch.isnan(out).any() assert not torch.isinf(out).any() def test_token_compressed_frobenius_check()-
Expand source code
def test_token_compressed_frobenius_check(): # If source weight is zero, RuntimeError must be raised src = DummyAttn(64, 4) src.q_proj.weight.data.zero_() with pytest.raises(RuntimeError, match="norm is near zero"): TokenCompressedAttention(config=None, pretrained_attn=src, hidden_size=64, num_heads=4) def test_token_compressed_gpt2_conv1d_and_lora_wrapper()-
Expand source code
def test_token_compressed_gpt2_conv1d_and_lora_wrapper(): # Conv1D layout test gpt2_attn = DummyGPT2Attn(64, 4) # Simulate Conv1D weight [in_features, out_features] gpt2_attn.c_attn.weight.data = torch.randn(64, 192) gpt2_attn.c_proj.weight.data = torch.randn(64, 64) # Wrap c_attn in a dummy LoRALinear having base_layer class LoRAWrapper(nn.Module): def __init__(self, base): super().__init__() self.base_layer = base self.lora_A = nn.Parameter(torch.randn(4, 64)) self.lora_B = nn.Parameter(torch.randn(192, 4)) self.lora_scaling = 2.0 wrapped_attn = types.SimpleNamespace( c_attn=LoRAWrapper(gpt2_attn.c_attn), c_proj=gpt2_attn.c_proj, num_heads=4, is_decoder=True ) attn = TokenCompressedAttention(config=None, pretrained_attn=wrapped_attn, hidden_size=64, num_heads=4, lora_rank=4) assert attn.is_decoder # Verify proper transposed slice expected_q = gpt2_attn.c_attn.weight.data.t()[:64, :] assert torch.allclose(attn.q_lin.weight, expected_q) def test_token_compressed_inject_safe()-
Expand source code
def test_token_compressed_inject_safe(): class DummyLayer(nn.Module): def __init__(self, d=64, h=4): super().__init__() self.attention = DummyAttn(d, h) layer = DummyLayer(64, 4) cfg = make_config(hidden_size=64, num_heads=4, num_kv_heads=2) comp_cfg = types.SimpleNamespace(lora_rank=8, lora_alpha=16.0, compression_ratio=0.5) injected = inject_token_compressed_attn(layer, model_config=cfg, comp_config=comp_cfg, old_attn=layer.attention) assert isinstance(injected, TokenCompressedAttention) assert layer.attention is injected assert injected.lora_rank == 8 assert injected.lora_alpha == 16.0 # Test failure: zeroed weight returns None without replacing layer.attention bad_layer = DummyLayer(64, 4) bad_layer.attention.q_proj.weight.data.zero_() orig_attn = bad_layer.attention result = inject_token_compressed_attn(bad_layer, model_config=cfg, comp_config=comp_cfg, old_attn=bad_layer.attention) assert result is None assert bad_layer.attention is orig_attn def test_token_compressed_lora_and_gradients()-
Expand source code
def test_token_compressed_lora_and_gradients(): cfg = make_config(hidden_size=64, num_heads=4, num_kv_heads=2) attn = TokenCompressedAttention(cfg, pretrained_attn=DummyAttn(64, 4), lora_rank=8) attn.train() # Base frozen, lora trainable assert not attn.q_lin.weight.requires_grad assert attn.q_lin.lora_A.requires_grad assert attn.q_lin.lora_B.requires_grad x = torch.randn(2, 8, 64, requires_grad=True) out, _ = attn(x) loss = out.sum() loss.backward() assert attn.q_lin.lora_A.grad is not None assert attn.q_lin.lora_B.grad is not None assert attn.q_lin.weight.grad is None def test_token_compressed_masks()-
Expand source code
def test_token_compressed_masks(): cfg = make_config(hidden_size=64, num_heads=4, num_kv_heads=2) attn = TokenCompressedAttention(cfg, pretrained_attn=DummyAttn(64, 4), compression_ratio=0.5) attn.eval() B, L, D = 2, 12, 64 x = torch.randn(B, L, D) # 2D mask mask_2d = torch.ones(B, L) mask_2d[:, -3:] = 0 out_2d, _ = attn(x, attention_mask=mask_2d) assert out_2d.shape == (B, L, D) assert not torch.isnan(out_2d).any() # 4D mask mask_4d = torch.zeros(B, 1, L, L) mask_4d[:, :, :, -3:] = -10000.0 out_4d, _ = attn(x, attention_mask=mask_4d) assert out_4d.shape == (B, L, D) assert not torch.isnan(out_4d).any() def test_token_compressed_roberta_nested_copy()-
Expand source code
def test_token_compressed_roberta_nested_copy(): layer = DummyRobertaLayer(64, 4) attn = TokenCompressedAttention(config=None, pretrained_attn=layer, hidden_size=64, num_heads=4) assert attn.is_nested_encoder assert torch.allclose(attn.q_lin.weight, layer.self.query.weight) assert torch.allclose(attn.k_lin.weight, layer.self.key.weight) # In forward, nested encoder bypasses out_lin x = torch.randn(2, 8, 64) out, _ = attn(x) assert out.shape == (2, 8, 64) def test_token_compressed_rotary_fallback()-
Expand source code
def test_token_compressed_rotary_fallback(): src = DummyAttn(64, 4) src.rotary_emb = DummyRotaryEmbedding(16) attn = TokenCompressedAttention(config=None, pretrained_attn=src, hidden_size=64, num_heads=4) assert attn.rotary_emb is not None # Forward without position_embeddings triggers self.rotary_emb x = torch.randn(2, 8, 64) out, _ = attn(x) assert out.shape == (2, 8, 64) assert not torch.isnan(out).any()
Classes
class DummyAttn (d=64, h=4)-
Expand source code
class DummyAttn(nn.Module): def __init__(self, d=64, h=4): super().__init__() self.q_proj = nn.Linear(d, d) self.k_proj = nn.Linear(d, d) self.v_proj = nn.Linear(d, d) self.o_proj = nn.Linear(d, d) self.hidden_size = d self.num_heads = hBase class for all neural network modules.
Your models should also subclass this class.
Modules can also contain other Modules, allowing them to be nested in a tree structure. You can assign the submodules as regular attributes::
import torch.nn as nn import torch.nn.functional as F class Model(nn.Module): def __init__(self) -> None: super().__init__() self.conv1 = nn.Conv2d(1, 20, 5) self.conv2 = nn.Conv2d(20, 20, 5) def forward(self, x): x = F.relu(self.conv1(x)) return F.relu(self.conv2(x))Submodules assigned in this way will be registered, and will also have their parameters converted when you call :meth:
to, etc.Note
As per the example above, an
__init__()call to the parent class must be made before assignment on the child.:ivar training: Boolean represents whether this module is in training or evaluation mode. :vartype training: bool
Initialize internal Module state, shared by both nn.Module and ScriptModule.
Ancestors
- torch.nn.modules.module.Module
class DummyDistilBertAttn (d=64, h=4)-
Expand source code
class DummyDistilBertAttn(nn.Module): def __init__(self, d=64, h=4): super().__init__() self.q_lin = nn.Linear(d, d) self.k_lin = nn.Linear(d, d) self.v_lin = nn.Linear(d, d) self.out_lin = nn.Linear(d, d) self.hidden_size = d self.num_heads = hBase class for all neural network modules.
Your models should also subclass this class.
Modules can also contain other Modules, allowing them to be nested in a tree structure. You can assign the submodules as regular attributes::
import torch.nn as nn import torch.nn.functional as F class Model(nn.Module): def __init__(self) -> None: super().__init__() self.conv1 = nn.Conv2d(1, 20, 5) self.conv2 = nn.Conv2d(20, 20, 5) def forward(self, x): x = F.relu(self.conv1(x)) return F.relu(self.conv2(x))Submodules assigned in this way will be registered, and will also have their parameters converted when you call :meth:
to, etc.Note
As per the example above, an
__init__()call to the parent class must be made before assignment on the child.:ivar training: Boolean represents whether this module is in training or evaluation mode. :vartype training: bool
Initialize internal Module state, shared by both nn.Module and ScriptModule.
Ancestors
- torch.nn.modules.module.Module
class DummyGPT2Attn (d=64, h=4)-
Expand source code
class DummyGPT2Attn(nn.Module): def __init__(self, d=64, h=4): super().__init__() self.c_attn = nn.Linear(d, 3 * d) self.c_proj = nn.Linear(d, d) self.split_size = d self.num_heads = h self.is_decoder = TrueBase class for all neural network modules.
Your models should also subclass this class.
Modules can also contain other Modules, allowing them to be nested in a tree structure. You can assign the submodules as regular attributes::
import torch.nn as nn import torch.nn.functional as F class Model(nn.Module): def __init__(self) -> None: super().__init__() self.conv1 = nn.Conv2d(1, 20, 5) self.conv2 = nn.Conv2d(20, 20, 5) def forward(self, x): x = F.relu(self.conv1(x)) return F.relu(self.conv2(x))Submodules assigned in this way will be registered, and will also have their parameters converted when you call :meth:
to, etc.Note
As per the example above, an
__init__()call to the parent class must be made before assignment on the child.:ivar training: Boolean represents whether this module is in training or evaluation mode. :vartype training: bool
Initialize internal Module state, shared by both nn.Module and ScriptModule.
Ancestors
- torch.nn.modules.module.Module
class DummyRobertaLayer (d=64, h=4)-
Expand source code
class DummyRobertaLayer(nn.Module): def __init__(self, d=64, h=4): super().__init__() self.self = DummyRobertaSelf(d, h) self.output = DummyRobertaOutput(d)Base class for all neural network modules.
Your models should also subclass this class.
Modules can also contain other Modules, allowing them to be nested in a tree structure. You can assign the submodules as regular attributes::
import torch.nn as nn import torch.nn.functional as F class Model(nn.Module): def __init__(self) -> None: super().__init__() self.conv1 = nn.Conv2d(1, 20, 5) self.conv2 = nn.Conv2d(20, 20, 5) def forward(self, x): x = F.relu(self.conv1(x)) return F.relu(self.conv2(x))Submodules assigned in this way will be registered, and will also have their parameters converted when you call :meth:
to, etc.Note
As per the example above, an
__init__()call to the parent class must be made before assignment on the child.:ivar training: Boolean represents whether this module is in training or evaluation mode. :vartype training: bool
Initialize internal Module state, shared by both nn.Module and ScriptModule.
Ancestors
- torch.nn.modules.module.Module
class DummyRobertaOutput (d=64)-
Expand source code
class DummyRobertaOutput(nn.Module): def __init__(self, d=64): super().__init__() self.dense = nn.Linear(d, d)Base class for all neural network modules.
Your models should also subclass this class.
Modules can also contain other Modules, allowing them to be nested in a tree structure. You can assign the submodules as regular attributes::
import torch.nn as nn import torch.nn.functional as F class Model(nn.Module): def __init__(self) -> None: super().__init__() self.conv1 = nn.Conv2d(1, 20, 5) self.conv2 = nn.Conv2d(20, 20, 5) def forward(self, x): x = F.relu(self.conv1(x)) return F.relu(self.conv2(x))Submodules assigned in this way will be registered, and will also have their parameters converted when you call :meth:
to, etc.Note
As per the example above, an
__init__()call to the parent class must be made before assignment on the child.:ivar training: Boolean represents whether this module is in training or evaluation mode. :vartype training: bool
Initialize internal Module state, shared by both nn.Module and ScriptModule.
Ancestors
- torch.nn.modules.module.Module
class DummyRobertaSelf (d=64, h=4)-
Expand source code
class DummyRobertaSelf(nn.Module): def __init__(self, d=64, h=4): super().__init__() self.query = nn.Linear(d, d) self.key = nn.Linear(d, d) self.value = nn.Linear(d, d)Base class for all neural network modules.
Your models should also subclass this class.
Modules can also contain other Modules, allowing them to be nested in a tree structure. You can assign the submodules as regular attributes::
import torch.nn as nn import torch.nn.functional as F class Model(nn.Module): def __init__(self) -> None: super().__init__() self.conv1 = nn.Conv2d(1, 20, 5) self.conv2 = nn.Conv2d(20, 20, 5) def forward(self, x): x = F.relu(self.conv1(x)) return F.relu(self.conv2(x))Submodules assigned in this way will be registered, and will also have their parameters converted when you call :meth:
to, etc.Note
As per the example above, an
__init__()call to the parent class must be made before assignment on the child.:ivar training: Boolean represents whether this module is in training or evaluation mode. :vartype training: bool
Initialize internal Module state, shared by both nn.Module and ScriptModule.
Ancestors
- torch.nn.modules.module.Module
class DummyRotaryEmbedding (dim)-
Expand source code
class DummyRotaryEmbedding(nn.Module): def __init__(self, dim): super().__init__() self.dim = dim def forward(self, x, seq_len=None): L = seq_len if seq_len is not None else x.shape[-2] inv_freq = 1.0 / (10000 ** (torch.arange(0, self.dim, 2).float() / self.dim)) t = torch.arange(L, device=x.device, dtype=inv_freq.dtype) freqs = torch.einsum("i,j->ij", t, inv_freq) emb = torch.cat((freqs, freqs), dim=-1) return emb.cos(), emb.sin()Base class for all neural network modules.
Your models should also subclass this class.
Modules can also contain other Modules, allowing them to be nested in a tree structure. You can assign the submodules as regular attributes::
import torch.nn as nn import torch.nn.functional as F class Model(nn.Module): def __init__(self) -> None: super().__init__() self.conv1 = nn.Conv2d(1, 20, 5) self.conv2 = nn.Conv2d(20, 20, 5) def forward(self, x): x = F.relu(self.conv1(x)) return F.relu(self.conv2(x))Submodules assigned in this way will be registered, and will also have their parameters converted when you call :meth:
to, etc.Note
As per the example above, an
__init__()call to the parent class must be made before assignment on the child.:ivar training: Boolean represents whether this module is in training or evaluation mode. :vartype training: bool
Initialize internal Module state, shared by both nn.Module and ScriptModule.
Ancestors
- torch.nn.modules.module.Module
Methods
def forward(self, x, seq_len=None) ‑> Callable[..., typing.Any]-
Expand source code
def forward(self, x, seq_len=None): L = seq_len if seq_len is not None else x.shape[-2] inv_freq = 1.0 / (10000 ** (torch.arange(0, self.dim, 2).float() / self.dim)) t = torch.arange(L, device=x.device, dtype=inv_freq.dtype) freqs = torch.einsum("i,j->ij", t, inv_freq) emb = torch.cat((freqs, freqs), dim=-1) return emb.cos(), emb.sin()Define the computation performed at every call.
Should be overridden by all subclasses.
Note
Although the recipe for forward pass needs to be defined within this function, one should call the :class:
Moduleinstance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.