Module neuralops.attentions.soa_attn

Shared Orthogonal Attention (SOA) with Per-Projection Latent Bottlenecks. Hardened for production use across diverse transformer architectures: - DistilBERT (Flat MHA) - RoBERTa / BERT (Nested Encoder Self-Attention) - GPT-2 (Causal Decoder with Conv1D) - Qwen / LLaMA (GQA with Rotary Position Embeddings)

Functions

def apply_rotary_pos_emb(q: torch.Tensor,
k: torch.Tensor,
cos: torch.Tensor,
sin: torch.Tensor,
position_ids: torch.Tensor | None = None,
unsqueeze_dim: int = 1) ‑> tuple[torch.Tensor, torch.Tensor]
Expand source code
def apply_rotary_pos_emb(
    q: torch.Tensor,
    k: torch.Tensor,
    cos: torch.Tensor,
    sin: torch.Tensor,
    position_ids: torch.Tensor | None = None,
    unsqueeze_dim: int = 1,
) -> tuple[torch.Tensor, torch.Tensor]:
    """Applies Rotary Position Embedding (RoPE) with partial dimension support."""
    rotary_dim = cos.shape[-1]
    head_dim = q.shape[-1]

    if rotary_dim > head_dim:
        cos = cos[..., :head_dim]
        sin = sin[..., :head_dim]
        rotary_dim = head_dim

    q_rot, q_pass = q[..., :rotary_dim], q[..., rotary_dim:]
    k_rot, k_pass = k[..., :rotary_dim], k[..., rotary_dim:]

    while cos.dim() < q_rot.dim():
        cos = cos.unsqueeze(unsqueeze_dim)
        sin = sin.unsqueeze(unsqueeze_dim)

    q_rot = (q_rot * cos) + (_rotate_half(q_rot) * sin)
    k_rot = (k_rot * cos) + (_rotate_half(k_rot) * sin)

    q = torch.cat([q_rot, q_pass], dim=-1) if q_pass.shape[-1] > 0 else q_rot
    k = torch.cat([k_rot, k_pass], dim=-1) if k_pass.shape[-1] > 0 else k_rot
    return q, k

Applies Rotary Position Embedding (RoPE) with partial dimension support.

def inject_soa(model: torch.nn.modules.module.Module | None = None,
layer: torch.nn.modules.module.Module | None = None,
model_config: Any = None,
comp_config: Any = None,
layer_idx: int = 0,
total_layers: int = 12,
old_attn: Any = None,
target_layer_idx: int | None = None,
**kwargs: Any) ‑> SOAAttention | torch.nn.modules.module.Module | None
Expand source code
@ATTENTION_REGISTRY.register("soa_attn_inject")
@ATTENTION_REGISTRY.register("soa_inject")
@ATTENTION_REGISTRY.register("soa_module_inject")
@ATTENTION_REGISTRY.register("inject_soa_attn")
@ATTENTION_REGISTRY.register("inject_soa")
@ATTENTION_REGISTRY.register("inject_soa_module")
def inject_soa_attn(
    model: nn.Module | None = None,
    layer: nn.Module | None = None,
    model_config: Any = None,
    comp_config: Any = None,
    layer_idx: int = 0,
    total_layers: int = 12,
    old_attn: Any = None,
    target_layer_idx: int | None = None,
    **kwargs: Any,
) -> SOAAttention | nn.Module | None:
    """Safely replace attention module with hardened SOAAttention across diverse transformer architectures."""
    target = layer if layer is not None else model
    if target is None:
        return None

    cfg = model_config
    if cfg is None and hasattr(target, "config"):
        cfg = target.config

    # 1. Whole model traversal
    layer_list = None
    if hasattr(target, "distilbert") and hasattr(target.distilbert, "transformer"):
        layer_list = target.distilbert.transformer.layer
    elif hasattr(target, "roberta") and hasattr(target.roberta, "encoder"):
        layer_list = target.roberta.encoder.layer
    elif hasattr(target, "transformer") and hasattr(target.transformer, "h"):
        layer_list = target.transformer.h
    elif hasattr(target, "model") and hasattr(target.model, "layers"):
        layer_list = target.model.layers
    elif hasattr(target, "encoder") and hasattr(target.encoder, "layer"):
        layer_list = target.encoder.layer
    elif (
        hasattr(target, "bert")
        and hasattr(target.bert, "encoder")
        and hasattr(target.bert.encoder, "layer")
    ):
        layer_list = target.bert.encoder.layer
    elif hasattr(target, "layers") and isinstance(target.layers, (nn.ModuleList, list)):
        layer_list = target.layers

    if layer_list is not None:
        num_injected = 0
        tot = len(layer_list)
        for idx, lyr in enumerate(layer_list):
            if target_layer_idx is not None and idx != target_layer_idx:
                continue
            res = inject_soa_attn(
                layer=lyr,
                model_config=cfg,
                comp_config=comp_config,
                layer_idx=idx,
                total_layers=tot,
                **kwargs,
            )
            if res is not None:
                num_injected += 1
        return target if num_injected > 0 else None

    # 2. Single layer injection
    try:
        src_attn = old_attn
        if src_attn is None and target is not None:
            for attr in ("attention", "self_attn", "attn", "self"):
                if hasattr(target, attr):
                    cand = getattr(target, attr)
                    if hasattr(cand, "self"):
                        src_attn = cand.self
                    else:
                        src_attn = cand
                    break

        if src_attn is None and target is not None and hasattr(target, "forward"):
            src_attn = target

        if src_attn is None:
            return None

        # Double-injection guard
        if src_attn is not None:
            if isinstance(src_attn, SOAAttention):
                return None
            if "SOA" in src_attn.__class__.__name__:
                return None
            if hasattr(src_attn, "inner") and isinstance(src_attn.inner, SOAAttention):
                return None
            if hasattr(src_attn, "_wrapped_attention") and isinstance(
                src_attn._wrapped_attention, SOAAttention
            ):
                return None

        if target is not None:
            for attr in ("attention", "self_attn", "attn", "self"):
                cand = getattr(target, attr, None)
                if cand is None:
                    continue
                if isinstance(cand, SOAAttention):
                    return None
                if "SOA" in cand.__class__.__name__:
                    return None
                if hasattr(cand, "inner") and isinstance(cand.inner, SOAAttention):
                    return None
                if hasattr(cand, "_wrapped_attention") and isinstance(
                    cand._wrapped_attention, SOAAttention
                ):
                    return None

        # Skip Qwen3.5 hybrid DeltaNet/LinearAttention layers
        if src_attn is not None:
            c_name = src_attn.__class__.__name__
            if "DeltaNet" in c_name or "LinearAttention" in c_name:
                return None

        if cfg is None and hasattr(src_attn, "config"):
            cfg = src_attn.config

        k_rank = getattr(
            comp_config,
            "soa_rank",
            getattr(comp_config, "rank", kwargs.pop("k_rank", 128)),
        )
        dropout = getattr(comp_config, "dropout", kwargs.pop("dropout", 0.1))

        new_attn = SOAAttention(
            config=cfg,
            k_rank=k_rank,
            dropout=dropout,
            pretrained_attn=src_attn,
            **kwargs,
        )

        if target is not None:
            if hasattr(target, "attention"):
                if hasattr(target.attention, "self"):
                    target.attention.self = new_attn
                    new_attn.is_nested_encoder = True
                else:
                    target.attention = new_attn
                return new_attn
            for attr in ("self_attn", "attn", "self"):
                if hasattr(target, attr):
                    setattr(target, attr, new_attn)
                    return new_attn
            target.attention = new_attn
            return new_attn
        return new_attn
    except Exception as e:
        logger.error("inject_soa_attn failed at layer %d: %s", layer_idx, e)
        return None

Safely replace attention module with hardened SOAAttention across diverse transformer architectures.

def inject_soa_attention(model: torch.nn.modules.module.Module | None = None,
layer: torch.nn.modules.module.Module | None = None,
model_config: Any = None,
comp_config: Any = None,
layer_idx: int = 0,
total_layers: int = 12,
old_attn: Any = None,
target_layer_idx: int | None = None,
**kwargs: Any) ‑> SOAAttention | torch.nn.modules.module.Module | None
Expand source code
@ATTENTION_REGISTRY.register("soa_attn_inject")
@ATTENTION_REGISTRY.register("soa_inject")
@ATTENTION_REGISTRY.register("soa_module_inject")
@ATTENTION_REGISTRY.register("inject_soa_attn")
@ATTENTION_REGISTRY.register("inject_soa")
@ATTENTION_REGISTRY.register("inject_soa_module")
def inject_soa_attn(
    model: nn.Module | None = None,
    layer: nn.Module | None = None,
    model_config: Any = None,
    comp_config: Any = None,
    layer_idx: int = 0,
    total_layers: int = 12,
    old_attn: Any = None,
    target_layer_idx: int | None = None,
    **kwargs: Any,
) -> SOAAttention | nn.Module | None:
    """Safely replace attention module with hardened SOAAttention across diverse transformer architectures."""
    target = layer if layer is not None else model
    if target is None:
        return None

    cfg = model_config
    if cfg is None and hasattr(target, "config"):
        cfg = target.config

    # 1. Whole model traversal
    layer_list = None
    if hasattr(target, "distilbert") and hasattr(target.distilbert, "transformer"):
        layer_list = target.distilbert.transformer.layer
    elif hasattr(target, "roberta") and hasattr(target.roberta, "encoder"):
        layer_list = target.roberta.encoder.layer
    elif hasattr(target, "transformer") and hasattr(target.transformer, "h"):
        layer_list = target.transformer.h
    elif hasattr(target, "model") and hasattr(target.model, "layers"):
        layer_list = target.model.layers
    elif hasattr(target, "encoder") and hasattr(target.encoder, "layer"):
        layer_list = target.encoder.layer
    elif (
        hasattr(target, "bert")
        and hasattr(target.bert, "encoder")
        and hasattr(target.bert.encoder, "layer")
    ):
        layer_list = target.bert.encoder.layer
    elif hasattr(target, "layers") and isinstance(target.layers, (nn.ModuleList, list)):
        layer_list = target.layers

    if layer_list is not None:
        num_injected = 0
        tot = len(layer_list)
        for idx, lyr in enumerate(layer_list):
            if target_layer_idx is not None and idx != target_layer_idx:
                continue
            res = inject_soa_attn(
                layer=lyr,
                model_config=cfg,
                comp_config=comp_config,
                layer_idx=idx,
                total_layers=tot,
                **kwargs,
            )
            if res is not None:
                num_injected += 1
        return target if num_injected > 0 else None

    # 2. Single layer injection
    try:
        src_attn = old_attn
        if src_attn is None and target is not None:
            for attr in ("attention", "self_attn", "attn", "self"):
                if hasattr(target, attr):
                    cand = getattr(target, attr)
                    if hasattr(cand, "self"):
                        src_attn = cand.self
                    else:
                        src_attn = cand
                    break

        if src_attn is None and target is not None and hasattr(target, "forward"):
            src_attn = target

        if src_attn is None:
            return None

        # Double-injection guard
        if src_attn is not None:
            if isinstance(src_attn, SOAAttention):
                return None
            if "SOA" in src_attn.__class__.__name__:
                return None
            if hasattr(src_attn, "inner") and isinstance(src_attn.inner, SOAAttention):
                return None
            if hasattr(src_attn, "_wrapped_attention") and isinstance(
                src_attn._wrapped_attention, SOAAttention
            ):
                return None

        if target is not None:
            for attr in ("attention", "self_attn", "attn", "self"):
                cand = getattr(target, attr, None)
                if cand is None:
                    continue
                if isinstance(cand, SOAAttention):
                    return None
                if "SOA" in cand.__class__.__name__:
                    return None
                if hasattr(cand, "inner") and isinstance(cand.inner, SOAAttention):
                    return None
                if hasattr(cand, "_wrapped_attention") and isinstance(
                    cand._wrapped_attention, SOAAttention
                ):
                    return None

        # Skip Qwen3.5 hybrid DeltaNet/LinearAttention layers
        if src_attn is not None:
            c_name = src_attn.__class__.__name__
            if "DeltaNet" in c_name or "LinearAttention" in c_name:
                return None

        if cfg is None and hasattr(src_attn, "config"):
            cfg = src_attn.config

        k_rank = getattr(
            comp_config,
            "soa_rank",
            getattr(comp_config, "rank", kwargs.pop("k_rank", 128)),
        )
        dropout = getattr(comp_config, "dropout", kwargs.pop("dropout", 0.1))

        new_attn = SOAAttention(
            config=cfg,
            k_rank=k_rank,
            dropout=dropout,
            pretrained_attn=src_attn,
            **kwargs,
        )

        if target is not None:
            if hasattr(target, "attention"):
                if hasattr(target.attention, "self"):
                    target.attention.self = new_attn
                    new_attn.is_nested_encoder = True
                else:
                    target.attention = new_attn
                return new_attn
            for attr in ("self_attn", "attn", "self"):
                if hasattr(target, attr):
                    setattr(target, attr, new_attn)
                    return new_attn
            target.attention = new_attn
            return new_attn
        return new_attn
    except Exception as e:
        logger.error("inject_soa_attn failed at layer %d: %s", layer_idx, e)
        return None

Safely replace attention module with hardened SOAAttention across diverse transformer architectures.

def inject_soa_attn(model: torch.nn.modules.module.Module | None = None,
layer: torch.nn.modules.module.Module | None = None,
model_config: Any = None,
comp_config: Any = None,
layer_idx: int = 0,
total_layers: int = 12,
old_attn: Any = None,
target_layer_idx: int | None = None,
**kwargs: Any) ‑> SOAAttention | torch.nn.modules.module.Module | None
Expand source code
@ATTENTION_REGISTRY.register("soa_attn_inject")
@ATTENTION_REGISTRY.register("soa_inject")
@ATTENTION_REGISTRY.register("soa_module_inject")
@ATTENTION_REGISTRY.register("inject_soa_attn")
@ATTENTION_REGISTRY.register("inject_soa")
@ATTENTION_REGISTRY.register("inject_soa_module")
def inject_soa_attn(
    model: nn.Module | None = None,
    layer: nn.Module | None = None,
    model_config: Any = None,
    comp_config: Any = None,
    layer_idx: int = 0,
    total_layers: int = 12,
    old_attn: Any = None,
    target_layer_idx: int | None = None,
    **kwargs: Any,
) -> SOAAttention | nn.Module | None:
    """Safely replace attention module with hardened SOAAttention across diverse transformer architectures."""
    target = layer if layer is not None else model
    if target is None:
        return None

    cfg = model_config
    if cfg is None and hasattr(target, "config"):
        cfg = target.config

    # 1. Whole model traversal
    layer_list = None
    if hasattr(target, "distilbert") and hasattr(target.distilbert, "transformer"):
        layer_list = target.distilbert.transformer.layer
    elif hasattr(target, "roberta") and hasattr(target.roberta, "encoder"):
        layer_list = target.roberta.encoder.layer
    elif hasattr(target, "transformer") and hasattr(target.transformer, "h"):
        layer_list = target.transformer.h
    elif hasattr(target, "model") and hasattr(target.model, "layers"):
        layer_list = target.model.layers
    elif hasattr(target, "encoder") and hasattr(target.encoder, "layer"):
        layer_list = target.encoder.layer
    elif (
        hasattr(target, "bert")
        and hasattr(target.bert, "encoder")
        and hasattr(target.bert.encoder, "layer")
    ):
        layer_list = target.bert.encoder.layer
    elif hasattr(target, "layers") and isinstance(target.layers, (nn.ModuleList, list)):
        layer_list = target.layers

    if layer_list is not None:
        num_injected = 0
        tot = len(layer_list)
        for idx, lyr in enumerate(layer_list):
            if target_layer_idx is not None and idx != target_layer_idx:
                continue
            res = inject_soa_attn(
                layer=lyr,
                model_config=cfg,
                comp_config=comp_config,
                layer_idx=idx,
                total_layers=tot,
                **kwargs,
            )
            if res is not None:
                num_injected += 1
        return target if num_injected > 0 else None

    # 2. Single layer injection
    try:
        src_attn = old_attn
        if src_attn is None and target is not None:
            for attr in ("attention", "self_attn", "attn", "self"):
                if hasattr(target, attr):
                    cand = getattr(target, attr)
                    if hasattr(cand, "self"):
                        src_attn = cand.self
                    else:
                        src_attn = cand
                    break

        if src_attn is None and target is not None and hasattr(target, "forward"):
            src_attn = target

        if src_attn is None:
            return None

        # Double-injection guard
        if src_attn is not None:
            if isinstance(src_attn, SOAAttention):
                return None
            if "SOA" in src_attn.__class__.__name__:
                return None
            if hasattr(src_attn, "inner") and isinstance(src_attn.inner, SOAAttention):
                return None
            if hasattr(src_attn, "_wrapped_attention") and isinstance(
                src_attn._wrapped_attention, SOAAttention
            ):
                return None

        if target is not None:
            for attr in ("attention", "self_attn", "attn", "self"):
                cand = getattr(target, attr, None)
                if cand is None:
                    continue
                if isinstance(cand, SOAAttention):
                    return None
                if "SOA" in cand.__class__.__name__:
                    return None
                if hasattr(cand, "inner") and isinstance(cand.inner, SOAAttention):
                    return None
                if hasattr(cand, "_wrapped_attention") and isinstance(
                    cand._wrapped_attention, SOAAttention
                ):
                    return None

        # Skip Qwen3.5 hybrid DeltaNet/LinearAttention layers
        if src_attn is not None:
            c_name = src_attn.__class__.__name__
            if "DeltaNet" in c_name or "LinearAttention" in c_name:
                return None

        if cfg is None and hasattr(src_attn, "config"):
            cfg = src_attn.config

        k_rank = getattr(
            comp_config,
            "soa_rank",
            getattr(comp_config, "rank", kwargs.pop("k_rank", 128)),
        )
        dropout = getattr(comp_config, "dropout", kwargs.pop("dropout", 0.1))

        new_attn = SOAAttention(
            config=cfg,
            k_rank=k_rank,
            dropout=dropout,
            pretrained_attn=src_attn,
            **kwargs,
        )

        if target is not None:
            if hasattr(target, "attention"):
                if hasattr(target.attention, "self"):
                    target.attention.self = new_attn
                    new_attn.is_nested_encoder = True
                else:
                    target.attention = new_attn
                return new_attn
            for attr in ("self_attn", "attn", "self"):
                if hasattr(target, attr):
                    setattr(target, attr, new_attn)
                    return new_attn
            target.attention = new_attn
            return new_attn
        return new_attn
    except Exception as e:
        logger.error("inject_soa_attn failed at layer %d: %s", layer_idx, e)
        return None

