Download ar/eval/batch_gen.py from AjayRangoji/AR: direct link, hf CLI and curl.
- Browser
- Download file 1.99 kB
-
https://huggingface.co/AjayRangoji/AR/resolve/main/ar/eval/batch_gen.py
- Command line
-
hf download hf://AjayRangoji/AR/ar/eval/batch_gen.py
-
curl -L -o batch_gen.py https://huggingface.co/AjayRangoji/AR/resolve/main/ar/eval/batch_gen.py
1.99 kB
| """Batched greedy generation for benchmarks (no KV cache: simple, not fast).""" | |
| import torch | |
| from ar.model.mask import build_doc_block_mask | |
| def generate_batch(model, tok, prompts, seq_len, max_new, stop, device): | |
| """Greedy-decode a batch of prompts; each output is cut at its first stop string.""" | |
| B = len(prompts) | |
| # fixed-size buffer: each row has its own prompt length and write position; | |
| # the causal mask hides the placeholder slots to the right of each position | |
| buf = torch.full((B, seq_len), tok.eot_id, dtype=torch.long, device=device) | |
| pos = [] | |
| for b, p in enumerate(prompts): | |
| x = tok.encode(p)[-(seq_len - max_new):] # keep the end if a prompt is too long | |
| buf[b, :len(x)] = torch.tensor(x, device=device) | |
| pos.append(len(x)) | |
| start = list(pos) | |
| seg = torch.zeros(B, seq_len, dtype=torch.int32, device=device) # one doc per row | |
| mask = build_doc_block_mask(seg, seq_len, device=device) | |
| done, outs = [False] * B, [""] * B | |
| rows = torch.arange(B, device=device) | |
| for _ in range(max_new): | |
| logits = model(buf, mask) | |
| # each row's next token = most likely token at its own current position | |
| idx = torch.tensor(pos, device=device) - 1 | |
| nxt = logits[rows, idx].argmax(-1).tolist() | |
| for b in range(B): | |
| if done[b]: | |
| continue | |
| if nxt[b] == tok.eot_id: # model ended the text | |
| done[b] = True | |
| continue | |
| buf[b, pos[b]] = nxt[b] | |
| pos[b] += 1 | |
| outs[b] = tok.decode(buf[b, start[b]:pos[b]].tolist()) | |
| if pos[b] >= seq_len or any(s in outs[b] for s in stop): | |
| done[b] = True | |
| if all(done): | |
| break | |
| # cut each output at its first stop string | |
| for b in range(B): | |
| hits = [outs[b].find(s) for s in stop if s in outs[b]] | |
| outs[b] = outs[b][: min(hits)] if hits else outs[b] | |
| return outs |