mukunds's picture
Publish frozen LoopFormer pointer checkpoint and inference code
e29f88c verified
Raw History Blame Contribute Delete
2.7 kB
"""Loop outputs and symbolic readout semantics."""
from dataclasses import dataclass
import torch
from torch import Tensor
@dataclass
class RecurrentOutput:
"""Tuple index t-1 represents loop t; h_0 is not a decoded start symbol.
Logits are [batch, vocab] in answer mode or [batch, sequence, vocab]
in all-token mode. Optional hidden states are [batch, sequence, hidden].
Margins are [batch, loops]. Tensors retain autograd unless the caller
disables it; observations never feed back into the recurrent trajectory.
"""
loop_logits: tuple[Tensor, ...]
hidden_states: tuple[Tensor, ...] | None = None
initial_hidden_state: Tensor | None = None
margins: Tensor | None = None
state_logits: Tensor | None = None # Direct R readout [B,T,26], never fed back.
stop_logits: Tensor | None = None # [batch, executed_loops], when completion is enabled.
@property
def logits(self) -> Tensor:
"""The final loop's logits."""
return self.loop_logits[-1]
def answer_margin(logits: Tensor, labels: Tensor, allowed_token_ids: Tensor) -> Tensor:
"""Correct raw logit minus the best *other allowed* logit, per example.
Shapes: logits [batch, vocab], labels [batch] (token IDs), allowed IDs
[answers]. Labels must belong to a unique answer set of at least two IDs.
A tie has margin zero, so it is not margin-based correctness.
"""
if logits.ndim != 2 or labels.shape != logits.shape[:1]:
raise ValueError("Expected logits [batch, vocab] and labels [batch]")
if labels.dtype != torch.long or allowed_token_ids.dtype != torch.long:
raise ValueError("Labels and allowed_token_ids must be torch.long token IDs")
if labels.device != logits.device or allowed_token_ids.device != logits.device:
raise ValueError("Logits, labels, and allowed_token_ids must share a device")
if allowed_token_ids.ndim != 1 or allowed_token_ids.numel() < 2:
raise ValueError("Provide at least two allowed token IDs in a 1D tensor")
if allowed_token_ids.unique().numel() != allowed_token_ids.numel():
raise ValueError("Allowed token IDs must be unique")
if (allowed_token_ids < 0).any() or (allowed_token_ids >= logits.shape[-1]).any():
raise ValueError("Allowed token IDs must be within the model vocabulary")
correct = labels[:, None] == allowed_token_ids[None, :]
if not correct.any(dim=-1).all():
raise ValueError("Every label must be an allowed token ID")
scores = logits.index_select(-1, allowed_token_ids)
wrong = scores.masked_fill(correct, -torch.inf).max(dim=-1).values
return logits.gather(-1, labels[:, None]).squeeze(-1) - wrong