Safely replace attention module with hardened SOAAttention across diverse transformer architectures.

def inject_soa_fused(model: torch.nn.modules.module.Module | None = None,
layer: torch.nn.modules.module.Module | None = None,
model_config: Any = None,
comp_config: Any = None,
layer_idx: int = 0,
total_layers: int = 12,
old_attn: Any = None,
target_layer_idx: int | None = None,
**kwargs: Any) ‑> SOAAttention | torch.nn.modules.module.Module | None
Expand source code
@ATTENTION_REGISTRY.register("soa_attn_inject")
@ATTENTION_REGISTRY.register("soa_inject")
@ATTENTION_REGISTRY.register("soa_module_inject")
@ATTENTION_REGISTRY.register("inject_soa_attn")
@ATTENTION_REGISTRY.register("inject_soa")
@ATTENTION_REGISTRY.register("inject_soa_module")
def inject_soa_attn(
    model: nn.Module | None = None,
    layer: nn.Module | None = None,
    model_config: Any = None,
    comp_config: Any = None,
    layer_idx: int = 0,
    total_layers: int = 12,
    old_attn: Any = None,
    target_layer_idx: int | None = None,
    **kwargs: Any,
) -> SOAAttention | nn.Module | None:
    """Safely replace attention module with hardened SOAAttention across diverse transformer architectures."""
    target = layer if layer is not None else model
    if target is None:
        return None

    cfg = model_config
    if cfg is None and hasattr(target, "config"):
        cfg = target.config

    # 1. Whole model traversal
    layer_list = None
    if hasattr(target, "distilbert") and hasattr(target.distilbert, "transformer"):
        layer_list = target.distilbert.transformer.layer
    elif hasattr(target, "roberta") and hasattr(target.roberta, "encoder"):
        layer_list = target.roberta.encoder.layer
    elif hasattr(target, "transformer") and hasattr(target.transformer, "h"):
        layer_list = target.transformer.h
    elif hasattr(target, "model") and hasattr(target.model, "layers"):
        layer_list = target.model.layers
    elif hasattr(target, "encoder") and hasattr(target.encoder, "layer"):
        layer_list = target.encoder.layer
    elif (
        hasattr(target, "bert")
        and hasattr(target.bert, "encoder")
        and hasattr(target.bert.encoder, "layer")
    ):
        layer_list = target.bert.encoder.layer
    elif hasattr(target, "layers") and isinstance(target.layers, (nn.ModuleList, list)):
        layer_list = target.layers

    if layer_list is not None:
        num_injected = 0
        tot = len(layer_list)
        for idx, lyr in enumerate(layer_list):
            if target_layer_idx is not None and idx != target_layer_idx:
                continue
            res = inject_soa_attn(
                layer=lyr,
                model_config=cfg,
                comp_config=comp_config,
                layer_idx=idx,
                total_layers=tot,
                **kwargs,
            )
            if res is not None:
                num_injected += 1
        return target if num_injected > 0 else None

    # 2. Single layer injection
    try:
        src_attn = old_attn
        if src_attn is None and target is not None:
            for attr in ("attention", "self_attn", "attn", "self"):
                if hasattr(target, attr):
                    cand = getattr(target, attr)
                    if hasattr(cand, "self"):
                        src_attn = cand.self
                    else:
                        src_attn = cand
                    break

        if src_attn is None and target is not None and hasattr(target, "forward"):
            src_attn = target

        if src_attn is None:
            return None

        # Double-injection guard
        if src_attn is not None:
            if isinstance(src_attn, SOAAttention):
                return None
            if "SOA" in src_attn.__class__.__name__:
                return None
            if hasattr(src_attn, "inner") and isinstance(src_attn.inner, SOAAttention):
                return None
            if hasattr(src_attn, "_wrapped_attention") and isinstance(
                src_attn._wrapped_attention, SOAAttention
            ):
                return None

        if target is not None:
            for attr in ("attention", "self_attn", "attn", "self"):
                cand = getattr(target, attr, None)
                if cand is None:
                    continue
                if isinstance(cand, SOAAttention):
                    return None
                if "SOA" in cand.__class__.__name__:
                    return None
                if hasattr(cand, "inner") and isinstance(cand.inner, SOAAttention):
                    return None
                if hasattr(cand, "_wrapped_attention") and isinstance(
                    cand._wrapped_attention, SOAAttention
                ):
                    return None

        # Skip Qwen3.5 hybrid DeltaNet/LinearAttention layers
        if src_attn is not None:
            c_name = src_attn.__class__.__name__
            if "DeltaNet" in c_name or "LinearAttention" in c_name:
                return None

        if cfg is None and hasattr(src_attn, "config"):
            cfg = src_attn.config

        k_rank = getattr(
            comp_config,
            "soa_rank",
            getattr(comp_config, "rank", kwargs.pop("k_rank", 128)),
        )
        dropout = getattr(comp_config, "dropout", kwargs.pop("dropout", 0.1))

        new_attn = SOAAttention(
            config=cfg,
            k_rank=k_rank,
            dropout=dropout,
            pretrained_attn=src_attn,
            **kwargs,
        )

        if target is not None:
            if hasattr(target, "attention"):
                if hasattr(target.attention, "self"):
                    target.attention.self = new_attn
                    new_attn.is_nested_encoder = True
                else:
                    target.attention = new_attn
                return new_attn
            for attr in ("self_attn", "attn", "self"):
                if hasattr(target, attr):
                    setattr(target, attr, new_attn)
                    return new_attn
            target.attention = new_attn
            return new_attn
        return new_attn
    except Exception as e:
        logger.error("inject_soa_attn failed at layer %d: %s", layer_idx, e)
        return None

Safely replace attention module with hardened SOAAttention across diverse transformer architectures.

def inject_soa_fused_attn(model: torch.nn.modules.module.Module | None = None,
layer: torch.nn.modules.module.Module | None = None,
model_config: Any = None,
comp_config: Any = None,
layer_idx: int = 0,
total_layers: int = 12,
old_attn: Any = None,
target_layer_idx: int | None = None,
**kwargs: Any) ‑> SOAAttention | torch.nn.modules.module.Module | None
Expand source code
@ATTENTION_REGISTRY.register("soa_attn_inject")
@ATTENTION_REGISTRY.register("soa_inject")
@ATTENTION_REGISTRY.register("soa_module_inject")
@ATTENTION_REGISTRY.register("inject_soa_attn")
@ATTENTION_REGISTRY.register("inject_soa")
@ATTENTION_REGISTRY.register("inject_soa_module")
def inject_soa_attn(
    model: nn.Module | None = None,
    layer: nn.Module | None = None,
    model_config: Any = None,
    comp_config: Any = None,
    layer_idx: int = 0,
    total_layers: int = 12,
    old_attn: Any = None,
    target_layer_idx: int | None = None,
    **kwargs: Any,
) -> SOAAttention | nn.Module | None:
    """Safely replace attention module with hardened SOAAttention across diverse transformer architectures."""
    target = layer if layer is not None else model
    if target is None:
        return None

    cfg = model_config
    if cfg is None and hasattr(target, "config"):
        cfg = target.config

    # 1. Whole model traversal
    layer_list = None
    if hasattr(target, "distilbert") and hasattr(target.distilbert, "transformer"):
        layer_list = target.distilbert.transformer.layer
    elif hasattr(target, "roberta") and hasattr(target.roberta, "encoder"):
        layer_list = target.roberta.encoder.layer
    elif hasattr(target, "transformer") and hasattr(target.transformer, "h"):
        layer_list = target.transformer.h
    elif hasattr(target, "model") and hasattr(target.model, "layers"):
        layer_list = target.model.layers
    elif hasattr(target, "encoder") and hasattr(target.encoder, "layer"):
        layer_list = target.encoder.layer
    elif (
        hasattr(target, "bert")
        and hasattr(target.bert, "encoder")
        and hasattr(target.bert.encoder, "layer")
    ):
        layer_list = target.bert.encoder.layer
    elif hasattr(target, "layers") and isinstance(target.layers, (nn.ModuleList, list)):
        layer_list = target.layers

    if layer_list is not None:
        num_injected = 0
        tot = len(layer_list)
        for idx, lyr in enumerate(layer_list):
            if target_layer_idx is not None and idx != target_layer_idx:
                continue
            res = inject_soa_attn(
                layer=lyr,
                model_config=cfg,
                comp_config=comp_config,
                layer_idx=idx,
                total_layers=tot,
                **kwargs,
            )
            if res is not None:
                num_injected += 1
        return target if num_injected > 0 else None

    # 2. Single layer injection
    try:
        src_attn = old_attn
        if src_attn is None and target is not None:
            for attr in ("attention", "self_attn", "attn", "self"):
                if hasattr(target, attr):
                    cand = getattr(target, attr)
                    if hasattr(cand, "self"):
                        src_attn = cand.self
                    else:
                        src_attn = cand
                    break

        if src_attn is None and target is not None and hasattr(target, "forward"):
            src_attn = target

        if src_attn is None:
            return None

        # Double-injection guard
        if src_attn is not None:
            if isinstance(src_attn, SOAAttention):
                return None
            if "SOA" in src_attn.__class__.__name__:
                return None
            if hasattr(src_attn, "inner") and isinstance(src_attn.inner, SOAAttention):
                return None
            if hasattr(src_attn, "_wrapped_attention") and isinstance(
                src_attn._wrapped_attention, SOAAttention
            ):
                return None

        if target is not None:
            for attr in ("attention", "self_attn", "attn", "self"):
                cand = getattr(target, attr, None)
                if cand is None:
                    continue
                if isinstance(cand, SOAAttention):
                    return None
                if "SOA" in cand.__class__.__name__:
                    return None
                if hasattr(cand, "inner") and isinstance(cand.inner, SOAAttention):
                    return None
                if hasattr(cand, "_wrapped_attention") and isinstance(
                    cand._wrapped_attention, SOAAttention
                ):
                    return None

        # Skip Qwen3.5 hybrid DeltaNet/LinearAttention layers
        if src_attn is not None:
            c_name = src_attn.__class__.__name__
            if "DeltaNet" in c_name or "LinearAttention" in c_name:
                return None

        if cfg is None and hasattr(src_attn, "config"):
            cfg = src_attn.config

        k_rank = getattr(
            comp_config,
            "soa_rank",
            getattr(comp_config, "rank", kwargs.pop("k_rank", 128)),
        )
        dropout = getattr(comp_config, "dropout", kwargs.pop("dropout", 0.1))

        new_attn = SOAAttention(
            config=cfg,
            k_rank=k_rank,
            dropout=dropout,
            pretrained_attn=src_attn,
            **kwargs,
        )

        if target is not None:
            if hasattr(target, "attention"):
                if hasattr(target.attention, "self"):
                    target.attention.self = new_attn
                    new_attn.is_nested_encoder = True
                else:
                    target.attention = new_attn
                return new_attn
            for attr in ("self_attn", "attn", "self"):
                if hasattr(target, attr):
                    setattr(target, attr, new_attn)
                    return new_attn
            target.attention = new_attn
            return new_attn
        return new_attn
    except Exception as e:
        logger.error("inject_soa_attn failed at layer %d: %s", layer_idx, e)
        return None

Safely replace attention module with hardened SOAAttention across diverse transformer architectures.

