| """Learned dense-to-local+algebra overlap blocks with physical export.""" |
|
|
| from __future__ import annotations |
|
|
| from dataclasses import dataclass |
|
|
| import torch |
| from torch import nn |
| from torch.nn import functional as F |
|
|
| from strata.modeling.algebra import HardConcreteGate |
| from strata.modeling.compose.lm_adapter import AlgebraGraphReadAdapter, SparseAlgebraGraphRead |
| from strata.modeling.ph_pat.config import PHPATConfig |
| from strata.modeling.ph_pat.replacement_block import ( |
| ChunkedLocalCausalAttention, |
| DenseGlobalBlock, |
| DenseGlobalCausalAttention, |
| ) |
|
|
|
|
| class AlgebraOverlapBlock(nn.Module): |
| """Exact dense endpoint and trainable local+graph endpoint for one block.""" |
|
|
| def __init__( |
| self, |
| dense_block: DenseGlobalBlock, |
| config: PHPATConfig, |
| *, |
| gamma_max: float = 0.02, |
| ) -> None: |
| super().__init__() |
| self.attn_norm = dense_block.attn_norm |
| self.global_attention = dense_block.attention |
| self.local_attention = ChunkedLocalCausalAttention(config) |
| self.local_attention.load_state_dict(self.global_attention.state_dict(), strict=True) |
| self.ffn_norm = dense_block.ffn_norm |
| self.ffn = dense_block.ffn |
| self.dropout = dense_block.dropout |
| self.graph_adapter = AlgebraGraphReadAdapter(config.d_model, config.d_model, gamma_max=gamma_max) |
| self.global_gate = HardConcreteGate(1, initial_probability=0.99) |
| reference = self.global_attention.qkv.weight |
| self.local_attention.to(device=reference.device, dtype=reference.dtype) |
| self.graph_adapter.to(device=reference.device, dtype=reference.dtype) |
| self.global_gate.to(device=reference.device) |
|
|
| def forward( |
| self, |
| hidden: torch.Tensor, |
| attention_mask: torch.Tensor, |
| *, |
| graph_values: torch.Tensor | None = None, |
| graph_reliability: torch.Tensor | None = None, |
| sparse_graph_read: SparseAlgebraGraphRead | None = None, |
| graph_enabled: bool = False, |
| gate_mode: str = "dense", |
| gate_override: torch.Tensor | float | None = None, |
| ) -> tuple[torch.Tensor, torch.Tensor]: |
| normalized = self.attn_norm(hidden) |
| if gate_override is not None: |
| gate = torch.as_tensor(gate_override, device=hidden.device, dtype=hidden.dtype) |
| if gate.numel() != 1 or bool((gate < 0).any() or (gate > 1).any()): |
| raise ValueError("gate_override must be one scalar in [0, 1]") |
| gate = gate.reshape(()) |
| if float(gate.detach()) == 1.0: |
| attention = self.global_attention(normalized, attention_mask) |
| elif float(gate.detach()) == 0.0: |
| attention = self.local_attention(normalized, attention_mask) |
| else: |
| local = self.local_attention(normalized, attention_mask) |
| global_value = self.global_attention(normalized, attention_mask) |
| attention = local + gate * (global_value - local) |
| elif gate_mode == "dense": |
| attention = self.global_attention(normalized, attention_mask) |
| gate = hidden.new_tensor(1.0) |
| elif gate_mode == "local": |
| attention = self.local_attention(normalized, attention_mask) |
| gate = hidden.new_tensor(0.0) |
| elif gate_mode in ("sample", "expected"): |
| local = self.local_attention(normalized, attention_mask) |
| global_value = self.global_attention(normalized, attention_mask) |
| gate = self.global_gate(sample=gate_mode == "sample")[0].to(hidden.dtype) |
| attention = local + gate * (global_value - local) |
| else: |
| raise ValueError("gate_mode must be dense, local, sample, or expected") |
| hidden = hidden + self.dropout(attention) |
| if graph_enabled: |
| if sparse_graph_read is not None: |
| hidden, _update, _relative = self.graph_adapter.forward_sparse( |
| hidden, sparse_graph_read |
| ) |
| else: |
| if graph_values is None or graph_reliability is None: |
| raise ValueError("enabled graph reads require values and reliability") |
| hidden, _update, _relative = self.graph_adapter( |
| hidden, graph_values, graph_reliability |
| ) |
| hidden = hidden + self.dropout(self.ffn(self.ffn_norm(hidden))) |
| return hidden, gate |
|
|
| def export_local(self) -> "ExportedAlgebraBlock": |
| return ExportedAlgebraBlock(self) |
|
|
| def restore_global(self, config: PHPATConfig) -> DenseGlobalBlock: |
| """Restore the original dense block without retaining local/chart modules.""" |
|
|
| restored = DenseGlobalBlock(config) |
| restored.attn_norm = self.attn_norm |
| restored.attention = self.global_attention |
| restored.ffn_norm = self.ffn_norm |
| restored.ffn = self.ffn |
| restored.dropout = self.dropout |
| return restored |
|
|
|
|
| class ExportedAlgebraBlock(nn.Module): |
| """Physical local+graph block; no dense Q/K/V module remains.""" |
|
|
| def __init__(self, source: AlgebraOverlapBlock) -> None: |
| super().__init__() |
| self.attn_norm = source.attn_norm |
| self.local_attention = source.local_attention |
| self.ffn_norm = source.ffn_norm |
| self.ffn = source.ffn |
| self.dropout = source.dropout |
| self.graph_adapter = source.graph_adapter |
|
|
| def forward( |
| self, |
| hidden: torch.Tensor, |
| attention_mask: torch.Tensor, |
| *, |
| graph_values: torch.Tensor | None = None, |
| graph_reliability: torch.Tensor | None = None, |
| sparse_graph_read: SparseAlgebraGraphRead | None = None, |
| graph_enabled: bool = False, |
| ) -> torch.Tensor: |
| hidden = hidden + self.dropout(self.local_attention(self.attn_norm(hidden), attention_mask)) |
| if graph_enabled: |
| if self.graph_adapter is not None: |
| if sparse_graph_read is not None: |
| hidden, _update, _relative = self.graph_adapter.forward_sparse( |
| hidden, sparse_graph_read |
| ) |
| else: |
| if graph_values is None or graph_reliability is None: |
| raise ValueError("enabled graph reads require values and reliability") |
| hidden, _update, _relative = self.graph_adapter( |
| hidden, graph_values, graph_reliability |
| ) |
| return hidden + self.dropout(self.ffn(self.ffn_norm(hidden))) |
|
|
|
|
| @dataclass(frozen=True, slots=True) |
| class PrunableLMOutput: |
| logits: torch.Tensor |
| loss: torch.Tensor | None |
| hidden_states: torch.Tensor |
| global_gates: torch.Tensor |
|
|
|
|
| class PrunableAlgebraLM(nn.Module): |
| """Install overlap blocks without altering unselected dense blocks.""" |
|
|
| def __init__( |
| self, |
| base_model: nn.Module, |
| config: PHPATConfig, |
| replacement_layers: tuple[int, ...], |
| *, |
| gamma_max: float = 0.02, |
| ) -> None: |
| super().__init__() |
| self.base_model = base_model |
| self.config = config |
| self.replacement_layers = tuple(sorted(int(index) for index in replacement_layers)) |
| if len(set(self.replacement_layers)) != len(self.replacement_layers): |
| raise ValueError("replacement layers must be unique") |
| for index in self.replacement_layers: |
| block = self.base_model.blocks[index] |
| if not isinstance(block, DenseGlobalBlock): |
| raise TypeError(f"layer {index} is not a dense global block") |
| self.base_model.blocks[index] = AlgebraOverlapBlock(block, config, gamma_max=gamma_max) |
|
|
| def install_overlap_layers( |
| self, |
| layer_indices: tuple[int, ...], |
| *, |
| gamma_max: float = 0.02, |
| ) -> tuple[int, ...]: |
| """Install candidate overlap paths while preserving prior physical exports.""" |
|
|
| requested = tuple(sorted(set(int(index) for index in layer_indices))) |
| installed = [] |
| for index in requested: |
| block = self.base_model.blocks[index] |
| if isinstance(block, (AlgebraOverlapBlock, ExportedAlgebraBlock)): |
| continue |
| if not isinstance(block, DenseGlobalBlock): |
| raise TypeError(f"layer {index} is not a dense global block") |
| self.base_model.blocks[index] = AlgebraOverlapBlock( |
| block, |
| self.config, |
| gamma_max=gamma_max, |
| ) |
| installed.append(index) |
| self.replacement_layers = tuple(sorted(set(self.replacement_layers).union(installed))) |
| return tuple(installed) |
|
|
| def restore_global_layers(self, layer_indices: tuple[int, ...]) -> tuple[int, ...]: |
| """Remove unselected overlap paths and retain their exact dense branches.""" |
|
|
| restored = [] |
| for index in sorted(set(int(value) for value in layer_indices)): |
| block = self.base_model.blocks[index] |
| if isinstance(block, ExportedAlgebraBlock): |
| raise ValueError(f"cannot restore physically exported layer {index}") |
| if not isinstance(block, AlgebraOverlapBlock): |
| continue |
| self.base_model.blocks[index] = block.restore_global(self.config) |
| restored.append(index) |
| if restored: |
| removed = set(restored) |
| self.replacement_layers = tuple( |
| index for index in self.replacement_layers if index not in removed |
| ) |
| return tuple(restored) |
|
|
| def export_layers(self, layer_indices: tuple[int, ...]) -> tuple[int, ...]: |
| """Physically export an explicit set of overlap branches to local blocks.""" |
|
|
| exported = [] |
| for index in sorted(set(int(value) for value in layer_indices)): |
| block = self.base_model.blocks[index] |
| if not isinstance(block, AlgebraOverlapBlock): |
| raise TypeError(f"layer {index} is not an overlap candidate") |
| self.base_model.blocks[index] = block.export_local() |
| exported.append(index) |
| return tuple(exported) |
|
|
| def forward_hidden( |
| self, |
| input_ids: torch.Tensor, |
| *, |
| attention_mask: torch.Tensor | None = None, |
| graph_values: torch.Tensor | None = None, |
| graph_reliability: torch.Tensor | None = None, |
| sparse_graph_read: SparseAlgebraGraphRead | None = None, |
| graph_enabled: bool = False, |
| graph_layer_indices: tuple[int, ...] | None = None, |
| gate_mode: str = "dense", |
| global_mask: torch.Tensor | None = None, |
| ) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor]: |
| if attention_mask is None: |
| attention_mask = torch.ones_like(input_ids, dtype=torch.bool) |
| else: |
| attention_mask = attention_mask.to(torch.bool) |
| positions = torch.arange(input_ids.shape[1], device=input_ids.device) |
| hidden = self.base_model.dropout( |
| self.base_model.token_embeddings(input_ids) |
| + self.base_model.position_embeddings(positions).unsqueeze(0) |
| ) |
| gates = [] |
| replacement_index = 0 |
| active_graph_layers = None if graph_layer_indices is None else set(graph_layer_indices) |
| for layer_index, block in enumerate(self.base_model.blocks): |
| if isinstance(block, AlgebraOverlapBlock): |
| override = None |
| if global_mask is not None: |
| if global_mask.shape != (len(self.replacement_layers),): |
| raise ValueError("global_mask must have one value per replacement layer") |
| override = global_mask[replacement_index] |
| hidden, gate = block( |
| hidden, |
| attention_mask, |
| graph_values=graph_values, |
| graph_reliability=graph_reliability, |
| sparse_graph_read=sparse_graph_read, |
| graph_enabled=graph_enabled and ( |
| active_graph_layers is None or layer_index in active_graph_layers |
| ), |
| gate_mode=gate_mode, |
| gate_override=override, |
| ) |
| gates.append(gate.reshape(1)) |
| replacement_index += 1 |
| elif isinstance(block, ExportedAlgebraBlock): |
| hidden = block( |
| hidden, |
| attention_mask, |
| graph_values=graph_values, |
| graph_reliability=graph_reliability, |
| sparse_graph_read=sparse_graph_read, |
| graph_enabled=graph_enabled and ( |
| active_graph_layers is None or layer_index in active_graph_layers |
| ), |
| ) |
| gates.append(hidden.new_zeros(1)) |
| replacement_index += 1 |
| else: |
| hidden, _read = block(hidden, attention_mask) |
| return hidden, attention_mask, torch.cat(gates) if gates else hidden.new_empty(0) |
|
|
| def forward( |
| self, |
| input_ids: torch.Tensor, |
| *, |
| attention_mask: torch.Tensor | None = None, |
| labels: torch.Tensor | None = None, |
| graph_values: torch.Tensor | None = None, |
| graph_reliability: torch.Tensor | None = None, |
| sparse_graph_read: SparseAlgebraGraphRead | None = None, |
| graph_enabled: bool = False, |
| graph_layer_indices: tuple[int, ...] | None = None, |
| gate_mode: str = "dense", |
| global_mask: torch.Tensor | None = None, |
| ) -> PrunableLMOutput: |
| hidden, _mask, gates = self.forward_hidden( |
| input_ids, |
| attention_mask=attention_mask, |
| graph_values=graph_values, |
| graph_reliability=graph_reliability, |
| sparse_graph_read=sparse_graph_read, |
| graph_enabled=graph_enabled, |
| graph_layer_indices=graph_layer_indices, |
| gate_mode=gate_mode, |
| global_mask=global_mask, |
| ) |
| hidden = self.base_model.final_norm(hidden) |
| logits = self.base_model.lm_head(hidden) |
| loss = None |
| if labels is not None: |
| loss = F.cross_entropy( |
| logits[:, :-1].contiguous().view(-1, logits.shape[-1]), |
| labels[:, 1:].contiguous().view(-1), |
| ignore_index=-100, |
| ) |
| return PrunableLMOutput(logits, loss, hidden, gates) |
|
|
| def expected_global_branches(self) -> torch.Tensor: |
| values = [ |
| block.global_gate.expected_l0()[0] |
| for block in self.base_model.blocks |
| if isinstance(block, AlgebraOverlapBlock) |
| ] |
| return torch.stack(values) if values else next(self.parameters()).new_empty(0) |
|
|
| def deterministic_global_branches(self) -> torch.Tensor: |
| values = [ |
| block.global_gate(sample=False)[0] |
| for block in self.base_model.blocks |
| if isinstance(block, AlgebraOverlapBlock) |
| ] |
| return torch.stack(values) if values else next(self.parameters()).new_empty(0) |
|
|
| def export_zero_gates(self, *, threshold: float = 0.5) -> tuple[int, ...]: |
| exported = [] |
| for index, block in enumerate(self.base_model.blocks): |
| if isinstance(block, AlgebraOverlapBlock) and not bool( |
| block.global_gate.export_mask(threshold=threshold)[0] |
| ): |
| self.base_model.blocks[index] = block.export_local() |
| exported.append(index) |
| return tuple(exported) |
|
|
| def dense_modules_in_replacement_layers(self) -> tuple[int, ...]: |
| found = [] |
| for index in self.replacement_layers: |
| if any(isinstance(module, DenseGlobalCausalAttention) for module in self.base_model.blocks[index].modules()): |
| found.append(index) |
| return tuple(found) |
|
|
| def physically_removed_layers(self) -> tuple[int, ...]: |
| return tuple( |
| index |
| for index, block in enumerate(self.base_model.blocks) |
| if isinstance(block, ExportedAlgebraBlock) |
| ) |
|
|
| def active_graph_layers(self, *, tolerance: float = 0.0) -> tuple[int, ...]: |
| """Return physical graph blocks whose BRR gate is not identically zero.""" |
|
|
| return tuple( |
| index |
| for index, block in enumerate(self.base_model.blocks) |
| if isinstance(block, ExportedAlgebraBlock) |
| and block.graph_adapter is not None |
| and bool(block.graph_adapter.brr.gate_parameter.detach().abs().max() > tolerance) |
| ) |
|
|
| def strip_inactive_graph_adapters(self, *, tolerance: float = 0.0) -> tuple[int, ...]: |
| """Physically remove adapters whose BRR contribution is exactly zero.""" |
|
|
| stripped = [] |
| for index, block in enumerate(self.base_model.blocks): |
| if not isinstance(block, ExportedAlgebraBlock) or block.graph_adapter is None: |
| continue |
| gate = block.graph_adapter.brr.gate_parameter.detach().abs().max() |
| if bool(gate <= tolerance): |
| block.graph_adapter = None |
| stripped.append(index) |
| return tuple(stripped) |
|
|
|
|
| __all__ = [ |
| "AlgebraOverlapBlock", |
| "ExportedAlgebraBlock", |
| "PrunableAlgebraLM", |
| "PrunableLMOutput", |
| ] |
|
|