# Copyright (c) 2023-2025, Songlin Yang, Yu Zhang import math import torch def tril_softmax(scores: torch.Tensor, strict: bool = True) -> torch.Tensor: """ Row-wise causal softmax over strictly lower-triangular (j < i) positions. Args: scores: [B, H, T, T] raw attention scores (q @ k^T). strict: if True, mask out diagonal as well (strictly causal). Otherwise include diagonal. Returns: probs: [B, H, T, T] with probabilities on j < i (or j <= i if strict=False), zeros elsewhere. """ T = scores.size(-1) device = scores.device i = torch.arange(T, device=device).view(1, 1, T, 1) j = torch.arange(T, device=device).view(1, 1, 1, T) if strict: mask = (j < i) else: mask = (j <= i) masked = scores.masked_fill(~mask, float('-inf')) max_per_row = masked.max(dim=-1, keepdim=True).values exp = (masked - max_per_row).exp() exp = exp.masked_fill(~mask, 0.0) denom = exp.sum(dim=-1, keepdim=True).clamp_min_(1e-20) probs = exp / denom return probs def naive_causal_attention_bhtd( q: torch.Tensor, k: torch.Tensor, v: torch.Tensor, ) -> torch.Tensor: B, H, T, D = q.shape qk_scale = 1.0 / math.sqrt(D) scores = torch.matmul(q, k.transpose(-1, -2)) * qk_scale # [B, H, T, T] causal_mask = torch.triu(torch.ones(T, T, device=q.device), diagonal=1).bool() scores = scores.masked_fill(causal_mask, float('-inf')) attn_weights = torch.softmax(scores, dim=-1) # [B, H, T, T] o = torch.matmul(attn_weights, v) # [B, H, T, D] return o def naive_deltaformer_attn_head_first( q: torch.Tensor, k: torch.Tensor, v: torch.Tensor, beta: torch.Tensor | None = None, ) -> torch.Tensor: """ Naive reference implementation of DeltaFormer attention for head-first format. Two-stage process: 1. Computes u[i] = v[i] - beta[i] * sum_{j torch.Tensor: """ Naive reference implementation of DeltaFormer attention for sequence-first format. Args: q: [B, T, H, D] k: [B, T, H, D] v: [B, T, H, D] beta: [B, T, H] or None (defaults to ones) Returns: o: [B, T, H, D] """ assert q.dim() == 4 and k.dim() == 4 and v.dim() == 4, "q,k,v must be [B,T,H,D]" B, T, H, D = q.shape assert k.shape == (B, T, H, D) and v.shape == (B, T, H, D) q_bhtd = q.transpose(1, 2) # [B, T, H, D] -> [B, H, T, D] k_bhtd = k.transpose(1, 2) # [B, T, H, D] -> [B, H, T, D] v_bhtd = v.transpose(1, 2) # [B, T, H, D] -> [B, H, T, D] if beta is not None: assert beta.shape == (B, T, H) beta_bhtd = beta.transpose(1, 2) # [B, T, H] -> [B, H, T] else: beta_bhtd = None o_bhtd = naive_deltaformer_attn_head_first(q_bhtd, k_bhtd, v_bhtd, beta_bhtd) o_bthd = o_bhtd.transpose(1, 2) # [B, H, T, D] -> [B, T, H, D] return o_bthd __all__ = [ 'naive_deltaformer_attn', 'tril_softmax', ]