def inject_soa_fused_module(model: torch.nn.modules.module.Module | None = None,
layer: torch.nn.modules.module.Module | None = None,
model_config: Any = None,
comp_config: Any = None,
layer_idx: int = 0,
total_layers: int = 12,
old_attn: Any = None,
target_layer_idx: int | None = None,
**kwargs: Any) ‑> SOAAttention | torch.nn.modules.module.Module | None
Expand source code
@ATTENTION_REGISTRY.register("soa_attn_inject")
@ATTENTION_REGISTRY.register("soa_inject")
@ATTENTION_REGISTRY.register("soa_module_inject")
@ATTENTION_REGISTRY.register("inject_soa_attn")
@ATTENTION_REGISTRY.register("inject_soa")
@ATTENTION_REGISTRY.register("inject_soa_module")
def inject_soa_attn(
    model: nn.Module | None = None,
    layer: nn.Module | None = None,
    model_config: Any = None,
    comp_config: Any = None,
    layer_idx: int = 0,
    total_layers: int = 12,
    old_attn: Any = None,
    target_layer_idx: int | None = None,
    **kwargs: Any,
) -> SOAAttention | nn.Module | None:
    """Safely replace attention module with hardened SOAAttention across diverse transformer architectures."""
    target = layer if layer is not None else model
    if target is None:
        return None

    cfg = model_config
    if cfg is None and hasattr(target, "config"):
        cfg = target.config

    # 1. Whole model traversal
    layer_list = None
    if hasattr(target, "distilbert") and hasattr(target.distilbert, "transformer"):
        layer_list = target.distilbert.transformer.layer
    elif hasattr(target, "roberta") and hasattr(target.roberta, "encoder"):
        layer_list = target.roberta.encoder.layer
    elif hasattr(target, "transformer") and hasattr(target.transformer, "h"):
        layer_list = target.transformer.h
    elif hasattr(target, "model") and hasattr(target.model, "layers"):
        layer_list = target.model.layers
    elif hasattr(target, "encoder") and hasattr(target.encoder, "layer"):
        layer_list = target.encoder.layer
    elif (
        hasattr(target, "bert")
        and hasattr(target.bert, "encoder")
        and hasattr(target.bert.encoder, "layer")
    ):
        layer_list = target.bert.encoder.layer
    elif hasattr(target, "layers") and isinstance(target.layers, (nn.ModuleList, list)):
        layer_list = target.layers

    if layer_list is not None:
        num_injected = 0
        tot = len(layer_list)
        for idx, lyr in enumerate(layer_list):
            if target_layer_idx is not None and idx != target_layer_idx:
                continue
            res = inject_soa_attn(
                layer=lyr,
                model_config=cfg,
                comp_config=comp_config,
                layer_idx=idx,
                total_layers=tot,
                **kwargs,
            )
            if res is not None:
                num_injected += 1
        return target if num_injected > 0 else None

    # 2. Single layer injection
    try:
        src_attn = old_attn
        if src_attn is None and target is not None:
            for attr in ("attention", "self_attn", "attn", "self"):
                if hasattr(target, attr):
                    cand = getattr(target, attr)
                    if hasattr(cand, "self"):
                        src_attn = cand.self
                    else:
                        src_attn = cand
                    break

        if src_attn is None and target is not None and hasattr(target, "forward"):
            src_attn = target

        if src_attn is None:
            return None

        # Double-injection guard
        if src_attn is not None:
            if isinstance(src_attn, SOAAttention):
                return None
            if "SOA" in src_attn.__class__.__name__:
                return None
            if hasattr(src_attn, "inner") and isinstance(src_attn.inner, SOAAttention):
                return None
            if hasattr(src_attn, "_wrapped_attention") and isinstance(
                src_attn._wrapped_attention, SOAAttention
            ):
                return None

        if target is not None:
            for attr in ("attention", "self_attn", "attn", "self"):
                cand = getattr(target, attr, None)
                if cand is None:
                    continue
                if isinstance(cand, SOAAttention):
                    return None
                if "SOA" in cand.__class__.__name__:
                    return None
                if hasattr(cand, "inner") and isinstance(cand.inner, SOAAttention):
                    return None
                if hasattr(cand, "_wrapped_attention") and isinstance(
                    cand._wrapped_attention, SOAAttention
                ):
                    return None

        # Skip Qwen3.5 hybrid DeltaNet/LinearAttention layers
        if src_attn is not None:
            c_name = src_attn.__class__.__name__
            if "DeltaNet" in c_name or "LinearAttention" in c_name:
                return None

        if cfg is None and hasattr(src_attn, "config"):
            cfg = src_attn.config

        k_rank = getattr(
            comp_config,
            "soa_rank",
            getattr(comp_config, "rank", kwargs.pop("k_rank", 128)),
        )
        dropout = getattr(comp_config, "dropout", kwargs.pop("dropout", 0.1))

        new_attn = SOAAttention(
            config=cfg,
            k_rank=k_rank,
            dropout=dropout,
            pretrained_attn=src_attn,
            **kwargs,
        )

        if target is not None:
            if hasattr(target, "attention"):
                if hasattr(target.attention, "self"):
                    target.attention.self = new_attn
                    new_attn.is_nested_encoder = True
                else:
                    target.attention = new_attn
                return new_attn
            for attr in ("self_attn", "attn", "self"):
                if hasattr(target, attr):
                    setattr(target, attr, new_attn)
                    return new_attn
            target.attention = new_attn
            return new_attn
        return new_attn
    except Exception as e:
        logger.error("inject_soa_attn failed at layer %d: %s", layer_idx, e)
        return None

Safely replace attention module with hardened SOAAttention across diverse transformer architectures.

def inject_soa_module(model: torch.nn.modules.module.Module | None = None,
layer: torch.nn.modules.module.Module | None = None,
model_config: Any = None,
comp_config: Any = None,
layer_idx: int = 0,
total_layers: int = 12,
old_attn: Any = None,
target_layer_idx: int | None = None,
**kwargs: Any) ‑> SOAAttention | torch.nn.modules.module.Module | None
Expand source code
@ATTENTION_REGISTRY.register("soa_attn_inject")
@ATTENTION_REGISTRY.register("soa_inject")
@ATTENTION_REGISTRY.register("soa_module_inject")
@ATTENTION_REGISTRY.register("inject_soa_attn")
@ATTENTION_REGISTRY.register("inject_soa")
@ATTENTION_REGISTRY.register("inject_soa_module")
def inject_soa_attn(
    model: nn.Module | None = None,
    layer: nn.Module | None = None,
    model_config: Any = None,
    comp_config: Any = None,
    layer_idx: int = 0,
    total_layers: int = 12,
    old_attn: Any = None,
    target_layer_idx: int | None = None,
    **kwargs: Any,
) -> SOAAttention | nn.Module | None:
    """Safely replace attention module with hardened SOAAttention across diverse transformer architectures."""
    target = layer if layer is not None else model
    if target is None:
        return None

    cfg = model_config
    if cfg is None and hasattr(target, "config"):
        cfg = target.config

    # 1. Whole model traversal
    layer_list = None
    if hasattr(target, "distilbert") and hasattr(target.distilbert, "transformer"):
        layer_list = target.distilbert.transformer.layer
    elif hasattr(target, "roberta") and hasattr(target.roberta, "encoder"):
        layer_list = target.roberta.encoder.layer
    elif hasattr(target, "transformer") and hasattr(target.transformer, "h"):
        layer_list = target.transformer.h
    elif hasattr(target, "model") and hasattr(target.model, "layers"):
        layer_list = target.model.layers
    elif hasattr(target, "encoder") and hasattr(target.encoder, "layer"):
        layer_list = target.encoder.layer
    elif (
        hasattr(target, "bert")
        and hasattr(target.bert, "encoder")
        and hasattr(target.bert.encoder, "layer")
    ):
        layer_list = target.bert.encoder.layer
    elif hasattr(target, "layers") and isinstance(target.layers, (nn.ModuleList, list)):
        layer_list = target.layers

    if layer_list is not None:
        num_injected = 0
        tot = len(layer_list)
        for idx, lyr in enumerate(layer_list):
            if target_layer_idx is not None and idx != target_layer_idx:
                continue
            res = inject_soa_attn(
                layer=lyr,
                model_config=cfg,
                comp_config=comp_config,
                layer_idx=idx,
                total_layers=tot,
                **kwargs,
            )
            if res is not None:
                num_injected += 1
        return target if num_injected > 0 else None

    # 2. Single layer injection
    try:
        src_attn = old_attn
        if src_attn is None and target is not None:
            for attr in ("attention", "self_attn", "attn", "self"):
                if hasattr(target, attr):
                    cand = getattr(target, attr)
                    if hasattr(cand, "self"):
                        src_attn = cand.self
                    else:
                        src_attn = cand
                    break

        if src_attn is None and target is not None and hasattr(target, "forward"):
            src_attn = target

        if src_attn is None:
            return None

        # Double-injection guard
        if src_attn is not None:
            if isinstance(src_attn, SOAAttention):
                return None
            if "SOA" in src_attn.__class__.__name__:
                return None
            if hasattr(src_attn, "inner") and isinstance(src_attn.inner, SOAAttention):
                return None
            if hasattr(src_attn, "_wrapped_attention") and isinstance(
                src_attn._wrapped_attention, SOAAttention
            ):
                return None

        if target is not None:
            for attr in ("attention", "self_attn", "attn", "self"):
                cand = getattr(target, attr, None)
                if cand is None:
                    continue
                if isinstance(cand, SOAAttention):
                    return None
                if "SOA" in cand.__class__.__name__:
                    return None
                if hasattr(cand, "inner") and isinstance(cand.inner, SOAAttention):
                    return None
                if hasattr(cand, "_wrapped_attention") and isinstance(
                    cand._wrapped_attention, SOAAttention
                ):
                    return None

        # Skip Qwen3.5 hybrid DeltaNet/LinearAttention layers
        if src_attn is not None:
            c_name = src_attn.__class__.__name__
            if "DeltaNet" in c_name or "LinearAttention" in c_name:
                return None

        if cfg is None and hasattr(src_attn, "config"):
            cfg = src_attn.config

        k_rank = getattr(
            comp_config,
            "soa_rank",
            getattr(comp_config, "rank", kwargs.pop("k_rank", 128)),
        )
        dropout = getattr(comp_config, "dropout", kwargs.pop("dropout", 0.1))

        new_attn = SOAAttention(
            config=cfg,
            k_rank=k_rank,
            dropout=dropout,
            pretrained_attn=src_attn,
            **kwargs,
        )

        if target is not None:
            if hasattr(target, "attention"):
                if hasattr(target.attention, "self"):
                    target.attention.self = new_attn
                    new_attn.is_nested_encoder = True
                else:
                    target.attention = new_attn
                return new_attn
            for attr in ("self_attn", "attn", "self"):
                if hasattr(target, attr):
                    setattr(target, attr, new_attn)
                    return new_attn
            target.attention = new_attn
            return new_attn
        return new_attn
    except Exception as e:
        logger.error("inject_soa_attn failed at layer %d: %s", layer_idx, e)
        return None

Safely replace attention module with hardened SOAAttention across diverse transformer architectures.

def inject_soafusedattention(model: torch.nn.modules.module.Module | None = None,
layer: torch.nn.modules.module.Module | None = None,
model_config: Any = None,
comp_config: Any = None,
layer_idx: int = 0,
total_layers: int = 12,
old_attn: Any = None,
target_layer_idx: int | None = None,
**kwargs: Any) ‑> SOAAttention | torch.nn.modules.module.Module | None
Expand source code
@ATTENTION_REGISTRY.register("soa_attn_inject")
@ATTENTION_REGISTRY.register("soa_inject")
@ATTENTION_REGISTRY.register("soa_module_inject")
@ATTENTION_REGISTRY.register("inject_soa_attn")
@ATTENTION_REGISTRY.register("inject_soa")
@ATTENTION_REGISTRY.register("inject_soa_module")
def inject_soa_attn(
    model: nn.Module | None = None,
    layer: nn.Module | None = None,
    model_config: Any = None,
    comp_config: Any = None,
    layer_idx: int = 0,
    total_layers: int = 12,
    old_attn: Any = None,
    target_layer_idx: int | None = None,
    **kwargs: Any,
) -> SOAAttention | nn.Module | None:
    """Safely replace attention module with hardened SOAAttention across diverse transformer architectures."""
    target = layer if layer is not None else model
    if target is None:
        return None

    cfg = model_config
    if cfg is None and hasattr(target, "config"):
        cfg = target.config

    # 1. Whole model traversal
    layer_list = None
    if hasattr(target, "distilbert") and hasattr(target.distilbert, "transformer"):
        layer_list = target.distilbert.transformer.layer
    elif hasattr(target, "roberta") and hasattr(target.roberta, "encoder"):
        layer_list = target.roberta.encoder.layer
    elif hasattr(target, "transformer") and hasattr(target.transformer, "h"):
        layer_list = target.transformer.h
    elif hasattr(target, "model") and hasattr(target.model, "layers"):
        layer_list = target.model.layers
    elif hasattr(target, "encoder") and hasattr(target.encoder, "layer"):
        layer_list = target.encoder.layer
    elif (
        hasattr(target, "bert")
        and hasattr(target.bert, "encoder")
        and hasattr(target.bert.encoder, "layer")
    ):
        layer_list = target.bert.encoder.layer
    elif hasattr(target, "layers") and isinstance(target.layers, (nn.ModuleList, list)):
        layer_list = target.layers

    if layer_list is not None:
        num_injected = 0
        tot = len(layer_list)
        for idx, lyr in enumerate(layer_list):
            if target_layer_idx is not None and idx != target_layer_idx:
                continue
            res = inject_soa_attn(
                layer=lyr,
                model_config=cfg,
                comp_config=comp_config,
                layer_idx=idx,
                total_layers=tot,
                **kwargs,
            )
            if res is not None:
                num_injected += 1
        return target if num_injected > 0 else None

    # 2. Single layer injection
    try:
        src_attn = old_attn
        if src_attn is None and target is not None:
            for attr in ("attention", "self_attn", "attn", "self"):
                if hasattr(target, attr):
                    cand = getattr(target, attr)
                    if hasattr(cand, "self"):
                        src_attn = cand.self
                    else:
                        src_attn = cand
                    break

        if src_attn is None and target is not None and hasattr(target, "forward"):
            src_attn = target

        if src_attn is None:
            return None

        # Double-injection guard
        if src_attn is not None:
            if isinstance(src_attn, SOAAttention):
                return None
            if "SOA" in src_attn.__class__.__name__:
                return None
            if hasattr(src_attn, "inner") and isinstance(src_attn.inner, SOAAttention):
                return None
            if hasattr(src_attn, "_wrapped_attention") and isinstance(
                src_attn._wrapped_attention, SOAAttention
            ):
                return None

        if target is not None:
            for attr in ("attention", "self_attn", "attn", "self"):
                cand = getattr(target, attr, None)
                if cand is None:
                    continue
                if isinstance(cand, SOAAttention):
                    return None
                if "SOA" in cand.__class__.__name__:
                    return None
                if hasattr(cand, "inner") and isinstance(cand.inner, SOAAttention):
                    return None
                if hasattr(cand, "_wrapped_attention") and isinstance(
                    cand._wrapped_attention, SOAAttention
                ):
                    return None

        # Skip Qwen3.5 hybrid DeltaNet/LinearAttention layers
        if src_attn is not None:
            c_name = src_attn.__class__.__name__
            if "DeltaNet" in c_name or "LinearAttention" in c_name:
                return None

        if cfg is None and hasattr(src_attn, "config"):
            cfg = src_attn.config

        k_rank = getattr(
            comp_config,
            "soa_rank",
            getattr(comp_config, "rank", kwargs.pop("k_rank", 128)),
        )
        dropout = getattr(comp_config, "dropout", kwargs.pop("dropout", 0.1))

        new_attn = SOAAttention(
            config=cfg,
            k_rank=k_rank,
            dropout=dropout,
            pretrained_attn=src_attn,
            **kwargs,
        )

        if target is not None:
            if hasattr(target, "attention"):
                if hasattr(target.attention, "self"):
                    target.attention.self = new_attn
                    new_attn.is_nested_encoder = True
                else:
                    target.attention = new_attn
                return new_attn
            for attr in ("self_attn", "attn", "self"):
                if hasattr(target, attr):
                    setattr(target, attr, new_attn)
                    return new_attn
            target.attention = new_attn
            return new_attn
        return new_attn
    except Exception as e:
        logger.error("inject_soa_attn failed at layer %d: %s", layer_idx, e)
        return None

Safely replace attention module with hardened SOAAttention across diverse transformer architectures.

Classes

class FactorizedLinear (down: torch.nn.modules.linear.Linear, up: torch.nn.modules.linear.Linear)
Expand source code
class FactorizedLinear(nn.Module):
    def __init__(self, down: nn.Linear, up: nn.Linear) -> None:
        super().__init__()
        self.down = down
        self.up = up

    @property
    def weight(self) -> torch.Tensor:
        return torch.matmul(self.up.weight, self.down.weight)

    @property
    def bias(self) -> torch.Tensor | None:
        return getattr(self.up, "bias", None)

    @property
    def in_features(self) -> int:
        return self.down.in_features

    @property
    def out_features(self) -> int:
        return self.up.out_features

    def forward(self, x: torch.Tensor) -> torch.Tensor:
        orig_dtype = x.dtype
        x_down = x.to(self.down.weight.dtype)
        latent = self.down(x_down)
        latent_up = latent.to(self.up.weight.dtype)
        return self.up(latent_up).to(orig_dtype)

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

Instance variables

prop bias : torch.Tensor | None
Expand source code
@property
def bias(self) -> torch.Tensor | None:
    return getattr(self.up, "bias", None)
prop in_features : int
Expand source code
@property
def in_features(self) -> int:
    return self.down.in_features
prop out_features : int
Expand source code
@property
def out_features(self) -> int:
    return self.up.out_features
prop weight : torch.Tensor
Expand source code
@property
def weight(self) -> torch.Tensor:
    return torch.matmul(self.up.weight, self.down.weight)

Methods

def forward(self, x: torch.Tensor) ‑> torch.Tensor
Expand source code
def forward(self, x: torch.Tensor) -> torch.Tensor:
    orig_dtype = x.dtype
    x_down = x.to(self.down.weight.dtype)
    latent = self.down(x_down)
    latent_up = latent.to(self.up.weight.dtype)
    return self.up(latent_up).to(orig_dtype)

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:Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

