Text Generation
Transformers
Safetensors
English
statehead
babylm
babylm-2026
strict-small
recurrent
linear-rnn
attention-free
efficient-lm
custom_code
Instructions to use haybales/statehead-10m with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use haybales/statehead-10m with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="haybales/statehead-10m", trust_remote_code=True)# Load model directly from transformers import AutoModelForCausalLM model = AutoModelForCausalLM.from_pretrained("haybales/statehead-10m", trust_remote_code=True, device_map="auto") - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use haybales/statehead-10m with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "haybales/statehead-10m" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "haybales/statehead-10m", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }'Use Docker
docker model run hf.co/haybales/statehead-10m
- SGLang
How to use haybales/statehead-10m with SGLang:
Install from pip and serve model
# Install SGLang from pip: pip install sglang # Start the SGLang server: python3 -m sglang.launch_server \ --model-path "haybales/statehead-10m" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "haybales/statehead-10m", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }'Use Docker images
docker run --gpus all \ --shm-size 32g \ -p 30000:30000 \ -v ~/.cache/huggingface:/root/.cache/huggingface \ --env "HF_TOKEN=<secret>" \ --ipc=host \ lmsysorg/sglang:latest \ python3 -m sglang.launch_server \ --model-path "haybales/statehead-10m" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "haybales/statehead-10m", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }' - Docker Model Runner
How to use haybales/statehead-10m with Docker Model Runner:
docker model run hf.co/haybales/statehead-10m
| from __future__ import annotations | |
| import os | |
| import shutil | |
| import warnings | |
| from collections.abc import Sequence | |
| from pathlib import Path | |
| from typing import Any | |
| import torch | |
| import torch.nn as nn | |
| import torch.nn.functional as F | |
| from transformers import PreTrainedModel | |
| from transformers.generation import GenerationMixin | |
| from transformers.modeling_outputs import ( | |
| BaseModelOutputWithPast, | |
| CausalLMOutputWithPast, | |
| ) | |
| from .configuration_statehead import StateHeadConfig | |
| def _sqrt_with_clipped_grad(x: torch.Tensor, max_grad: float) -> torch.Tensor: | |
| eps = 1.0 / (4.0 * max_grad * max_grad) | |
| return torch.sqrt(torch.clamp(x, min=0.0) + eps) | |
| def _retention_write_scale_from_logits(a_logits: torch.Tensor, max_grad: float) -> torch.Tensor: | |
| a = torch.sigmoid(a_logits) | |
| scale_square = torch.sigmoid(-a_logits) * (1.0 + a) | |
| return _sqrt_with_clipped_grad(scale_square, max_grad) | |
| def _statehead_scan_torch( | |
| gates: torch.Tensor, | |
| initial_state: torch.Tensor, | |
| attention_mask: torch.Tensor | None = None, | |
| write_scale_by_retention: bool = False, | |
| write_scale_by_retention_multiplier: float = 1.0, | |
| write_scale_sqrt_grad_clip: float = 1000.0, | |
| ) -> tuple[torch.Tensor, torch.Tensor]: | |
| batch, seq_len, four, n_head, head_dim = gates.shape | |
| if four != 4: | |
| raise ValueError("gates must have shape [batch, seq, 4, n_head, head_dim]") | |
| if initial_state.shape != (batch, n_head, head_dim): | |
| raise ValueError("initial_state must have shape [batch, n_head, head_dim]") | |
| if attention_mask is not None: | |
| if attention_mask.shape != (batch, seq_len): | |
| raise ValueError("attention_mask must have shape [batch, seq]") | |
| attention_mask = attention_mask.to(dtype=gates.dtype, device=gates.device) | |
| state = initial_state | |
| outputs: list[torch.Tensor] = [] | |
| for t in range(seq_len): | |
| a_logits, b_logits, c_logits, o_logits = gates[:, t].unbind(dim=1) | |
| a = torch.sigmoid(a_logits) | |
| b = torch.sigmoid(b_logits) | |
| c = torch.tanh(c_logits) | |
| o = torch.sigmoid(o_logits) | |
| write = b * c | |
| if write_scale_by_retention: | |
| write = ( | |
| write_scale_by_retention_multiplier | |
| * _retention_write_scale_from_logits(a_logits, write_scale_sqrt_grad_clip) | |
| * write | |
| ) | |
| next_state = a * state + write | |
| y = o * next_state | |
| if attention_mask is not None: | |
| mask = attention_mask[:, t].view(batch, 1, 1) | |
| state = mask * next_state + (1.0 - mask) * state | |
| y = mask * y | |
| else: | |
| state = next_state | |
| outputs.append(y) | |
| return torch.stack(outputs, dim=1), state | |
| def _statehead_scan_parallel( | |
| gates: torch.Tensor, | |
| initial_state: torch.Tensor, | |
| attention_mask: torch.Tensor | None = None, | |
| chunk_size: int = 64, | |
| write_scale_by_retention: bool = False, | |
| write_scale_by_retention_multiplier: float = 1.0, | |
| write_scale_sqrt_grad_clip: float = 1000.0, | |
| ) -> tuple[torch.Tensor, torch.Tensor]: | |
| batch, seq_len, four, n_head, head_dim = gates.shape | |
| if four != 4: | |
| raise ValueError("gates must have shape [batch, seq, 4, n_head, head_dim]") | |
| if initial_state.shape != (batch, n_head, head_dim): | |
| raise ValueError("initial_state must have shape [batch, n_head, head_dim]") | |
| if attention_mask is not None and attention_mask.shape != (batch, seq_len): | |
| raise ValueError("attention_mask must have shape [batch, seq]") | |
| if chunk_size < 1: | |
| raise ValueError("chunk_size must be positive") | |
| original_dtype = gates.dtype | |
| scan_dtype = torch.float32 if gates.dtype in {torch.float16, torch.bfloat16} else gates.dtype | |
| gates = gates.to(scan_dtype) | |
| state = initial_state.to(scan_dtype) | |
| if attention_mask is not None: | |
| attention_mask = attention_mask.to(dtype=scan_dtype, device=gates.device) | |
| a_logits, b_logits, c_logits, o_logits = gates.unbind(dim=2) | |
| a = torch.sigmoid(a_logits) | |
| u = torch.sigmoid(b_logits) * torch.tanh(c_logits) | |
| if write_scale_by_retention: | |
| u = ( | |
| write_scale_by_retention_multiplier | |
| * _retention_write_scale_from_logits(a_logits, write_scale_sqrt_grad_clip) | |
| * u | |
| ) | |
| o = torch.sigmoid(o_logits) | |
| mask = None | |
| if attention_mask is not None: | |
| mask = attention_mask.view(batch, seq_len, 1, 1) | |
| a = mask * a + (1.0 - mask) | |
| u = mask * u | |
| chunk_size = min(chunk_size, seq_len) | |
| n_chunks = (seq_len + chunk_size - 1) // chunk_size | |
| padded_seq_len = n_chunks * chunk_size | |
| pad_len = padded_seq_len - seq_len | |
| if pad_len: | |
| pad_shape = (batch, pad_len, n_head, head_dim) | |
| a = torch.cat([a, torch.ones(pad_shape, dtype=scan_dtype, device=gates.device)], dim=1) | |
| u = torch.cat([u, torch.zeros(pad_shape, dtype=scan_dtype, device=gates.device)], dim=1) | |
| a = a.view(batch, n_chunks, chunk_size, n_head, head_dim) | |
| u = u.view(batch, n_chunks, chunk_size, n_head, head_dim) | |
| prefix_a, prefix_u = _statehead_associative_prefix(a, u, dim=2) | |
| chunk_a = prefix_a[:, :, -1] | |
| chunk_u = prefix_u[:, :, -1] | |
| chunk_prefix_a, chunk_prefix_u = _statehead_associative_prefix(chunk_a, chunk_u, dim=1) | |
| states_after_chunks = chunk_prefix_a * state.unsqueeze(1) + chunk_prefix_u | |
| chunk_initials = torch.cat([state.unsqueeze(1), states_after_chunks[:, :-1]], dim=1) | |
| states = prefix_a * chunk_initials.unsqueeze(2) + prefix_u | |
| states = states.reshape(batch, padded_seq_len, n_head, head_dim)[:, :seq_len] | |
| y = o * states | |
| if mask is not None: | |
| y = mask * y | |
| return y.to(original_dtype), states_after_chunks[:, -1].to(original_dtype) | |
| def _statehead_associative_prefix( | |
| a: torch.Tensor, | |
| u: torch.Tensor, | |
| *, | |
| dim: int, | |
| ) -> tuple[torch.Tensor, torch.Tensor]: | |
| """Parallel prefix for elementwise recurrences s[t] = a[t] * s[t-1] + u[t].""" | |
| size = a.shape[dim] | |
| offset = 1 | |
| while offset < size: | |
| head = [slice(None)] * a.ndim | |
| tail = [slice(None)] * a.ndim | |
| prev = [slice(None)] * a.ndim | |
| head[dim] = slice(0, offset) | |
| tail[dim] = slice(offset, None) | |
| prev[dim] = slice(0, -offset) | |
| head_idx = tuple(head) | |
| tail_idx = tuple(tail) | |
| prev_idx = tuple(prev) | |
| a_tail = a[tail_idx] | |
| u_tail = u[tail_idx] | |
| a = torch.cat([a[head_idx], a_tail * a[prev_idx]], dim=dim) | |
| u = torch.cat([u[head_idx], a_tail * u[prev_idx] + u_tail], dim=dim) | |
| offset <<= 1 | |
| return a, u | |
| def _statehead_scan_chunk_loop( | |
| gates: torch.Tensor, | |
| initial_state: torch.Tensor, | |
| attention_mask: torch.Tensor | None = None, | |
| chunk_size: int = 64, | |
| write_scale_by_retention: bool = False, | |
| write_scale_by_retention_multiplier: float = 1.0, | |
| write_scale_sqrt_grad_clip: float = 1000.0, | |
| ) -> tuple[torch.Tensor, torch.Tensor]: | |
| batch, seq_len, four, n_head, head_dim = gates.shape | |
| if four != 4: | |
| raise ValueError("gates must have shape [batch, seq, 4, n_head, head_dim]") | |
| if initial_state.shape != (batch, n_head, head_dim): | |
| raise ValueError("initial_state must have shape [batch, n_head, head_dim]") | |
| if attention_mask is not None and attention_mask.shape != (batch, seq_len): | |
| raise ValueError("attention_mask must have shape [batch, seq]") | |
| if chunk_size < 1: | |
| raise ValueError("chunk_size must be positive") | |
| original_dtype = gates.dtype | |
| scan_dtype = torch.float32 if gates.dtype in {torch.float16, torch.bfloat16} else gates.dtype | |
| gates = gates.to(scan_dtype) | |
| state = initial_state.to(scan_dtype) | |
| if attention_mask is not None: | |
| attention_mask = attention_mask.to(dtype=scan_dtype, device=gates.device) | |
| chunks: list[torch.Tensor] = [] | |
| for start in range(0, seq_len, chunk_size): | |
| stop = min(start + chunk_size, seq_len) | |
| chunk_outputs: list[torch.Tensor] = [] | |
| for t in range(start, stop): | |
| a_logits, b_logits, c_logits, o_logits = gates[:, t].unbind(dim=1) | |
| a = torch.sigmoid(a_logits) | |
| b = torch.sigmoid(b_logits) | |
| c = torch.tanh(c_logits) | |
| o = torch.sigmoid(o_logits) | |
| write = b * c | |
| if write_scale_by_retention: | |
| write = ( | |
| write_scale_by_retention_multiplier | |
| * _retention_write_scale_from_logits(a_logits, write_scale_sqrt_grad_clip) | |
| * write | |
| ) | |
| next_state = a * state + write | |
| y = o * next_state | |
| if attention_mask is not None: | |
| mask = attention_mask[:, t].view(batch, 1, 1) | |
| state = mask * next_state + (1.0 - mask) * state | |
| y = mask * y | |
| else: | |
| state = next_state | |
| chunk_outputs.append(y) | |
| chunks.append(torch.stack(chunk_outputs, dim=1)) | |
| return torch.cat(chunks, dim=1).to(original_dtype), state.to(original_dtype) | |
| _compiled_parallel_scan = None | |
| def _parallel_scan_fn(): | |
| """Opt-in compiled scan: set STATEHEAD_COMPILE=1. Inference-only (compiled | |
| backward measured slower), dynamic shapes, bit-exact vs eager; falls back to | |
| eager permanently if compilation or the first compiled call fails.""" | |
| global _compiled_parallel_scan | |
| if _compiled_parallel_scan is None: | |
| try: | |
| _compiled_parallel_scan = torch.compile(_statehead_scan_parallel, dynamic=True) | |
| except Exception: | |
| _compiled_parallel_scan = _statehead_scan_parallel | |
| return _compiled_parallel_scan | |
| def statehead_scan( | |
| gates: torch.Tensor, | |
| initial_state: torch.Tensor, | |
| attention_mask: torch.Tensor | None = None, | |
| backend: str = "torch", | |
| chunk_size: int = 64, | |
| write_scale_by_retention: bool = False, | |
| write_scale_by_retention_multiplier: float = 1.0, | |
| write_scale_sqrt_grad_clip: float = 1000.0, | |
| ) -> tuple[torch.Tensor, torch.Tensor]: | |
| if backend == "auto": | |
| backend = "parallel" | |
| if backend == "torch": | |
| backend = "parallel" | |
| if backend == "parallel": | |
| args = ( | |
| gates, | |
| initial_state, | |
| attention_mask, | |
| chunk_size, | |
| write_scale_by_retention, | |
| write_scale_by_retention_multiplier, | |
| write_scale_sqrt_grad_clip, | |
| ) | |
| if os.environ.get("STATEHEAD_COMPILE", "0") == "1" and not torch.is_grad_enabled(): | |
| global _compiled_parallel_scan | |
| try: | |
| return _parallel_scan_fn()(*args) | |
| except Exception: | |
| _compiled_parallel_scan = _statehead_scan_parallel | |
| return _statehead_scan_parallel(*args) | |
| if backend == "chunk_loop": | |
| return _statehead_scan_chunk_loop( | |
| gates, | |
| initial_state, | |
| attention_mask, | |
| chunk_size, | |
| write_scale_by_retention, | |
| write_scale_by_retention_multiplier, | |
| write_scale_sqrt_grad_clip, | |
| ) | |
| if backend == "torch_loop": | |
| return _statehead_scan_torch( | |
| gates, | |
| initial_state, | |
| attention_mask, | |
| write_scale_by_retention, | |
| write_scale_by_retention_multiplier, | |
| write_scale_sqrt_grad_clip, | |
| ) | |
| if backend == "triton": | |
| warnings.warn( | |
| "The Triton StateHead scan is not wired yet; falling back to the PyTorch scan.", | |
| RuntimeWarning, | |
| stacklevel=2, | |
| ) | |
| return _statehead_scan_parallel( | |
| gates, | |
| initial_state, | |
| attention_mask, | |
| chunk_size, | |
| write_scale_by_retention, | |
| write_scale_by_retention_multiplier, | |
| write_scale_sqrt_grad_clip, | |
| ) | |
| raise ValueError(f"Unknown StateHead scan backend: {backend}") | |
| def count_unique_parameters(model: nn.Module) -> int: | |
| seen: set[int] = set() | |
| total = 0 | |
| for parameter in model.parameters(): | |
| pointer = id(parameter) | |
| if pointer in seen: | |
| continue | |
| seen.add(pointer) | |
| total += parameter.numel() | |
| return total | |
| class StateHeadMLP(nn.Module): | |
| def __init__(self, config: StateHeadConfig) -> None: | |
| super().__init__() | |
| hidden_dim = config.mlp_ratio * config.n_embd | |
| self.up = nn.Linear(config.n_embd, hidden_dim) | |
| self.down = nn.Linear(hidden_dim, config.n_embd) | |
| self.dropout = nn.Dropout(config.dropout) | |
| def forward(self, x: torch.Tensor) -> torch.Tensor: | |
| return self.dropout(self.down(F.gelu(self.up(x)))) | |
| class StateHeadBank(nn.Module): | |
| def __init__(self, config: StateHeadConfig) -> None: | |
| super().__init__() | |
| self.n_head = config.n_head | |
| self.head_dim = config.head_dim | |
| self.n_embd = config.n_embd | |
| self.scan_backend = config.scan_backend | |
| self.scan_chunk_size = config.scan_chunk_size | |
| self.write_scale_by_retention = config.state_write_scale_by_retention | |
| self.write_scale_by_retention_multiplier = config.state_write_scale_by_retention_multiplier | |
| self.write_scale_sqrt_grad_clip = config.state_write_scale_sqrt_grad_clip | |
| self.gate = nn.Linear(config.n_embd, 4 * config.n_embd) | |
| self.proj = nn.Linear(config.n_embd, config.n_embd) | |
| self.dropout = nn.Dropout(config.dropout) | |
| if config.learned_initial_state: | |
| initial_state = torch.zeros(config.n_head, config.head_dim) | |
| if config.initial_state_std > 0: | |
| initial_state.normal_(mean=0.0, std=config.initial_state_std) | |
| self.initial_state = nn.Parameter(initial_state) | |
| else: | |
| self.register_parameter("initial_state", None) | |
| def reset_statehead_bias(self, retention_bias: float, write_gate_bias: float, output_gate_bias: float) -> None: | |
| with torch.no_grad(): | |
| self.gate.bias.zero_() | |
| self.gate.bias[: self.n_embd].fill_(retention_bias) | |
| self.gate.bias[self.n_embd : 2 * self.n_embd].fill_(write_gate_bias) | |
| self.gate.bias[3 * self.n_embd :].fill_(output_gate_bias) | |
| def zero_state(self, batch_size: int, *, device: torch.device, dtype: torch.dtype) -> torch.Tensor: | |
| return torch.zeros(batch_size, self.n_head, self.head_dim, device=device, dtype=dtype) | |
| def fresh_state(self, batch_size: int, *, device: torch.device, dtype: torch.dtype) -> torch.Tensor: | |
| if self.initial_state is None: | |
| return self.zero_state(batch_size, device=device, dtype=dtype) | |
| return self.initial_state.to(device=device, dtype=dtype).unsqueeze(0).expand(batch_size, -1, -1) | |
| def forward( | |
| self, | |
| x: torch.Tensor, | |
| state: torch.Tensor | None = None, | |
| attention_mask: torch.Tensor | None = None, | |
| ) -> tuple[torch.Tensor, torch.Tensor]: | |
| batch, seq_len, _ = x.shape | |
| if state is None: | |
| state = self.fresh_state(batch, device=x.device, dtype=x.dtype) | |
| gates = self.gate(x).view(batch, seq_len, 4, self.n_head, self.head_dim) | |
| y, next_state = statehead_scan( | |
| gates, | |
| state, | |
| attention_mask, | |
| self.scan_backend, | |
| self.scan_chunk_size, | |
| self.write_scale_by_retention, | |
| self.write_scale_by_retention_multiplier, | |
| self.write_scale_sqrt_grad_clip, | |
| ) | |
| y = y.reshape(batch, seq_len, self.n_embd) | |
| return self.dropout(self.proj(y)), next_state | |
| class StateHeadBlock(nn.Module): | |
| def __init__(self, config: StateHeadConfig) -> None: | |
| super().__init__() | |
| self.residual_scale = config.residual_scale | |
| self.norm_state = nn.RMSNorm(config.n_embd, eps=config.layer_norm_eps) | |
| self.state_bank = StateHeadBank(config) | |
| self.norm_mlp = nn.RMSNorm(config.n_embd, eps=config.layer_norm_eps) | |
| self.mlp = StateHeadMLP(config) | |
| def forward( | |
| self, | |
| x: torch.Tensor, | |
| state: torch.Tensor | None = None, | |
| attention_mask: torch.Tensor | None = None, | |
| ) -> tuple[torch.Tensor, torch.Tensor]: | |
| y, next_state = self.state_bank(self.norm_state(x), state, attention_mask) | |
| x = x + self.residual_scale * y | |
| x = x + self.residual_scale * self.mlp(self.norm_mlp(x)) | |
| return x, next_state | |
| class StateHeadBackbone(nn.Module): | |
| def __init__(self, config: StateHeadConfig) -> None: | |
| super().__init__() | |
| self.config = config | |
| self.token_embedding = nn.Embedding(config.vocab_size, config.n_embd) | |
| self.position_embedding = ( | |
| nn.Embedding(config.block_size, config.n_embd) if config.use_position_embeddings else None | |
| ) | |
| self.dropout = nn.Dropout(config.dropout) | |
| self.blocks = nn.ModuleList(StateHeadBlock(config) for _ in range(config.n_layer)) | |
| self.norm = nn.RMSNorm(config.n_embd, eps=config.layer_norm_eps) | |
| def reset_statehead_biases(self) -> None: | |
| for block in self.blocks: | |
| block.state_bank.reset_statehead_bias( | |
| self.config.state_retention_bias, | |
| self.config.state_write_gate_bias, | |
| self.config.state_output_gate_bias, | |
| ) | |
| def zero_state(self, batch_size: int, *, device: torch.device, dtype: torch.dtype) -> tuple[torch.Tensor, ...]: | |
| return tuple(block.state_bank.fresh_state(batch_size, device=device, dtype=dtype) for block in self.blocks) | |
| def forward( | |
| self, | |
| input_ids: torch.LongTensor | None = None, | |
| attention_mask: torch.Tensor | None = None, | |
| inputs_embeds: torch.Tensor | None = None, | |
| position_ids: torch.LongTensor | None = None, | |
| past_key_values: Sequence[torch.Tensor] | None = None, | |
| use_cache: bool = False, | |
| output_hidden_states: bool = False, | |
| ) -> BaseModelOutputWithPast: | |
| if input_ids is None and inputs_embeds is None: | |
| raise ValueError("Either input_ids or inputs_embeds must be provided") | |
| if input_ids is not None and inputs_embeds is not None: | |
| raise ValueError("Only one of input_ids or inputs_embeds may be provided") | |
| if inputs_embeds is None: | |
| inputs_embeds = self.token_embedding(input_ids) | |
| batch_size, seq_len, _ = inputs_embeds.shape | |
| if attention_mask is not None: | |
| if attention_mask.shape[-1] != seq_len: | |
| attention_mask = attention_mask[:, -seq_len:] | |
| attention_mask = attention_mask.to(device=inputs_embeds.device) | |
| x = inputs_embeds | |
| if self.position_embedding is not None: | |
| if position_ids is None: | |
| position_ids = torch.arange(seq_len, device=x.device).unsqueeze(0) | |
| if position_ids.shape[-1] != seq_len: | |
| position_ids = position_ids[:, -seq_len:] | |
| position_ids = position_ids.clamp(max=self.config.block_size - 1) | |
| x = x + self.position_embedding(position_ids) | |
| x = self.dropout(x) | |
| if past_key_values is None: | |
| states: Sequence[torch.Tensor | None] = [None] * len(self.blocks) | |
| else: | |
| if len(past_key_values) != len(self.blocks): | |
| raise ValueError("past_key_values must contain one state per layer") | |
| states = past_key_values | |
| all_hidden_states: tuple[torch.Tensor, ...] | None = () if output_hidden_states else None | |
| if all_hidden_states is not None: | |
| all_hidden_states += (x,) | |
| next_states: list[torch.Tensor] = [] | |
| for block, state in zip(self.blocks, states, strict=True): | |
| x, next_state = block(x, state, attention_mask) | |
| next_states.append(next_state) | |
| if all_hidden_states is not None: | |
| all_hidden_states += (x,) | |
| x = self.norm(x) | |
| return BaseModelOutputWithPast( | |
| last_hidden_state=x, | |
| past_key_values=tuple(next_states) if use_cache else None, | |
| hidden_states=all_hidden_states, | |
| ) | |
| class StateHeadPreTrainedModel(PreTrainedModel): | |
| config_class = StateHeadConfig | |
| base_model_prefix = "statehead" | |
| supports_gradient_checkpointing = False | |
| _no_split_modules = ["StateHeadBlock"] | |
| def _init_weights(self, module: nn.Module) -> None: | |
| if isinstance(module, nn.Linear): | |
| module.weight.data.normal_(mean=0.0, std=self.config.initializer_range) | |
| if module.bias is not None: | |
| module.bias.data.zero_() | |
| elif isinstance(module, nn.Embedding): | |
| module.weight.data.normal_(mean=0.0, std=self.config.initializer_range) | |
| if module.padding_idx is not None: | |
| module.weight.data[module.padding_idx].zero_() | |
| def save_pretrained(self, save_directory: str | Path, *args: Any, **kwargs: Any): | |
| result = super().save_pretrained(save_directory, *args, **kwargs) | |
| save_path = Path(save_directory) | |
| source_dir = Path(__file__).parent | |
| for filename in ("configuration_statehead.py", "modeling_statehead.py"): | |
| shutil.copy2(source_dir / filename, save_path / filename) | |
| return result | |
| class StateHeadModel(StateHeadPreTrainedModel): | |
| def __init__(self, config: StateHeadConfig) -> None: | |
| super().__init__(config) | |
| self.statehead = StateHeadBackbone(config) | |
| self.post_init() | |
| self.statehead.reset_statehead_biases() | |
| def get_input_embeddings(self) -> nn.Embedding: | |
| return self.statehead.token_embedding | |
| def set_input_embeddings(self, value: nn.Embedding) -> None: | |
| self.statehead.token_embedding = value | |
| def forward( | |
| self, | |
| input_ids: torch.LongTensor | None = None, | |
| attention_mask: torch.Tensor | None = None, | |
| inputs_embeds: torch.Tensor | None = None, | |
| position_ids: torch.LongTensor | None = None, | |
| past_key_values: Sequence[torch.Tensor] | None = None, | |
| use_cache: bool | None = None, | |
| output_hidden_states: bool | None = None, | |
| return_dict: bool | None = None, | |
| **_: Any, | |
| ) -> BaseModelOutputWithPast | tuple[torch.Tensor, ...]: | |
| use_cache = use_cache if use_cache is not None else self.config.use_cache | |
| output_hidden_states = ( | |
| output_hidden_states if output_hidden_states is not None else self.config.output_hidden_states | |
| ) | |
| return_dict = return_dict if return_dict is not None else self.config.use_return_dict | |
| outputs = self.statehead( | |
| input_ids=input_ids, | |
| attention_mask=attention_mask, | |
| inputs_embeds=inputs_embeds, | |
| position_ids=position_ids, | |
| past_key_values=past_key_values, | |
| use_cache=use_cache, | |
| output_hidden_states=output_hidden_states, | |
| ) | |
| if return_dict: | |
| return outputs | |
| result: tuple[torch.Tensor, ...] = (outputs.last_hidden_state,) | |
| if use_cache: | |
| result += (outputs.past_key_values,) | |
| if output_hidden_states: | |
| result += (outputs.hidden_states,) | |
| return result | |
| class StateHeadForCausalLM(StateHeadPreTrainedModel, GenerationMixin): | |
| _tied_weights_keys = ["lm_head.weight"] | |
| def __init__(self, config: StateHeadConfig) -> None: | |
| super().__init__(config) | |
| self.statehead = StateHeadBackbone(config) | |
| self.lm_head = nn.Linear(config.n_embd, config.vocab_size, bias=False) | |
| self.post_init() | |
| self.statehead.reset_statehead_biases() | |
| def get_input_embeddings(self) -> nn.Embedding: | |
| return self.statehead.token_embedding | |
| def set_input_embeddings(self, value: nn.Embedding) -> None: | |
| self.statehead.token_embedding = value | |
| def get_output_embeddings(self) -> nn.Linear: | |
| return self.lm_head | |
| def set_output_embeddings(self, new_embeddings: nn.Linear) -> None: | |
| self.lm_head = new_embeddings | |
| def prepare_inputs_for_generation( | |
| self, | |
| input_ids: torch.LongTensor, | |
| past_key_values: Sequence[torch.Tensor] | None = None, | |
| attention_mask: torch.Tensor | None = None, | |
| **kwargs: Any, | |
| ) -> dict[str, Any]: | |
| if past_key_values is not None: | |
| input_ids = input_ids[:, -1:] | |
| if attention_mask is not None: | |
| attention_mask = attention_mask[:, -1:] | |
| return { | |
| "input_ids": input_ids, | |
| "past_key_values": past_key_values, | |
| "attention_mask": attention_mask, | |
| "use_cache": kwargs.get("use_cache", True), | |
| } | |
| def forward( | |
| self, | |
| input_ids: torch.LongTensor | None = None, | |
| attention_mask: torch.Tensor | None = None, | |
| inputs_embeds: torch.Tensor | None = None, | |
| position_ids: torch.LongTensor | None = None, | |
| past_key_values: Sequence[torch.Tensor] | None = None, | |
| labels: torch.LongTensor | None = None, | |
| use_cache: bool | None = None, | |
| output_hidden_states: bool | None = None, | |
| return_dict: bool | None = None, | |
| **_: Any, | |
| ) -> CausalLMOutputWithPast | tuple[torch.Tensor, ...]: | |
| use_cache = use_cache if use_cache is not None else self.config.use_cache | |
| output_hidden_states = ( | |
| output_hidden_states if output_hidden_states is not None else self.config.output_hidden_states | |
| ) | |
| return_dict = return_dict if return_dict is not None else self.config.use_return_dict | |
| outputs = self.statehead( | |
| input_ids=input_ids, | |
| attention_mask=attention_mask, | |
| inputs_embeds=inputs_embeds, | |
| position_ids=position_ids, | |
| past_key_values=past_key_values, | |
| use_cache=use_cache, | |
| output_hidden_states=output_hidden_states, | |
| ) | |
| logits = self.lm_head(outputs.last_hidden_state) | |
| loss = None | |
| if labels is not None: | |
| shift_logits = logits[:, :-1, :].contiguous() | |
| shift_labels = labels[:, 1:].contiguous() | |
| loss = F.cross_entropy( | |
| shift_logits.view(-1, shift_logits.size(-1)), | |
| shift_labels.view(-1), | |
| ignore_index=-100, | |
| ) | |
| if return_dict: | |
| return CausalLMOutputWithPast( | |
| loss=loss, | |
| logits=logits, | |
| past_key_values=outputs.past_key_values, | |
| hidden_states=outputs.hidden_states, | |
| ) | |
| result: tuple[torch.Tensor, ...] = (logits,) | |
| if use_cache: | |
| result += (outputs.past_key_values,) | |
| if output_hidden_states: | |
| result += (outputs.hidden_states,) | |
| return ((loss,) + result) if loss is not None else result | |