Spaces:
Sleeping
Sleeping
File size: 2,039 Bytes
3afc977 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | """Autoregressive fill-in-the-middle baseline (EXPERIMENTS.md).
Same backbone, causal mask. Trained left-to-right; loss only on the middle (hole
+ eos) span so the objective matches diffusion's hole-only loss. The FIM ordering
([pre] prefix [suf] suffix [mid] hole) lets the AR model condition on the suffix
too — the fair counterpart to diffusion's bidirectional view.
The decode is strictly sequential: one token per forward pass. That sequential
cost is exactly what the iso-latency comparison weighs against diffusion's
parallel refinement.
"""
from __future__ import annotations
import torch
import torch.nn.functional as F
def loss(model, ids, loss_mask, attn_mask, tok):
"""Causal next-token CE on the mid span. ids,(B,T); loss_mask,(B,T) marks the
mid tokens; attn_mask,(B,T) non-pad."""
logits = model(ids, attn_mask) # (B,T,V)
# Predict token q from position q-1.
pred = logits[:, :-1, :]
target = ids[:, 1:]
mask = loss_mask[:, 1:]
ce = F.cross_entropy(
pred.reshape(-1, pred.size(-1)), target.reshape(-1), reduction="none"
).view(target.shape)
ce = ce * mask.float()
return ce.sum() / mask.float().sum().clamp(min=1)
@torch.no_grad()
def sample(model, head_ids, tok, max_new: int, seq_len: int):
"""KV-cached greedy decode of the hole for one FIM prompt. head_ids: 1-D tensor
[bos pre ...prefix... suf ...suffix... mid]. Returns the decoded hole string."""
out = model.generate(head_ids, max_new=max_new, eos_id=tok.eos_id)
return tok.decode(out)
def build_prompt(tok, prefix, suffix, taskcfg):
"""The FIM prompt head for inference: returns a list of ids, or None if the
context doesn't fit. prefix/suffix are id lists (lua) or strings (char)."""
pre = list(prefix) if tok.mode == "lua" else tok.encode(prefix)
suf = list(suffix) if tok.mode == "lua" else tok.encode(suffix)
head = [tok.bos_id, tok.pre_id] + pre + [tok.suf_id] + suf + [tok.mid_id]
if len(head) + 1 >= taskcfg.seq_len:
return None
return head
|