class FactorizedLoRAUp (in_features: int,
out_features: int,
bias: bool = True,
lora_rank: int = 16,
lora_alpha: float = 32.0)
Expand source code
class FactorizedLoRAUp(nn.Module):
    """Up-projection with frozen base weight and trainable LoRA adapter."""

    def __init__(
        self,
        in_features: int,
        out_features: int,
        bias: bool = True,
        lora_rank: int = 16,
        lora_alpha: float = 32.0,
    ) -> None:
        super().__init__()
        self.in_features = in_features
        self.out_features = out_features
        self.lora_rank = lora_rank
        self.weight = nn.Parameter(torch.empty(out_features, in_features))
        if bias:
            self.bias = nn.Parameter(torch.empty(out_features))
        else:
            self.register_parameter("bias", None)
        nn.init.kaiming_uniform_(self.weight, a=math.sqrt(5))
        if self.bias is not None:
            fan_in, _ = nn.init._calculate_fan_in_and_fan_out(self.weight)
            bound = 1 / math.sqrt(fan_in) if fan_in > 0 else 0
            nn.init.uniform_(self.bias, -bound, bound)
        if lora_rank > 0:
            self.lora_A = nn.Parameter(torch.empty(lora_rank, in_features))
            self.lora_B = nn.Parameter(torch.empty(out_features, lora_rank))
            nn.init.kaiming_uniform_(self.lora_A, a=math.sqrt(5))
            nn.init.zeros_(self.lora_B)
            self.scaling = lora_alpha / lora_rank
        else:
            self.register_parameter("lora_A", None)
            self.register_parameter("lora_B", None)
            self.scaling = 1.0
        self.weight.requires_grad = False
        if self.bias is not None:
            self.bias.requires_grad = False

    def freeze_base_weights(self) -> None:
        self.weight.requires_grad = False
        if self.bias is not None:
            self.bias.requires_grad = False
        if self.lora_A is not None:
            self.lora_A.requires_grad = True
        if self.lora_B is not None:
            self.lora_B.requires_grad = True

    def forward(self, x: torch.Tensor) -> torch.Tensor:
        out = F.linear(x, self.weight, self.bias)
        if self.lora_rank > 0 and self.lora_A is not None and self.lora_B is not None:
            out = out + F.linear(F.linear(x, self.lora_A), self.lora_B) * self.scaling
        return out

Up-projection with frozen base weight and trainable LoRA adapter.

Initialize internal Module state, shared by both nn.Module and ScriptModule.

Ancestors

  • torch.nn.modules.module.Module

Methods

def forward(self, x: torch.Tensor) ‑> torch.Tensor
Expand source code
def forward(self, x: torch.Tensor) -> torch.Tensor:
    out = F.linear(x, self.weight, self.bias)
    if self.lora_rank > 0 and self.lora_A is not None and self.lora_B is not None:
        out = out + F.linear(F.linear(x, self.lora_A), self.lora_B) * self.scaling
    return out

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:Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

def freeze_base_weights(self) ‑> None
Expand source code
def freeze_base_weights(self) -> None:
    self.weight.requires_grad = False
    if self.bias is not None:
        self.bias.requires_grad = False
    if self.lora_A is not None:
        self.lora_A.requires_grad = True
    if self.lora_B is not None:
        self.lora_B.requires_grad = True
class LoRALinear (in_features: int,
out_features: int,
bias: bool = True,
lora_rank: int = 0,
lora_alpha: float = 1.0,
freeze_base: bool = True)
Expand source code
class LoRALinear(nn.Module):
    """Linear projection with frozen base weights and trainable LoRA adapters."""

    def __init__(
        self,
        in_features: int,
        out_features: int,
        bias: bool = True,
        lora_rank: int = 0,
        lora_alpha: float = 1.0,
        freeze_base: bool = True,
    ):
        super().__init__()
        self.in_features = in_features
        self.out_features = out_features
        self.lora_rank = lora_rank
        self.lora_alpha = lora_alpha
        self.scaling = lora_alpha / max(1, lora_rank)

        self.weight = nn.Parameter(torch.empty(out_features, in_features))
        if bias:
            self.bias = nn.Parameter(torch.empty(out_features))
        else:
            self.register_parameter("bias", None)

        nn.init.kaiming_uniform_(self.weight, a=math.sqrt(5))
        if self.bias is not None:
            fan_in, _ = nn.init._calculate_fan_in_and_fan_out(self.weight)
            bound = 1 / math.sqrt(fan_in) if fan_in > 0 else 0
            nn.init.uniform_(self.bias, -bound, bound)

        if lora_rank > 0:
            self.lora_A = nn.Parameter(torch.empty(lora_rank, in_features))
            self.lora_B = nn.Parameter(torch.empty(out_features, lora_rank))
            nn.init.kaiming_uniform_(self.lora_A, a=math.sqrt(5))
            nn.init.zeros_(self.lora_B)
        else:
            self.register_parameter("lora_A", None)
            self.register_parameter("lora_B", None)

        if freeze_base:
            self.freeze_base_weights()

    def freeze_base_weights(self) -> None:
        self.weight.requires_grad = False
        if self.bias is not None:
            self.bias.requires_grad = False
        if self.lora_rank > 0:
            if self.lora_A is not None:
                self.lora_A.requires_grad = True
            if self.lora_B is not None:
                self.lora_B.requires_grad = True

    def forward(self, x: torch.Tensor) -> torch.Tensor:
        out = F.linear(x, self.weight, self.bias)
        if self.lora_rank > 0 and self.lora_A is not None and self.lora_B is not None:
            lora_out = F.linear(F.linear(x, self.lora_A), self.lora_B) * self.scaling
            out = out + lora_out
        return out

Linear projection with frozen base weights and trainable LoRA adapters.

Initialize internal Module state, shared by both nn.Module and ScriptModule.

Ancestors

  • torch.nn.modules.module.Module

Methods

def forward(self, x: torch.Tensor) ‑> torch.Tensor
Expand source code
def forward(self, x: torch.Tensor) -> torch.Tensor:
    out = F.linear(x, self.weight, self.bias)
    if self.lora_rank > 0 and self.lora_A is not None and self.lora_B is not None:
        lora_out = F.linear(F.linear(x, self.lora_A), self.lora_B) * self.scaling
        out = out + lora_out
    return out

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:Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

def freeze_base_weights(self) ‑> None
Expand source code
def freeze_base_weights(self) -> None:
    self.weight.requires_grad = False
    if self.bias is not None:
        self.bias.requires_grad = False
    if self.lora_rank > 0:
        if self.lora_A is not None:
            self.lora_A.requires_grad = True
        if self.lora_B is not None:
            self.lora_B.requires_grad = True
class SOAAttention (config: Any | None = None,
model_config: Any | None = None,
rank: int | None = None,
k_rank: int = 64,
dropout: float = 0.1,
pretrained_attn: Any | None = None,
old_attn: Any | None = None,
lora_rank: int = 16,
lora_alpha: float = 32.0,
is_decoder: bool | None = None,
**kwargs: Any)
Expand source code
@ATTENTION_REGISTRY.register("soa_module", supports_causal=True, supports_gqa=True)
@ATTENTION_REGISTRY.register("soa_attn")
@ATTENTION_REGISTRY.register("soa_fused_module")
@ATTENTION_REGISTRY.register("soafusedattention")
@ATTENTION_REGISTRY.register("soa_fused_attn")
class SOAAttention(BaseAttention):
    r"""Shared Orthogonal Attention (SOA) with Per-Projection Latent Bottlenecks.

    Factorizes dense Q, K, and V linear projections into low-rank bottleneck pairs
    initialized via truncated SVD from pretrained transformer weights.
    """

    supports_gqa: bool = True
    is_custom_attention: bool = True

    def __init__(
        self,
        config: Any | None = None,
        model_config: Any | None = None,
        rank: int | None = None,
        k_rank: int = 64,
        dropout: float = 0.1,
        pretrained_attn: Any | None = None,
        old_attn: Any | None = None,
        lora_rank: int = 16,
        lora_alpha: float = 32.0,
        is_decoder: bool | None = None,
        **kwargs: Any,
    ) -> None:
        cfg = config or model_config or kwargs.get("config")
        src_attn = (
            pretrained_attn
            if pretrained_attn is not None
            else (old_attn if old_attn is not None else kwargs.get("source_attn"))
        )
        super().__init__(cfg, rank=k_rank, **kwargs)

        # 1. Architecture detection & dimensions
        self.hidden_size: int = (
            getattr(
                cfg,
                "hidden_size",
                getattr(cfg, "dim", kwargs.get("hidden_size", kwargs.get("dim", 768))),
            )
            if cfg is not None
            else kwargs.get("hidden_size", kwargs.get("dim", 768))
        )

        self.num_heads: int = (
            getattr(
                cfg,
                "num_attention_heads",
                getattr(
                    cfg,
                    "n_heads",
                    getattr(
                        cfg,
                        "num_heads",
                        kwargs.get("num_attention_heads", kwargs.get("num_heads", 12)),
                    ),
                ),
            )
            if cfg is not None
            else kwargs.get("num_attention_heads", kwargs.get("num_heads", 12))
        )
        self.num_heads = int(self.num_heads or 12)

        # Probe head_dim from source attention if available
        head_dim = kwargs.get("head_dim")
        if not head_dim and src_attn is not None:
            for attr in ("q_proj", "query", "q_lin"):
                mod = getattr(src_attn, attr, None)
                if mod is not None and hasattr(mod, "weight") and mod.weight is not None:
                    if mod.weight.ndim == 2:
                        head_dim = mod.weight.shape[0] // max(1, self.num_heads)
                        break
            if not head_dim:
                head_dim = getattr(src_attn, "head_dim", None)
        if not head_dim and cfg is not None:
            head_dim = getattr(cfg, "head_dim", None)
        if not head_dim or head_dim <= 0:
            head_dim = self.hidden_size // max(1, self.num_heads)
        self.head_dim = int(head_dim)

        cfg_kv = (
            getattr(
                cfg,
                "num_key_value_heads",
                getattr(
                    cfg,
                    "num_kv_heads",
                    kwargs.get("num_key_value_heads", kwargs.get("num_kv_heads")),
                ),
            )
            if cfg is not None
            else kwargs.get("num_key_value_heads", kwargs.get("num_kv_heads"))
        )
        self.num_kv_heads: int = int(cfg_kv) if cfg_kv is not None else self.num_heads
        self.num_key_value_groups: int = max(1, self.num_heads // max(1, self.num_kv_heads))
        self.kv_repeat: int = self.num_key_value_groups

        self.q_head_size: int = self.num_heads * self.head_dim
        self.kv_head_size: int = self.num_kv_heads * self.head_dim

        # Adaptive k_rank
        comp_config = getattr(cfg, "compression_config", None)
        if k_rank is None or k_rank == 64:
            effective_rank = getattr(
                comp_config,
                "k_rank",
                getattr(
                    comp_config,
                    "soa_rank",
                    rank if rank is not None else max(128, self.hidden_size // 4),
                ),
            )
        else:
            effective_rank = min(k_rank, self.hidden_size)
        self.k_rank: int = effective_rank
        self.rank = effective_rank
        self.lora_rank: int = lora_rank
        self.lora_alpha: float = lora_alpha

        # Decoder / Causal flag
        _mt = str(getattr(cfg, "model_type", "") or "").lower() if cfg else ""
        _decoder_prefixes = (
            "gpt",
            "qwen",
            "llama",
            "mistral",
            "gemma",
            "phi",
            "opt",
            "bloom",
            "falcon",
            "olmo",
            "mpt",
            "stablelm",
        )
        is_dec = (
            bool(_cfg_get(cfg, "is_decoder", False))
            or bool(_cfg_get(cfg, "is_causal", False))
            or any(_mt.startswith(p) for p in _decoder_prefixes)
            or (src_attn is not None and hasattr(src_attn, "c_attn"))
            or (src_attn is not None and getattr(src_attn, "is_causal", False))
            or (src_attn is not None and getattr(src_attn, "is_decoder", False))
            or bool(kwargs.get("is_causal", False))
            or bool(kwargs.get("is_decoder", False))
        )
        self.is_decoder: bool = is_dec
        self.is_causal: bool = is_dec
        self.is_nested_encoder: bool = False

        # 2. Factorized SVD linear projections for Q, K, V
        self.q_down = nn.Linear(self.hidden_size, self.k_rank, bias=False)
        self.q_up = FactorizedLoRAUp(
            self.k_rank,
            self.q_head_size,
            bias=True,
            lora_rank=self.lora_rank,
            lora_alpha=self.lora_alpha,
        )

        self.k_down = nn.Linear(self.hidden_size, self.k_rank, bias=False)
        self.k_up = FactorizedLoRAUp(
            self.k_rank,
            self.kv_head_size,
            bias=True,
            lora_rank=self.lora_rank,
            lora_alpha=self.lora_alpha,
        )

        self.v_down = nn.Linear(self.hidden_size, self.k_rank, bias=False)
        self.v_up = FactorizedLoRAUp(
            self.k_rank,
            self.kv_head_size,
            bias=True,
            lora_rank=self.lora_rank,
            lora_alpha=self.lora_alpha,
        )

        # Output projection with trainable LoRA adapter
        self.out_proj = LoRALinear(
            self.q_head_size,
            self.hidden_size,
            bias=True,
            lora_rank=self.lora_rank,
            lora_alpha=self.lora_alpha,
            freeze_base=True,
        )

        dropout_p = (
            getattr(cfg, "dropout", getattr(cfg, "attention_probs_dropout_prob", dropout))
            if cfg is not None
            else dropout
        )
        self.dropout = nn.Dropout(dropout_p)

        target_dtype = kwargs.get("dtype")
        if target_dtype is None and src_attn is not None:
            target_dtype = next(src_attn.parameters(), torch.tensor([])).dtype
            if not isinstance(target_dtype, torch.dtype):
                target_dtype = torch.float32

        # 3. Pretrained weight transfer
        if src_attn is not None:
            self.copy_weights(src_attn)

        if target_dtype is not None:
            self.to(target_dtype)

    @property
    def q_proj(self) -> FactorizedLinear:
        return FactorizedLinear(self.q_down, self.q_up)

    @property
    def k_proj(self) -> FactorizedLinear:
        return FactorizedLinear(self.k_down, self.k_up)

    @property
    def v_proj(self) -> FactorizedLinear:
        return FactorizedLinear(self.v_down, self.v_up)

    @property
    def query(self) -> FactorizedLinear:
        return self.q_proj

    @property
    def key(self) -> FactorizedLinear:
        return self.k_proj

    @property
    def value(self) -> FactorizedLinear:
        return self.v_proj

    def copy_weights(self, old_attn: nn.Module) -> None:
        """Robust weight extraction and SVD factorization across all architectures."""
        with torch.no_grad():
            w_q, b_q = None, None
            w_k, b_k = None, None
            w_v, b_v = None, None
            w_o, b_o = None, None

            # Check nested encoder container
            src_cls_name = getattr(old_attn, "__class__", type(old_attn)).__name__
            has_out_lin = (
                hasattr(old_attn, "out_lin")
                or hasattr(old_attn, "c_proj")
                or hasattr(old_attn, "o_proj")
                or hasattr(old_attn, "dense")
            )
            if src_cls_name in ("BertSelfAttention", "RobertaSelfAttention") or (
                hasattr(old_attn, "query") and not has_out_lin
            ):
                self.is_nested_encoder = True

            if hasattr(old_attn, "self") and hasattr(old_attn, "output"):
                self.is_nested_encoder = True
                src = old_attn.self
                if hasattr(old_attn.output, "dense"):
                    w_o = old_attn.output.dense.weight
                    b_o = old_attn.output.dense.bias
            else:
                src = old_attn

            # Pattern 1: GPT-2 Fused c_attn
            if hasattr(src, "c_attn") and hasattr(src, "c_proj"):
                self.is_decoder = True
                self.is_causal = True

                c_attn_mod = src.c_attn
                base_c = getattr(c_attn_mod, "base_layer", c_attn_mod)
                c_attn_w = getattr(base_c, "weight", getattr(c_attn_mod, "weight", None)).detach()
                c_attn_b = getattr(base_c, "bias", getattr(c_attn_mod, "bias", None))
                c_attn_b = c_attn_b.detach() if c_attn_b is not None else None

                c_cls = getattr(base_c, "__class__", type(base_c)).__name__
                if (
                    ("Conv1D" in c_cls)
                    or hasattr(base_c, "nf")
                    or ("Conv1D" in getattr(c_attn_mod, "__class__", type(c_attn_mod)).__name__)
                    or hasattr(c_attn_mod, "nf")
                    or (c_attn_w.dim() == 2 and c_attn_w.shape[0] < c_attn_w.shape[1])
                ):
                    c_attn_w = c_attn_w.t().contiguous()

                q_dim = self.q_head_size
                k_dim = self.kv_head_size
                v_dim = self.kv_head_size

                w_q = c_attn_w[:q_dim, :]
                w_k = c_attn_w[q_dim : q_dim + k_dim, :]
                w_v = c_attn_w[q_dim + k_dim : q_dim + k_dim + v_dim, :]

                if c_attn_b is not None:
                    b_q = c_attn_b[:q_dim]
                    b_k = c_attn_b[q_dim : q_dim + k_dim]
                    b_v = c_attn_b[q_dim + k_dim : q_dim + k_dim + v_dim]

                c_proj_mod = src.c_proj
                base_p = getattr(c_proj_mod, "base_layer", c_proj_mod)
                out_w = getattr(base_p, "weight", getattr(c_proj_mod, "weight", None)).detach()
                b_o = getattr(base_p, "bias", getattr(c_proj_mod, "bias", None))
                b_o = b_o.detach() if b_o is not None else None

                p_cls = getattr(base_p, "__class__", type(base_p)).__name__
                if (
                    ("Conv1D" in p_cls)
                    or hasattr(base_p, "nf")
                    or ("Conv1D" in getattr(c_proj_mod, "__class__", type(c_proj_mod)).__name__)
                    or hasattr(c_proj_mod, "nf")
                    or (out_w.dim() == 2 and out_w.shape[0] < out_w.shape[1])
                ):
                    out_w = out_w.t().contiguous()
                w_o = out_w

            # Pattern 2: RoBERTa / BERT separate query, key, value
            elif hasattr(src, "query") and hasattr(src, "key") and hasattr(src, "value"):
                w_q = src.query.weight.detach()
                b_q = src.query.bias.detach() if src.query.bias is not None else None
                w_k = src.key.weight.detach()
                b_k = src.key.bias.detach() if src.key.bias is not None else None
                w_v = src.value.weight.detach()
                b_v = src.value.bias.detach() if src.value.bias is not None else None

                if w_o is None:
                    for attr in ("dense", "out_proj", "o_proj"):
                        if hasattr(src, attr):
                            proj = getattr(src, attr)
                            w_o = proj.weight.detach()
                            b_o = proj.bias.detach() if proj.bias is not None else None
                            break

            # Pattern 3: Qwen / LLaMA (q_proj, k_proj, v_proj, o_proj)
            elif hasattr(src, "q_proj") and hasattr(src, "k_proj") and hasattr(src, "v_proj"):
                w_q = src.q_proj.weight.detach()
                b_q = src.q_proj.bias.detach() if src.q_proj.bias is not None else None
                w_k = src.k_proj.weight.detach()
                b_k = src.k_proj.bias.detach() if src.k_proj.bias is not None else None
                w_v = src.v_proj.weight.detach()
                b_v = src.v_proj.bias.detach() if src.v_proj.bias is not None else None

                if hasattr(src, "o_proj"):
                    w_o = src.o_proj.weight.detach()
                    b_o = src.o_proj.bias.detach() if src.o_proj.bias is not None else None

            # Pattern 4: DistilBERT (q_lin, k_lin, v_lin, out_lin)
            elif hasattr(src, "q_lin") and hasattr(src, "k_lin") and hasattr(src, "v_lin"):
                w_q = src.q_lin.weight.detach()
                b_q = src.q_lin.bias.detach() if src.q_lin.bias is not None else None
                w_k = src.k_lin.weight.detach()
                b_k = src.k_lin.bias.detach() if src.k_lin.bias is not None else None
                w_v = src.v_lin.weight.detach()
                b_v = src.v_lin.bias.detach() if src.v_lin.bias is not None else None

                if hasattr(src, "out_lin"):
                    w_o = src.out_lin.weight.detach()
                    b_o = src.out_lin.bias.detach() if src.out_lin.bias is not None else None

            # Pattern 5: UniversalAdapter fallback
            if w_q is None or w_k is None or w_v is None:
                try:
                    adapter = UniversalAdapter()
                    w_q, b_q = adapter.get_weight_bias(src, "q")
                    w_k, b_k = adapter.get_weight_bias(src, "k")
                    w_v, b_v = adapter.get_weight_bias(src, "v")
                    if w_o is None:
                        w_o, b_o = adapter.get_weight_bias(src, "o")
                except Exception:
                    pass

            # Strict validation
            missing = []
            if w_q is None:
                missing.append("Q projection")
            if w_k is None:
                missing.append("K projection")
            if w_v is None:
                missing.append("V projection")
            if w_o is None and not self.is_nested_encoder:
                missing.append("Out projection")

            if missing:
                raise RuntimeError(
                    f"SOAAttention: Failed to extract weights: {', '.join(missing)} from {type(old_attn)}"
                )

            # SVD Factorization helper
            def _factorize_svd(
                W: torch.Tensor,
                down: nn.Linear,
                up: nn.Linear,
                bias: torch.Tensor | None,
            ) -> None:
                W_f = W.float()
                U, S, Vt = torch.linalg.svd(W_f, full_matrices=False)
                S = S.clamp(min=1e-6)
                r = min(self.k_rank, U.size(1), Vt.size(0))

                down.weight.zero_()
                up.weight.zero_()
                sqrt_s = torch.sqrt(S[:r])
                down.weight[:r, :].copy_((sqrt_s.unsqueeze(1) * Vt[:r, :]).to(down.weight.dtype))
                up.weight[:, :r].copy_((U[:, :r] * sqrt_s).to(up.weight.dtype))

                if bias is not None and up.bias is not None:
                    up.bias.copy_(bias.to(up.bias.dtype))
                elif up.bias is not None:
                    up.bias.zero_()

                # Frobenius check
                rec = up.weight @ down.weight
                f_norm = float(torch.linalg.norm(rec))
                if f_norm < 1e-4:
                    logger.warning(
                        f"SOAAttention: SVD reconstructed weight norm is near zero: {f_norm}"
                    )

            _factorize_svd(w_q, self.q_down, self.q_up, b_q)
            _factorize_svd(w_k, self.k_down, self.k_up, b_k)
            _factorize_svd(w_v, self.v_down, self.v_up, b_v)

            if w_o is not None and not self.is_nested_encoder:
                self.out_proj.weight.copy_(w_o.to(self.out_proj.weight.dtype))
                if b_o is not None and self.out_proj.bias is not None:
                    self.out_proj.bias.copy_(b_o.to(self.out_proj.bias.dtype))
                f_norm_o = float(torch.linalg.norm(self.out_proj.weight))
                if f_norm_o < 1e-4:
                    logger.warning(f"SOAAttention: Out projection norm is near zero: {f_norm_o}")
            elif self.is_nested_encoder:
                if hasattr(self.out_proj, "weight") and self.out_proj.weight.ndim == 2:
                    nn.init.eye_(self.out_proj.weight)
                if hasattr(self.out_proj, "bias") and self.out_proj.bias is not None:
                    nn.init.zeros_(self.out_proj.bias)

            # Freeze base weights
            for mod in [self.q_down, self.k_down, self.v_down]:
                mod.weight.requires_grad = False
                if getattr(mod, "bias", None) is not None:
                    mod.bias.requires_grad = False
            for mod in [self.q_up, self.k_up, self.v_up]:
                if hasattr(mod, "freeze_base_weights"):
                    mod.freeze_base_weights()
                else:
                    mod.weight.requires_grad = False
                    if getattr(mod, "bias", None) is not None:
                        mod.bias.requires_grad = False
                    if getattr(mod, "lora_A", None) is not None:
                        mod.lora_A.requires_grad = True
                    if getattr(mod, "lora_B", None) is not None:
                        mod.lora_B.requires_grad = True
            if hasattr(self.out_proj, "freeze_base_weights"):
                self.out_proj.freeze_base_weights()
            else:
                self.out_proj.weight.requires_grad = False
                if getattr(self.out_proj, "bias", None) is not None:
                    self.out_proj.bias.requires_grad = False
                if getattr(self.out_proj, "lora_A", None) is not None:
                    self.out_proj.lora_A.requires_grad = True
                if getattr(self.out_proj, "lora_B", None) is not None:
                    self.out_proj.lora_B.requires_grad = True

    @classmethod
    def from_distilbert_pretrained(
        cls, old_attn: nn.Module, model_config: Any | None = None, **kwargs: Any
    ) -> "SOAAttention":
        return cls(model_config=model_config, pretrained_attn=old_attn, **kwargs)

    def forward(
        self,
        hidden_states: torch.Tensor,
        attention_mask: torch.Tensor | None = None,
        head_mask: torch.Tensor | None = None,
        encoder_hidden_states: torch.Tensor | None = None,
        encoder_attention_mask: torch.Tensor | None = None,
        past_key_value: Any | None = None,
        output_attentions: bool | None = False,
        output_hidden_states: bool | None = False,
        return_dict: bool | None = True,
        *args: Any,
        **kwargs: Any,
    ) -> tuple[torch.Tensor, torch.Tensor | None] | torch.Tensor:
        B, N, _ = hidden_states.shape

        # Factorized projections
        z_q = self.q_down(hidden_states)
        z_k = self.k_down(hidden_states)
        z_v = self.v_down(hidden_states)

        q = self.q_up(z_q)
        k = self.k_up(z_k)
        v = self.v_up(z_v)

        H = self.num_heads
        H_kv = self.num_kv_heads
        D = self.head_dim

        q = q.view(B, N, H, D).transpose(1, 2).contiguous()
        k = k.view(B, N, H_kv, D).transpose(1, 2).contiguous()
        v = v.view(B, N, H_kv, D).transpose(1, 2).contiguous()

        # Partial Rotary Position Embeddings (RoPE)
        pos_emb = kwargs.get("position_embeddings")
        if pos_emb is not None and isinstance(pos_emb, tuple) and len(pos_emb) == 2:
            cos, sin = pos_emb
            q, k = apply_rotary_pos_emb(q, k, cos, sin)

        # Grouped-Query Attention expansion
        if H_kv != H:
            k = repeat_kv(k, self.num_key_value_groups)
            v = repeat_kv(v, self.num_key_value_groups)

        scale = 1.0 / math.sqrt(D)
        # Memory-efficient: use SDPA to avoid OOM on large seqs

        try:
            _qs = q.half() if q.dtype == torch.float32 else q

            _ks = k.half() if k.dtype == torch.float32 else k

            _vs = v.half() if v.dtype == torch.float32 else v

            _sdpa_out = torch.nn.functional.scaled_dot_product_attention(
                _qs,
                _ks,
                _vs,
                is_causal=getattr(self, "is_decoder", False) and N > 1,
                dropout_p=self.dropout.p if self.training else 0.0,
            )

            _sdpa_out = (
                _sdpa_out.to(hidden_states.dtype)
                .transpose(1, 2)
                .contiguous()
                .view(B, N, self.all_head_size)
            )

            _sdpa_out = torch.nan_to_num(_sdpa_out, nan=0.0, posinf=1e4, neginf=-1e4)

            return (
                self.out_proj(_sdpa_out)
                if not getattr(self, "is_nested_encoder", False)
                else _sdpa_out
            ), None

        except Exception:
            pass

        scores = torch.matmul(q.float(), k.float().transpose(-2, -1).contiguous()) * scale

        # Causal mask for decoders
        is_causal = (
            self.is_decoder or getattr(self, "is_causal", False) or kwargs.get("is_causal", False)
        ) and (encoder_hidden_states is None)
        if is_causal and N > 1:
            causal_mask = (
                torch.triu(
                    torch.full((N, N), float("-inf"), device=scores.device, dtype=torch.float32),
                    diagonal=1,
                )
                .unsqueeze(0)
                .unsqueeze(0)
            )
            scores = scores + causal_mask

        # Standard Attention Mask
        mask = attention_mask if attention_mask is not None else kwargs.get("attn_mask")
        if mask is not None:
            if mask.dim() == 4 and mask.dtype == torch.bool:
                scores = scores.masked_fill(~mask, -10000.0)
            else:
                scores = apply_attention_mask(scores, mask)

        attn_weights = F.softmax(scores, dim=-1)
        attn_weights = torch.nan_to_num(attn_weights, nan=0.0)
        attn_weights = self.dropout(attn_weights.to(v.dtype))

        if head_mask is not None:
            if head_mask.dim() == 1:
                head_mask = head_mask.view(1, -1, 1, 1)
            elif head_mask.dim() == 2:
                head_mask = head_mask.view(head_mask.size(0), head_mask.size(1), 1, 1)
            attn_weights = attn_weights * head_mask

        context = torch.matmul(attn_weights, v)
        context = context.transpose(1, 2).contiguous().view(B, N, H * D)

        if self.is_nested_encoder:
            return (context, attn_weights if output_attentions else None)

        output = self.out_proj(context)
        return (output, attn_weights if output_attentions else None)

Shared Orthogonal Attention (SOA) with Per-Projection Latent Bottlenecks.

Factorizes dense Q, K, and V linear projections into low-rank bottleneck pairs initialized via truncated SVD from pretrained transformer weights.

Initialize internal Module state, shared by both nn.Module and ScriptModule.

Ancestors

Class variables

var is_custom_attention : bool

The type of the None singleton.

var supports_gqa : bool

The type of the None singleton.

Static methods

def from_distilbert_pretrained(old_attn: torch.nn.modules.module.Module,
model_config: Any | None = None,
**kwargs: Any) ‑> SOAAttention

Instance variables

prop k_proj : FactorizedLinear
Expand source code
@property
def k_proj(self) -> FactorizedLinear:
    return FactorizedLinear(self.k_down, self.k_up)
prop key : FactorizedLinear
Expand source code
@property
def key(self) -> FactorizedLinear:
    return self.k_proj
prop q_proj : FactorizedLinear
Expand source code
@property
def q_proj(self) -> FactorizedLinear:
    return FactorizedLinear(self.q_down, self.q_up)
prop query : FactorizedLinear
Expand source code
@property
def query(self) -> FactorizedLinear:
    return self.q_proj
prop v_proj : FactorizedLinear
Expand source code
@property
def v_proj(self) -> FactorizedLinear:
    return FactorizedLinear(self.v_down, self.v_up)
prop value : FactorizedLinear
Expand source code
@property
def value(self) -> FactorizedLinear:
    return self.v_proj

Methods

def copy_weights(self, old_attn: torch.nn.modules.module.Module) ‑> None
Expand source code
def copy_weights(self, old_attn: nn.Module) -> None:
    """Robust weight extraction and SVD factorization across all architectures."""
    with torch.no_grad():
        w_q, b_q = None, None
        w_k, b_k = None, None
        w_v, b_v = None, None
        w_o, b_o = None, None

        # Check nested encoder container
        src_cls_name = getattr(old_attn, "__class__", type(old_attn)).__name__
        has_out_lin = (
            hasattr(old_attn, "out_lin")
            or hasattr(old_attn, "c_proj")
            or hasattr(old_attn, "o_proj")
            or hasattr(old_attn, "dense")
        )
        if src_cls_name in ("BertSelfAttention", "RobertaSelfAttention") or (
            hasattr(old_attn, "query") and not has_out_lin
        ):
            self.is_nested_encoder = True

        if hasattr(old_attn, "self") and hasattr(old_attn, "output"):
            self.is_nested_encoder = True
            src = old_attn.self
            if hasattr(old_attn.output, "dense"):
                w_o = old_attn.output.dense.weight
                b_o = old_attn.output.dense.bias
        else:
            src = old_attn

        # Pattern 1: GPT-2 Fused c_attn
        if hasattr(src, "c_attn") and hasattr(src, "c_proj"):
            self.is_decoder = True
            self.is_causal = True

            c_attn_mod = src.c_attn
            base_c = getattr(c_attn_mod, "base_layer", c_attn_mod)
            c_attn_w = getattr(base_c, "weight", getattr(c_attn_mod, "weight", None)).detach()
            c_attn_b = getattr(base_c, "bias", getattr(c_attn_mod, "bias", None))
            c_attn_b = c_attn_b.detach() if c_attn_b is not None else None

            c_cls = getattr(base_c, "__class__", type(base_c)).__name__
            if (
                ("Conv1D" in c_cls)
                or hasattr(base_c, "nf")
                or ("Conv1D" in getattr(c_attn_mod, "__class__", type(c_attn_mod)).__name__)
                or hasattr(c_attn_mod, "nf")
                or (c_attn_w.dim() == 2 and c_attn_w.shape[0] < c_attn_w.shape[1])
            ):
                c_attn_w = c_attn_w.t().contiguous()

            q_dim = self.q_head_size
            k_dim = self.kv_head_size
            v_dim = self.kv_head_size

            w_q = c_attn_w[:q_dim, :]
            w_k = c_attn_w[q_dim : q_dim + k_dim, :]
            w_v = c_attn_w[q_dim + k_dim : q_dim + k_dim + v_dim, :]

            if c_attn_b is not None:
                b_q = c_attn_b[:q_dim]
                b_k = c_attn_b[q_dim : q_dim + k_dim]
                b_v = c_attn_b[q_dim + k_dim : q_dim + k_dim + v_dim]

            c_proj_mod = src.c_proj
            base_p = getattr(c_proj_mod, "base_layer", c_proj_mod)
            out_w = getattr(base_p, "weight", getattr(c_proj_mod, "weight", None)).detach()
            b_o = getattr(base_p, "bias", getattr(c_proj_mod, "bias", None))
            b_o = b_o.detach() if b_o is not None else None

            p_cls = getattr(base_p, "__class__", type(base_p)).__name__
            if (
                ("Conv1D" in p_cls)
                or hasattr(base_p, "nf")
                or ("Conv1D" in getattr(c_proj_mod, "__class__", type(c_proj_mod)).__name__)
                or hasattr(c_proj_mod, "nf")
                or (out_w.dim() == 2 and out_w.shape[0] < out_w.shape[1])
            ):
                out_w = out_w.t().contiguous()
            w_o = out_w

        # Pattern 2: RoBERTa / BERT separate query, key, value
        elif hasattr(src, "query") and hasattr(src, "key") and hasattr(src, "value"):
            w_q = src.query.weight.detach()
            b_q = src.query.bias.detach() if src.query.bias is not None else None
            w_k = src.key.weight.detach()
            b_k = src.key.bias.detach() if src.key.bias is not None else None
            w_v = src.value.weight.detach()
            b_v = src.value.bias.detach() if src.value.bias is not None else None

            if w_o is None:
                for attr in ("dense", "out_proj", "o_proj"):
                    if hasattr(src, attr):
                        proj = getattr(src, attr)
                        w_o = proj.weight.detach()
                        b_o = proj.bias.detach() if proj.bias is not None else None
                        break

        # Pattern 3: Qwen / LLaMA (q_proj, k_proj, v_proj, o_proj)
        elif hasattr(src, "q_proj") and hasattr(src, "k_proj") and hasattr(src, "v_proj"):
            w_q = src.q_proj.weight.detach()
            b_q = src.q_proj.bias.detach() if src.q_proj.bias is not None else None
            w_k = src.k_proj.weight.detach()
            b_k = src.k_proj.bias.detach() if src.k_proj.bias is not None else None
            w_v = src.v_proj.weight.detach()
            b_v = src.v_proj.bias.detach() if src.v_proj.bias is not None else None

            if hasattr(src, "o_proj"):
                w_o = src.o_proj.weight.detach()
                b_o = src.o_proj.bias.detach() if src.o_proj.bias is not None else None

        # Pattern 4: DistilBERT (q_lin, k_lin, v_lin, out_lin)
        elif hasattr(src, "q_lin") and hasattr(src, "k_lin") and hasattr(src, "v_lin"):
            w_q = src.q_lin.weight.detach()
            b_q = src.q_lin.bias.detach() if src.q_lin.bias is not None else None
            w_k = src.k_lin.weight.detach()
            b_k = src.k_lin.bias.detach() if src.k_lin.bias is not None else None
            w_v = src.v_lin.weight.detach()
            b_v = src.v_lin.bias.detach() if src.v_lin.bias is not None else None

            if hasattr(src, "out_lin"):
                w_o = src.out_lin.weight.detach()
                b_o = src.out_lin.bias.detach() if src.out_lin.bias is not None else None

        # Pattern 5: UniversalAdapter fallback
        if w_q is None or w_k is None or w_v is None:
            try:
                adapter = UniversalAdapter()
                w_q, b_q = adapter.get_weight_bias(src, "q")
                w_k, b_k = adapter.get_weight_bias(src, "k")
                w_v, b_v = adapter.get_weight_bias(src, "v")
                if w_o is None:
                    w_o, b_o = adapter.get_weight_bias(src, "o")
            except Exception:
                pass

        # Strict validation
        missing = []
        if w_q is None:
            missing.append("Q projection")
        if w_k is None:
            missing.append("K projection")
        if w_v is None:
            missing.append("V projection")
        if w_o is None and not self.is_nested_encoder:
            missing.append("Out projection")

        if missing:
            raise RuntimeError(
                f"SOAAttention: Failed to extract weights: {', '.join(missing)} from {type(old_attn)}"
            )

        # SVD Factorization helper
        def _factorize_svd(
            W: torch.Tensor,
            down: nn.Linear,
            up: nn.Linear,
            bias: torch.Tensor | None,
        ) -> None:
            W_f = W.float()
            U, S, Vt = torch.linalg.svd(W_f, full_matrices=False)
            S = S.clamp(min=1e-6)
            r = min(self.k_rank, U.size(1), Vt.size(0))

            down.weight.zero_()
            up.weight.zero_()
            sqrt_s = torch.sqrt(S[:r])
            down.weight[:r, :].copy_((sqrt_s.unsqueeze(1) * Vt[:r, :]).to(down.weight.dtype))
            up.weight[:, :r].copy_((U[:, :r] * sqrt_s).to(up.weight.dtype))

            if bias is not None and up.bias is not None:
                up.bias.copy_(bias.to(up.bias.dtype))
            elif up.bias is not None:
                up.bias.zero_()

            # Frobenius check
            rec = up.weight @ down.weight
            f_norm = float(torch.linalg.norm(rec))
            if f_norm < 1e-4:
                logger.warning(
                    f"SOAAttention: SVD reconstructed weight norm is near zero: {f_norm}"
                )

        _factorize_svd(w_q, self.q_down, self.q_up, b_q)
        _factorize_svd(w_k, self.k_down, self.k_up, b_k)
        _factorize_svd(w_v, self.v_down, self.v_up, b_v)

        if w_o is not None and not self.is_nested_encoder:
            self.out_proj.weight.copy_(w_o.to(self.out_proj.weight.dtype))
            if b_o is not None and self.out_proj.bias is not None:
                self.out_proj.bias.copy_(b_o.to(self.out_proj.bias.dtype))
            f_norm_o = float(torch.linalg.norm(self.out_proj.weight))
            if f_norm_o < 1e-4:
                logger.warning(f"SOAAttention: Out projection norm is near zero: {f_norm_o}")
        elif self.is_nested_encoder:
            if hasattr(self.out_proj, "weight") and self.out_proj.weight.ndim == 2:
                nn.init.eye_(self.out_proj.weight)
            if hasattr(self.out_proj, "bias") and self.out_proj.bias is not None:
                nn.init.zeros_(self.out_proj.bias)

        # Freeze base weights
        for mod in [self.q_down, self.k_down, self.v_down]:
            mod.weight.requires_grad = False
            if getattr(mod, "bias", None) is not None:
                mod.bias.requires_grad = False
        for mod in [self.q_up, self.k_up, self.v_up]:
            if hasattr(mod, "freeze_base_weights"):
                mod.freeze_base_weights()
            else:
                mod.weight.requires_grad = False
                if getattr(mod, "bias", None) is not None:
                    mod.bias.requires_grad = False
                if getattr(mod, "lora_A", None) is not None:
                    mod.lora_A.requires_grad = True
                if getattr(mod, "lora_B", None) is not None:
                    mod.lora_B.requires_grad = True
        if hasattr(self.out_proj, "freeze_base_weights"):
            self.out_proj.freeze_base_weights()
        else:
            self.out_proj.weight.requires_grad = False
            if getattr(self.out_proj, "bias", None) is not None:
                self.out_proj.bias.requires_grad = False
            if getattr(self.out_proj, "lora_A", None) is not None:
                self.out_proj.lora_A.requires_grad = True
            if getattr(self.out_proj, "lora_B", None) is not None:
                self.out_proj.lora_B.requires_grad = True

Robust weight extraction and SVD factorization across all architectures.

def forward(self,
hidden_states: torch.Tensor,
attention_mask: torch.Tensor | None = None,
head_mask: torch.Tensor | None = None,
encoder_hidden_states: torch.Tensor | None = None,
encoder_attention_mask: torch.Tensor | None = None,
past_key_value: Any | None = None,
output_attentions: bool | None = False,
output_hidden_states: bool | None = False,
return_dict: bool | None = True,
*args: Any,
**kwargs: Any) ‑> tuple[torch.Tensor, torch.Tensor | None] | torch.Tensor
Expand source code
def forward(
    self,
    hidden_states: torch.Tensor,
    attention_mask: torch.Tensor | None = None,
    head_mask: torch.Tensor | None = None,
    encoder_hidden_states: torch.Tensor | None = None,
    encoder_attention_mask: torch.Tensor | None = None,
    past_key_value: Any | None = None,
    output_attentions: bool | None = False,
    output_hidden_states: bool | None = False,
    return_dict: bool | None = True,
    *args: Any,
    **kwargs: Any,
) -> tuple[torch.Tensor, torch.Tensor | None] | torch.Tensor:
    B, N, _ = hidden_states.shape

    # Factorized projections
    z_q = self.q_down(hidden_states)
    z_k = self.k_down(hidden_states)
    z_v = self.v_down(hidden_states)

    q = self.q_up(z_q)
    k = self.k_up(z_k)
    v = self.v_up(z_v)

    H = self.num_heads
    H_kv = self.num_kv_heads
    D = self.head_dim

    q = q.view(B, N, H, D).transpose(1, 2).contiguous()
    k = k.view(B, N, H_kv, D).transpose(1, 2).contiguous()
    v = v.view(B, N, H_kv, D).transpose(1, 2).contiguous()

    # Partial Rotary Position Embeddings (RoPE)
    pos_emb = kwargs.get("position_embeddings")
    if pos_emb is not None and isinstance(pos_emb, tuple) and len(pos_emb) == 2:
        cos, sin = pos_emb
        q, k = apply_rotary_pos_emb(q, k, cos, sin)

    # Grouped-Query Attention expansion
    if H_kv != H:
        k = repeat_kv(k, self.num_key_value_groups)
        v = repeat_kv(v, self.num_key_value_groups)

    scale = 1.0 / math.sqrt(D)
    # Memory-efficient: use SDPA to avoid OOM on large seqs

    try:
        _qs = q.half() if q.dtype == torch.float32 else q

        _ks = k.half() if k.dtype == torch.float32 else k

        _vs = v.half() if v.dtype == torch.float32 else v

        _sdpa_out = torch.nn.functional.scaled_dot_product_attention(
            _qs,
            _ks,
            _vs,
            is_causal=getattr(self, "is_decoder", False) and N > 1,
            dropout_p=self.dropout.p if self.training else 0.0,
        )

        _sdpa_out = (
            _sdpa_out.to(hidden_states.dtype)
            .transpose(1, 2)
            .contiguous()
            .view(B, N, self.all_head_size)
        )

        _sdpa_out = torch.nan_to_num(_sdpa_out, nan=0.0, posinf=1e4, neginf=-1e4)

        return (
            self.out_proj(_sdpa_out)
            if not getattr(self, "is_nested_encoder", False)
            else _sdpa_out
        ), None

    except Exception:
        pass

    scores = torch.matmul(q.float(), k.float().transpose(-2, -1).contiguous()) * scale

    # Causal mask for decoders
    is_causal = (
        self.is_decoder or getattr(self, "is_causal", False) or kwargs.get("is_causal", False)
    ) and (encoder_hidden_states is None)
    if is_causal and N > 1:
        causal_mask = (
            torch.triu(
                torch.full((N, N), float("-inf"), device=scores.device, dtype=torch.float32),
                diagonal=1,
            )
            .unsqueeze(0)
            .unsqueeze(0)
        )
        scores = scores + causal_mask

    # Standard Attention Mask
    mask = attention_mask if attention_mask is not None else kwargs.get("attn_mask")
    if mask is not None:
        if mask.dim() == 4 and mask.dtype == torch.bool:
            scores = scores.masked_fill(~mask, -10000.0)
        else:
            scores = apply_attention_mask(scores, mask)

    attn_weights = F.softmax(scores, dim=-1)
    attn_weights = torch.nan_to_num(attn_weights, nan=0.0)
    attn_weights = self.dropout(attn_weights.to(v.dtype))

    if head_mask is not None:
        if head_mask.dim() == 1:
            head_mask = head_mask.view(1, -1, 1, 1)
        elif head_mask.dim() == 2:
            head_mask = head_mask.view(head_mask.size(0), head_mask.size(1), 1, 1)
        attn_weights = attn_weights * head_mask

    context = torch.matmul(attn_weights, v)
    context = context.transpose(1, 2).contiguous().view(B, N, H * D)

    if self.is_nested_encoder:
        return (context, attn_weights if output_attentions else None)

    output = self.out_proj(context)
    return (output, attn_weights if output_attentions else None)

Must return (output, attention_weights_or_None).

class SOAFusedAttention (config: Any | None = None,
model_config: Any | None = None,
rank: int | None = None,
k_rank: int = 64,
dropout: float = 0.1,
pretrained_attn: Any | None = None,
old_attn: Any | None = None,
lora_rank: int = 16,
lora_alpha: float = 32.0,
is_decoder: bool | None = None,
**kwargs: Any)
Expand source code
@ATTENTION_REGISTRY.register("soa_module", supports_causal=True, supports_gqa=True)
@ATTENTION_REGISTRY.register("soa_attn")
@ATTENTION_REGISTRY.register("soa_fused_module")
@ATTENTION_REGISTRY.register("soafusedattention")
@ATTENTION_REGISTRY.register("soa_fused_attn")
class SOAAttention(BaseAttention):
    r"""Shared Orthogonal Attention (SOA) with Per-Projection Latent Bottlenecks.

    Factorizes dense Q, K, and V linear projections into low-rank bottleneck pairs
    initialized via truncated SVD from pretrained transformer weights.
    """

    supports_gqa: bool = True
    is_custom_attention: bool = True

    def __init__(
        self,
        config: Any | None = None,
        model_config: Any | None = None,
        rank: int | None = None,
        k_rank: int = 64,
        dropout: float = 0.1,
        pretrained_attn: Any | None = None,
        old_attn: Any | None = None,
        lora_rank: int = 16,
        lora_alpha: float = 32.0,
        is_decoder: bool | None = None,
        **kwargs: Any,
    ) -> None:
        cfg = config or model_config or kwargs.get("config")
        src_attn = (
            pretrained_attn
            if pretrained_attn is not None
            else (old_attn if old_attn is not None else kwargs.get("source_attn"))
        )
        super().__init__(cfg, rank=k_rank, **kwargs)

        # 1. Architecture detection & dimensions
        self.hidden_size: int = (
            getattr(
                cfg,
                "hidden_size",
                getattr(cfg, "dim", kwargs.get("hidden_size", kwargs.get("dim", 768))),
            )
            if cfg is not None
            else kwargs.get("hidden_size", kwargs.get("dim", 768))
        )

        self.num_heads: int = (
            getattr(
                cfg,
                "num_attention_heads",
                getattr(
                    cfg,
                    "n_heads",
                    getattr(
                        cfg,
                        "num_heads",
                        kwargs.get("num_attention_heads", kwargs.get("num_heads", 12)),
                    ),
                ),
            )
            if cfg is not None
            else kwargs.get("num_attention_heads", kwargs.get("num_heads", 12))
        )
        self.num_heads = int(self.num_heads or 12)

        # Probe head_dim from source attention if available
        head_dim = kwargs.get("head_dim")
        if not head_dim and src_attn is not None:
            for attr in ("q_proj", "query", "q_lin"):
                mod = getattr(src_attn, attr, None)
                if mod is not None and hasattr(mod, "weight") and mod.weight is not None:
                    if mod.weight.ndim == 2:
                        head_dim = mod.weight.shape[0] // max(1, self.num_heads)
                        break
            if not head_dim:
                head_dim = getattr(src_attn, "head_dim", None)
        if not head_dim and cfg is not None:
            head_dim = getattr(cfg, "head_dim", None)
        if not head_dim or head_dim <= 0:
            head_dim = self.hidden_size // max(1, self.num_heads)
        self.head_dim = int(head_dim)

        cfg_kv = (
            getattr(
                cfg,
                "num_key_value_heads",
                getattr(
                    cfg,
                    "num_kv_heads",
                    kwargs.get("num_key_value_heads", kwargs.get("num_kv_heads")),
                ),
            )
            if cfg is not None
            else kwargs.get("num_key_value_heads", kwargs.get("num_kv_heads"))
        )
        self.num_kv_heads: int = int(cfg_kv) if cfg_kv is not None else self.num_heads
        self.num_key_value_groups: int = max(1, self.num_heads // max(1, self.num_kv_heads))
        self.kv_repeat: int = self.num_key_value_groups

        self.q_head_size: int = self.num_heads * self.head_dim
        self.kv_head_size: int = self.num_kv_heads * self.head_dim

        # Adaptive k_rank
        comp_config = getattr(cfg, "compression_config", None)
        if k_rank is None or k_rank == 64:
            effective_rank = getattr(
                comp_config,
                "k_rank",
                getattr(
                    comp_config,
                    "soa_rank",
                    rank if rank is not None else max(128, self.hidden_size // 4),
                ),
            )
        else:
            effective_rank = min(k_rank, self.hidden_size)
        self.k_rank: int = effective_rank
        self.rank = effective_rank
        self.lora_rank: int = lora_rank
        self.lora_alpha: float = lora_alpha

        # Decoder / Causal flag
        _mt = str(getattr(cfg, "model_type", "") or "").lower() if cfg else ""
        _decoder_prefixes = (
            "gpt",
            "qwen",
            "llama",
            "mistral",
            "gemma",
            "phi",
            "opt",
            "bloom",
            "falcon",
            "olmo",
            "mpt",
            "stablelm",
        )
        is_dec = (
            bool(_cfg_get(cfg, "is_decoder", False))
            or bool(_cfg_get(cfg, "is_causal", False))
            or any(_mt.startswith(p) for p in _decoder_prefixes)
            or (src_attn is not None and hasattr(src_attn, "c_attn"))
            or (src_attn is not None and getattr(src_attn, "is_causal", False))
            or (src_attn is not None and getattr(src_attn, "is_decoder", False))
            or bool(kwargs.get("is_causal", False))
            or bool(kwargs.get("is_decoder", False))
        )
        self.is_decoder: bool = is_dec
        self.is_causal: bool = is_dec
        self.is_nested_encoder: bool = False

        # 2. Factorized SVD linear projections for Q, K, V
        self.q_down = nn.Linear(self.hidden_size, self.k_rank, bias=False)
        self.q_up = FactorizedLoRAUp(
            self.k_rank,
            self.q_head_size,
            bias=True,
            lora_rank=self.lora_rank,
            lora_alpha=self.lora_alpha,
        )

        self.k_down = nn.Linear(self.hidden_size, self.k_rank, bias=False)
        self.k_up = FactorizedLoRAUp(
            self.k_rank,
            self.kv_head_size,
            bias=True,
            lora_rank=self.lora_rank,
            lora_alpha=self.lora_alpha,
        )

        self.v_down = nn.Linear(self.hidden_size, self.k_rank, bias=False)
        self.v_up = FactorizedLoRAUp(
            self.k_rank,
            self.kv_head_size,
            bias=True,
            lora_rank=self.lora_rank,
            lora_alpha=self.lora_alpha,
        )

        # Output projection with trainable LoRA adapter
        self.out_proj = LoRALinear(
            self.q_head_size,
            self.hidden_size,
            bias=True,
            lora_rank=self.lora_rank,
            lora_alpha=self.lora_alpha,
            freeze_base=True,
        )

        dropout_p = (
            getattr(cfg, "dropout", getattr(cfg, "attention_probs_dropout_prob", dropout))
            if cfg is not None
            else dropout
        )
        self.dropout = nn.Dropout(dropout_p)

        target_dtype = kwargs.get("dtype")
        if target_dtype is None and src_attn is not None:
            target_dtype = next(src_attn.parameters(), torch.tensor([])).dtype
            if not isinstance(target_dtype, torch.dtype):
                target_dtype = torch.float32

        # 3. Pretrained weight transfer
        if src_attn is not None:
            self.copy_weights(src_attn)

        if target_dtype is not None:
            self.to(target_dtype)

    @property
    def q_proj(self) -> FactorizedLinear:
        return FactorizedLinear(self.q_down, self.q_up)

    @property
    def k_proj(self) -> FactorizedLinear:
        return FactorizedLinear(self.k_down, self.k_up)

    @property
    def v_proj(self) -> FactorizedLinear:
        return FactorizedLinear(self.v_down, self.v_up)

    @property
    def query(self) -> FactorizedLinear:
        return self.q_proj

    @property
    def key(self) -> FactorizedLinear:
        return self.k_proj

    @property
    def value(self) -> FactorizedLinear:
        return self.v_proj

    def copy_weights(self, old_attn: nn.Module) -> None:
        """Robust weight extraction and SVD factorization across all architectures."""
        with torch.no_grad():
            w_q, b_q = None, None
            w_k, b_k = None, None
            w_v, b_v = None, None
            w_o, b_o = None, None

            # Check nested encoder container
            src_cls_name = getattr(old_attn, "__class__", type(old_attn)).__name__
            has_out_lin = (
                hasattr(old_attn, "out_lin")
                or hasattr(old_attn, "c_proj")
                or hasattr(old_attn, "o_proj")
                or hasattr(old_attn, "dense")
            )
            if src_cls_name in ("BertSelfAttention", "RobertaSelfAttention") or (
                hasattr(old_attn, "query") and not has_out_lin
            ):
                self.is_nested_encoder = True

            if hasattr(old_attn, "self") and hasattr(old_attn, "output"):
                self.is_nested_encoder = True
                src = old_attn.self
                if hasattr(old_attn.output, "dense"):
                    w_o = old_attn.output.dense.weight
                    b_o = old_attn.output.dense.bias
            else:
                src = old_attn

            # Pattern 1: GPT-2 Fused c_attn
            if hasattr(src, "c_attn") and hasattr(src, "c_proj"):
                self.is_decoder = True
                self.is_causal = True

                c_attn_mod = src.c_attn
                base_c = getattr(c_attn_mod, "base_layer", c_attn_mod)
                c_attn_w = getattr(base_c, "weight", getattr(c_attn_mod, "weight", None)).detach()
                c_attn_b = getattr(base_c, "bias", getattr(c_attn_mod, "bias", None))
                c_attn_b = c_attn_b.detach() if c_attn_b is not None else None

                c_cls = getattr(base_c, "__class__", type(base_c)).__name__
                if (
                    ("Conv1D" in c_cls)
                    or hasattr(base_c, "nf")
                    or ("Conv1D" in getattr(c_attn_mod, "__class__", type(c_attn_mod)).__name__)
                    or hasattr(c_attn_mod, "nf")
                    or (c_attn_w.dim() == 2 and c_attn_w.shape[0] < c_attn_w.shape[1])
                ):
                    c_attn_w = c_attn_w.t().contiguous()

                q_dim = self.q_head_size
                k_dim = self.kv_head_size
                v_dim = self.kv_head_size

                w_q = c_attn_w[:q_dim, :]
                w_k = c_attn_w[q_dim : q_dim + k_dim, :]
                w_v = c_attn_w[q_dim + k_dim : q_dim + k_dim + v_dim, :]

                if c_attn_b is not None:
                    b_q = c_attn_b[:q_dim]
                    b_k = c_attn_b[q_dim : q_dim + k_dim]
                    b_v = c_attn_b[q_dim + k_dim : q_dim + k_dim + v_dim]

                c_proj_mod = src.c_proj
                base_p = getattr(c_proj_mod, "base_layer", c_proj_mod)
                out_w = getattr(base_p, "weight", getattr(c_proj_mod, "weight", None)).detach()
                b_o = getattr(base_p, "bias", getattr(c_proj_mod, "bias", None))
                b_o = b_o.detach() if b_o is not None else None

                p_cls = getattr(base_p, "__class__", type(base_p)).__name__
                if (
                    ("Conv1D" in p_cls)
                    or hasattr(base_p, "nf")
                    or ("Conv1D" in getattr(c_proj_mod, "__class__", type(c_proj_mod)).__name__)
                    or hasattr(c_proj_mod, "nf")
                    or (out_w.dim() == 2 and out_w.shape[0] < out_w.shape[1])
                ):
                    out_w = out_w.t().contiguous()
                w_o = out_w

            # Pattern 2: RoBERTa / BERT separate query, key, value
            elif hasattr(src, "query") and hasattr(src, "key") and hasattr(src, "value"):
                w_q = src.query.weight.detach()
                b_q = src.query.bias.detach() if src.query.bias is not None else None
                w_k = src.key.weight.detach()
                b_k = src.key.bias.detach() if src.key.bias is not None else None
                w_v = src.value.weight.detach()
                b_v = src.value.bias.detach() if src.value.bias is not None else None

                if w_o is None:
                    for attr in ("dense", "out_proj", "o_proj"):
                        if hasattr(src, attr):
                            proj = getattr(src, attr)
                            w_o = proj.weight.detach()
                            b_o = proj.bias.detach() if proj.bias is not None else None
                            break

            # Pattern 3: Qwen / LLaMA (q_proj, k_proj, v_proj, o_proj)
            elif hasattr(src, "q_proj") and hasattr(src, "k_proj") and hasattr(src, "v_proj"):
                w_q = src.q_proj.weight.detach()
                b_q = src.q_proj.bias.detach() if src.q_proj.bias is not None else None
                w_k = src.k_proj.weight.detach()
                b_k = src.k_proj.bias.detach() if src.k_proj.bias is not None else None
                w_v = src.v_proj.weight.detach()
                b_v = src.v_proj.bias.detach() if src.v_proj.bias is not None else None

                if hasattr(src, "o_proj"):
                    w_o = src.o_proj.weight.detach()
                    b_o = src.o_proj.bias.detach() if src.o_proj.bias is not None else None

            # Pattern 4: DistilBERT (q_lin, k_lin, v_lin, out_lin)
            elif hasattr(src, "q_lin") and hasattr(src, "k_lin") and hasattr(src, "v_lin"):
                w_q = src.q_lin.weight.detach()
                b_q = src.q_lin.bias.detach() if src.q_lin.bias is not None else None
                w_k = src.k_lin.weight.detach()
                b_k = src.k_lin.bias.detach() if src.k_lin.bias is not None else None
                w_v = src.v_lin.weight.detach()
                b_v = src.v_lin.bias.detach() if src.v_lin.bias is not None else None

                if hasattr(src, "out_lin"):
                    w_o = src.out_lin.weight.detach()
                    b_o = src.out_lin.bias.detach() if src.out_lin.bias is not None else None

            # Pattern 5: UniversalAdapter fallback
            if w_q is None or w_k is None or w_v is None:
                try:
                    adapter = UniversalAdapter()
                    w_q, b_q = adapter.get_weight_bias(src, "q")
                    w_k, b_k = adapter.get_weight_bias(src, "k")
                    w_v, b_v = adapter.get_weight_bias(src, "v")
                    if w_o is None:
                        w_o, b_o = adapter.get_weight_bias(src, "o")
                except Exception:
                    pass

            # Strict validation
            missing = []
            if w_q is None:
                missing.append("Q projection")
            if w_k is None:
                missing.append("K projection")
            if w_v is None:
                missing.append("V projection")
            if w_o is None and not self.is_nested_encoder:
                missing.append("Out projection")

            if missing:
                raise RuntimeError(
                    f"SOAAttention: Failed to extract weights: {', '.join(missing)} from {type(old_attn)}"
                )

            # SVD Factorization helper
            def _factorize_svd(
                W: torch.Tensor,
                down: nn.Linear,
                up: nn.Linear,
                bias: torch.Tensor | None,
            ) -> None:
                W_f = W.float()
                U, S, Vt = torch.linalg.svd(W_f, full_matrices=False)
                S = S.clamp(min=1e-6)
                r = min(self.k_rank, U.size(1), Vt.size(0))

                down.weight.zero_()
                up.weight.zero_()
                sqrt_s = torch.sqrt(S[:r])
                down.weight[:r, :].copy_((sqrt_s.unsqueeze(1) * Vt[:r, :]).to(down.weight.dtype))
                up.weight[:, :r].copy_((U[:, :r] * sqrt_s).to(up.weight.dtype))

                if bias is not None and up.bias is not None:
                    up.bias.copy_(bias.to(up.bias.dtype))
                elif up.bias is not None:
                    up.bias.zero_()

                # Frobenius check
                rec = up.weight @ down.weight
                f_norm = float(torch.linalg.norm(rec))
                if f_norm < 1e-4:
                    logger.warning(
                        f"SOAAttention: SVD reconstructed weight norm is near zero: {f_norm}"
                    )

            _factorize_svd(w_q, self.q_down, self.q_up, b_q)
            _factorize_svd(w_k, self.k_down, self.k_up, b_k)
            _factorize_svd(w_v, self.v_down, self.v_up, b_v)

            if w_o is not None and not self.is_nested_encoder:
                self.out_proj.weight.copy_(w_o.to(self.out_proj.weight.dtype))
                if b_o is not None and self.out_proj.bias is not None:
                    self.out_proj.bias.copy_(b_o.to(self.out_proj.bias.dtype))
                f_norm_o = float(torch.linalg.norm(self.out_proj.weight))
                if f_norm_o < 1e-4:
                    logger.warning(f"SOAAttention: Out projection norm is near zero: {f_norm_o}")
            elif self.is_nested_encoder:
                if hasattr(self.out_proj, "weight") and self.out_proj.weight.ndim == 2:
                    nn.init.eye_(self.out_proj.weight)
                if hasattr(self.out_proj, "bias") and self.out_proj.bias is not None:
                    nn.init.zeros_(self.out_proj.bias)

            # Freeze base weights
            for mod in [self.q_down, self.k_down, self.v_down]:
                mod.weight.requires_grad = False
                if getattr(mod, "bias", None) is not None:
                    mod.bias.requires_grad = False
            for mod in [self.q_up, self.k_up, self.v_up]:
                if hasattr(mod, "freeze_base_weights"):
                    mod.freeze_base_weights()
                else:
                    mod.weight.requires_grad = False
                    if getattr(mod, "bias", None) is not None:
                        mod.bias.requires_grad = False
                    if getattr(mod, "lora_A", None) is not None:
                        mod.lora_A.requires_grad = True
                    if getattr(mod, "lora_B", None) is not None:
                        mod.lora_B.requires_grad = True
            if hasattr(self.out_proj, "freeze_base_weights"):
                self.out_proj.freeze_base_weights()
            else:
                self.out_proj.weight.requires_grad = False
                if getattr(self.out_proj, "bias", None) is not None:
                    self.out_proj.bias.requires_grad = False
                if getattr(self.out_proj, "lora_A", None) is not None:
                    self.out_proj.lora_A.requires_grad = True
                if getattr(self.out_proj, "lora_B", None) is not None:
                    self.out_proj.lora_B.requires_grad = True

    @classmethod
    def from_distilbert_pretrained(
        cls, old_attn: nn.Module, model_config: Any | None = None, **kwargs: Any
    ) -> "SOAAttention":
        return cls(model_config=model_config, pretrained_attn=old_attn, **kwargs)

    def forward(
        self,
        hidden_states: torch.Tensor,
        attention_mask: torch.Tensor | None = None,
        head_mask: torch.Tensor | None = None,
        encoder_hidden_states: torch.Tensor | None = None,
        encoder_attention_mask: torch.Tensor | None = None,
        past_key_value: Any | None = None,
        output_attentions: bool | None = False,
        output_hidden_states: bool | None = False,
        return_dict: bool | None = True,
        *args: Any,
        **kwargs: Any,
    ) -> tuple[torch.Tensor, torch.Tensor | None] | torch.Tensor:
        B, N, _ = hidden_states.shape

        # Factorized projections
        z_q = self.q_down(hidden_states)
        z_k = self.k_down(hidden_states)
        z_v = self.v_down(hidden_states)

        q = self.q_up(z_q)
        k = self.k_up(z_k)
        v = self.v_up(z_v)

        H = self.num_heads
        H_kv = self.num_kv_heads
        D = self.head_dim

        q = q.view(B, N, H, D).transpose(1, 2).contiguous()
        k = k.view(B, N, H_kv, D).transpose(1, 2).contiguous()
        v = v.view(B, N, H_kv, D).transpose(1, 2).contiguous()

        # Partial Rotary Position Embeddings (RoPE)
        pos_emb = kwargs.get("position_embeddings")
        if pos_emb is not None and isinstance(pos_emb, tuple) and len(pos_emb) == 2:
            cos, sin = pos_emb
            q, k = apply_rotary_pos_emb(q, k, cos, sin)

        # Grouped-Query Attention expansion
        if H_kv != H:
            k = repeat_kv(k, self.num_key_value_groups)
            v = repeat_kv(v, self.num_key_value_groups)

        scale = 1.0 / math.sqrt(D)
        # Memory-efficient: use SDPA to avoid OOM on large seqs

        try:
            _qs = q.half() if q.dtype == torch.float32 else q

            _ks = k.half() if k.dtype == torch.float32 else k

            _vs = v.half() if v.dtype == torch.float32 else v

            _sdpa_out = torch.nn.functional.scaled_dot_product_attention(
                _qs,
                _ks,
                _vs,
                is_causal=getattr(self, "is_decoder", False) and N > 1,
                dropout_p=self.dropout.p if self.training else 0.0,
            )

            _sdpa_out = (
                _sdpa_out.to(hidden_states.dtype)
                .transpose(1, 2)
                .contiguous()
                .view(B, N, self.all_head_size)
            )

            _sdpa_out = torch.nan_to_num(_sdpa_out, nan=0.0, posinf=1e4, neginf=-1e4)

            return (
                self.out_proj(_sdpa_out)
                if not getattr(self, "is_nested_encoder", False)
                else _sdpa_out
            ), None

        except Exception:
            pass

        scores = torch.matmul(q.float(), k.float().transpose(-2, -1).contiguous()) * scale

        # Causal mask for decoders
        is_causal = (
            self.is_decoder or getattr(self, "is_causal", False) or kwargs.get("is_causal", False)
        ) and (encoder_hidden_states is None)
        if is_causal and N > 1:
            causal_mask = (
                torch.triu(
                    torch.full((N, N), float("-inf"), device=scores.device, dtype=torch.float32),
                    diagonal=1,
                )
                .unsqueeze(0)
                .unsqueeze(0)
            )
            scores = scores + causal_mask

        # Standard Attention Mask
        mask = attention_mask if attention_mask is not None else kwargs.get("attn_mask")
        if mask is not None:
            if mask.dim() == 4 and mask.dtype == torch.bool:
                scores = scores.masked_fill(~mask, -10000.0)
            else:
                scores = apply_attention_mask(scores, mask)

        attn_weights = F.softmax(scores, dim=-1)
        attn_weights = torch.nan_to_num(attn_weights, nan=0.0)
        attn_weights = self.dropout(attn_weights.to(v.dtype))

        if head_mask is not None:
            if head_mask.dim() == 1:
                head_mask = head_mask.view(1, -1, 1, 1)
            elif head_mask.dim() == 2:
                head_mask = head_mask.view(head_mask.size(0), head_mask.size(1), 1, 1)
            attn_weights = attn_weights * head_mask

        context = torch.matmul(attn_weights, v)
        context = context.transpose(1, 2).contiguous().view(B, N, H * D)

        if self.is_nested_encoder:
            return (context, attn_weights if output_attentions else None)

        output = self.out_proj(context)
        return (output, attn_weights if output_attentions else None)

Shared Orthogonal Attention (SOA) with Per-Projection Latent Bottlenecks.

Factorizes dense Q, K, and V linear projections into low-rank bottleneck pairs initialized via truncated SVD from pretrained transformer weights.

Initialize internal Module state, shared by both nn.Module and ScriptModule.

Ancestors

Class variables

var is_custom_attention : bool

The type of the None singleton.

var supports_gqa : bool

The type of the None singleton.

Static methods

def from_distilbert_pretrained(old_attn: torch.nn.modules.module.Module,
model_config: Any | None = None,
**kwargs: Any) ‑> SOAAttention

Instance variables

prop k_proj : FactorizedLinear
Expand source code
@property
def k_proj(self) -> FactorizedLinear:
    return FactorizedLinear(self.k_down, self.k_up)
prop key : FactorizedLinear
Expand source code
@property
def key(self) -> FactorizedLinear:
    return self.k_proj
prop q_proj : FactorizedLinear
Expand source code
@property
def q_proj(self) -> FactorizedLinear:
    return FactorizedLinear(self.q_down, self.q_up)
prop query : FactorizedLinear
Expand source code
@property
def query(self) -> FactorizedLinear:
    return self.q_proj
prop v_proj : FactorizedLinear
Expand source code
@property
def v_proj(self) -> FactorizedLinear:
    return FactorizedLinear(self.v_down, self.v_up)
prop value : FactorizedLinear
Expand source code
@property
def value(self) -> FactorizedLinear:
    return self.v_proj

Methods

def copy_weights(self, old_attn: torch.nn.modules.module.Module) ‑> None
Expand source code
def copy_weights(self, old_attn: nn.Module) -> None:
    """Robust weight extraction and SVD factorization across all architectures."""
    with torch.no_grad():
        w_q, b_q = None, None
        w_k, b_k = None, None
        w_v, b_v = None, None
        w_o, b_o = None, None

        # Check nested encoder container
        src_cls_name = getattr(old_attn, "__class__", type(old_attn)).__name__
        has_out_lin = (
            hasattr(old_attn, "out_lin")
            or hasattr(old_attn, "c_proj")
            or hasattr(old_attn, "o_proj")
            or hasattr(old_attn, "dense")
        )
        if src_cls_name in ("BertSelfAttention", "RobertaSelfAttention") or (
            hasattr(old_attn, "query") and not has_out_lin
        ):
            self.is_nested_encoder = True

        if hasattr(old_attn, "self") and hasattr(old_attn, "output"):
            self.is_nested_encoder = True
            src = old_attn.self
            if hasattr(old_attn.output, "dense"):
                w_o = old_attn.output.dense.weight
                b_o = old_attn.output.dense.bias
        else:
            src = old_attn

        # Pattern 1: GPT-2 Fused c_attn
        if hasattr(src, "c_attn") and hasattr(src, "c_proj"):
            self.is_decoder = True
            self.is_causal = True

            c_attn_mod = src.c_attn
            base_c = getattr(c_attn_mod, "base_layer", c_attn_mod)
            c_attn_w = getattr(base_c, "weight", getattr(c_attn_mod, "weight", None)).detach()
            c_attn_b = getattr(base_c, "bias", getattr(c_attn_mod, "bias", None))
            c_attn_b = c_attn_b.detach() if c_attn_b is not None else None

            c_cls = getattr(base_c, "__class__", type(base_c)).__name__
            if (
                ("Conv1D" in c_cls)
                or hasattr(base_c, "nf")
                or ("Conv1D" in getattr(c_attn_mod, "__class__", type(c_attn_mod)).__name__)
                or hasattr(c_attn_mod, "nf")
                or (c_attn_w.dim() == 2 and c_attn_w.shape[0] < c_attn_w.shape[1])
            ):
                c_attn_w = c_attn_w.t().contiguous()

            q_dim = self.q_head_size
            k_dim = self.kv_head_size
            v_dim = self.kv_head_size

            w_q = c_attn_w[:q_dim, :]
            w_k = c_attn_w[q_dim : q_dim + k_dim, :]
            w_v = c_attn_w[q_dim + k_dim : q_dim + k_dim + v_dim, :]

            if c_attn_b is not None:
                b_q = c_attn_b[:q_dim]
                b_k = c_attn_b[q_dim : q_dim + k_dim]
                b_v = c_attn_b[q_dim + k_dim : q_dim + k_dim + v_dim]

            c_proj_mod = src.c_proj
            base_p = getattr(c_proj_mod, "base_layer", c_proj_mod)
            out_w = getattr(base_p, "weight", getattr(c_proj_mod, "weight", None)).detach()
            b_o = getattr(base_p, "bias", getattr(c_proj_mod, "bias", None))
            b_o = b_o.detach() if b_o is not None else None

            p_cls = getattr(base_p, "__class__", type(base_p)).__name__
            if (
                ("Conv1D" in p_cls)
                or hasattr(base_p, "nf")
                or ("Conv1D" in getattr(c_proj_mod, "__class__", type(c_proj_mod)).__name__)
                or hasattr(c_proj_mod, "nf")
                or (out_w.dim() == 2 and out_w.shape[0] < out_w.shape[1])
            ):
                out_w = out_w.t().contiguous()
            w_o = out_w

        # Pattern 2: RoBERTa / BERT separate query, key, value
        elif hasattr(src, "query") and hasattr(src, "key") and hasattr(src, "value"):
            w_q = src.query.weight.detach()
            b_q = src.query.bias.detach() if src.query.bias is not None else None
            w_k = src.key.weight.detach()
            b_k = src.key.bias.detach() if src.key.bias is not None else None
            w_v = src.value.weight.detach()
            b_v = src.value.bias.detach() if src.value.bias is not None else None

            if w_o is None:
                for attr in ("dense", "out_proj", "o_proj"):
                    if hasattr(src, attr):
                        proj = getattr(src, attr)
                        w_o = proj.weight.detach()
                        b_o = proj.bias.detach() if proj.bias is not None else None
                        break

        # Pattern 3: Qwen / LLaMA (q_proj, k_proj, v_proj, o_proj)
        elif hasattr(src, "q_proj") and hasattr(src, "k_proj") and hasattr(src, "v_proj"):
            w_q = src.q_proj.weight.detach()
            b_q = src.q_proj.bias.detach() if src.q_proj.bias is not None else None
            w_k = src.k_proj.weight.detach()
            b_k = src.k_proj.bias.detach() if src.k_proj.bias is not None else None
            w_v = src.v_proj.weight.detach()
            b_v = src.v_proj.bias.detach() if src.v_proj.bias is not None else None

            if hasattr(src, "o_proj"):
                w_o = src.o_proj.weight.detach()
                b_o = src.o_proj.bias.detach() if src.o_proj.bias is not None else None

        # Pattern 4: DistilBERT (q_lin, k_lin, v_lin, out_lin)
        elif hasattr(src, "q_lin") and hasattr(src, "k_lin") and hasattr(src, "v_lin"):
            w_q = src.q_lin.weight.detach()
            b_q = src.q_lin.bias.detach() if src.q_lin.bias is not None else None
            w_k = src.k_lin.weight.detach()
            b_k = src.k_lin.bias.detach() if src.k_lin.bias is not None else None
            w_v = src.v_lin.weight.detach()
            b_v = src.v_lin.bias.detach() if src.v_lin.bias is not None else None

            if hasattr(src, "out_lin"):
                w_o = src.out_lin.weight.detach()
                b_o = src.out_lin.bias.detach() if src.out_lin.bias is not None else None

        # Pattern 5: UniversalAdapter fallback
        if w_q is None or w_k is None or w_v is None:
            try:
                adapter = UniversalAdapter()
                w_q, b_q = adapter.get_weight_bias(src, "q")
                w_k, b_k = adapter.get_weight_bias(src, "k")
                w_v, b_v = adapter.get_weight_bias(src, "v")
                if w_o is None:
                    w_o, b_o = adapter.get_weight_bias(src, "o")
            except Exception:
                pass

        # Strict validation
        missing = []
        if w_q is None:
            missing.append("Q projection")
        if w_k is None:
            missing.append("K projection")
        if w_v is None:
            missing.append("V projection")
        if w_o is None and not self.is_nested_encoder:
            missing.append("Out projection")

        if missing:
            raise RuntimeError(
                f"SOAAttention: Failed to extract weights: {', '.join(missing)} from {type(old_attn)}"
            )

        # SVD Factorization helper
        def _factorize_svd(
            W: torch.Tensor,
            down: nn.Linear,
            up: nn.Linear,
            bias: torch.Tensor | None,
        ) -> None:
            W_f = W.float()
            U, S, Vt = torch.linalg.svd(W_f, full_matrices=False)
            S = S.clamp(min=1e-6)
            r = min(self.k_rank, U.size(1), Vt.size(0))

            down.weight.zero_()
            up.weight.zero_()
            sqrt_s = torch.sqrt(S[:r])
            down.weight[:r, :].copy_((sqrt_s.unsqueeze(1) * Vt[:r, :]).to(down.weight.dtype))
            up.weight[:, :r].copy_((U[:, :r] * sqrt_s).to(up.weight.dtype))

            if bias is not None and up.bias is not None:
                up.bias.copy_(bias.to(up.bias.dtype))
            elif up.bias is not None:
                up.bias.zero_()

            # Frobenius check
            rec = up.weight @ down.weight
            f_norm = float(torch.linalg.norm(rec))
            if f_norm < 1e-4:
                logger.warning(
                    f"SOAAttention: SVD reconstructed weight norm is near zero: {f_norm}"
                )

        _factorize_svd(w_q, self.q_down, self.q_up, b_q)
        _factorize_svd(w_k, self.k_down, self.k_up, b_k)
        _factorize_svd(w_v, self.v_down, self.v_up, b_v)

        if w_o is not None and not self.is_nested_encoder:
            self.out_proj.weight.copy_(w_o.to(self.out_proj.weight.dtype))
            if b_o is not None and self.out_proj.bias is not None:
                self.out_proj.bias.copy_(b_o.to(self.out_proj.bias.dtype))
            f_norm_o = float(torch.linalg.norm(self.out_proj.weight))
            if f_norm_o < 1e-4:
                logger.warning(f"SOAAttention: Out projection norm is near zero: {f_norm_o}")
        elif self.is_nested_encoder:
            if hasattr(self.out_proj, "weight") and self.out_proj.weight.ndim == 2:
                nn.init.eye_(self.out_proj.weight)
            if hasattr(self.out_proj, "bias") and self.out_proj.bias is not None:
                nn.init.zeros_(self.out_proj.bias)

        # Freeze base weights
        for mod in [self.q_down, self.k_down, self.v_down]:
            mod.weight.requires_grad = False
            if getattr(mod, "bias", None) is not None:
                mod.bias.requires_grad = False
        for mod in [self.q_up, self.k_up, self.v_up]:
            if hasattr(mod, "freeze_base_weights"):
                mod.freeze_base_weights()
            else:
                mod.weight.requires_grad = False
                if getattr(mod, "bias", None) is not None:
                    mod.bias.requires_grad = False
                if getattr(mod, "lora_A", None) is not None:
                    mod.lora_A.requires_grad = True
                if getattr(mod, "lora_B", None) is not None:
                    mod.lora_B.requires_grad = True
        if hasattr(self.out_proj, "freeze_base_weights"):
            self.out_proj.freeze_base_weights()
        else:
            self.out_proj.weight.requires_grad = False
            if getattr(self.out_proj, "bias", None) is not None:
                self.out_proj.bias.requires_grad = False
            if getattr(self.out_proj, "lora_A", None) is not None:
                self.out_proj.lora_A.requires_grad = True
            if getattr(self.out_proj, "lora_B", None) is not None:
                self.out_proj.lora_B.requires_grad = True

Robust weight extraction and SVD factorization across all architectures.

Inherited members